summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2016-02-09 18:40:49 +0100
committerFulup Ar Foll <fulup@iot.bzh>2016-02-09 18:40:49 +0100
commit3d2fda7dd39e2363682f1fa353c951ab0d44ddfa (patch)
treeaf968a8ac5d4fde1f3cebcec5fb0973eb2bfb2cb
parent12a3520ba440316c76b95d92a684666f03f7b47d (diff)
Implemented URL query parsing for initial token /opa/?token=abcde
-rw-r--r--afb-client/app/Frontend/app.js11
-rw-r--r--afb-client/app/Frontend/etc/ConfigApp.js6
-rw-r--r--afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js2
-rw-r--r--afb-client/bower_components/angular-animate/.bower.json19
-rw-r--r--afb-client/bower_components/angular-animate/README.md68
-rw-r--r--afb-client/bower_components/angular-animate/angular-animate.js2142
-rw-r--r--afb-client/bower_components/angular-animate/angular-animate.min.js33
-rw-r--r--afb-client/bower_components/angular-animate/angular-animate.min.js.map8
-rw-r--r--afb-client/bower_components/angular-animate/bower.json9
-rw-r--r--afb-client/bower_components/angular-animate/index.js2
-rw-r--r--afb-client/bower_components/angular-animate/package.json26
-rw-r--r--afb-client/bower_components/angular-cookies/.bower.json19
-rw-r--r--afb-client/bower_components/angular-cookies/README.md68
-rw-r--r--afb-client/bower_components/angular-cookies/angular-cookies.js207
-rw-r--r--afb-client/bower_components/angular-cookies/angular-cookies.min.js8
-rw-r--r--afb-client/bower_components/angular-cookies/angular-cookies.min.js.map8
-rw-r--r--afb-client/bower_components/angular-cookies/bower.json9
-rw-r--r--afb-client/bower_components/angular-cookies/index.js2
-rw-r--r--afb-client/bower_components/angular-cookies/package.json26
-rw-r--r--afb-client/bower_components/angular-ui-notification/.bower.json45
-rw-r--r--afb-client/bower_components/angular-ui-notification/LICENSE21
-rw-r--r--afb-client/bower_components/angular-ui-notification/README.md174
-rw-r--r--afb-client/bower_components/angular-ui-notification/bower.json36
-rw-r--r--afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css8
-rw-r--r--afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.js8
-rw-r--r--afb-client/bower_components/angular-ui-notification/gulpfile.js92
-rw-r--r--afb-client/bower_components/angular-ui-notification/package.json45
-rw-r--r--afb-client/bower_components/angular-ui-notification/protractor_conf.js24
-rw-r--r--afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.html4
-rw-r--r--afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.js172
-rw-r--r--afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.less55
-rw-r--r--afb-client/bower_components/angular-ui-router/.bower.json34
-rw-r--r--afb-client/bower_components/angular-ui-router/CHANGELOG.md316
-rw-r--r--afb-client/bower_components/angular-ui-router/CONTRIBUTING.md65
-rw-r--r--afb-client/bower_components/angular-ui-router/LICENSE21
-rw-r--r--afb-client/bower_components/angular-ui-router/README.md252
-rw-r--r--afb-client/bower_components/angular-ui-router/bower.json24
-rw-r--r--afb-client/bower_components/angular-ui-router/release/angular-ui-router.js4539
-rw-r--r--afb-client/bower_components/angular-ui-router/release/angular-ui-router.min.js8
-rw-r--r--afb-client/bower_components/angular-ui-router/src/common.js293
-rw-r--r--afb-client/bower_components/angular-ui-router/src/resolve.js252
-rw-r--r--afb-client/bower_components/angular-ui-router/src/state.js1470
-rw-r--r--afb-client/bower_components/angular-ui-router/src/stateDirectives.js391
-rw-r--r--afb-client/bower_components/angular-ui-router/src/stateFilters.js39
-rw-r--r--afb-client/bower_components/angular-ui-router/src/templateFactory.js110
-rw-r--r--afb-client/bower_components/angular-ui-router/src/urlMatcherFactory.js1081
-rw-r--r--afb-client/bower_components/angular-ui-router/src/urlRouter.js431
-rw-r--r--afb-client/bower_components/angular-ui-router/src/view.js45
-rw-r--r--afb-client/bower_components/angular-ui-router/src/viewDirective.js351
-rw-r--r--afb-client/bower_components/angular-ui-router/src/viewScroll.js52
-rw-r--r--afb-client/bower_components/angular/.bower.json17
-rw-r--r--afb-client/bower_components/angular/README.md64
-rw-r--r--afb-client/bower_components/angular/angular-csp.css13
-rw-r--r--afb-client/bower_components/angular/angular.js26451
-rw-r--r--afb-client/bower_components/angular/angular.min.js253
-rw-r--r--afb-client/bower_components/angular/angular.min.js.gzipbin0 -> 46451 bytes
-rw-r--r--afb-client/bower_components/angular/angular.min.js.map8
-rw-r--r--afb-client/bower_components/angular/bower.json8
-rw-r--r--afb-client/bower_components/angular/index.js2
-rw-r--r--afb-client/bower_components/angular/package.json25
-rw-r--r--afb-client/bower_components/fastclick/.bower.json23
-rw-r--r--afb-client/bower_components/fastclick/LICENSE22
-rw-r--r--afb-client/bower_components/fastclick/README.md140
-rw-r--r--afb-client/bower_components/fastclick/bower.json12
-rw-r--r--afb-client/bower_components/fastclick/lib/fastclick.js841
-rw-r--r--afb-client/bower_components/foundation-apps/.bower.json57
-rw-r--r--afb-client/bower_components/foundation-apps/CHANGELOG.md301
-rw-r--r--afb-client/bower_components/foundation-apps/LICENSE22
-rwxr-xr-xafb-client/bower_components/foundation-apps/README.md83
-rw-r--r--afb-client/bower_components/foundation-apps/bin/gulp-dynamic-routing.js56
-rwxr-xr-xafb-client/bower_components/foundation-apps/bower.json48
-rwxr-xr-xafb-client/bower_components/foundation-apps/dist/css/foundation-apps.css6146
-rwxr-xr-xafb-client/bower_components/foundation-apps/dist/css/foundation-apps.min.css1
-rw-r--r--afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.js170
-rw-r--r--afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.min.js1
-rwxr-xr-xafb-client/bower_components/foundation-apps/dist/js/foundation-apps.js3136
-rwxr-xr-xafb-client/bower_components/foundation-apps/dist/js/foundation-apps.min.js2
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/account.svg44
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/action.svg38
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/ban.svg17
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/bell.svg22
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/bookmark.svg14
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/cart.svg35
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/chevron.svg28
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/circle-check.svg25
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/circle-x.svg25
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/cog.svg17
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/comment-square.svg14
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/dashboard.svg38
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/document.svg28
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/envelope.svg44
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/flag.svg24
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/home.svg28
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/lock.svg55
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/magnifying-glass.svg26
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/person.svg62
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/reload.svg19
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/share-boxed.svg17
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/star.svg14
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/thumb.svg38
-rwxr-xr-xafb-client/bower_components/foundation-apps/iconic/zoom.svg56
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/app.js35
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html4
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html2
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js107
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html6
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html8
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html3
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js226
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/common/common.js171
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js186
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js94
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.html9
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.js291
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html9
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html12
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.html12
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.js417
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html5
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js102
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.html6
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.js144
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.html2
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.js160
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html8
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html3
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html8
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js311
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/foundation.js22
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.animation.js129
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.js163
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.animations.js125
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.js156
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/services/foundation.mediaquery.js198
-rw-r--r--afb-client/bower_components/foundation-apps/js/angular/vendor/markdown.js10
-rwxr-xr-xafb-client/bower_components/foundation-apps/js/angular/vendor/svgDirs.js101
-rwxr-xr-xafb-client/bower_components/foundation-apps/js/vendor/iconic.min.js6
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/_global.scss131
-rw-r--r--afb-client/bower_components/foundation-apps/scss/_settings.scss614
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_accordion.scss72
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_action-sheet.scss265
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_block-list.scss350
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_button-group.scss197
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_button.scss205
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_card.scss93
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_extras.scss54
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/components/_forms.scss458
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_grid.scss420
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_iconic.scss95
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_label.scss134
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/components/_list.scss19
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_menu-bar.scss363
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_modal.scss126
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_motion.scss524
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_notification.scss207
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_off-canvas.scss169
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_panel.scss134
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_popup.scss68
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_switch.scss130
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_tabs.scss100
-rw-r--r--afb-client/bower_components/foundation-apps/scss/components/_title-bar.scss135
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/components/_typography.scss345
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/components/_utilities.scss160
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/foundation.scss50
-rw-r--r--afb-client/bower_components/foundation-apps/scss/helpers/_breakpoints.scss154
-rwxr-xr-xafb-client/bower_components/foundation-apps/scss/helpers/_functions.scss343
-rw-r--r--afb-client/bower_components/foundation-apps/scss/helpers/_images.scss19
-rw-r--r--afb-client/bower_components/foundation-apps/scss/helpers/_mixins.scss123
-rw-r--r--afb-client/bower_components/foundation-apps/scss/vendor/_normalize.scss425
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/.bower.json17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/.fontcustom-data298
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/.gitignore1
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/README.md5
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/_foundation-icons.scss596
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/bower.json6
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/foundation-icons.css594
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/foundation-icons.eotbin0 -> 54568 bytes
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/foundation-icons.svg970
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/foundation-icons.ttfbin0 -> 56976 bytes
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/foundation-icons.woffbin0 -> 32020 bytes
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/index.html3797
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-address-book.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-alert.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-center.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-justify.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-left.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-right.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-anchor.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-annotate.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-archive.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-down.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-left.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-right.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-up.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-compress.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-expand.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-in.svg32
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-out.svg32
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-asl.svg52
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-asterisk.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-at-sign.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-background-color.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-empty.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-full.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-half.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin-circle.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-blind.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-bluetooth.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-bold.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-book-bookmark.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-book.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-bookmark.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-braille.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-new.svg25
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-sale.svg29
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-calendar.svg29
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-camera.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-check.svg10
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-checkbox.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-notes.svg32
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-pencil.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-clock.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-closed-caption.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-cloud.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-minus.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-quotes.svg29
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-video.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-comments.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-compass.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-contrast.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-credit-card.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-crop.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-crown.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-css3.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-database.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-five.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-four.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-one.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-six.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-three.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-two.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-dislike.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar-bill.svg31
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-download.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-eject.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-elevator.svg35
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-euro.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-eye.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-fast-forward.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-female-symbol.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-female.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-filter.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-first-aid.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-flag.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-add.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-lock.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-foot.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-foundation.svg42
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-bar.svg24
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-horizontal.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-pie.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-trend.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-guide-dog.svg25
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-hearing-aid.svg30
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-heart.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-home.svg9
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-html5.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-less.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-more.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-info.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-italic.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-key.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-laptop.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-layout.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-lightbulb.svg31
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-like.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-link.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-bullet.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-number.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-thumbnails.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-list.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-lock.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-loop.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-magnifying-glass.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-mail.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-female.svg34
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-symbol.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-male.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-map.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-marker.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-megaphone.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-microphone.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus-circle.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus.svg8
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile-signal.svg29
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-monitor.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-mountains.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-music.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-next.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-dogs.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-smoking.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-add.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-copy.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-csv.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-delete.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-doc.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-edit.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-csv.svg25
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-doc.svg25
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-pdf.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-filled.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-multiple.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-pdf.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-remove.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-search.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-page.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-paint-bucket.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-paperclip.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-pause.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-paw.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-paypal.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-pencil.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-photo.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-circle.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-video.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-play.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-plus.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-pound.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-power.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-previous.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-price-tag.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-pricetag-multiple.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-print.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-prohibited.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-projection-screen.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-puzzle.svg24
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-quote.svg28
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-record.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-refresh.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-results-demographics.svg27
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-results.svg42
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind-ten.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-rss.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-safety-cone.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-save.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-share.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-sheriff-badge.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-shield.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-bag.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-cart.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-shuffle.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-skull.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-500px.svg30
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-adobe.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-amazon.svg28
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-android.svg25
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-apple.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-behance.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-bing.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-blogger.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-delicious.svg9
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-designer-news.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-deviant-art.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-digg.svg39
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dribbble.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-drive.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dropbox.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-evernote.svg24
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-facebook.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-flickr.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-forrst.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-foursquare.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-game-center.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-github.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-google-plus.svg28
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hacker-news.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hi5.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-instagram.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-joomla.svg30
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-lastfm.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-linkedin.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-medium.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-myspace.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-orkut.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-path.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-picasa.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-pinterest.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-rdio.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-reddit.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skillshare.svg33
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skype.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-smashing-mag.svg35
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-snapchat.svg24
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-spotify.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-squidoo.svg32
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stack-overflow.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-steam.svg18
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stumbleupon.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-treehouse.svg24
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-tumblr.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-twitter.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-vimeo.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-windows.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-xbox.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yahoo.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yelp.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-youtube.svg41
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zerply.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zurb.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-sound.svg49
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-star.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-stop.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-strikethrough.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-subscript.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-superscript.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-landscape.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-portrait.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-target-two.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-target.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone-accessible.svg44
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-text-color.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-thumbnails.svg35
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-ticket.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-business.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-female.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso.svg13
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all-female.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-female-male.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-male-female.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-trash.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-trees.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-trophy.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-underline.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-universal-access.svg22
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlink.svg37
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlock.svg11
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload-cloud.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload.svg15
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-usb.svg14
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-video.svg8
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-none.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-strike.svg27
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume.svg26
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-web.svg16
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-wheelchair.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-widget.svg21
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-wrench.svg17
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-x-circle.svg19
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-x.svg12
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-yen.svg20
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-in.svg23
-rw-r--r--afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-out.svg19
-rw-r--r--afb-client/bower_components/hammerjs/.bower.json27
-rw-r--r--afb-client/bower_components/hammerjs/CHANGELOG.md54
-rw-r--r--afb-client/bower_components/hammerjs/CONTRIBUTING.md41
-rw-r--r--afb-client/bower_components/hammerjs/LICENSE.md21
-rw-r--r--afb-client/bower_components/hammerjs/README.md49
-rw-r--r--afb-client/bower_components/hammerjs/bower.json16
-rw-r--r--afb-client/bower_components/hammerjs/changelog.js71
-rw-r--r--afb-client/bower_components/hammerjs/hammer.js2568
-rw-r--r--afb-client/bower_components/hammerjs/hammer.min.js7
-rw-r--r--afb-client/bower_components/hammerjs/hammer.min.map1
-rw-r--r--afb-client/bower_components/jszip/.bower.json32
-rw-r--r--afb-client/bower_components/jszip/CHANGES.md69
-rw-r--r--afb-client/bower_components/jszip/Gruntfile.js130
-rw-r--r--afb-client/bower_components/jszip/LICENSE.markdown651
-rw-r--r--afb-client/bower_components/jszip/README.markdown41
-rw-r--r--afb-client/bower_components/jszip/_config.yml25
-rw-r--r--afb-client/bower_components/jszip/bower.json23
-rw-r--r--afb-client/bower_components/jszip/component.json16
-rw-r--r--afb-client/bower_components/jszip/dist/jszip.js9155
-rw-r--r--afb-client/bower_components/jszip/dist/jszip.min.js14
-rw-r--r--afb-client/bower_components/jszip/docs/APPNOTE.TXT3217
-rw-r--r--afb-client/bower_components/jszip/docs/ZIP spec.txt66
-rw-r--r--afb-client/bower_components/jszip/docs/references.txt18
-rw-r--r--afb-client/bower_components/jszip/documentation/_layouts/default.html158
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip.md15
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/constructor.md23
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/constructor_load.md22
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/file_data.md90
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/file_name.md46
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/file_regex.md49
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/filter.md43
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/folder_data.md34
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/folder_regex.md40
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/generate.md139
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/load.md81
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/remove.md37
-rw-r--r--afb-client/bower_components/jszip/documentation/api_jszip/support.md16
-rw-r--r--afb-client/bower_components/jszip/documentation/api_zipobject.md37
-rw-r--r--afb-client/bower_components/jszip/documentation/contributing.md62
-rw-r--r--afb-client/bower_components/jszip/documentation/css/main.css24
-rw-r--r--afb-client/bower_components/jszip/documentation/css/pygments.css64
-rw-r--r--afb-client/bower_components/jszip/documentation/examples.md115
-rw-r--r--afb-client/bower_components/jszip/documentation/examples/download-zip-file.html59
-rw-r--r--afb-client/bower_components/jszip/documentation/examples/downloader.html58
-rw-r--r--afb-client/bower_components/jszip/documentation/examples/downloader.js89
-rw-r--r--afb-client/bower_components/jszip/documentation/examples/get-binary-files-ajax.html43
-rw-r--r--afb-client/bower_components/jszip/documentation/examples/read-local-file-api.html87
-rw-r--r--afb-client/bower_components/jszip/documentation/faq.md19
-rw-r--r--afb-client/bower_components/jszip/documentation/howto/read_zip.md152
-rw-r--r--afb-client/bower_components/jszip/documentation/howto/write_zip.md106
-rw-r--r--afb-client/bower_components/jszip/documentation/limitations.md73
-rw-r--r--afb-client/bower_components/jszip/documentation/upgrade_guide.md57
-rw-r--r--afb-client/bower_components/jszip/index.html169
-rw-r--r--afb-client/bower_components/jszip/lib/base64.js70
-rw-r--r--afb-client/bower_components/jszip/lib/compressedObject.js28
-rw-r--r--afb-client/bower_components/jszip/lib/compressions.js13
-rw-r--r--afb-client/bower_components/jszip/lib/crc32.js102
-rw-r--r--afb-client/bower_components/jszip/lib/dataReader.js107
-rw-r--r--afb-client/bower_components/jszip/lib/defaults.js11
-rw-r--r--afb-client/bower_components/jszip/lib/deprecatedPublicUtils.js105
-rw-r--r--afb-client/bower_components/jszip/lib/flate.js16
-rw-r--r--afb-client/bower_components/jszip/lib/index.js79
-rw-r--r--afb-client/bower_components/jszip/lib/license_header.js11
-rw-r--r--afb-client/bower_components/jszip/lib/load.js31
-rw-r--r--afb-client/bower_components/jszip/lib/nodeBuffer.js7
-rw-r--r--afb-client/bower_components/jszip/lib/nodeBufferReader.js20
-rw-r--r--afb-client/bower_components/jszip/lib/object.js883
-rw-r--r--afb-client/bower_components/jszip/lib/signature.js7
-rw-r--r--afb-client/bower_components/jszip/lib/stringReader.js36
-rw-r--r--afb-client/bower_components/jszip/lib/stringWriter.js30
-rw-r--r--afb-client/bower_components/jszip/lib/support.js34
-rw-r--r--afb-client/bower_components/jszip/lib/uint8ArrayReader.js47
-rw-r--r--afb-client/bower_components/jszip/lib/uint8ArrayWriter.js36
-rw-r--r--afb-client/bower_components/jszip/lib/utf8.js207
-rw-r--r--afb-client/bower_components/jszip/lib/utils.js326
-rw-r--r--afb-client/bower_components/jszip/lib/zipEntries.js221
-rw-r--r--afb-client/bower_components/jszip/lib/zipEntry.js310
-rw-r--r--afb-client/bower_components/jszip/package.json53
-rw-r--r--afb-client/bower_components/jszip/vendor/FileSaver.js247
-rw-r--r--afb-client/bower_components/tether/.bower.json31
-rw-r--r--afb-client/bower_components/tether/LICENSE8
-rw-r--r--afb-client/bower_components/tether/README.md11
-rw-r--r--afb-client/bower_components/tether/bower.json22
-rw-r--r--afb-client/bower_components/tether/coffee/abutment.coffee40
-rw-r--r--afb-client/bower_components/tether/coffee/constraint.coffee260
-rw-r--r--afb-client/bower_components/tether/coffee/markAttachment.coffee30
-rw-r--r--afb-client/bower_components/tether/coffee/shift.coffee27
-rw-r--r--afb-client/bower_components/tether/coffee/tether.coffee573
-rw-r--r--afb-client/bower_components/tether/coffee/utils.coffee211
-rw-r--r--afb-client/bower_components/tether/component.json19
-rw-r--r--afb-client/bower_components/tether/css/tether-theme-arrows-dark.css112
-rw-r--r--afb-client/bower_components/tether/css/tether-theme-arrows.css120
-rw-r--r--afb-client/bower_components/tether/css/tether-theme-basic.css29
-rw-r--r--afb-client/bower_components/tether/css/tether.css10
-rw-r--r--afb-client/bower_components/tether/docs/1-Overview/1-why_you_should_use_tether.md43
-rw-r--r--afb-client/bower_components/tether/docs/1-Overview/2-repositioning.md46
-rw-r--r--afb-client/bower_components/tether/docs/1-Overview/3-why_we_dont_support_IE_8.md47
-rw-r--r--afb-client/bower_components/tether/docs/2-Examples/1-list_of_examples.md27
-rw-r--r--afb-client/bower_components/tether/docs/2-Examples/2-projects_using_tether.md29
-rw-r--r--afb-client/bower_components/tether/docs/3-Advanced/1-embedding_tether.md9
-rw-r--r--afb-client/bower_components/tether/docs/3-Advanced/2-extending_tether.md54
-rw-r--r--afb-client/bower_components/tether/docs/coffee/intro.coffee113
-rw-r--r--afb-client/bower_components/tether/docs/css/intro.css219
-rw-r--r--afb-client/bower_components/tether/docs/intro.md600
-rw-r--r--afb-client/bower_components/tether/docs/js/intro.js117
-rw-r--r--afb-client/bower_components/tether/docs/sass/intro.sass228
-rw-r--r--afb-client/bower_components/tether/docs/welcome/browser-demo.html76
-rw-r--r--afb-client/bower_components/tether/docs/welcome/coffee/welcome.coffee212
-rw-r--r--afb-client/bower_components/tether/docs/welcome/css/browser-demo.css91
-rw-r--r--afb-client/bower_components/tether/docs/welcome/css/prism.css2
-rw-r--r--afb-client/bower_components/tether/docs/welcome/css/welcome.css272
-rw-r--r--afb-client/bower_components/tether/docs/welcome/index.html227
-rw-r--r--afb-client/bower_components/tether/docs/welcome/js/drop.js239
-rw-r--r--afb-client/bower_components/tether/docs/welcome/js/jquery.js9597
-rw-r--r--afb-client/bower_components/tether/docs/welcome/js/log.js134
-rw-r--r--afb-client/bower_components/tether/docs/welcome/js/tether-v0.1.3.js2
-rw-r--r--afb-client/bower_components/tether/docs/welcome/js/welcome.js193
-rw-r--r--afb-client/bower_components/tether/docs/welcome/sass/browser-demo.sass93
-rw-r--r--afb-client/bower_components/tether/docs/welcome/sass/welcome.sass282
-rw-r--r--afb-client/bower_components/tether/examples/chosen/chosen-sprite.pngbin0 -> 646 bytes
-rw-r--r--afb-client/bower_components/tether/examples/chosen/chosen.css430
-rw-r--r--afb-client/bower_components/tether/examples/chosen/chosen.js1166
-rw-r--r--afb-client/bower_components/tether/examples/chosen/index.html110
-rw-r--r--afb-client/bower_components/tether/examples/common/css/style.css48
-rw-r--r--afb-client/bower_components/tether/examples/content-visible/index.html64
-rw-r--r--afb-client/bower_components/tether/examples/dolls/dolls.css18
-rw-r--r--afb-client/bower_components/tether/examples/dolls/dolls.js83
-rw-r--r--afb-client/bower_components/tether/examples/dolls/index.html7
-rw-r--r--afb-client/bower_components/tether/examples/element-scroll/index.html499
-rw-r--r--afb-client/bower_components/tether/examples/enable-disable/index.html37
-rw-r--r--afb-client/bower_components/tether/examples/facebook/facebook.css86
-rw-r--r--afb-client/bower_components/tether/examples/facebook/index.html209
-rw-r--r--afb-client/bower_components/tether/examples/out-of-bounds/index.html35
-rw-r--r--afb-client/bower_components/tether/examples/pin/index.html30
-rw-r--r--afb-client/bower_components/tether/examples/resources/css/base.css10
-rw-r--r--afb-client/bower_components/tether/examples/resources/js/jquery.js9597
-rw-r--r--afb-client/bower_components/tether/examples/resources/js/log.js134
-rw-r--r--afb-client/bower_components/tether/examples/scroll/index.html922
-rw-r--r--afb-client/bower_components/tether/examples/simple/index.html30
-rw-r--r--afb-client/bower_components/tether/examples/testbed/index.html36
-rw-r--r--afb-client/bower_components/tether/examples/tooltip/index.html86
-rw-r--r--afb-client/bower_components/tether/examples/viewport/colors.css145
-rw-r--r--afb-client/bower_components/tether/examples/viewport/index.html70
-rw-r--r--afb-client/bower_components/tether/gulpfile.coffee65
-rw-r--r--afb-client/bower_components/tether/gulpfile.js2
-rw-r--r--afb-client/bower_components/tether/js/abutment.js59
-rw-r--r--afb-client/bower_components/tether/js/constraint.js308
-rw-r--r--afb-client/bower_components/tether/js/markAttachment.js46
-rw-r--r--afb-client/bower_components/tether/js/shift.js38
-rw-r--r--afb-client/bower_components/tether/js/tether.js686
-rw-r--r--afb-client/bower_components/tether/js/tether.min.js2
-rw-r--r--afb-client/bower_components/tether/js/utils.js331
-rw-r--r--afb-client/bower_components/tether/package.json21
-rw-r--r--afb-client/bower_components/tether/sass/helpers/_tether-theme-arrows.sass136
-rw-r--r--afb-client/bower_components/tether/sass/helpers/_tether-theme-basic.sass16
-rw-r--r--afb-client/bower_components/tether/sass/helpers/_tether.sass14
-rw-r--r--afb-client/bower_components/tether/sass/mixins/_pointer-events.scss6
-rw-r--r--afb-client/bower_components/tether/sass/tether-theme-arrows-dark.sass12
-rw-r--r--afb-client/bower_components/tether/sass/tether-theme-arrows.sass12
-rw-r--r--afb-client/bower_components/tether/sass/tether-theme-basic.sass10
-rw-r--r--afb-client/bower_components/tether/sass/tether.sass5
-rw-r--r--afb-client/bower_components/tether/tether.js1443
-rw-r--r--afb-client/bower_components/tether/tether.min.js2
-rw-r--r--afb-client/bower_components/viewport-units-buggyfill/.bower.json30
-rwxr-xr-xafb-client/bower_components/viewport-units-buggyfill/Gruntfile.js19
-rwxr-xr-xafb-client/bower_components/viewport-units-buggyfill/bower.json20
-rwxr-xr-xafb-client/bower_components/viewport-units-buggyfill/package.json43
-rw-r--r--afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.hacks.js138
-rwxr-xr-xafb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js347
633 files changed, 126731 insertions, 7 deletions
diff --git a/afb-client/app/Frontend/app.js b/afb-client/app/Frontend/app.js
index 72e8123..ed4d2ea 100644
--- a/afb-client/app/Frontend/app.js
+++ b/afb-client/app/Frontend/app.js
@@ -1,5 +1,13 @@
(function() {
'use strict';
+
+ function ParseQueryString () {
+ var qd = {};
+ location.search.substr(1).split("&").forEach(function(item) {
+ var k = item.split("=")[0], v = decodeURIComponent(item.split("=")[1]); (k in qd) ? qd[k].push(v) : qd[k] = [v];
+ });
+ return qd;
+ }
angular.module('@@APPNAME@@', [ // Warning: Appname should fit with gulpfile.js & index.html
'ui.router',
@@ -24,14 +32,13 @@
'RangeSlider',
'ModalNotification'
])
+ .value ('urlquery', ParseQueryString())
.config(config)
.run(run)
;
config.$inject = ['$urlRouterProvider', '$locationProvider'];
- console.log ("***location=" + window.location + " search" + window.search);
-
function config($urlProvider, $locationProvider, ConfigApp) {
$urlProvider.otherwise('/home');
diff --git a/afb-client/app/Frontend/etc/ConfigApp.js b/afb-client/app/Frontend/etc/ConfigApp.js
index 27e2e3e..a6a0cad 100644
--- a/afb-client/app/Frontend/etc/ConfigApp.js
+++ b/afb-client/app/Frontend/etc/ConfigApp.js
@@ -5,9 +5,7 @@
angular.module('ConfigApp', [])
// Factory is a singleton and share its context within all instances.
- .factory('ConfigApp', function ($location, $window) {
-
- // console.log ("URL="+ $location.url() + " Query=" + location.href+ " window=" + document.referrer);
+ .factory('ConfigApp', function (urlquery) {
var myConfig = {
paths: { // Warning paths should end with /
@@ -27,7 +25,7 @@
check : '/api/token/check',
reset : '/api/token/reset',
ping : '/api/token/check',
- initial : '123456789', // typical dev initial token
+ initial : urlquery.token || '123456789', // typical dev initial token
timeout : 3600, // timeout is updated client sessin context creation
pingrate: 60, // Ping rate to check if server is still alive
uuid : '', // uuid map with cookie or long term session access key
diff --git a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js b/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js
index 1b94e25..cba2aeb 100644
--- a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js
+++ b/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js
@@ -24,7 +24,7 @@
var tmpl = '<div ng-click="clicked()"> <span>' +
'<i class="{{icon}}"></i>' +
'<span>{{label}}</span>' +
- '</span></div>';
+ '</div>';
angular.module('SubmitButton', [])
.directive('submitButton', function () {
diff --git a/afb-client/bower_components/angular-animate/.bower.json b/afb-client/bower_components/angular-animate/.bower.json
new file mode 100644
index 0000000..f34908f
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/.bower.json
@@ -0,0 +1,19 @@
+{
+ "name": "angular-animate",
+ "version": "1.3.20",
+ "main": "./angular-animate.js",
+ "ignore": [],
+ "dependencies": {
+ "angular": "1.3.20"
+ },
+ "homepage": "https://github.com/angular/bower-angular-animate",
+ "_release": "1.3.20",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.3.20",
+ "commit": "a0d4208f770315df80866fcb449eff913efbbbdc"
+ },
+ "_source": "git://github.com/angular/bower-angular-animate.git",
+ "_target": "~1.3.4",
+ "_originalSource": "angular-animate"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-animate/README.md b/afb-client/bower_components/angular-animate/README.md
new file mode 100644
index 0000000..8313da6
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/README.md
@@ -0,0 +1,68 @@
+# packaged angular-animate
+
+This repo is for distribution on `npm` and `bower`. The source for this module is in the
+[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngAnimate).
+Please file issues and pull requests against that repo.
+
+## Install
+
+You can install this package either with `npm` or with `bower`.
+
+### npm
+
+```shell
+npm install angular-animate
+```
+
+Then add `ngAnimate` as a dependency for your app:
+
+```javascript
+angular.module('myApp', [require('angular-animate')]);
+```
+
+### bower
+
+```shell
+bower install angular-animate
+```
+
+Then add a `<script>` to your `index.html`:
+
+```html
+<script src="/bower_components/angular-animate/angular-animate.js"></script>
+```
+
+Then add `ngAnimate` as a dependency for your app:
+
+```javascript
+angular.module('myApp', ['ngAnimate']);
+```
+
+## Documentation
+
+Documentation is available on the
+[AngularJS docs site](http://docs.angularjs.org/api/ngAnimate).
+
+## License
+
+The MIT License
+
+Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/angular-animate/angular-animate.js b/afb-client/bower_components/angular-animate/angular-animate.js
new file mode 100644
index 0000000..d0a3f54
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/angular-animate.js
@@ -0,0 +1,2142 @@
+/**
+ * @license AngularJS v1.3.20
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/* jshint maxlen: false */
+
+/**
+ * @ngdoc module
+ * @name ngAnimate
+ * @description
+ *
+ * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.
+ *
+ * <div doc-module-components="ngAnimate"></div>
+ *
+ * # Usage
+ *
+ * To see animations in action, all that is required is to define the appropriate CSS classes
+ * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are:
+ * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation
+ * by using the `$animate` service.
+ *
+ * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:
+ *
+ * | Directive | Supported Animations |
+ * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
+ * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
+ * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
+ * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
+ * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
+ * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
+ * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
+ * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
+ * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
+ * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
+ * | {@link module:ngMessages#animations ngMessage} | enter and leave |
+ *
+ * You can find out more information about animations upon visiting each directive page.
+ *
+ * Below is an example of how to apply animations to a directive that supports animation hooks:
+ *
+ * ```html
+ * <style type="text/css">
+ * .slide.ng-enter, .slide.ng-leave {
+ * -webkit-transition:0.5s linear all;
+ * transition:0.5s linear all;
+ * }
+ *
+ * .slide.ng-enter { } /&#42; starting animations for enter &#42;/
+ * .slide.ng-enter.ng-enter-active { } /&#42; terminal animations for enter &#42;/
+ * .slide.ng-leave { } /&#42; starting animations for leave &#42;/
+ * .slide.ng-leave.ng-leave-active { } /&#42; terminal animations for leave &#42;/
+ * </style>
+ *
+ * <!--
+ * the animate service will automatically add .ng-enter and .ng-leave to the element
+ * to trigger the CSS transition/animations
+ * -->
+ * <ANY class="slide" ng-include="..."></ANY>
+ * ```
+ *
+ * Keep in mind that, by default, if an animation is running, any child elements cannot be animated
+ * until the parent element's animation has completed. This blocking feature can be overridden by
+ * placing the `ng-animate-children` attribute on a parent container tag.
+ *
+ * ```html
+ * <div class="slide-animation" ng-if="on" ng-animate-children>
+ * <div class="fade-animation" ng-if="on">
+ * <div class="explode-animation" ng-if="on">
+ * ...
+ * </div>
+ * </div>
+ * </div>
+ * ```
+ *
+ * When the `on` expression value changes and an animation is triggered then each of the elements within
+ * will all animate without the block being applied to child elements.
+ *
+ * ## Are animations run when the application starts?
+ * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid
+ * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work,
+ * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering
+ * layout changes in the application will trigger animations as normal.
+ *
+ * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular
+ * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests
+ * are complete.
+ *
+ * ## CSS-defined Animations
+ * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes
+ * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported
+ * and can be used to play along with this naming structure.
+ *
+ * The following code below demonstrates how to perform animations using **CSS transitions** with Angular:
+ *
+ * ```html
+ * <style type="text/css">
+ * /&#42;
+ * The animate class is apart of the element and the ng-enter class
+ * is attached to the element once the enter animation event is triggered
+ * &#42;/
+ * .reveal-animation.ng-enter {
+ * -webkit-transition: 1s linear all; /&#42; Safari/Chrome &#42;/
+ * transition: 1s linear all; /&#42; All other modern browsers and IE10+ &#42;/
+ *
+ * /&#42; The animation preparation code &#42;/
+ * opacity: 0;
+ * }
+ *
+ * /&#42;
+ * Keep in mind that you want to combine both CSS
+ * classes together to avoid any CSS-specificity
+ * conflicts
+ * &#42;/
+ * .reveal-animation.ng-enter.ng-enter-active {
+ * /&#42; The animation code itself &#42;/
+ * opacity: 1;
+ * }
+ * </style>
+ *
+ * <div class="view-container">
+ * <div ng-view class="reveal-animation"></div>
+ * </div>
+ * ```
+ *
+ * The following code below demonstrates how to perform animations using **CSS animations** with Angular:
+ *
+ * ```html
+ * <style type="text/css">
+ * .reveal-animation.ng-enter {
+ * -webkit-animation: enter_sequence 1s linear; /&#42; Safari/Chrome &#42;/
+ * animation: enter_sequence 1s linear; /&#42; IE10+ and Future Browsers &#42;/
+ * }
+ * @-webkit-keyframes enter_sequence {
+ * from { opacity:0; }
+ * to { opacity:1; }
+ * }
+ * @keyframes enter_sequence {
+ * from { opacity:0; }
+ * to { opacity:1; }
+ * }
+ * </style>
+ *
+ * <div class="view-container">
+ * <div ng-view class="reveal-animation"></div>
+ * </div>
+ * ```
+ *
+ * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing.
+ *
+ * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add
+ * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically
+ * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be
+ * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end
+ * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element
+ * has no CSS transition/animation classes applied to it.
+ *
+ * ### Structural transition animations
+ *
+ * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition
+ * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave`
+ * or `.ng-move`) class. This means that any active transition animations operating on the element
+ * will be cut off to make way for the enter, leave or move animation.
+ *
+ * ### Class-based transition animations
+ *
+ * Class-based transitions refer to transition animations that are triggered when a CSS class is
+ * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,
+ * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).
+ * They are different when compared to structural animations since they **do not cancel existing
+ * animations** nor do they **block successive transitions** from rendering on the same element.
+ * This distinction allows for **multiple class-based transitions** to be performed on the same element.
+ *
+ * In addition to ngAnimate supporting the default (natural) functionality of class-based transition
+ * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the
+ * developer in further styling the element throughout the transition animation. Earlier versions
+ * of ngAnimate may have caused natural CSS transitions to break and not render properly due to
+ * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class
+ * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of
+ * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS
+ * class transitions are compatible with ngAnimate.
+ *
+ * There is, however, one special case when dealing with class-based transitions in ngAnimate.
+ * When rendering class-based transitions that make use of the setup and active CSS classes
+ * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define
+ * the transition value **on the active CSS class** and not the setup class.
+ *
+ * ```css
+ * .fade-add {
+ * /&#42; remember to place a 0s transition here
+ * to ensure that the styles are applied instantly
+ * even if the element already has a transition style &#42;/
+ * transition:0s linear all;
+ *
+ * /&#42; starting CSS styles &#42;/
+ * opacity:1;
+ * }
+ * .fade-add.fade-add-active {
+ * /&#42; this will be the length of the animation &#42;/
+ * transition:1s linear all;
+ * opacity:0;
+ * }
+ * ```
+ *
+ * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it
+ * has a duration of zero. This may not be required, however, incase the browser is unable to render
+ * the styling present in this CSS class instantly then it could be that the browser is attempting
+ * to perform an unnecessary transition.
+ *
+ * This workaround, however, does not apply to standard class-based transitions that are rendered
+ * when a CSS class containing a transition is applied to an element:
+ *
+ * ```css
+ * /&#42; this works as expected &#42;/
+ * .fade {
+ * transition:1s linear all;
+ * opacity:0;
+ * }
+ * ```
+ *
+ * Please keep this in mind when coding the CSS markup that will be used within class-based transitions.
+ * Also, try not to mix the two class-based animation flavors together since the CSS code may become
+ * overly complex.
+ *
+ *
+ * ### Preventing Collisions With Third Party Libraries
+ *
+ * Some third-party frameworks place animation duration defaults across many element or className
+ * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
+ * is expecting actual animations on these elements and has to wait for their completion.
+ *
+ * You can prevent this unwanted behavior by using a prefix on all your animation classes:
+ *
+ * ```css
+ * /&#42; prefixed with animate- &#42;/
+ * .animate-fade-add.animate-fade-add-active {
+ * transition:1s linear all;
+ * opacity:0;
+ * }
+ * ```
+ *
+ * You then configure `$animate` to enforce this prefix:
+ *
+ * ```js
+ * $animateProvider.classNameFilter(/animate-/);
+ * ```
+ * </div>
+ *
+ * ### CSS Staggering Animations
+ * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
+ * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
+ * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
+ * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
+ * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
+ *
+ * ```css
+ * .my-animation.ng-enter {
+ * /&#42; standard transition code &#42;/
+ * -webkit-transition: 1s linear all;
+ * transition: 1s linear all;
+ * opacity:0;
+ * }
+ * .my-animation.ng-enter-stagger {
+ * /&#42; this will have a 100ms delay between each successive leave animation &#42;/
+ * -webkit-transition-delay: 0.1s;
+ * transition-delay: 0.1s;
+ *
+ * /&#42; in case the stagger doesn't work then these two values
+ * must be set to 0 to avoid an accidental CSS inheritance &#42;/
+ * -webkit-transition-duration: 0s;
+ * transition-duration: 0s;
+ * }
+ * .my-animation.ng-enter.ng-enter-active {
+ * /&#42; standard transition styles &#42;/
+ * opacity:1;
+ * }
+ * ```
+ *
+ * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
+ * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
+ * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
+ * will also be reset if more than 10ms has passed after the last animation has been fired.
+ *
+ * The following code will issue the **ng-leave-stagger** event on the element provided:
+ *
+ * ```js
+ * var kids = parent.children();
+ *
+ * $animate.leave(kids[0]); //stagger index=0
+ * $animate.leave(kids[1]); //stagger index=1
+ * $animate.leave(kids[2]); //stagger index=2
+ * $animate.leave(kids[3]); //stagger index=3
+ * $animate.leave(kids[4]); //stagger index=4
+ *
+ * $timeout(function() {
+ * //stagger has reset itself
+ * $animate.leave(kids[5]); //stagger index=0
+ * $animate.leave(kids[6]); //stagger index=1
+ * }, 100, false);
+ * ```
+ *
+ * Stagger animations are currently only supported within CSS-defined animations.
+ *
+ * ## JavaScript-defined Animations
+ * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not
+ * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module.
+ *
+ * ```js
+ * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.
+ * var ngModule = angular.module('YourApp', ['ngAnimate']);
+ * ngModule.animation('.my-crazy-animation', function() {
+ * return {
+ * enter: function(element, done) {
+ * //run the animation here and call done when the animation is complete
+ * return function(cancelled) {
+ * //this (optional) function will be called when the animation
+ * //completes or when the animation is cancelled (the cancelled
+ * //flag will be set to true if cancelled).
+ * };
+ * },
+ * leave: function(element, done) { },
+ * move: function(element, done) { },
+ *
+ * //animation that can be triggered before the class is added
+ * beforeAddClass: function(element, className, done) { },
+ *
+ * //animation that can be triggered after the class is added
+ * addClass: function(element, className, done) { },
+ *
+ * //animation that can be triggered before the class is removed
+ * beforeRemoveClass: function(element, className, done) { },
+ *
+ * //animation that can be triggered after the class is removed
+ * removeClass: function(element, className, done) { }
+ * };
+ * });
+ * ```
+ *
+ * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run
+ * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits
+ * the element's CSS class attribute value and then run the matching animation event function (if found).
+ * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will
+ * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported).
+ *
+ * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned.
+ * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run,
+ * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation
+ * or transition code that is defined via a stylesheet).
+ *
+ *
+ * ### Applying Directive-specific Styles to an Animation
+ * In some cases a directive or service may want to provide `$animate` with extra details that the animation will
+ * include into its animation. Let's say for example we wanted to render an animation that animates an element
+ * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click
+ * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function
+ * call to `$animate.addClass`.
+ *
+ * ```js
+ * canvas.on('click', function(e) {
+ * $animate.addClass(element, 'on', {
+ * to: {
+ * left : e.client.x + 'px',
+ * top : e.client.y + 'px'
+ * }
+ * }):
+ * });
+ * ```
+ *
+ * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will
+ * also include and transition the styling of the `left` and `top` properties into its running animation. If we want
+ * to provide some starting animation values then we can do so by placing the starting animations styles into an object
+ * called `from` in the same object as the `to` animations.
+ *
+ * ```js
+ * canvas.on('click', function(e) {
+ * $animate.addClass(element, 'on', {
+ * from: {
+ * position: 'absolute',
+ * left: '0px',
+ * top: '0px'
+ * },
+ * to: {
+ * left : e.client.x + 'px',
+ * top : e.client.y + 'px'
+ * }
+ * }):
+ * });
+ * ```
+ *
+ * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the
+ * element. If `ngAnimate` is not present then the styles will be applied immediately.
+ *
+ */
+
+angular.module('ngAnimate', ['ng'])
+
+ /**
+ * @ngdoc provider
+ * @name $animateProvider
+ * @description
+ *
+ * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module.
+ * When an animation is triggered, the $animate service will query the $animate service to find any animations that match
+ * the provided name value.
+ *
+ * Requires the {@link ngAnimate `ngAnimate`} module to be installed.
+ *
+ * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
+ *
+ */
+ .directive('ngAnimateChildren', function() {
+ var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
+ return function(scope, element, attrs) {
+ var val = attrs.ngAnimateChildren;
+ if (angular.isString(val) && val.length === 0) { //empty attribute
+ element.data(NG_ANIMATE_CHILDREN, true);
+ } else {
+ scope.$watch(val, function(value) {
+ element.data(NG_ANIMATE_CHILDREN, !!value);
+ });
+ }
+ };
+ })
+
+ //this private service is only used within CSS-enabled animations
+ //IE8 + IE9 do not support rAF natively, but that is fine since they
+ //also don't support transitions and keyframes which means that the code
+ //below will never be used by the two browsers.
+ .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {
+ var bod = $document[0].body;
+ return function(fn) {
+ //the returned function acts as the cancellation function
+ return $$rAF(function() {
+ //the line below will force the browser to perform a repaint
+ //so that all the animated elements within the animation frame
+ //will be properly updated and drawn on screen. This is
+ //required to perform multi-class CSS based animations with
+ //Firefox. DO NOT REMOVE THIS LINE. DO NOT OPTIMIZE THIS LINE.
+ //THE MINIFIER WILL REMOVE IT OTHERWISE WHICH WILL RESULT IN AN
+ //UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND WILL
+ //TAKE YEARS AWAY FROM YOUR LIFE!
+ fn(bod.offsetWidth);
+ });
+ };
+ }])
+
+ .config(['$provide', '$animateProvider', function($provide, $animateProvider) {
+ var noop = angular.noop;
+ var forEach = angular.forEach;
+ var selectors = $animateProvider.$$selectors;
+ var isArray = angular.isArray;
+ var isString = angular.isString;
+ var isObject = angular.isObject;
+
+ var ELEMENT_NODE = 1;
+ var NG_ANIMATE_STATE = '$$ngAnimateState';
+ var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
+ var NG_ANIMATE_CLASS_NAME = 'ng-animate';
+ var rootAnimateState = {running: true};
+
+ function extractElementNode(element) {
+ for (var i = 0; i < element.length; i++) {
+ var elm = element[i];
+ if (elm.nodeType == ELEMENT_NODE) {
+ return elm;
+ }
+ }
+ }
+
+ function prepareElement(element) {
+ return element && angular.element(element);
+ }
+
+ function stripCommentsFromElement(element) {
+ return angular.element(extractElementNode(element));
+ }
+
+ function isMatchingElement(elm1, elm2) {
+ return extractElementNode(elm1) == extractElementNode(elm2);
+ }
+ var $$jqLite;
+ $provide.decorator('$animate',
+ ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite',
+ function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest, $$$jqLite) {
+
+ $$jqLite = $$$jqLite;
+ $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);
+
+ // Wait until all directive and route-related templates are downloaded and
+ // compiled. The $templateRequest.totalPendingRequests variable keeps track of
+ // all of the remote templates being currently downloaded. If there are no
+ // templates currently downloading then the watcher will still fire anyway.
+ var deregisterWatch = $rootScope.$watch(
+ function() { return $templateRequest.totalPendingRequests; },
+ function(val, oldVal) {
+ if (val !== 0) return;
+ deregisterWatch();
+
+ // Now that all templates have been downloaded, $animate will wait until
+ // the post digest queue is empty before enabling animations. By having two
+ // calls to $postDigest calls we can ensure that the flag is enabled at the
+ // very end of the post digest queue. Since all of the animations in $animate
+ // use $postDigest, it's important that the code below executes at the end.
+ // This basically means that the page is fully downloaded and compiled before
+ // any animations are triggered.
+ $rootScope.$$postDigest(function() {
+ $rootScope.$$postDigest(function() {
+ rootAnimateState.running = false;
+ });
+ });
+ }
+ );
+
+ var globalAnimationCounter = 0;
+ var classNameFilter = $animateProvider.classNameFilter();
+ var isAnimatableClassName = !classNameFilter
+ ? function() { return true; }
+ : function(className) {
+ return classNameFilter.test(className);
+ };
+
+ function classBasedAnimationsBlocked(element, setter) {
+ var data = element.data(NG_ANIMATE_STATE) || {};
+ if (setter) {
+ data.running = true;
+ data.structural = true;
+ element.data(NG_ANIMATE_STATE, data);
+ }
+ return data.disabled || (data.running && data.structural);
+ }
+
+ function runAnimationPostDigest(fn) {
+ var cancelFn, defer = $$q.defer();
+ defer.promise.$$cancelFn = function() {
+ cancelFn && cancelFn();
+ };
+ $rootScope.$$postDigest(function() {
+ cancelFn = fn(function() {
+ defer.resolve();
+ });
+ });
+ return defer.promise;
+ }
+
+ function parseAnimateOptions(options) {
+ // some plugin code may still be passing in the callback
+ // function as the last param for the $animate methods so
+ // it's best to only allow string or array values for now
+ if (isObject(options)) {
+ if (options.tempClasses && isString(options.tempClasses)) {
+ options.tempClasses = options.tempClasses.split(/\s+/);
+ }
+ return options;
+ }
+ }
+
+ function resolveElementClasses(element, cache, runningAnimations) {
+ runningAnimations = runningAnimations || {};
+
+ var lookup = {};
+ forEach(runningAnimations, function(data, selector) {
+ forEach(selector.split(' '), function(s) {
+ lookup[s]=data;
+ });
+ });
+
+ var hasClasses = Object.create(null);
+ forEach((element.attr('class') || '').split(/\s+/), function(className) {
+ hasClasses[className] = true;
+ });
+
+ var toAdd = [], toRemove = [];
+ forEach((cache && cache.classes) || [], function(status, className) {
+ var hasClass = hasClasses[className];
+ var matchingAnimation = lookup[className] || {};
+
+ // When addClass and removeClass is called then $animate will check to
+ // see if addClass and removeClass cancel each other out. When there are
+ // more calls to removeClass than addClass then the count falls below 0
+ // and then the removeClass animation will be allowed. Otherwise if the
+ // count is above 0 then that means an addClass animation will commence.
+ // Once an animation is allowed then the code will also check to see if
+ // there exists any on-going animation that is already adding or remvoing
+ // the matching CSS class.
+ if (status === false) {
+ //does it have the class or will it have the class
+ if (hasClass || matchingAnimation.event == 'addClass') {
+ toRemove.push(className);
+ }
+ } else if (status === true) {
+ //is the class missing or will it be removed?
+ if (!hasClass || matchingAnimation.event == 'removeClass') {
+ toAdd.push(className);
+ }
+ }
+ });
+
+ return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')];
+ }
+
+ function lookup(name) {
+ if (name) {
+ var matches = [],
+ flagMap = {},
+ classes = name.substr(1).split('.');
+
+ //the empty string value is the default animation
+ //operation which performs CSS transition and keyframe
+ //animations sniffing. This is always included for each
+ //element animation procedure if the browser supports
+ //transitions and/or keyframe animations. The default
+ //animation is added to the top of the list to prevent
+ //any previous animations from affecting the element styling
+ //prior to the element being animated.
+ if ($sniffer.transitions || $sniffer.animations) {
+ matches.push($injector.get(selectors['']));
+ }
+
+ for (var i=0; i < classes.length; i++) {
+ var klass = classes[i],
+ selectorFactoryName = selectors[klass];
+ if (selectorFactoryName && !flagMap[klass]) {
+ matches.push($injector.get(selectorFactoryName));
+ flagMap[klass] = true;
+ }
+ }
+ return matches;
+ }
+ }
+
+ function animationRunner(element, animationEvent, className, options) {
+ //transcluded directives may sometimes fire an animation using only comment nodes
+ //best to catch this early on to prevent any animation operations from occurring
+ var node = element[0];
+ if (!node) {
+ return;
+ }
+
+ if (options) {
+ options.to = options.to || {};
+ options.from = options.from || {};
+ }
+
+ var classNameAdd;
+ var classNameRemove;
+ if (isArray(className)) {
+ classNameAdd = className[0];
+ classNameRemove = className[1];
+ if (!classNameAdd) {
+ className = classNameRemove;
+ animationEvent = 'removeClass';
+ } else if (!classNameRemove) {
+ className = classNameAdd;
+ animationEvent = 'addClass';
+ } else {
+ className = classNameAdd + ' ' + classNameRemove;
+ }
+ }
+
+ var isSetClassOperation = animationEvent == 'setClass';
+ var isClassBased = isSetClassOperation
+ || animationEvent == 'addClass'
+ || animationEvent == 'removeClass'
+ || animationEvent == 'animate';
+
+ var currentClassName = element.attr('class');
+ var classes = currentClassName + ' ' + className;
+ if (!isAnimatableClassName(classes)) {
+ return;
+ }
+
+ var beforeComplete = noop,
+ beforeCancel = [],
+ before = [],
+ afterComplete = noop,
+ afterCancel = [],
+ after = [];
+
+ var animationLookup = (' ' + classes).replace(/\s+/g,'.');
+ forEach(lookup(animationLookup), function(animationFactory) {
+ var created = registerAnimation(animationFactory, animationEvent);
+ if (!created && isSetClassOperation) {
+ registerAnimation(animationFactory, 'addClass');
+ registerAnimation(animationFactory, 'removeClass');
+ }
+ });
+
+ function registerAnimation(animationFactory, event) {
+ var afterFn = animationFactory[event];
+ var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)];
+ if (afterFn || beforeFn) {
+ if (event == 'leave') {
+ beforeFn = afterFn;
+ //when set as null then animation knows to skip this phase
+ afterFn = null;
+ }
+ after.push({
+ event: event, fn: afterFn
+ });
+ before.push({
+ event: event, fn: beforeFn
+ });
+ return true;
+ }
+ }
+
+ function run(fns, cancellations, allCompleteFn) {
+ var animations = [];
+ forEach(fns, function(animation) {
+ animation.fn && animations.push(animation);
+ });
+
+ var count = 0;
+ function afterAnimationComplete(index) {
+ if (cancellations) {
+ (cancellations[index] || noop)();
+ if (++count < animations.length) return;
+ cancellations = null;
+ }
+ allCompleteFn();
+ }
+
+ //The code below adds directly to the array in order to work with
+ //both sync and async animations. Sync animations are when the done()
+ //operation is called right away. DO NOT REFACTOR!
+ forEach(animations, function(animation, index) {
+ var progress = function() {
+ afterAnimationComplete(index);
+ };
+ switch (animation.event) {
+ case 'setClass':
+ cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options));
+ break;
+ case 'animate':
+ cancellations.push(animation.fn(element, className, options.from, options.to, progress));
+ break;
+ case 'addClass':
+ cancellations.push(animation.fn(element, classNameAdd || className, progress, options));
+ break;
+ case 'removeClass':
+ cancellations.push(animation.fn(element, classNameRemove || className, progress, options));
+ break;
+ default:
+ cancellations.push(animation.fn(element, progress, options));
+ break;
+ }
+ });
+
+ if (cancellations && cancellations.length === 0) {
+ allCompleteFn();
+ }
+ }
+
+ return {
+ node: node,
+ event: animationEvent,
+ className: className,
+ isClassBased: isClassBased,
+ isSetClassOperation: isSetClassOperation,
+ applyStyles: function() {
+ if (options) {
+ element.css(angular.extend(options.from || {}, options.to || {}));
+ }
+ },
+ before: function(allCompleteFn) {
+ beforeComplete = allCompleteFn;
+ run(before, beforeCancel, function() {
+ beforeComplete = noop;
+ allCompleteFn();
+ });
+ },
+ after: function(allCompleteFn) {
+ afterComplete = allCompleteFn;
+ run(after, afterCancel, function() {
+ afterComplete = noop;
+ allCompleteFn();
+ });
+ },
+ cancel: function() {
+ if (beforeCancel) {
+ forEach(beforeCancel, function(cancelFn) {
+ (cancelFn || noop)(true);
+ });
+ beforeComplete(true);
+ }
+ if (afterCancel) {
+ forEach(afterCancel, function(cancelFn) {
+ (cancelFn || noop)(true);
+ });
+ afterComplete(true);
+ }
+ }
+ };
+ }
+
+ /**
+ * @ngdoc service
+ * @name $animate
+ * @kind object
+ *
+ * @description
+ * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.
+ * When any of these operations are run, the $animate service
+ * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object)
+ * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run.
+ *
+ * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives
+ * will work out of the box without any extra configuration.
+ *
+ * Requires the {@link ngAnimate `ngAnimate`} module to be installed.
+ *
+ * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
+ * ## Callback Promises
+ * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The
+ * promise itself is then resolved once the animation has completed itself, has been cancelled or has been
+ * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still
+ * call the resolve function of the animation.)
+ *
+ * ```js
+ * $animate.enter(element, container).then(function() {
+ * //...this is called once the animation is complete...
+ * });
+ * ```
+ *
+ * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope,
+ * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using
+ * `$scope.$apply(...)`;
+ *
+ * ```js
+ * $animate.leave(element).then(function() {
+ * $scope.$apply(function() {
+ * $location.path('/new-page');
+ * });
+ * });
+ * ```
+ *
+ * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided
+ * promise that was returned when the animation was started.
+ *
+ * ```js
+ * var promise = $animate.addClass(element, 'super-long-animation');
+ * promise.then(function() {
+ * //this will still be called even if cancelled
+ * });
+ *
+ * element.on('click', function() {
+ * //tooo lazy to wait for the animation to end
+ * $animate.cancel(promise);
+ * });
+ * ```
+ *
+ * (Keep in mind that the promise cancellation is unique to `$animate` since promises in
+ * general cannot be cancelled.)
+ *
+ */
+ return {
+ /**
+ * @ngdoc method
+ * @name $animate#animate
+ * @kind function
+ *
+ * @description
+ * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element.
+ * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation
+ * will take on the provided styles. For example, if a transition animation is set for the given className then the
+ * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is
+ * detected then the provided styles will be given in as function paramters.
+ *
+ * ```js
+ * ngModule.animation('.my-inline-animation', function() {
+ * return {
+ * animate : function(element, className, from, to, done) {
+ * //styles
+ * }
+ * }
+ * });
+ * ```
+ *
+ * Below is a breakdown of each step that occurs during the `animate` animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|
+ * | 1. `$animate.animate(...)` is called | `class="my-animation"` |
+ * | 2. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` |
+ * | 3. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` |
+ * | 4. the `className` class value is added to the element | `class="my-animation ng-animate className"` |
+ * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate className"` |
+ * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class="my-animation ng-animate className"` |
+ * | 7. `$animate` applies the provided collection of `from` CSS styles to the element | `class="my-animation ng-animate className"` |
+ * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate className"` |
+ * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate className"` |
+ * | 10. the `className-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate className className-active"` |
+ * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition | `class="my-animation ng-animate className className-active"` |
+ * | 12. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate className className-active"` |
+ * | 13. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` |
+ * | 14. The returned promise is resolved. | `class="my-animation"` |
+ *
+ * @param {DOMElement} element the element that will be the focus of the enter animation
+ * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation
+ * @param {object} to a collection of CSS styles that the element will animate towards
+ * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`)
+ * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ animate: function(element, from, to, className, options) {
+ className = className || 'ng-inline-animate';
+ options = parseAnimateOptions(options) || {};
+ options.from = to ? from : null;
+ options.to = to ? to : from;
+
+ return runAnimationPostDigest(function(done) {
+ return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done);
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#enter
+ * @kind function
+ *
+ * @description
+ * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once
+ * the animation is started, the following CSS classes will be present on the element for the duration of the animation:
+ *
+ * Below is a breakdown of each step that occurs during enter animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
+ * | 1. `$animate.enter(...)` is called | `class="my-animation"` |
+ * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element | `class="my-animation"` |
+ * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` |
+ * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` |
+ * | 5. the `.ng-enter` class is added to the element | `class="my-animation ng-animate ng-enter"` |
+ * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-enter"` |
+ * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class="my-animation ng-animate ng-enter"` |
+ * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-enter"` |
+ * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-enter"` |
+ * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-enter ng-enter-active"` |
+ * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-enter ng-enter-active"` |
+ * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` |
+ * | 13. The returned promise is resolved. | `class="my-animation"` |
+ *
+ * @param {DOMElement} element the element that will be the focus of the enter animation
+ * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation
+ * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation
+ * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ enter: function(element, parentElement, afterElement, options) {
+ options = parseAnimateOptions(options);
+ element = angular.element(element);
+ parentElement = prepareElement(parentElement);
+ afterElement = prepareElement(afterElement);
+
+ classBasedAnimationsBlocked(element, true);
+ $delegate.enter(element, parentElement, afterElement);
+ return runAnimationPostDigest(function(done) {
+ return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#leave
+ * @kind function
+ *
+ * @description
+ * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once
+ * the animation is started, the following CSS classes will be added for the duration of the animation:
+ *
+ * Below is a breakdown of each step that occurs during leave animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
+ * | 1. `$animate.leave(...)` is called | `class="my-animation"` |
+ * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` |
+ * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` |
+ * | 4. the `.ng-leave` class is added to the element | `class="my-animation ng-animate ng-leave"` |
+ * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-leave"` |
+ * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class="my-animation ng-animate ng-leave"` |
+ * | 7. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-leave"` |
+ * | 8. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-leave"` |
+ * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-leave ng-leave-active"` |
+ * | 10. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-leave ng-leave-active"` |
+ * | 11. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` |
+ * | 12. The element is removed from the DOM | ... |
+ * | 13. The returned promise is resolved. | ... |
+ *
+ * @param {DOMElement} element the element that will be the focus of the leave animation
+ * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ leave: function(element, options) {
+ options = parseAnimateOptions(options);
+ element = angular.element(element);
+
+ cancelChildAnimations(element);
+ classBasedAnimationsBlocked(element, true);
+ return runAnimationPostDigest(function(done) {
+ return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
+ $delegate.leave(element);
+ }, options, done);
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#move
+ * @kind function
+ *
+ * @description
+ * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or
+ * add the element directly after the afterElement element if present. Then the move animation will be run. Once
+ * the animation is started, the following CSS classes will be added for the duration of the animation:
+ *
+ * Below is a breakdown of each step that occurs during move animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
+ * | 1. `$animate.move(...)` is called | `class="my-animation"` |
+ * | 2. element is moved into the parentElement element or beside the afterElement element | `class="my-animation"` |
+ * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` |
+ * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` |
+ * | 5. the `.ng-move` class is added to the element | `class="my-animation ng-animate ng-move"` |
+ * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-move"` |
+ * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class="my-animation ng-animate ng-move"` |
+ * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-move"` |
+ * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-move"` |
+ * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-move ng-move-active"` |
+ * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-move ng-move-active"` |
+ * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` |
+ * | 13. The returned promise is resolved. | `class="my-animation"` |
+ *
+ * @param {DOMElement} element the element that will be the focus of the move animation
+ * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation
+ * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation
+ * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ move: function(element, parentElement, afterElement, options) {
+ options = parseAnimateOptions(options);
+ element = angular.element(element);
+ parentElement = prepareElement(parentElement);
+ afterElement = prepareElement(afterElement);
+
+ cancelChildAnimations(element);
+ classBasedAnimationsBlocked(element, true);
+ $delegate.move(element, parentElement, afterElement);
+ return runAnimationPostDigest(function(done) {
+ return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#addClass
+ *
+ * @description
+ * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.
+ * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide
+ * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions
+ * or keyframes are defined on the -add-active or base CSS class).
+ *
+ * Below is a breakdown of each step that occurs during addClass animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
+ * | 1. `$animate.addClass(element, 'super')` is called | `class="my-animation"` |
+ * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` |
+ * | 3. the `.super-add` class is added to the element | `class="my-animation ng-animate super-add"` |
+ * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate super-add"` |
+ * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class="my-animation ng-animate super super-add super-add-active"` |
+ * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super super-add super-add-active"` |
+ * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super super-add super-add-active"` |
+ * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation super"` |
+ * | 9. The super class is kept on the element | `class="my-animation super"` |
+ * | 10. The returned promise is resolved. | `class="my-animation super"` |
+ *
+ * @param {DOMElement} element the element that will be animated
+ * @param {string} className the CSS class that will be added to the element and then animated
+ * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ addClass: function(element, className, options) {
+ return this.setClass(element, className, [], options);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#removeClass
+ *
+ * @description
+ * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value
+ * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in
+ * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if
+ * no CSS transitions or keyframes are defined on the -remove or base CSS classes).
+ *
+ * Below is a breakdown of each step that occurs during removeClass animation:
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
+ * | 1. `$animate.removeClass(element, 'super')` is called | `class="my-animation super"` |
+ * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation super ng-animate"` |
+ * | 3. the `.super-remove` class is added to the element | `class="my-animation super ng-animate super-remove"` |
+ * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation super ng-animate super-remove"` |
+ * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate super-remove super-remove-active"` |
+ * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super-remove super-remove-active"` |
+ * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super-remove super-remove-active"` |
+ * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` |
+ * | 9. The returned promise is resolved. | `class="my-animation"` |
+ *
+ *
+ * @param {DOMElement} element the element that will be animated
+ * @param {string} className the CSS class that will be animated and then removed from the element
+ * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ removeClass: function(element, className, options) {
+ return this.setClass(element, [], className, options);
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#setClass
+ *
+ * @description Adds and/or removes the given CSS classes to and from the element.
+ * Once complete, the `done()` callback will be fired (if provided).
+ *
+ * | Animation Step | What the element class attribute looks like |
+ * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
+ * | 1. `$animate.setClass(element, 'on', 'off')` is called | `class="my-animation off"` |
+ * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate off"` |
+ * | 3. the `.on-add` and `.off-remove` classes are added to the element | `class="my-animation ng-animate on-add off-remove off"` |
+ * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate on-add off-remove off"` |
+ * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` |
+ * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` |
+ * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` |
+ * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation on"` |
+ * | 9. The returned promise is resolved. | `class="my-animation on"` |
+ *
+ * @param {DOMElement} element the element which will have its CSS classes changed
+ * removed from it
+ * @param {string} add the CSS classes which will be added to the element
+ * @param {string} remove the CSS class which will be removed from the element
+ * CSS classes have been set on the element
+ * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
+ * @return {Promise} the animation callback promise
+ */
+ setClass: function(element, add, remove, options) {
+ options = parseAnimateOptions(options);
+
+ var STORAGE_KEY = '$$animateClasses';
+ element = angular.element(element);
+ element = stripCommentsFromElement(element);
+
+ if (classBasedAnimationsBlocked(element)) {
+ return $delegate.$$setClassImmediately(element, add, remove, options);
+ }
+
+ // we're using a combined array for both the add and remove
+ // operations since the ORDER OF addClass and removeClass matters
+ var classes, cache = element.data(STORAGE_KEY);
+ var hasCache = !!cache;
+ if (!cache) {
+ cache = {};
+ cache.classes = {};
+ }
+ classes = cache.classes;
+
+ add = isArray(add) ? add : add.split(' ');
+ forEach(add, function(c) {
+ if (c && c.length) {
+ classes[c] = true;
+ }
+ });
+
+ remove = isArray(remove) ? remove : remove.split(' ');
+ forEach(remove, function(c) {
+ if (c && c.length) {
+ classes[c] = false;
+ }
+ });
+
+ if (hasCache) {
+ if (options && cache.options) {
+ cache.options = angular.extend(cache.options || {}, options);
+ }
+
+ //the digest cycle will combine all the animations into one function
+ return cache.promise;
+ } else {
+ element.data(STORAGE_KEY, cache = {
+ classes: classes,
+ options: options
+ });
+ }
+
+ return cache.promise = runAnimationPostDigest(function(done) {
+ var cache, parentNode, parentElement, elementNode = extractElementNode(element);
+ if (elementNode) {
+ cache = element.data(STORAGE_KEY);
+ element.removeData(STORAGE_KEY);
+
+ parentElement = element.parent();
+ parentNode = elementNode.parentNode;
+ }
+
+ // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed
+ if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {
+ done();
+ return;
+ }
+
+ var state = element.data(NG_ANIMATE_STATE) || {};
+ var classes = resolveElementClasses(element, cache, state.active);
+ return !classes
+ ? done()
+ : performAnimation('setClass', classes, element, parentElement, null, function() {
+ if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]);
+ if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]);
+ }, cache.options, done);
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#cancel
+ * @kind function
+ *
+ * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
+ *
+ * @description
+ * Cancels the provided animation.
+ */
+ cancel: function(promise) {
+ promise.$$cancelFn();
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#enabled
+ * @kind function
+ *
+ * @param {boolean=} value If provided then set the animation on or off.
+ * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation
+ * @return {boolean} Current animation state.
+ *
+ * @description
+ * Globally enables/disables animations.
+ *
+ */
+ enabled: function(value, element) {
+ switch (arguments.length) {
+ case 2:
+ if (value) {
+ cleanup(element);
+ } else {
+ var data = element.data(NG_ANIMATE_STATE) || {};
+ data.disabled = true;
+ element.data(NG_ANIMATE_STATE, data);
+ }
+ break;
+
+ case 1:
+ rootAnimateState.disabled = !value;
+ break;
+
+ default:
+ value = !rootAnimateState.disabled;
+ break;
+ }
+ return !!value;
+ }
+ };
+
+ /*
+ all animations call this shared animation triggering function internally.
+ The animationEvent variable refers to the JavaScript animation event that will be triggered
+ and the className value is the name of the animation that will be applied within the
+ CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation
+ and the onComplete callback will be fired once the animation is fully complete.
+ */
+ function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) {
+ var noopCancel = noop;
+ var runner = animationRunner(element, animationEvent, className, options);
+ if (!runner) {
+ fireDOMOperation();
+ fireBeforeCallbackAsync();
+ fireAfterCallbackAsync();
+ closeAnimation();
+ return noopCancel;
+ }
+
+ animationEvent = runner.event;
+ className = runner.className;
+ var elementEvents = angular.element._data(runner.node);
+ elementEvents = elementEvents && elementEvents.events;
+
+ if (!parentElement) {
+ parentElement = afterElement ? afterElement.parent() : element.parent();
+ }
+
+ //skip the animation if animations are disabled, a parent is already being animated,
+ //the element is not currently attached to the document body or then completely close
+ //the animation if any matching animations are not found at all.
+ //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.
+ if (animationsDisabled(element, parentElement)) {
+ fireDOMOperation();
+ fireBeforeCallbackAsync();
+ fireAfterCallbackAsync();
+ closeAnimation();
+ return noopCancel;
+ }
+
+ var ngAnimateState = element.data(NG_ANIMATE_STATE) || {};
+ var runningAnimations = ngAnimateState.active || {};
+ var totalActiveAnimations = ngAnimateState.totalActive || 0;
+ var lastAnimation = ngAnimateState.last;
+ var skipAnimation = false;
+
+ if (totalActiveAnimations > 0) {
+ var animationsToCancel = [];
+ if (!runner.isClassBased) {
+ if (animationEvent == 'leave' && runningAnimations['ng-leave']) {
+ skipAnimation = true;
+ } else {
+ //cancel all animations when a structural animation takes place
+ for (var klass in runningAnimations) {
+ animationsToCancel.push(runningAnimations[klass]);
+ }
+ ngAnimateState = {};
+ cleanup(element, true);
+ }
+ } else if (lastAnimation.event == 'setClass') {
+ animationsToCancel.push(lastAnimation);
+ cleanup(element, className);
+ } else if (runningAnimations[className]) {
+ var current = runningAnimations[className];
+ if (current.event == animationEvent) {
+ skipAnimation = true;
+ } else {
+ animationsToCancel.push(current);
+ cleanup(element, className);
+ }
+ }
+
+ if (animationsToCancel.length > 0) {
+ forEach(animationsToCancel, function(operation) {
+ operation.cancel();
+ });
+ }
+ }
+
+ if (runner.isClassBased
+ && !runner.isSetClassOperation
+ && animationEvent != 'animate'
+ && !skipAnimation) {
+ skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR
+ }
+
+ if (skipAnimation) {
+ fireDOMOperation();
+ fireBeforeCallbackAsync();
+ fireAfterCallbackAsync();
+ fireDoneCallbackAsync();
+ return noopCancel;
+ }
+
+ runningAnimations = ngAnimateState.active || {};
+ totalActiveAnimations = ngAnimateState.totalActive || 0;
+
+ if (animationEvent == 'leave') {
+ //there's no need to ever remove the listener since the element
+ //will be removed (destroyed) after the leave animation ends or
+ //is cancelled midway
+ element.one('$destroy', function(e) {
+ var element = angular.element(this);
+ var state = element.data(NG_ANIMATE_STATE);
+ if (state) {
+ var activeLeaveAnimation = state.active['ng-leave'];
+ if (activeLeaveAnimation) {
+ activeLeaveAnimation.cancel();
+ cleanup(element, 'ng-leave');
+ }
+ }
+ });
+ }
+
+ //the ng-animate class does nothing, but it's here to allow for
+ //parent animations to find and cancel child animations when needed
+ $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME);
+ if (options && options.tempClasses) {
+ forEach(options.tempClasses, function(className) {
+ $$jqLite.addClass(element, className);
+ });
+ }
+
+ var localAnimationCount = globalAnimationCounter++;
+ totalActiveAnimations++;
+ runningAnimations[className] = runner;
+
+ element.data(NG_ANIMATE_STATE, {
+ last: runner,
+ active: runningAnimations,
+ index: localAnimationCount,
+ totalActive: totalActiveAnimations
+ });
+
+ //first we run the before animations and when all of those are complete
+ //then we perform the DOM operation and run the next set of animations
+ fireBeforeCallbackAsync();
+ runner.before(function(cancelled) {
+ var data = element.data(NG_ANIMATE_STATE);
+ cancelled = cancelled ||
+ !data || !data.active[className] ||
+ (runner.isClassBased && data.active[className].event != animationEvent);
+
+ fireDOMOperation();
+ if (cancelled === true) {
+ closeAnimation();
+ } else {
+ fireAfterCallbackAsync();
+ runner.after(closeAnimation);
+ }
+ });
+
+ return runner.cancel;
+
+ function fireDOMCallback(animationPhase) {
+ var eventName = '$animate:' + animationPhase;
+ if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {
+ $$asyncCallback(function() {
+ element.triggerHandler(eventName, {
+ event: animationEvent,
+ className: className
+ });
+ });
+ }
+ }
+
+ function fireBeforeCallbackAsync() {
+ fireDOMCallback('before');
+ }
+
+ function fireAfterCallbackAsync() {
+ fireDOMCallback('after');
+ }
+
+ function fireDoneCallbackAsync() {
+ fireDOMCallback('close');
+ doneCallback();
+ }
+
+ //it is less complicated to use a flag than managing and canceling
+ //timeouts containing multiple callbacks.
+ function fireDOMOperation() {
+ if (!fireDOMOperation.hasBeenRun) {
+ fireDOMOperation.hasBeenRun = true;
+ domOperation();
+ }
+ }
+
+ function closeAnimation() {
+ if (!closeAnimation.hasBeenRun) {
+ if (runner) { //the runner doesn't exist if it fails to instantiate
+ runner.applyStyles();
+ }
+
+ closeAnimation.hasBeenRun = true;
+ if (options && options.tempClasses) {
+ forEach(options.tempClasses, function(className) {
+ $$jqLite.removeClass(element, className);
+ });
+ }
+
+ var data = element.data(NG_ANIMATE_STATE);
+ if (data) {
+
+ /* only structural animations wait for reflow before removing an
+ animation, but class-based animations don't. An example of this
+ failing would be when a parent HTML tag has a ng-class attribute
+ causing ALL directives below to skip animations during the digest */
+ if (runner && runner.isClassBased) {
+ cleanup(element, className);
+ } else {
+ $$asyncCallback(function() {
+ var data = element.data(NG_ANIMATE_STATE) || {};
+ if (localAnimationCount == data.index) {
+ cleanup(element, className, animationEvent);
+ }
+ });
+ element.data(NG_ANIMATE_STATE, data);
+ }
+ }
+ fireDoneCallbackAsync();
+ }
+ }
+ }
+
+ function cancelChildAnimations(element) {
+ var node = extractElementNode(element);
+ if (node) {
+ var nodes = angular.isFunction(node.getElementsByClassName) ?
+ node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) :
+ node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME);
+ forEach(nodes, function(element) {
+ element = angular.element(element);
+ var data = element.data(NG_ANIMATE_STATE);
+ if (data && data.active) {
+ forEach(data.active, function(runner) {
+ runner.cancel();
+ });
+ }
+ });
+ }
+ }
+
+ function cleanup(element, className) {
+ if (isMatchingElement(element, $rootElement)) {
+ if (!rootAnimateState.disabled) {
+ rootAnimateState.running = false;
+ rootAnimateState.structural = false;
+ }
+ } else if (className) {
+ var data = element.data(NG_ANIMATE_STATE) || {};
+
+ var removeAnimations = className === true;
+ if (!removeAnimations && data.active && data.active[className]) {
+ data.totalActive--;
+ delete data.active[className];
+ }
+
+ if (removeAnimations || !data.totalActive) {
+ $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME);
+ element.removeData(NG_ANIMATE_STATE);
+ }
+ }
+ }
+
+ function animationsDisabled(element, parentElement) {
+ if (rootAnimateState.disabled) {
+ return true;
+ }
+
+ if (isMatchingElement(element, $rootElement)) {
+ return rootAnimateState.running;
+ }
+
+ var allowChildAnimations, parentRunningAnimation, hasParent;
+ do {
+ //the element did not reach the root element which means that it
+ //is not apart of the DOM. Therefore there is no reason to do
+ //any animations on it
+ if (parentElement.length === 0) break;
+
+ var isRoot = isMatchingElement(parentElement, $rootElement);
+ var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});
+ if (state.disabled) {
+ return true;
+ }
+
+ //no matter what, for an animation to work it must reach the root element
+ //this implies that the element is attached to the DOM when the animation is run
+ if (isRoot) {
+ hasParent = true;
+ }
+
+ //once a flag is found that is strictly false then everything before
+ //it will be discarded and all child animations will be restricted
+ if (allowChildAnimations !== false) {
+ var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);
+ if (angular.isDefined(animateChildrenFlag)) {
+ allowChildAnimations = animateChildrenFlag;
+ }
+ }
+
+ parentRunningAnimation = parentRunningAnimation ||
+ state.running ||
+ (state.last && !state.last.isClassBased);
+ }
+ while (parentElement = parentElement.parent());
+
+ return !hasParent || (!allowChildAnimations && parentRunningAnimation);
+ }
+ }]);
+
+ $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',
+ function($window, $sniffer, $timeout, $$animateReflow) {
+ // Detect proper transitionend/animationend event names.
+ var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
+
+ // If unprefixed events are not supported but webkit-prefixed are, use the latter.
+ // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
+ // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
+ // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
+ // Register both events in case `window.onanimationend` is not supported because of that,
+ // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
+ // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
+ // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition
+ if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
+ CSS_PREFIX = '-webkit-';
+ TRANSITION_PROP = 'WebkitTransition';
+ TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
+ } else {
+ TRANSITION_PROP = 'transition';
+ TRANSITIONEND_EVENT = 'transitionend';
+ }
+
+ if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
+ CSS_PREFIX = '-webkit-';
+ ANIMATION_PROP = 'WebkitAnimation';
+ ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
+ } else {
+ ANIMATION_PROP = 'animation';
+ ANIMATIONEND_EVENT = 'animationend';
+ }
+
+ var DURATION_KEY = 'Duration';
+ var PROPERTY_KEY = 'Property';
+ var DELAY_KEY = 'Delay';
+ var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
+ var ANIMATION_PLAYSTATE_KEY = 'PlayState';
+ var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';
+ var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';
+ var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
+ var CLOSING_TIME_BUFFER = 1.5;
+ var ONE_SECOND = 1000;
+
+ var lookupCache = {};
+ var parentCounter = 0;
+ var animationReflowQueue = [];
+ var cancelAnimationReflow;
+ function clearCacheAfterReflow() {
+ if (!cancelAnimationReflow) {
+ cancelAnimationReflow = $$animateReflow(function() {
+ animationReflowQueue = [];
+ cancelAnimationReflow = null;
+ lookupCache = {};
+ });
+ }
+ }
+
+ function afterReflow(element, callback) {
+ if (cancelAnimationReflow) {
+ cancelAnimationReflow();
+ }
+ animationReflowQueue.push(callback);
+ cancelAnimationReflow = $$animateReflow(function() {
+ forEach(animationReflowQueue, function(fn) {
+ fn();
+ });
+
+ animationReflowQueue = [];
+ cancelAnimationReflow = null;
+ lookupCache = {};
+ });
+ }
+
+ var closingTimer = null;
+ var closingTimestamp = 0;
+ var animationElementQueue = [];
+ function animationCloseHandler(element, totalTime) {
+ var node = extractElementNode(element);
+ element = angular.element(node);
+
+ //this item will be garbage collected by the closing
+ //animation timeout
+ animationElementQueue.push(element);
+
+ //but it may not need to cancel out the existing timeout
+ //if the timestamp is less than the previous one
+ var futureTimestamp = Date.now() + totalTime;
+ if (futureTimestamp <= closingTimestamp) {
+ return;
+ }
+
+ $timeout.cancel(closingTimer);
+
+ closingTimestamp = futureTimestamp;
+ closingTimer = $timeout(function() {
+ closeAllAnimations(animationElementQueue);
+ animationElementQueue = [];
+ }, totalTime, false);
+ }
+
+ function closeAllAnimations(elements) {
+ forEach(elements, function(element) {
+ var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
+ if (elementData) {
+ forEach(elementData.closeAnimationFns, function(fn) {
+ fn();
+ });
+ }
+ });
+ }
+
+ function getElementAnimationDetails(element, cacheKey) {
+ var data = cacheKey ? lookupCache[cacheKey] : null;
+ if (!data) {
+ var transitionDuration = 0;
+ var transitionDelay = 0;
+ var animationDuration = 0;
+ var animationDelay = 0;
+
+ //we want all the styles defined before and after
+ forEach(element, function(element) {
+ if (element.nodeType == ELEMENT_NODE) {
+ var elementStyles = $window.getComputedStyle(element) || {};
+
+ var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY];
+ transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration);
+
+ var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY];
+ transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);
+
+ var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY];
+ animationDelay = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay);
+
+ var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]);
+
+ if (aDuration > 0) {
+ aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1;
+ }
+ animationDuration = Math.max(aDuration, animationDuration);
+ }
+ });
+ data = {
+ total: 0,
+ transitionDelay: transitionDelay,
+ transitionDuration: transitionDuration,
+ animationDelay: animationDelay,
+ animationDuration: animationDuration
+ };
+ if (cacheKey) {
+ lookupCache[cacheKey] = data;
+ }
+ }
+ return data;
+ }
+
+ function parseMaxTime(str) {
+ var maxValue = 0;
+ var values = isString(str) ?
+ str.split(/\s*,\s*/) :
+ [];
+ forEach(values, function(value) {
+ maxValue = Math.max(parseFloat(value) || 0, maxValue);
+ });
+ return maxValue;
+ }
+
+ function getCacheKey(element) {
+ var parentElement = element.parent();
+ var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY);
+ if (!parentID) {
+ parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);
+ parentID = parentCounter;
+ }
+ return parentID + '-' + extractElementNode(element).getAttribute('class');
+ }
+
+ function animateSetup(animationEvent, element, className, styles) {
+ var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;
+
+ var cacheKey = getCacheKey(element);
+ var eventCacheKey = cacheKey + ' ' + className;
+ var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;
+
+ var stagger = {};
+ if (itemIndex > 0) {
+ var staggerClassName = className + '-stagger';
+ var staggerCacheKey = cacheKey + ' ' + staggerClassName;
+ var applyClasses = !lookupCache[staggerCacheKey];
+
+ applyClasses && $$jqLite.addClass(element, staggerClassName);
+
+ stagger = getElementAnimationDetails(element, staggerCacheKey);
+
+ applyClasses && $$jqLite.removeClass(element, staggerClassName);
+ }
+
+ $$jqLite.addClass(element, className);
+
+ var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};
+ var timings = getElementAnimationDetails(element, eventCacheKey);
+ var transitionDuration = timings.transitionDuration;
+ var animationDuration = timings.animationDuration;
+
+ if (structural && transitionDuration === 0 && animationDuration === 0) {
+ $$jqLite.removeClass(element, className);
+ return false;
+ }
+
+ var blockTransition = styles || (structural && transitionDuration > 0);
+ var blockAnimation = animationDuration > 0 &&
+ stagger.animationDelay > 0 &&
+ stagger.animationDuration === 0;
+
+ var closeAnimationFns = formerData.closeAnimationFns || [];
+ element.data(NG_ANIMATE_CSS_DATA_KEY, {
+ stagger: stagger,
+ cacheKey: eventCacheKey,
+ running: formerData.running || 0,
+ itemIndex: itemIndex,
+ blockTransition: blockTransition,
+ closeAnimationFns: closeAnimationFns
+ });
+
+ var node = extractElementNode(element);
+
+ if (blockTransition) {
+ blockTransitions(node, true);
+ if (styles) {
+ element.css(styles);
+ }
+ }
+
+ if (blockAnimation) {
+ blockAnimations(node, true);
+ }
+
+ return true;
+ }
+
+ function animateRun(animationEvent, element, className, activeAnimationComplete, styles) {
+ var node = extractElementNode(element);
+ var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
+ if (node.getAttribute('class').indexOf(className) == -1 || !elementData) {
+ activeAnimationComplete();
+ return;
+ }
+
+ var activeClassName = '';
+ var pendingClassName = '';
+ forEach(className.split(' '), function(klass, i) {
+ var prefix = (i > 0 ? ' ' : '') + klass;
+ activeClassName += prefix + '-active';
+ pendingClassName += prefix + '-pending';
+ });
+
+ var style = '';
+ var appliedStyles = [];
+ var itemIndex = elementData.itemIndex;
+ var stagger = elementData.stagger;
+ var staggerTime = 0;
+ if (itemIndex > 0) {
+ var transitionStaggerDelay = 0;
+ if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {
+ transitionStaggerDelay = stagger.transitionDelay * itemIndex;
+ }
+
+ var animationStaggerDelay = 0;
+ if (stagger.animationDelay > 0 && stagger.animationDuration === 0) {
+ animationStaggerDelay = stagger.animationDelay * itemIndex;
+ appliedStyles.push(CSS_PREFIX + 'animation-play-state');
+ }
+
+ staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100;
+ }
+
+ if (!staggerTime) {
+ $$jqLite.addClass(element, activeClassName);
+ if (elementData.blockTransition) {
+ blockTransitions(node, false);
+ }
+ }
+
+ var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;
+ var timings = getElementAnimationDetails(element, eventCacheKey);
+ var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
+ if (maxDuration === 0) {
+ $$jqLite.removeClass(element, activeClassName);
+ animateClose(element, className);
+ activeAnimationComplete();
+ return;
+ }
+
+ if (!staggerTime && styles && Object.keys(styles).length > 0) {
+ if (!timings.transitionDuration) {
+ element.css('transition', timings.animationDuration + 's linear all');
+ appliedStyles.push('transition');
+ }
+ element.css(styles);
+ }
+
+ var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);
+ var maxDelayTime = maxDelay * ONE_SECOND;
+
+ if (appliedStyles.length > 0) {
+ //the element being animated may sometimes contain comment nodes in
+ //the jqLite object, so we're safe to use a single variable to house
+ //the styles since there is always only one element being animated
+ var oldStyle = node.getAttribute('style') || '';
+ if (oldStyle.charAt(oldStyle.length - 1) !== ';') {
+ oldStyle += ';';
+ }
+ node.setAttribute('style', oldStyle + ' ' + style);
+ }
+
+ var startTime = Date.now();
+ var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;
+ var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;
+ var totalTime = (staggerTime + animationTime) * ONE_SECOND;
+
+ var staggerTimeout;
+ if (staggerTime > 0) {
+ $$jqLite.addClass(element, pendingClassName);
+ staggerTimeout = $timeout(function() {
+ staggerTimeout = null;
+
+ if (timings.transitionDuration > 0) {
+ blockTransitions(node, false);
+ }
+ if (timings.animationDuration > 0) {
+ blockAnimations(node, false);
+ }
+
+ $$jqLite.addClass(element, activeClassName);
+ $$jqLite.removeClass(element, pendingClassName);
+
+ if (styles) {
+ if (timings.transitionDuration === 0) {
+ element.css('transition', timings.animationDuration + 's linear all');
+ }
+ element.css(styles);
+ appliedStyles.push('transition');
+ }
+ }, staggerTime * ONE_SECOND, false);
+ }
+
+ element.on(css3AnimationEvents, onAnimationProgress);
+ elementData.closeAnimationFns.push(function() {
+ onEnd();
+ activeAnimationComplete();
+ });
+
+ elementData.running++;
+ animationCloseHandler(element, totalTime);
+ return onEnd;
+
+ // This will automatically be called by $animate so
+ // there is no need to attach this internally to the
+ // timeout done method.
+ function onEnd() {
+ element.off(css3AnimationEvents, onAnimationProgress);
+ $$jqLite.removeClass(element, activeClassName);
+ $$jqLite.removeClass(element, pendingClassName);
+ if (staggerTimeout) {
+ $timeout.cancel(staggerTimeout);
+ }
+ animateClose(element, className);
+ var node = extractElementNode(element);
+ for (var i in appliedStyles) {
+ node.style.removeProperty(appliedStyles[i]);
+ }
+ }
+
+ function onAnimationProgress(event) {
+ event.stopPropagation();
+ var ev = event.originalEvent || event;
+ var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
+
+ /* Firefox (or possibly just Gecko) likes to not round values up
+ * when a ms measurement is used for the animation */
+ var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
+
+ /* $manualTimeStamp is a mocked timeStamp value which is set
+ * within browserTrigger(). This is only here so that tests can
+ * mock animations properly. Real events fallback to event.timeStamp,
+ * or, if they don't, then a timeStamp is automatically created for them.
+ * We're checking to see if the timeStamp surpasses the expected delay,
+ * but we're using elapsedTime instead of the timeStamp on the 2nd
+ * pre-condition since animations sometimes close off early */
+ if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
+ activeAnimationComplete();
+ }
+ }
+ }
+
+ function blockTransitions(node, bool) {
+ node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : '';
+ }
+
+ function blockAnimations(node, bool) {
+ node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : '';
+ }
+
+ function animateBefore(animationEvent, element, className, styles) {
+ if (animateSetup(animationEvent, element, className, styles)) {
+ return function(cancelled) {
+ cancelled && animateClose(element, className);
+ };
+ }
+ }
+
+ function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) {
+ if (element.data(NG_ANIMATE_CSS_DATA_KEY)) {
+ return animateRun(animationEvent, element, className, afterAnimationComplete, styles);
+ } else {
+ animateClose(element, className);
+ afterAnimationComplete();
+ }
+ }
+
+ function animate(animationEvent, element, className, animationComplete, options) {
+ //If the animateSetup function doesn't bother returning a
+ //cancellation function then it means that there is no animation
+ //to perform at all
+ var preReflowCancellation = animateBefore(animationEvent, element, className, options.from);
+ if (!preReflowCancellation) {
+ clearCacheAfterReflow();
+ animationComplete();
+ return;
+ }
+
+ //There are two cancellation functions: one is before the first
+ //reflow animation and the second is during the active state
+ //animation. The first function will take care of removing the
+ //data from the element which will not make the 2nd animation
+ //happen in the first place
+ var cancel = preReflowCancellation;
+ afterReflow(element, function() {
+ //once the reflow is complete then we point cancel to
+ //the new cancellation function which will remove all of the
+ //animation properties from the active animation
+ cancel = animateAfter(animationEvent, element, className, animationComplete, options.to);
+ });
+
+ return function(cancelled) {
+ (cancel || noop)(cancelled);
+ };
+ }
+
+ function animateClose(element, className) {
+ $$jqLite.removeClass(element, className);
+ var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
+ if (data) {
+ if (data.running) {
+ data.running--;
+ }
+ if (!data.running || data.running === 0) {
+ element.removeData(NG_ANIMATE_CSS_DATA_KEY);
+ }
+ }
+ }
+
+ return {
+ animate: function(element, className, from, to, animationCompleted, options) {
+ options = options || {};
+ options.from = from;
+ options.to = to;
+ return animate('animate', element, className, animationCompleted, options);
+ },
+
+ enter: function(element, animationCompleted, options) {
+ options = options || {};
+ return animate('enter', element, 'ng-enter', animationCompleted, options);
+ },
+
+ leave: function(element, animationCompleted, options) {
+ options = options || {};
+ return animate('leave', element, 'ng-leave', animationCompleted, options);
+ },
+
+ move: function(element, animationCompleted, options) {
+ options = options || {};
+ return animate('move', element, 'ng-move', animationCompleted, options);
+ },
+
+ beforeSetClass: function(element, add, remove, animationCompleted, options) {
+ options = options || {};
+ var className = suffixClasses(remove, '-remove') + ' ' +
+ suffixClasses(add, '-add');
+ var cancellationMethod = animateBefore('setClass', element, className, options.from);
+ if (cancellationMethod) {
+ afterReflow(element, animationCompleted);
+ return cancellationMethod;
+ }
+ clearCacheAfterReflow();
+ animationCompleted();
+ },
+
+ beforeAddClass: function(element, className, animationCompleted, options) {
+ options = options || {};
+ var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from);
+ if (cancellationMethod) {
+ afterReflow(element, animationCompleted);
+ return cancellationMethod;
+ }
+ clearCacheAfterReflow();
+ animationCompleted();
+ },
+
+ beforeRemoveClass: function(element, className, animationCompleted, options) {
+ options = options || {};
+ var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from);
+ if (cancellationMethod) {
+ afterReflow(element, animationCompleted);
+ return cancellationMethod;
+ }
+ clearCacheAfterReflow();
+ animationCompleted();
+ },
+
+ setClass: function(element, add, remove, animationCompleted, options) {
+ options = options || {};
+ remove = suffixClasses(remove, '-remove');
+ add = suffixClasses(add, '-add');
+ var className = remove + ' ' + add;
+ return animateAfter('setClass', element, className, animationCompleted, options.to);
+ },
+
+ addClass: function(element, className, animationCompleted, options) {
+ options = options || {};
+ return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to);
+ },
+
+ removeClass: function(element, className, animationCompleted, options) {
+ options = options || {};
+ return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to);
+ }
+ };
+
+ function suffixClasses(classes, suffix) {
+ var className = '';
+ classes = isArray(classes) ? classes : classes.split(/\s+/);
+ forEach(classes, function(klass, i) {
+ if (klass && klass.length > 0) {
+ className += (i > 0 ? ' ' : '') + klass + suffix;
+ }
+ });
+ return className;
+ }
+ }]);
+ }]);
+
+
+})(window, window.angular);
diff --git a/afb-client/bower_components/angular-animate/angular-animate.min.js b/afb-client/bower_components/angular-animate/angular-animate.min.js
new file mode 100644
index 0000000..70c25a3
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/angular-animate.min.js
@@ -0,0 +1,33 @@
+/*
+ AngularJS v1.3.20
+ (c) 2010-2014 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(N,f,W){'use strict';f.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(X,r,g){g=g.ngAnimateChildren;f.isString(g)&&0===g.length?r.data("$$ngAnimateChildren",!0):X.$watch(g,function(f){r.data("$$ngAnimateChildren",!!f)})}}).factory("$$animateReflow",["$$rAF","$document",function(f,r){var g=r[0].body;return function(r){return f(function(){r(g.offsetWidth)})}}]).config(["$provide","$animateProvider",function(X,r){function g(f){for(var n=0;n<f.length;n++){var g=
+f[n];if(1==g.nodeType)return g}}function ba(f,n){return g(f)==g(n)}var t=f.noop,n=f.forEach,ca=r.$$selectors,aa=f.isArray,da=f.isString,ga=f.isObject,w={running:!0},u;X.decorator("$animate",["$delegate","$$q","$injector","$sniffer","$rootElement","$$asyncCallback","$rootScope","$document","$templateRequest","$$jqLite",function(O,N,M,Y,y,I,P,W,Z,Q){function R(a,c){var b=a.data("$$ngAnimateState")||{};c&&(b.running=!0,b.structural=!0,a.data("$$ngAnimateState",b));return b.disabled||b.running&&b.structural}
+function D(a){var c,b=N.defer();b.promise.$$cancelFn=function(){c&&c()};P.$$postDigest(function(){c=a(function(){b.resolve()})});return b.promise}function J(a){if(ga(a))return a.tempClasses&&da(a.tempClasses)&&(a.tempClasses=a.tempClasses.split(/\s+/)),a}function S(a,c,b){b=b||{};var d={};n(b,function(e,a){n(a.split(" "),function(a){d[a]=e})});var h=Object.create(null);n((a.attr("class")||"").split(/\s+/),function(e){h[e]=!0});var f=[],k=[];n(c&&c.classes||[],function(e,a){var b=h[a],c=d[a]||{};!1===
+e?(b||"addClass"==c.event)&&k.push(a):!0===e&&(b&&"removeClass"!=c.event||f.push(a))});return 0<f.length+k.length&&[f.join(" "),k.join(" ")]}function T(a){if(a){var c=[],b={};a=a.substr(1).split(".");(Y.transitions||Y.animations)&&c.push(M.get(ca[""]));for(var d=0;d<a.length;d++){var f=a[d],l=ca[f];l&&!b[f]&&(c.push(M.get(l)),b[f]=!0)}return c}}function U(a,c,b,d){function h(e,a){var b=e[a],c=e["before"+a.charAt(0).toUpperCase()+a.substr(1)];if(b||c)return"leave"==a&&(c=b,b=null),u.push({event:a,
+fn:b}),fa.push({event:a,fn:c}),!0}function l(c,k,x){var E=[];n(c,function(a){a.fn&&E.push(a)});var m=0;n(E,function(c,f){var p=function(){a:{if(k){(k[f]||t)();if(++m<E.length)break a;k=null}x()}};switch(c.event){case "setClass":k.push(c.fn(a,e,A,p,d));break;case "animate":k.push(c.fn(a,b,d.from,d.to,p));break;case "addClass":k.push(c.fn(a,e||b,p,d));break;case "removeClass":k.push(c.fn(a,A||b,p,d));break;default:k.push(c.fn(a,p,d))}});k&&0===k.length&&x()}var k=a[0];if(k){d&&(d.to=d.to||{},d.from=
+d.from||{});var e,A;aa(b)&&(e=b[0],A=b[1],e?A?b=e+" "+A:(b=e,c="addClass"):(b=A,c="removeClass"));var x="setClass"==c,E=x||"addClass"==c||"removeClass"==c||"animate"==c,p=a.attr("class")+" "+b;if(B(p)){var G=t,m=[],fa=[],g=t,s=[],u=[],p=(" "+p).replace(/\s+/g,".");n(T(p),function(a){!h(a,c)&&x&&(h(a,"addClass"),h(a,"removeClass"))});return{node:k,event:c,className:b,isClassBased:E,isSetClassOperation:x,applyStyles:function(){d&&a.css(f.extend(d.from||{},d.to||{}))},before:function(a){G=a;l(fa,m,function(){G=
+t;a()})},after:function(a){g=a;l(u,s,function(){g=t;a()})},cancel:function(){m&&(n(m,function(a){(a||t)(!0)}),G(!0));s&&(n(s,function(a){(a||t)(!0)}),g(!0))}}}}}function H(a,c,b,d,h,l,k,e){function A(e){var k="$animate:"+e;g&&g[k]&&0<g[k].length&&I(function(){b.triggerHandler(k,{event:a,className:c})})}function x(){A("before")}function E(){A("after")}function p(){p.hasBeenRun||(p.hasBeenRun=!0,l())}function G(){if(!G.hasBeenRun){m&&m.applyStyles();G.hasBeenRun=!0;k&&k.tempClasses&&n(k.tempClasses,
+function(a){u.removeClass(b,a)});var x=b.data("$$ngAnimateState");x&&(m&&m.isClassBased?C(b,c):(I(function(){var e=b.data("$$ngAnimateState")||{};ea==e.index&&C(b,c,a)}),b.data("$$ngAnimateState",x)));A("close");e()}}var m=U(b,a,c,k);if(!m)return p(),x(),E(),G(),t;a=m.event;c=m.className;var g=f.element._data(m.node),g=g&&g.events;d||(d=h?h.parent():b.parent());if(z(b,d))return p(),x(),E(),G(),t;d=b.data("$$ngAnimateState")||{};var L=d.active||{},s=d.totalActive||0,q=d.last;h=!1;if(0<s){s=[];if(m.isClassBased)"setClass"==
+q.event?(s.push(q),C(b,c)):L[c]&&(v=L[c],v.event==a?h=!0:(s.push(v),C(b,c)));else if("leave"==a&&L["ng-leave"])h=!0;else{for(var v in L)s.push(L[v]);d={};C(b,!0)}0<s.length&&n(s,function(a){a.cancel()})}!m.isClassBased||m.isSetClassOperation||"animate"==a||h||(h="addClass"==a==b.hasClass(c));if(h)return p(),x(),E(),A("close"),e(),t;L=d.active||{};s=d.totalActive||0;if("leave"==a)b.one("$destroy",function(a){a=f.element(this);var e=a.data("$$ngAnimateState");e&&(e=e.active["ng-leave"])&&(e.cancel(),
+C(a,"ng-leave"))});u.addClass(b,"ng-animate");k&&k.tempClasses&&n(k.tempClasses,function(a){u.addClass(b,a)});var ea=K++;s++;L[c]=m;b.data("$$ngAnimateState",{last:m,active:L,index:ea,totalActive:s});x();m.before(function(e){var k=b.data("$$ngAnimateState");e=e||!k||!k.active[c]||m.isClassBased&&k.active[c].event!=a;p();!0===e?G():(E(),m.after(G))});return m.cancel}function q(a){if(a=g(a))a=f.isFunction(a.getElementsByClassName)?a.getElementsByClassName("ng-animate"):a.querySelectorAll(".ng-animate"),
+n(a,function(a){a=f.element(a);(a=a.data("$$ngAnimateState"))&&a.active&&n(a.active,function(a){a.cancel()})})}function C(a,c){if(ba(a,y))w.disabled||(w.running=!1,w.structural=!1);else if(c){var b=a.data("$$ngAnimateState")||{},d=!0===c;!d&&b.active&&b.active[c]&&(b.totalActive--,delete b.active[c]);if(d||!b.totalActive)u.removeClass(a,"ng-animate"),a.removeData("$$ngAnimateState")}}function z(a,c){if(w.disabled)return!0;if(ba(a,y))return w.running;var b,d,g;do{if(0===c.length)break;var l=ba(c,y),
+k=l?w:c.data("$$ngAnimateState")||{};if(k.disabled)return!0;l&&(g=!0);!1!==b&&(l=c.data("$$ngAnimateChildren"),f.isDefined(l)&&(b=l));d=d||k.running||k.last&&!k.last.isClassBased}while(c=c.parent());return!g||!b&&d}u=Q;y.data("$$ngAnimateState",w);var $=P.$watch(function(){return Z.totalPendingRequests},function(a,c){0===a&&($(),P.$$postDigest(function(){P.$$postDigest(function(){w.running=!1})}))}),K=0,V=r.classNameFilter(),B=V?function(a){return V.test(a)}:function(){return!0};return{animate:function(a,
+c,b,d,h){d=d||"ng-inline-animate";h=J(h)||{};h.from=b?c:null;h.to=b?b:c;return D(function(b){return H("animate",d,f.element(g(a)),null,null,t,h,b)})},enter:function(a,c,b,d){d=J(d);a=f.element(a);c=c&&f.element(c);b=b&&f.element(b);R(a,!0);O.enter(a,c,b);return D(function(h){return H("enter","ng-enter",f.element(g(a)),c,b,t,d,h)})},leave:function(a,c){c=J(c);a=f.element(a);q(a);R(a,!0);return D(function(b){return H("leave","ng-leave",f.element(g(a)),null,null,function(){O.leave(a)},c,b)})},move:function(a,
+c,b,d){d=J(d);a=f.element(a);c=c&&f.element(c);b=b&&f.element(b);q(a);R(a,!0);O.move(a,c,b);return D(function(h){return H("move","ng-move",f.element(g(a)),c,b,t,d,h)})},addClass:function(a,c,b){return this.setClass(a,c,[],b)},removeClass:function(a,c,b){return this.setClass(a,[],c,b)},setClass:function(a,c,b,d){d=J(d);a=f.element(a);a=f.element(g(a));if(R(a))return O.$$setClassImmediately(a,c,b,d);var h,l=a.data("$$animateClasses"),k=!!l;l||(l={classes:{}});h=l.classes;c=aa(c)?c:c.split(" ");n(c,
+function(a){a&&a.length&&(h[a]=!0)});b=aa(b)?b:b.split(" ");n(b,function(a){a&&a.length&&(h[a]=!1)});if(k)return d&&l.options&&(l.options=f.extend(l.options||{},d)),l.promise;a.data("$$animateClasses",l={classes:h,options:d});return l.promise=D(function(e){var k,b,c,d=g(a);d&&(k=a.data("$$animateClasses"),a.removeData("$$animateClasses"),c=a.parent(),b=d.parentNode);if(!b||b.$$NG_REMOVED||d.$$NG_REMOVED)e();else{b=a.data("$$ngAnimateState")||{};var f=S(a,k,b.active);return f?H("setClass",f,a,c,null,
+function(){f[0]&&O.$$addClassImmediately(a,f[0]);f[1]&&O.$$removeClassImmediately(a,f[1])},k.options,e):e()}})},cancel:function(a){a.$$cancelFn()},enabled:function(a,c){switch(arguments.length){case 2:if(a)C(c);else{var b=c.data("$$ngAnimateState")||{};b.disabled=!0;c.data("$$ngAnimateState",b)}break;case 1:w.disabled=!a;break;default:a=!w.disabled}return!!a}}}]);r.register("",["$window","$sniffer","$timeout","$$animateReflow",function(r,w,M,Y){function y(){b||(b=Y(function(){c=[];b=null;B={}}))}
+function I(a,e){b&&b();c.push(e);b=Y(function(){n(c,function(a){a()});c=[];b=null;B={}})}function P(a,e){var b=g(a);a=f.element(b);l.push(a);b=Date.now()+e;b<=h||(M.cancel(d),h=b,d=M(function(){X(l);l=[]},e,!1))}function X(a){n(a,function(a){(a=a.data("$$ngAnimateCSS3Data"))&&n(a.closeAnimationFns,function(a){a()})})}function Z(a,e){var b=e?B[e]:null;if(!b){var c=0,d=0,f=0,g=0;n(a,function(a){if(1==a.nodeType){a=r.getComputedStyle(a)||{};c=Math.max(Q(a[z+"Duration"]),c);d=Math.max(Q(a[z+"Delay"]),
+d);g=Math.max(Q(a[K+"Delay"]),g);var e=Q(a[K+"Duration"]);0<e&&(e*=parseInt(a[K+"IterationCount"],10)||1);f=Math.max(e,f)}});b={total:0,transitionDelay:d,transitionDuration:c,animationDelay:g,animationDuration:f};e&&(B[e]=b)}return b}function Q(a){var e=0;a=da(a)?a.split(/\s*,\s*/):[];n(a,function(a){e=Math.max(parseFloat(a)||0,e)});return e}function R(b,e,c,d){b=0<=["ng-enter","ng-leave","ng-move"].indexOf(c);var f,p=e.parent(),h=p.data("$$ngAnimateKey");h||(p.data("$$ngAnimateKey",++a),h=a);f=h+
+"-"+g(e).getAttribute("class");var p=f+" "+c,h=B[p]?++B[p].total:0,m={};if(0<h){var n=c+"-stagger",m=f+" "+n;(f=!B[m])&&u.addClass(e,n);m=Z(e,m);f&&u.removeClass(e,n)}u.addClass(e,c);var n=e.data("$$ngAnimateCSS3Data")||{},l=Z(e,p);f=l.transitionDuration;l=l.animationDuration;if(b&&0===f&&0===l)return u.removeClass(e,c),!1;c=d||b&&0<f;b=0<l&&0<m.animationDelay&&0===m.animationDuration;e.data("$$ngAnimateCSS3Data",{stagger:m,cacheKey:p,running:n.running||0,itemIndex:h,blockTransition:c,closeAnimationFns:n.closeAnimationFns||
+[]});p=g(e);c&&(J(p,!0),d&&e.css(d));b&&(p.style[K+"PlayState"]="paused");return!0}function D(a,e,b,c,d){function f(){e.off(D,h);u.removeClass(e,l);u.removeClass(e,t);z&&M.cancel(z);H(e,b);var a=g(e),c;for(c in s)a.style.removeProperty(s[c])}function h(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-I,0)>=B&&b>=y&&c()}var m=g(e);a=e.data("$$ngAnimateCSS3Data");if(-1!=m.getAttribute("class").indexOf(b)&&
+a){var l="",t="";n(b.split(" "),function(a,b){var e=(0<b?" ":"")+a;l+=e+"-active";t+=e+"-pending"});var s=[],q=a.itemIndex,v=a.stagger,r=0;if(0<q){r=0;0<v.transitionDelay&&0===v.transitionDuration&&(r=v.transitionDelay*q);var w=0;0<v.animationDelay&&0===v.animationDuration&&(w=v.animationDelay*q,s.push(C+"animation-play-state"));r=Math.round(100*Math.max(r,w))/100}r||(u.addClass(e,l),a.blockTransition&&J(m,!1));var F=Z(e,a.cacheKey+" "+l),y=Math.max(F.transitionDuration,F.animationDuration);if(0===
+y)u.removeClass(e,l),H(e,b),c();else{!r&&d&&0<Object.keys(d).length&&(F.transitionDuration||(e.css("transition",F.animationDuration+"s linear all"),s.push("transition")),e.css(d));var q=Math.max(F.transitionDelay,F.animationDelay),B=1E3*q;0<s.length&&(v=m.getAttribute("style")||"",";"!==v.charAt(v.length-1)&&(v+=";"),m.setAttribute("style",v+" "));var I=Date.now(),D=V+" "+$,q=1E3*(r+1.5*(q+y)),z;0<r&&(u.addClass(e,t),z=M(function(){z=null;0<F.transitionDuration&&J(m,!1);0<F.animationDuration&&(m.style[K+
+"PlayState"]="");u.addClass(e,l);u.removeClass(e,t);d&&(0===F.transitionDuration&&e.css("transition",F.animationDuration+"s linear all"),e.css(d),s.push("transition"))},1E3*r,!1));e.on(D,h);a.closeAnimationFns.push(function(){f();c()});a.running++;P(e,q);return f}}else c()}function J(a,b){a.style[z+"Property"]=b?"none":""}function S(a,b,c,d){if(R(a,b,c,d))return function(a){a&&H(b,c)}}function T(a,b,c,d,f){if(b.data("$$ngAnimateCSS3Data"))return D(a,b,c,d,f);H(b,c);d()}function U(a,b,c,d,f){var g=
+S(a,b,c,f.from);if(g){var h=g;I(b,function(){h=T(a,b,c,d,f.to)});return function(a){(h||t)(a)}}y();d()}function H(a,b){u.removeClass(a,b);var c=a.data("$$ngAnimateCSS3Data");c&&(c.running&&c.running--,c.running&&0!==c.running||a.removeData("$$ngAnimateCSS3Data"))}function q(a,b){var c="";a=aa(a)?a:a.split(/\s+/);n(a,function(a,d){a&&0<a.length&&(c+=(0<d?" ":"")+a+b)});return c}var C="",z,$,K,V;N.ontransitionend===W&&N.onwebkittransitionend!==W?(C="-webkit-",z="WebkitTransition",$="webkitTransitionEnd transitionend"):
+(z="transition",$="transitionend");N.onanimationend===W&&N.onwebkitanimationend!==W?(C="-webkit-",K="WebkitAnimation",V="webkitAnimationEnd animationend"):(K="animation",V="animationend");var B={},a=0,c=[],b,d=null,h=0,l=[];return{animate:function(a,b,c,d,f,g){g=g||{};g.from=c;g.to=d;return U("animate",a,b,f,g)},enter:function(a,b,c){c=c||{};return U("enter",a,"ng-enter",b,c)},leave:function(a,b,c){c=c||{};return U("leave",a,"ng-leave",b,c)},move:function(a,b,c){c=c||{};return U("move",a,"ng-move",
+b,c)},beforeSetClass:function(a,b,c,d,f){f=f||{};b=q(c,"-remove")+" "+q(b,"-add");if(f=S("setClass",a,b,f.from))return I(a,d),f;y();d()},beforeAddClass:function(a,b,c,d){d=d||{};if(b=S("addClass",a,q(b,"-add"),d.from))return I(a,c),b;y();c()},beforeRemoveClass:function(a,b,c,d){d=d||{};if(b=S("removeClass",a,q(b,"-remove"),d.from))return I(a,c),b;y();c()},setClass:function(a,b,c,d,f){f=f||{};c=q(c,"-remove");b=q(b,"-add");return T("setClass",a,c+" "+b,d,f.to)},addClass:function(a,b,c,d){d=d||{};return T("addClass",
+a,q(b,"-add"),c,d.to)},removeClass:function(a,b,c,d){d=d||{};return T("removeClass",a,q(b,"-remove"),c,d.to)}}}])}])})(window,window.angular);
+//# sourceMappingURL=angular-animate.min.js.map
diff --git a/afb-client/bower_components/angular-animate/angular-animate.min.js.map b/afb-client/bower_components/angular-animate/angular-animate.min.js.map
new file mode 100644
index 0000000..b9ada6b
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/angular-animate.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-animate.min.js",
+"lineCount":32,
+"mappings":"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",
+"sources":["angular-animate.js"],
+"names":["window","angular","undefined","module","directive","scope","element","attrs","val","ngAnimateChildren","isString","length","data","NG_ANIMATE_CHILDREN","$watch","value","factory","$$rAF","$document","bod","body","fn","offsetWidth","config","$provide","$animateProvider","extractElementNode","i","elm","ELEMENT_NODE","nodeType","isMatchingElement","elm1","elm2","noop","forEach","selectors","$$selectors","isArray","isObject","rootAnimateState","running","$$jqLite","decorator","$delegate","$$q","$injector","$sniffer","$rootElement","$$asyncCallback","$rootScope","$templateRequest","$$$jqLite","classBasedAnimationsBlocked","setter","NG_ANIMATE_STATE","structural","disabled","runAnimationPostDigest","cancelFn","defer","promise","$$cancelFn","defer.promise.$$cancelFn","$$postDigest","resolve","parseAnimateOptions","options","tempClasses","split","resolveElementClasses","cache","runningAnimations","lookup","selector","s","hasClasses","Object","create","attr","className","toAdd","toRemove","classes","status","hasClass","matchingAnimation","event","push","join","name","matches","flagMap","substr","transitions","animations","get","klass","selectorFactoryName","animationRunner","animationEvent","registerAnimation","animationFactory","afterFn","beforeFn","charAt","toUpperCase","after","before","run","fns","cancellations","allCompleteFn","animation","count","index","progress","classNameAdd","classNameRemove","from","to","node","isSetClassOperation","isClassBased","currentClassName","isAnimatableClassName","beforeComplete","beforeCancel","afterComplete","afterCancel","animationLookup","replace","created","applyStyles","css","extend","cancel","performAnimation","parentElement","afterElement","domOperation","doneCallback","fireDOMCallback","animationPhase","eventName","elementEvents","triggerHandler","fireBeforeCallbackAsync","fireAfterCallbackAsync","fireDOMOperation","hasBeenRun","closeAnimation","runner","removeClass","cleanup","localAnimationCount","_data","events","parent","animationsDisabled","ngAnimateState","active","totalActiveAnimations","totalActive","lastAnimation","last","skipAnimation","animationsToCancel","current","operation","one","e","state","activeLeaveAnimation","addClass","NG_ANIMATE_CLASS_NAME","globalAnimationCounter","cancelled","cancelChildAnimations","nodes","isFunction","getElementsByClassName","querySelectorAll","removeAnimations","removeData","allowChildAnimations","parentRunningAnimation","hasParent","isRoot","animateChildrenFlag","isDefined","deregisterWatch","totalPendingRequests","oldVal","classNameFilter","test","animate","done","enter","leave","move","setClass","add","remove","$$setClassImmediately","STORAGE_KEY","hasCache","c","parentNode","elementNode","$$addClassImmediately","$$removeClassImmediately","enabled","arguments","register","$window","$timeout","$$animateReflow","clearCacheAfterReflow","cancelAnimationReflow","animationReflowQueue","lookupCache","afterReflow","callback","animationCloseHandler","totalTime","animationElementQueue","futureTimestamp","Date","now","closingTimestamp","closingTimer","closeAllAnimations","elements","elementData","NG_ANIMATE_CSS_DATA_KEY","closeAnimationFns","getElementAnimationDetails","cacheKey","transitionDuration","transitionDelay","animationDuration","animationDelay","elementStyles","getComputedStyle","Math","max","parseMaxTime","transitionDurationStyle","TRANSITION_PROP","DURATION_KEY","transitionDelayStyle","DELAY_KEY","ANIMATION_PROP","aDuration","parseInt","ANIMATION_ITERATION_COUNT_KEY","total","str","maxValue","values","parseFloat","animateSetup","styles","indexOf","parentID","NG_ANIMATE_PARENT_KEY","parentCounter","getAttribute","eventCacheKey","itemIndex","stagger","staggerClassName","staggerCacheKey","applyClasses","formerData","timings","blockTransition","blockAnimation","blockTransitions","style","ANIMATION_PLAYSTATE_KEY","animateRun","activeAnimationComplete","onEnd","off","css3AnimationEvents","onAnimationProgress","activeClassName","pendingClassName","staggerTimeout","animateClose","appliedStyles","removeProperty","stopPropagation","ev","originalEvent","timeStamp","$manualTimeStamp","elapsedTime","toFixed","ELAPSED_TIME_MAX_DECIMAL_PLACES","startTime","maxDelayTime","maxDuration","prefix","staggerTime","transitionStaggerDelay","animationStaggerDelay","CSS_PREFIX","round","keys","maxDelay","ONE_SECOND","oldStyle","setAttribute","ANIMATIONEND_EVENT","TRANSITIONEND_EVENT","CLOSING_TIME_BUFFER","on","bool","PROPERTY_KEY","animateBefore","animateAfter","afterAnimationComplete","animationComplete","preReflowCancellation","suffixClasses","suffix","ontransitionend","onwebkittransitionend","onanimationend","onwebkitanimationend","animationCompleted","beforeSetClass","cancellationMethod","beforeAddClass","beforeRemoveClass"]
+}
diff --git a/afb-client/bower_components/angular-animate/bower.json b/afb-client/bower_components/angular-animate/bower.json
new file mode 100644
index 0000000..eb11f6a
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/bower.json
@@ -0,0 +1,9 @@
+{
+ "name": "angular-animate",
+ "version": "1.3.20",
+ "main": "./angular-animate.js",
+ "ignore": [],
+ "dependencies": {
+ "angular": "1.3.20"
+ }
+}
diff --git a/afb-client/bower_components/angular-animate/index.js b/afb-client/bower_components/angular-animate/index.js
new file mode 100644
index 0000000..6ec0a35
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/index.js
@@ -0,0 +1,2 @@
+require('./angular-animate');
+module.exports = 'ngAnimate';
diff --git a/afb-client/bower_components/angular-animate/package.json b/afb-client/bower_components/angular-animate/package.json
new file mode 100644
index 0000000..983094d
--- /dev/null
+++ b/afb-client/bower_components/angular-animate/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "angular-animate",
+ "version": "1.3.20",
+ "description": "AngularJS module for animations",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular/angular.js.git"
+ },
+ "keywords": [
+ "angular",
+ "framework",
+ "browser",
+ "animation",
+ "client-side"
+ ],
+ "author": "Angular Core Team <angular-core+npm@google.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/angular/angular.js/issues"
+ },
+ "homepage": "http://angularjs.org"
+}
diff --git a/afb-client/bower_components/angular-cookies/.bower.json b/afb-client/bower_components/angular-cookies/.bower.json
new file mode 100644
index 0000000..5138a2a
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/.bower.json
@@ -0,0 +1,19 @@
+{
+ "name": "angular-cookies",
+ "version": "1.3.20",
+ "main": "./angular-cookies.js",
+ "ignore": [],
+ "dependencies": {
+ "angular": "1.3.20"
+ },
+ "homepage": "https://github.com/angular/bower-angular-cookies",
+ "_release": "1.3.20",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.3.20",
+ "commit": "fe6acf196d30f65b2d75438c9f7d9eb283da0d6f"
+ },
+ "_source": "git://github.com/angular/bower-angular-cookies.git",
+ "_target": "~1.3.4",
+ "_originalSource": "angular-cookies"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-cookies/README.md b/afb-client/bower_components/angular-cookies/README.md
new file mode 100644
index 0000000..7b190d3
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/README.md
@@ -0,0 +1,68 @@
+# packaged angular-cookies
+
+This repo is for distribution on `npm` and `bower`. The source for this module is in the
+[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngCookies).
+Please file issues and pull requests against that repo.
+
+## Install
+
+You can install this package either with `npm` or with `bower`.
+
+### npm
+
+```shell
+npm install angular-cookies
+```
+
+Then add `ngCookies` as a dependency for your app:
+
+```javascript
+angular.module('myApp', [require('angular-cookies')]);
+```
+
+### bower
+
+```shell
+bower install angular-cookies
+```
+
+Add a `<script>` to your `index.html`:
+
+```html
+<script src="/bower_components/angular-cookies/angular-cookies.js"></script>
+```
+
+Then add `ngCookies` as a dependency for your app:
+
+```javascript
+angular.module('myApp', ['ngCookies']);
+```
+
+## Documentation
+
+Documentation is available on the
+[AngularJS docs site](http://docs.angularjs.org/api/ngCookies).
+
+## License
+
+The MIT License
+
+Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/angular-cookies/angular-cookies.js b/afb-client/bower_components/angular-cookies/angular-cookies.js
new file mode 100644
index 0000000..d564aa2
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/angular-cookies.js
@@ -0,0 +1,207 @@
+/**
+ * @license AngularJS v1.3.20
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/**
+ * @ngdoc module
+ * @name ngCookies
+ * @description
+ *
+ * # ngCookies
+ *
+ * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
+ *
+ *
+ * <div doc-module-components="ngCookies"></div>
+ *
+ * See {@link ngCookies.$cookies `$cookies`} and
+ * {@link ngCookies.$cookieStore `$cookieStore`} for usage.
+ */
+
+
+angular.module('ngCookies', ['ng']).
+ /**
+ * @ngdoc service
+ * @name $cookies
+ *
+ * @description
+ * Provides read/write access to browser's cookies.
+ *
+ * Only a simple Object is exposed and by adding or removing properties to/from this object, new
+ * cookies are created/deleted at the end of current $eval.
+ * The object's properties can only be strings.
+ *
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
+ *
+ * @example
+ *
+ * ```js
+ * angular.module('cookiesExample', ['ngCookies'])
+ * .controller('ExampleController', ['$cookies', function($cookies) {
+ * // Retrieving a cookie
+ * var favoriteCookie = $cookies.myFavorite;
+ * // Setting a cookie
+ * $cookies.myFavorite = 'oatmeal';
+ * }]);
+ * ```
+ */
+ factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {
+ var cookies = {},
+ lastCookies = {},
+ lastBrowserCookies,
+ runEval = false,
+ copy = angular.copy,
+ isUndefined = angular.isUndefined;
+
+ //creates a poller fn that copies all cookies from the $browser to service & inits the service
+ $browser.addPollFn(function() {
+ var currentCookies = $browser.cookies();
+ if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
+ lastBrowserCookies = currentCookies;
+ copy(currentCookies, lastCookies);
+ copy(currentCookies, cookies);
+ if (runEval) $rootScope.$apply();
+ }
+ })();
+
+ runEval = true;
+
+ //at the end of each eval, push cookies
+ //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
+ // strings or browser refuses to store some cookies, we update the model in the push fn.
+ $rootScope.$watch(push);
+
+ return cookies;
+
+
+ /**
+ * Pushes all the cookies from the service to the browser and verifies if all cookies were
+ * stored.
+ */
+ function push() {
+ var name,
+ value,
+ browserCookies,
+ updated;
+
+ //delete any cookies deleted in $cookies
+ for (name in lastCookies) {
+ if (isUndefined(cookies[name])) {
+ $browser.cookies(name, undefined);
+ delete lastCookies[name];
+ }
+ }
+
+ //update all cookies updated in $cookies
+ for (name in cookies) {
+ value = cookies[name];
+ if (!angular.isString(value)) {
+ value = '' + value;
+ cookies[name] = value;
+ }
+ if (value !== lastCookies[name]) {
+ $browser.cookies(name, value);
+ lastCookies[name] = value;
+ updated = true;
+ }
+ }
+
+ //verify what was actually stored
+ if (updated) {
+ browserCookies = $browser.cookies();
+
+ for (name in cookies) {
+ if (cookies[name] !== browserCookies[name]) {
+ //delete or reset all cookies that the browser dropped from $cookies
+ if (isUndefined(browserCookies[name])) {
+ delete cookies[name];
+ delete lastCookies[name];
+ } else {
+ cookies[name] = lastCookies[name] = browserCookies[name];
+ }
+ }
+ }
+ }
+ }
+ }]).
+
+
+ /**
+ * @ngdoc service
+ * @name $cookieStore
+ * @requires $cookies
+ *
+ * @description
+ * Provides a key-value (string-object) storage, that is backed by session cookies.
+ * Objects put or retrieved from this storage are automatically serialized or
+ * deserialized by angular's toJson/fromJson.
+ *
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
+ *
+ * @example
+ *
+ * ```js
+ * angular.module('cookieStoreExample', ['ngCookies'])
+ * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
+ * // Put cookie
+ * $cookieStore.put('myFavorite','oatmeal');
+ * // Get cookie
+ * var favoriteCookie = $cookieStore.get('myFavorite');
+ * // Removing a cookie
+ * $cookieStore.remove('myFavorite');
+ * }]);
+ * ```
+ */
+ factory('$cookieStore', ['$cookies', function($cookies) {
+
+ return {
+ /**
+ * @ngdoc method
+ * @name $cookieStore#get
+ *
+ * @description
+ * Returns the value of given cookie key
+ *
+ * @param {string} key Id to use for lookup.
+ * @returns {Object} Deserialized cookie value.
+ */
+ get: function(key) {
+ var value = $cookies[key];
+ return value ? angular.fromJson(value) : value;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookieStore#put
+ *
+ * @description
+ * Sets a value for given cookie key
+ *
+ * @param {string} key Id for the `value`.
+ * @param {Object} value Value to be stored.
+ */
+ put: function(key, value) {
+ $cookies[key] = angular.toJson(value);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookieStore#remove
+ *
+ * @description
+ * Remove given cookie
+ *
+ * @param {string} key Id of the key-value pair to delete.
+ */
+ remove: function(key) {
+ delete $cookies[key];
+ }
+ };
+
+ }]);
+
+
+})(window, window.angular);
diff --git a/afb-client/bower_components/angular-cookies/angular-cookies.min.js b/afb-client/bower_components/angular-cookies/angular-cookies.min.js
new file mode 100644
index 0000000..f73736b
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/angular-cookies.min.js
@@ -0,0 +1,8 @@
+/*
+ AngularJS v1.3.20
+ (c) 2010-2014 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(p,g,n){'use strict';g.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},f={},h,k=!1,l=g.copy,m=g.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,f),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in f)m(c[a])&&(b.cookies(a,n),delete f[a]);for(a in c)d=c[a],g.isString(d)||(d=""+d,c[a]=d),d!==f[a]&&(b.cookies(a,d),f[a]=d,e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?(delete c[a],delete f[a]):c[a]=
+f[a]=d[a])});return c}]).factory("$cookieStore",["$cookies",function(e){return{get:function(b){return(b=e[b])?g.fromJson(b):b},put:function(b,c){e[b]=g.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular);
+//# sourceMappingURL=angular-cookies.min.js.map
diff --git a/afb-client/bower_components/angular-cookies/angular-cookies.min.js.map b/afb-client/bower_components/angular-cookies/angular-cookies.min.js.map
new file mode 100644
index 0000000..87491ad
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/angular-cookies.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-cookies.min.js",
+"lineCount":7,
+"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA0BW,UA1BX,CA0BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAQ,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACvEC,EAAU,EAD6D,CAEvEC,EAAc,EAFyD,CAGvEC,CAHuE,CAIvEC,EAAU,CAAA,CAJ6D,CAKvEC,EAAOV,CAAAU,KALgE,CAMvEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CACA,CAAA,OAAOM,CAAA,CAAYU,CAAZ,CAFT,CAOF,KAAKA,CAAL,GAAaX,EAAb,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CAEA,CADAX,CAAA,CAAYU,CAAZ,CACA,CADoBC,CACpB,CAAAC,CAAA,CAAU,CAAA,CAHZ,CAQF,IAAIA,CAAJ,CAGE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,EACE,OAAOX,CAAA,CAAQW,CAAR,CACP,CAAA,OAAOV,CAAA,CAAYU,CAAZ,CAFT,EAIEX,CAAA,CAAQW,CAAR,CAJF;AAIkBV,CAAA,CAAYU,CAAZ,CAJlB,CAIsCI,CAAA,CAAeJ,CAAf,CANxC,CAjCU,CAThB,CAEA,OAAOX,EA1BoE,CAA1D,CA1BvB,CAAAH,QAAA,CAqIW,cArIX,CAqI2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,CAWLC,IAAKA,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,CA0BLQ,IAAKA,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,CAuCLU,OAAQA,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CArI3B,CAnBsC,CAArC,CAAD,CAyMGzB,MAzMH,CAyMWA,MAAAC,QAzMX;",
+"sources":["angular-cookies.js"],
+"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"]
+}
diff --git a/afb-client/bower_components/angular-cookies/bower.json b/afb-client/bower_components/angular-cookies/bower.json
new file mode 100644
index 0000000..d4075a2
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/bower.json
@@ -0,0 +1,9 @@
+{
+ "name": "angular-cookies",
+ "version": "1.3.20",
+ "main": "./angular-cookies.js",
+ "ignore": [],
+ "dependencies": {
+ "angular": "1.3.20"
+ }
+}
diff --git a/afb-client/bower_components/angular-cookies/index.js b/afb-client/bower_components/angular-cookies/index.js
new file mode 100644
index 0000000..6576675
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/index.js
@@ -0,0 +1,2 @@
+require('./angular-cookies');
+module.exports = 'ngCookies';
diff --git a/afb-client/bower_components/angular-cookies/package.json b/afb-client/bower_components/angular-cookies/package.json
new file mode 100644
index 0000000..97e7420
--- /dev/null
+++ b/afb-client/bower_components/angular-cookies/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "angular-cookies",
+ "version": "1.3.20",
+ "description": "AngularJS module for cookies",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular/angular.js.git"
+ },
+ "keywords": [
+ "angular",
+ "framework",
+ "browser",
+ "cookies",
+ "client-side"
+ ],
+ "author": "Angular Core Team <angular-core+npm@google.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/angular/angular.js/issues"
+ },
+ "homepage": "http://angularjs.org"
+}
diff --git a/afb-client/bower_components/angular-ui-notification/.bower.json b/afb-client/bower_components/angular-ui-notification/.bower.json
new file mode 100644
index 0000000..5134bb2
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/.bower.json
@@ -0,0 +1,45 @@
+{
+ "name": "angular-ui-notification",
+ "version": "0.0.14",
+ "homepage": "https://github.com/alexcrack/angular-ui-notification",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/alexcrack/angular-ui-notification"
+ },
+ "authors": [
+ "Alexey Avramchik"
+ ],
+ "description": "Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating",
+ "main": [
+ "dist/angular-ui-notification.min.css",
+ "dist/angular-ui-notification.min.js"
+ ],
+ "keywords": [
+ "angular",
+ "notification",
+ "notify",
+ "bootstrap"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests",
+ "demo",
+ "build"
+ ],
+ "devDependencies": {
+ "bootstrap": "~3.3.2"
+ },
+ "_release": "0.0.14",
+ "_resolution": {
+ "type": "version",
+ "tag": "v0.0.14",
+ "commit": "bef09d9274cfc37030f065e452f259ddd2fd9c57"
+ },
+ "_source": "git://github.com/alexcrack/angular-ui-notification.git",
+ "_target": "~0.0.14",
+ "_originalSource": "angular-ui-notification"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-notification/LICENSE b/afb-client/bower_components/angular-ui-notification/LICENSE
new file mode 100644
index 0000000..678fd37
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Alexey Avramchik
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/afb-client/bower_components/angular-ui-notification/README.md b/afb-client/bower_components/angular-ui-notification/README.md
new file mode 100644
index 0000000..544b3a0
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/README.md
@@ -0,0 +1,174 @@
+angular-ui-notification
+=======================
+
+[![Dependency Status](https://david-dm.org/alexcrack/angular-ui-notification.png)](https://david-dm.org/alexcrack/angular-ui-notification)
+[![devDependency Status](https://david-dm.org/alexcrack/angular-ui-notification/dev-status.png)](https://david-dm.org/alexcrack/angular-ui-notification#info=devDependencies)
+[![Build Status](https://travis-ci.org/alexcrack/angular-ui-notification.svg?branch=master)](https://travis-ci.org/alexcrack/angular-ui-notification)
+[![Dependency Status](https://www.versioneye.com/user/projects/54f96af44f3108e7800000e4/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54f96af44f3108e7800000e4)
+[![Code Climate](https://codeclimate.com/github/alexcrack/angular-ui-notification/badges/gpa.svg)](https://codeclimate.com/github/alexcrack/angular-ui-notification)
+
+Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animations
+
+## Features
+* No dependencies except of angular.js.
+* CSS3 Animations.
+* Small size.
+* 5 message types.
+* Use HTML in your messages.
+* Configure options globally py the provider
+* Use custom options by the message
+* Use custom template
+
+## Install
+
+To install the package using bower and save as a dependency use...
+```bash
+bower install angular-ui-notification --save
+```
+
+## Usage
+ [Heres a plunker demo](http://plnkr.co/edit/5Gk8UVvzUsjyof7Gxsua?p=preview)
+
+
+In your html/template add
+```html
+...
+ <link rel="stylesheet" href="angular-ui-notification.min.css">
+...
+ <script src="angular-ui-notification.min.js"></script>
+...
+
+```
+
+In your application, declare dependency injection like so..
+
+```javascript
+ angular.module('notificationTest', ['ui-notification']);
+...
+```
+
+You can configure module by the provider
+```javascript
+angular.module('notificationTest', ['ui-notification'])
+ .config(function(NotificationProvider) {
+ NotificationProvider.setOptions({
+ delay: 10000,
+ startTop: 20,
+ startRight: 10,
+ verticalSpacing: 20,
+ horizontalSpacing: 20,
+ positionX: 'left',
+ positionY: 'bottom'
+ });
+ });
+...
+```
+
+
+And when you need to show notifications, inject service and call it!
+
+```javascript
+angular.module('notificationTest').controller('notificationController', function($scope, Notification) {
+
+ Notification.primary('Primary notification');
+ // or simply..
+ Notification('Primary notification');
+
+ // Other Options
+ // Success
+ Notification.success('Success notification');
+
+ // With Title
+ Notification({message: 'Primary notification', title: 'Primary notification'});
+
+ // Message with custom delay
+ Notification.error({message: 'Error notification 1s', delay: 1000});
+
+ // Embed HTML within your message.....
+ Notification.success({message: 'Success notification<br>Some other <b>content</b><br><a href="https://github.com/alexcrack/angular-ui-notification">This is a link</a><br><img src="https://angularjs.org/img/AngularJS-small.png">', title: 'Html content'});
+
+ // Change position notification
+ Notification.error({message: 'Error Bottom Right', positionY: 'bottom', positionX: 'right'});
+
+ // Replace message
+ Notification.error({message: 'Error notification 1s', replaceMessage: true});
+}
+```
+
+## Service
+
+Module name: "ui-notification"
+
+Service: "Notification"
+
+Configuration provider: "NotificationProvider"
+
+
+## Options
+
+Options can be passed to configuration provider globally or used in the current message.
+
+The options list:
+
+| Option | Possible values | Default value | Description |
+| ----------------- | ------------------------- | ------------------------------ | ------------------------------------------------------------------------ |
+| delay | Any integer value | 5000 | The time in ms the message is showing before start fading out |
+| startTop | Any integer value | 10 | Vertical padding between messages and vertical border of the browser |
+| startRight | Any integer value | 10 | Horizontal padding between messages and horizontal border of the browser |
+| verticalSpacing | Any integer value | 10 | Vertical spacing between messages |
+| horizontalSpacing | Any integer value | 10 | Horizontal spacing between messages |
+| positionX | "right", "left", "center" | "right" | Horizontal position of the message |
+| positionY | "top", "bottom" | "top" | Vertical position of the message |
+| replaceMessage | true, false | false | If true every next appearing message replace old messages |
+| templateUrl | Any string | "angular-ui-notification.html" | Custom template filename (URL) |
+
+Also you can pass the "scope" option. This is an angular scope option Notification scope will be inherited from. This option can be passed only in the methods. The default value is $rootScope
+
+## Methods
+
+#### Notification service methods
+
+| Method name | Description |
+|----------------------------------------|-------------------------------------------------|
+| Notification(), Notification.primary() | Show the message with bootstrap's primary class |
+| Notification.info() | Show the message with bootstrap's info class |
+| Notification.success() | Show the message with bootstrap's success class |
+| Notification.warning() | Show the message with bootstrap's warn class |
+| Notification.error() | Show the message with bootstrap's danger class |
+| Notification.clearAll() | Remove all shown messages |
+
+#### Notification service options
+
+| Option | Possible values | Default value | Description |
+| -------------- | ------------------------------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------ |
+| title | *String* | `""` | Title to appear at the top of the notification |
+| message | *String* | `""` | Message to appear in the notification |
+| templateUrl | *String* | `"angular-ui-notification.html"` | URL of template to be used for notification |
+| delay | *Int* (?) | `5000` or configured global delay | Number of ms before notification fades out. If not an integer, notification will persist until killed. |
+| type | "primary", "info", "success", "warning", "error" | `"primary"` | Bootstrap flavoring |
+| positionY | "top", "bottom" | `"top"` | |
+| positionX | "right", "left", "center" | `"right" | |
+| replaceMessage | *Boolean* | `false` | If true this message will replace old(er) message(s) |
+
+#### Returning value
+
+Every "show" method returns a promise resolves a notification scope with methods:
+
+| Method name | Description |
+|--------------------------------|------------------------------------------------------------------------------------------------------------------|
+| notificationScope.kill(isHard) | Remove the specific message<br>isHard - if false or omitted kill message with fadeout effect (default). If true - immediately remove the message|
+
+
+
+## Custom Templates
+
+Custom template can be provided.
+
+```html
+<div class="ui-notification">
+ <h3 ng-show="title" ng-bind-html="title"></h3>
+ <div class="message" ng-bind-html="message"></div>
+</div>
+```
+Default existing scope values is "title" - the title of the message and "message".
+Also any custom scope's properties can be used.
diff --git a/afb-client/bower_components/angular-ui-notification/bower.json b/afb-client/bower_components/angular-ui-notification/bower.json
new file mode 100644
index 0000000..8daf8fd
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/bower.json
@@ -0,0 +1,36 @@
+{
+ "name": "angular-ui-notification",
+ "version": "0.0.12",
+ "homepage": "https://github.com/alexcrack/angular-ui-notification",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/alexcrack/angular-ui-notification"
+ },
+ "authors": [
+ "Alexey Avramchik"
+ ],
+ "description": "Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating",
+ "main": [
+ "dist/angular-ui-notification.min.css",
+ "dist/angular-ui-notification.min.js"
+ ],
+ "keywords": [
+ "angular",
+ "notification",
+ "notify",
+ "bootstrap"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests",
+ "demo",
+ "build"
+ ],
+ "devDependencies": {
+ "bootstrap": "~3.3.2"
+ }
+}
diff --git a/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css b/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css
new file mode 100644
index 0000000..491ef93
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css
@@ -0,0 +1,8 @@
+/**
+ * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
+ * @author Alex_Crack
+ * @version v0.0.14
+ * @link https://github.com/alexcrack/angular-ui-notification
+ * @license MIT
+ */
+.ui-notification{position:fixed;z-index:9999;width:300px;cursor:pointer;-webkit-transition:all ease .5s;-o-transition:all ease .5s;transition:all ease .5s;color:#fff;background:#337ab7;box-shadow:5px 5px 10px rgba(0,0,0,.3)}.ui-notification.killed{-webkit-transition:opacity ease 1s;-o-transition:opacity ease 1s;transition:opacity ease 1s;opacity:0}.ui-notification>h3{font-size:14px;font-weight:700;display:block;margin:10px 10px 0;padding:0 0 5px;text-align:left;border-bottom:1px solid rgba(255,255,255,.3)}.ui-notification a{color:#fff}.ui-notification a:hover{text-decoration:underline}.ui-notification>.message{margin:10px}.ui-notification.warning{color:#fff;background:#f0ad4e}.ui-notification.error{color:#fff;background:#d9534f}.ui-notification.success{color:#fff;background:#5cb85c}.ui-notification.info{color:#fff;background:#5bc0de}.ui-notification:hover{opacity:.7} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.js b/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.js
new file mode 100644
index 0000000..e69118a
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/dist/angular-ui-notification.min.js
@@ -0,0 +1,8 @@
+/**
+ * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
+ * @author Alex_Crack
+ * @version v0.0.14
+ * @link https://github.com/alexcrack/angular-ui-notification
+ * @license MIT
+ */
+angular.module("ui-notification",[]),angular.module("ui-notification").provider("Notification",function(){this.options={delay:5e3,startTop:10,startRight:10,verticalSpacing:10,horizontalSpacing:10,positionX:"right",positionY:"top",replaceMessage:!1,templateUrl:"angular-ui-notification.html"},this.setOptions=function(t){if(!angular.isObject(t))throw new Error("Options should be an object!");this.options=angular.extend({},this.options,t)},this.$get=["$timeout","$http","$compile","$templateCache","$rootScope","$injector","$sce","$q","$window",function(t,e,i,n,o,s,a,r,l){var p=this.options,c=p.startTop,u=p.startRight,d=p.verticalSpacing,m=p.horizontalSpacing,g=p.delay,f=[],h=!1,v=function(s,v){var y=r.defer();return"object"!=typeof s&&(s={message:s}),s.scope=s.scope?s.scope:o,s.template=s.templateUrl?s.templateUrl:p.templateUrl,s.delay=angular.isUndefined(s.delay)?g:s.delay,s.type=v?v:"",s.positionY=s.positionY?s.positionY:p.positionY,s.positionX=s.positionX?s.positionX:p.positionX,s.replaceMessage=s.replaceMessage?s.replaceMessage:p.replaceMessage,e.get(s.template,{cache:n}).success(function(e){var n=s.scope.$new();n.message=a.trustAsHtml(s.message),n.title=a.trustAsHtml(s.title),n.t=s.type.substr(0,1),n.delay=s.delay;var o=function(){for(var t=0,e=0,i=c,n=u,o=[],a=f.length-1;a>=0;a--){var r=f[a];if(s.replaceMessage&&a<f.length-1)r.addClass("killed");else{var l=parseInt(r[0].offsetHeight),p=parseInt(r[0].offsetWidth),g=o[r._positionY+r._positionX];h+l>window.innerHeight&&(g=c,e++,t=0);var h=i=g?0===t?g:g+d:c,v=n+e*(m+p);r.css(r._positionY,h+"px"),"center"==r._positionX?r.css("left",parseInt(window.innerWidth/2-p/2)+"px"):r.css(r._positionX,v+"px"),o[r._positionY+r._positionX]=h+l,t++}}},r=i(e)(n);r._positionY=s.positionY,r._positionX=s.positionX,r.addClass(s.type),r.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd click",function(t){t=t.originalEvent||t,("click"===t.type||"opacity"===t.propertyName&&t.elapsedTime>=1)&&(r.remove(),f.splice(f.indexOf(r),1),o())}),angular.isNumber(s.delay)&&t(function(){r.addClass("killed")},s.delay),angular.element(document.getElementsByTagName("body")).append(r);var p=-(parseInt(r[0].offsetHeight)+50);r.css(r._positionY,p+"px"),f.push(r),n._templateElement=r,n.kill=function(e){e?(f.splice(f.indexOf(n._templateElement),1),n._templateElement.remove(),t(o)):n._templateElement.addClass("killed")},t(o),h||(angular.element(l).bind("resize",function(){t(o)}),h=!0),y.resolve(n)}).error(function(t){throw new Error("Template ("+s.template+") could not be loaded. "+t)}),y.promise};return v.primary=function(t){return this(t,"primary")},v.error=function(t){return this(t,"error")},v.success=function(t){return this(t,"success")},v.info=function(t){return this(t,"info")},v.warning=function(t){return this(t,"warning")},v.clearAll=function(){angular.forEach(f,function(t){t.addClass("killed")})},v}]}),angular.module("ui-notification").run(["$templateCache",function(t){t.put("angular-ui-notification.html",'<div class="ui-notification"><h3 ng-show="title" ng-bind-html="title"></h3><div class="message" ng-bind-html="message"></div></div>')}]); \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-notification/gulpfile.js b/afb-client/bower_components/angular-ui-notification/gulpfile.js
new file mode 100644
index 0000000..f7c7d59
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/gulpfile.js
@@ -0,0 +1,92 @@
+var gulp = require('gulp');
+var less = require('gulp-less');
+var minifyCSS = require('gulp-minify-css');
+var csscomb = require('gulp-csscomb');
+var ngAnnotate = require('gulp-ng-annotate');
+var uglify = require('gulp-uglify');
+var jshint = require('gulp-jshint');
+var rename = require('gulp-rename');
+var header = require('gulp-header');
+var templateCache = require('gulp-angular-templatecache');
+var minifyHtml = require("gulp-minify-html");
+var concat = require('gulp-concat');
+var addsrc = require('gulp-add-src');
+var order = require("gulp-order");
+var protractor = require("gulp-protractor").protractor;
+
+var pkg = require('./package.json');
+var banner = ['/**',
+ ' * <%= pkg.name %> - <%= pkg.description %>',
+ ' * @author <%= pkg.author %>',
+ ' * @version v<%= pkg.version %>',
+ ' * @link <%= pkg.homepage %>',
+ ' * @license <%= pkg.license %>',
+ ' */',
+ ''].join('\n');
+
+ // ==== Styles
+gulp.task('styles', function() {
+ gulp.src('src/angular-ui-notification.less')
+ .pipe(less({
+ strictMath: true
+ }))
+ .pipe(csscomb())
+ .pipe(minifyCSS())
+ .pipe(rename({
+ suffix: '.min'
+ }))
+ .pipe(header(banner, { pkg : pkg }))
+ .pipe(gulp.dest('dist'))
+ .pipe(gulp.dest('demo'));
+});
+
+// ====== Templates
+gulp.task('templates', function() {
+ gulp.src(['*.html'], {cwd: 'src'})
+ .pipe(minifyHtml({
+ empty: true,
+ spare: true,
+ quotes: true
+ }))
+ .pipe(templateCache({
+ module: 'ui-notification',
+ }))
+ .pipe(rename('angular-ui-notification.templates.js'))
+ .pipe(gulp.dest("build"));
+});
+
+gulp.task('service', function() {
+ gulp.src(['src/*.js'])
+ .pipe(jshint())
+ .pipe(jshint.reporter('default'))
+ .pipe(jshint.reporter('fail'))
+ .pipe(ngAnnotate())
+ .pipe(addsrc('build/*.js'))
+ .pipe(order([
+ 'src/*.js',
+ 'build/angular-ui-notification.templates.js'
+ ]))
+ .pipe(concat('angular-ui-notification.js'))
+ .pipe(uglify())
+ .pipe(rename({
+ suffix: '.min'
+ }))
+ .pipe(header(banner, { pkg : pkg }))
+ .pipe(gulp.dest('dist'))
+ .pipe(gulp.dest('demo'));
+});
+
+// ======
+gulp.task('e2eTest', function() {
+ gulp.src(['./test/**/*_spec.js'])
+ .pipe(protractor({
+ configFile: "protractor_conf.js",
+ }))
+ .on('error', function(e) {throw e});
+});
+
+gulp.task('tests', ['e2eTest']);
+gulp.task('build', ['templates', 'service', 'styles']);
+gulp.task('deploy', ['build', 'tests']);
+
+gulp.task('default', ['deploy'], function() {}); \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-notification/package.json b/afb-client/bower_components/angular-ui-notification/package.json
new file mode 100644
index 0000000..68f5905
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "angular-ui-notification",
+ "version": "0.0.14",
+ "description": "Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating",
+ "main": "dist/angular-ui-notification.min",
+ "scripts": {
+ "update-chromedriver": "./node_modules/protractor/bin/webdriver-manager update",
+ "test": "gulp tests"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/alexcrack/angular-ui-notification.git"
+ },
+ "keywords": [
+ "angular",
+ "notification",
+ "notify",
+ "bootstrap"
+ ],
+ "author": "Alex_Crack",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/alexcrack/angular-ui-notification/issues"
+ },
+ "homepage": "https://github.com/alexcrack/angular-ui-notification",
+ "devDependencies": {
+ "chromedriver": "^2.14.1",
+ "gulp": "^3.8.11",
+ "gulp-add-src": "^0.2.0",
+ "gulp-angular-templatecache": "^1.5.0",
+ "gulp-concat": "^2.5.2",
+ "gulp-csscomb": "^3.0.3",
+ "gulp-header": "^1.2.2",
+ "gulp-jshint": "^1.9.2",
+ "gulp-less": "^3.0.1",
+ "gulp-minify-css": "^0.5.1",
+ "gulp-minify-html": "^1.0.0",
+ "gulp-ng-annotate": "^0.5.2",
+ "gulp-order": "^1.1.1",
+ "gulp-protractor": "0.0.12",
+ "gulp-rename": "^1.2.0",
+ "gulp-uglify": "^1.1.0",
+ "protractor": "^1.8.0"
+ }
+}
diff --git a/afb-client/bower_components/angular-ui-notification/protractor_conf.js b/afb-client/bower_components/angular-ui-notification/protractor_conf.js
new file mode 100644
index 0000000..5ceda91
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/protractor_conf.js
@@ -0,0 +1,24 @@
+// An example configuration file.
+exports.config = {
+ allScriptsTimeout: 99999,
+ // Do not start a Selenium Standalone sever - only run this using chrome.
+ directConnect: true,
+ //chromeDriver: './node_modules/protractor/selenium/chromedriver',
+
+ seleniumArgs: ['-browserTimeout=60'],
+
+ // Capabilities to be passed to the webdriver instance.
+ capabilities: {
+ 'browserName': 'firefox'
+ },
+
+ // Spec patterns are relative to the current working directly when
+ // protractor is called.
+ specs: ['test/e2e/**/*.spec.js'],
+
+ // Options to be passed to Jasmine-node.
+ jasmineNodeOpts: {
+ showColors: true,
+ defaultTimeoutInterval: 30000,
+ }
+};
diff --git a/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.html b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.html
new file mode 100644
index 0000000..5f628fc
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.html
@@ -0,0 +1,4 @@
+<div class="ui-notification">
+ <h3 ng-show="title" ng-bind-html="title"></h3>
+ <div class="message" ng-bind-html="message"></div>
+</div> \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.js b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.js
new file mode 100644
index 0000000..e94fa2c
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.js
@@ -0,0 +1,172 @@
+angular.module('ui-notification',[]);
+
+angular.module('ui-notification').provider('Notification', function() {
+
+ this.options = {
+ delay: 5000,
+ startTop: 10,
+ startRight: 10,
+ verticalSpacing: 10,
+ horizontalSpacing: 10,
+ positionX: 'right',
+ positionY: 'top',
+ replaceMessage: false,
+ templateUrl: 'angular-ui-notification.html'
+ };
+
+ this.setOptions = function(options) {
+ if (!angular.isObject(options)) throw new Error("Options should be an object!");
+ this.options = angular.extend({}, this.options, options);
+ };
+
+ this.$get = function($timeout, $http, $compile, $templateCache, $rootScope, $injector, $sce, $q, $window) {
+ var options = this.options;
+
+ var startTop = options.startTop;
+ var startRight = options.startRight;
+ var verticalSpacing = options.verticalSpacing;
+ var horizontalSpacing = options.horizontalSpacing;
+ var delay = options.delay;
+
+ var messageElements = [];
+ var isResizeBound = false;
+
+ var notify = function(args, t){
+ var deferred = $q.defer();
+
+ if (typeof args !== 'object') {
+ args = {message:args};
+ }
+
+ args.scope = args.scope ? args.scope : $rootScope;
+ args.template = args.templateUrl ? args.templateUrl : options.templateUrl;
+ args.delay = !angular.isUndefined(args.delay) ? args.delay : delay;
+ args.type = t ? t : '';
+ args.positionY = args.positionY ? args.positionY : options.positionY;
+ args.positionX = args.positionX ? args.positionX : options.positionX;
+ args.replaceMessage = args.replaceMessage ? args.replaceMessage : options.replaceMessage;
+
+ $http.get(args.template,{cache: $templateCache}).success(function(template) {
+
+ var scope = args.scope.$new();
+ scope.message = $sce.trustAsHtml(args.message);
+ scope.title = $sce.trustAsHtml(args.title);
+ scope.t = args.type.substr(0,1);
+ scope.delay = args.delay;
+
+ var reposite = function() {
+ var j = 0;
+ var k = 0;
+ var lastTop = startTop;
+ var lastRight = startRight;
+ var lastPosition = [];
+ for(var i = messageElements.length - 1; i >= 0; i --) {
+ var element = messageElements[i];
+ if (args.replaceMessage && i < messageElements.length - 1) {
+ element.addClass('killed');
+ continue;
+ }
+ var elHeight = parseInt(element[0].offsetHeight);
+ var elWidth = parseInt(element[0].offsetWidth);
+ var position = lastPosition[element._positionY+element._positionX];
+
+ if ((top + elHeight) > window.innerHeight) {
+ position = startTop;
+ k ++;
+ j = 0;
+ }
+
+ var top = (lastTop = position ? (j === 0 ? position : position + verticalSpacing) : startTop);
+ var right = lastRight + (k * (horizontalSpacing + elWidth));
+
+ element.css(element._positionY, top + 'px');
+ if (element._positionX == 'center') {
+ element.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
+ } else {
+ element.css(element._positionX, right + 'px');
+ }
+
+ lastPosition[element._positionY+element._positionX] = top + elHeight;
+
+ j ++;
+ }
+ };
+
+ var templateElement = $compile(template)(scope);
+ templateElement._positionY = args.positionY;
+ templateElement._positionX = args.positionX;
+ templateElement.addClass(args.type);
+ templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd click', function(e){
+ e = e.originalEvent || e;
+ if (e.type === 'click' || (e.propertyName === 'opacity' && e.elapsedTime >= 1)){
+ templateElement.remove();
+ messageElements.splice(messageElements.indexOf(templateElement), 1);
+ reposite();
+ }
+ });
+ if (angular.isNumber(args.delay)) {
+ $timeout(function() {
+ templateElement.addClass('killed');
+ }, args.delay);
+ }
+
+ angular.element(document.getElementsByTagName('body')).append(templateElement);
+ var offset = -(parseInt(templateElement[0].offsetHeight) + 50);
+ templateElement.css(templateElement._positionY, offset + "px");
+ messageElements.push(templateElement);
+
+ scope._templateElement = templateElement;
+
+ scope.kill = function(isHard) {
+ if (isHard) {
+ messageElements.splice(messageElements.indexOf(scope._templateElement), 1);
+ scope._templateElement.remove();
+ $timeout(reposite);
+ } else {
+ scope._templateElement.addClass('killed');
+ }
+ };
+
+ $timeout(reposite);
+
+ if (!isResizeBound) {
+ angular.element($window).bind('resize', function(e) {
+ $timeout(reposite);
+ });
+ isResizeBound = true;
+ }
+
+ deferred.resolve(scope);
+
+ }).error(function(data){
+ throw new Error('Template ('+args.template+') could not be loaded. ' + data);
+ });
+
+ return deferred.promise;
+ };
+
+ notify.primary = function(args) {
+ return this(args, 'primary');
+ };
+ notify.error = function(args) {
+ return this(args, 'error');
+ };
+ notify.success = function(args) {
+ return this(args, 'success');
+ };
+ notify.info = function(args) {
+ return this(args, 'info');
+ };
+ notify.warning = function(args) {
+ return this(args, 'warning');
+ };
+
+ notify.clearAll = function() {
+ angular.forEach(messageElements, function(element) {
+ element.addClass('killed');
+ });
+ };
+
+ return notify;
+ };
+});
diff --git a/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.less b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.less
new file mode 100644
index 0000000..5b66b01
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-notification/src/angular-ui-notification.less
@@ -0,0 +1,55 @@
+@import "../bower_components/bootstrap/less/variables.less";
+@import "../bower_components/bootstrap/less/mixins.less";
+
+
+.ui-notification {
+ position: fixed;
+ z-index: 9999;
+ box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3);
+ cursor: pointer;
+ width: 300px;
+ color: @btn-primary-color;
+ background: @brand-primary;
+ .transition(all ease 0.5s);
+ &.killed {
+ opacity: 0;
+ .transition(opacity ease 1s);
+ }
+ & > h3 {
+ display: block;
+ margin: 10px 10px 0 10px;
+ padding: 0 0 5px 0;
+ text-align: left;
+ font-size: @font-size-base;
+ font-weight: bold;
+ border-bottom: 1px solid fadeout(@btn-primary-color, 70%);
+ }
+ & a {
+ color: @btn-primary-color;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ & > .message {
+ margin: 10px 10px 10px 10px;
+ }
+ &.warning {
+ color: @btn-warning-color;
+ background: @brand-warning;
+ }
+ &.error {
+ color: @btn-danger-color;
+ background: @brand-danger;
+ }
+ &.success {
+ color: @btn-success-color;
+ background: @brand-success;
+ }
+ &.info {
+ color: @btn-info-color;
+ background: @brand-info;
+ }
+ &:hover {
+ opacity: 0.7;
+ }
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-router/.bower.json b/afb-client/bower_components/angular-ui-router/.bower.json
new file mode 100644
index 0000000..7b4d748
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/.bower.json
@@ -0,0 +1,34 @@
+{
+ "name": "angular-ui-router",
+ "version": "0.2.18",
+ "license": "MIT",
+ "main": "./release/angular-ui-router.js",
+ "dependencies": {
+ "angular": "^1.0.8"
+ },
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "component.json",
+ "package.json",
+ "lib",
+ "config",
+ "sample",
+ "test",
+ "tests",
+ "ngdoc_assets",
+ "Gruntfile.js",
+ "files.js"
+ ],
+ "homepage": "https://github.com/angular-ui/ui-router",
+ "_release": "0.2.18",
+ "_resolution": {
+ "type": "version",
+ "tag": "0.2.18",
+ "commit": "ec6ca36b625e578e59e631b3c9e786a6ac70678c"
+ },
+ "_source": "git://github.com/angular-ui/ui-router.git",
+ "_target": "~0.2.12",
+ "_originalSource": "angular-ui-router"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-router/CHANGELOG.md b/afb-client/bower_components/angular-ui-router/CHANGELOG.md
new file mode 100644
index 0000000..060b4bf
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/CHANGELOG.md
@@ -0,0 +1,316 @@
+<a name="0.2.18"></a>
+### 0.2.18 (2016-02-07)
+
+This is a maintenance release which fixes a few known bugs introduced in 0.2.16.
+
+#### Bug Fixes
+
+* **$urlRouter:** revert BC: resolve clashing of routes This reverts commit b5c57c8ec2e14e17e75104 ([2f1ebefc](https://github.com/angular-ui/ui-router/commit/2f1ebefc242ff48960e0bf63da359296a38f6852), closes [#2501](https://github.com/angular-ui/ui-router/issues/2501))
+* **uiState:** Corrected typo for 'ref' variable (#2488, #2508) ([b8f3c144](https://github.com/angular-ui/ui-router/commit/b8f3c144b913e620f177b78f3b4f52afa61d41a6))
+* **$urlMatcherFactory:** Fix to make the YUI Javascript compressor work ([ad9c41d2](https://github.com/angular-ui/ui-router/commit/ad9c41d2e723d50e30dd3452fbd274b7057dc3d9))
+* **stateBuilder:** fix non-url params on a state without a url. The parameters are now applied when ([d6d8c332](https://github.com/angular-ui/ui-router/commit/d6d8c3322c4dde8bb5b8dde25f9fcda49e9c4c81), closes [#2025](https://github.com/angular-ui/ui-router/issues/2025))
+* **ui-view:** (ui-view) use static renderer when no animation is present for a ui-view ([2523bbdb](https://github.com/angular-ui/ui-router/commit/2523bbdb5542483a489c22804f1751b8b9f71703), closes [#2485](https://github.com/angular-ui/ui-router/issues/2485)). This allows a ui-view scope to be destroyed when switching states, before the next view is initialized.
+
+
+#### Features
+
+* **ui-view:** Add noanimation attribute to specify static renderer. ([2523bbdb](https://github.com/angular-ui/ui-router/commit/2523bbdb5542483a489c22804f1751b8b9f71703), closes [#2485](https://github.com/angular-ui/ui-router/issues/2485)). This allows a ui-view scope to be destroyed before the next ui-view is initialized, when ui-view animation is not present.
+
+
+<a name="0.2.17"></a>
+### 0.2.17 (2016-01-25)
+
+
+#### Bug Fixes
+
+* **uiSrefActive:** allow multiple classes ([a89114a0](https://github.com/angular-ui/ui-router/commit/a89114a083813c1a7280c48fc18e626caa5a31f4), closes [#2481](https://github.com/angular-ui/ui-router/issues/2481), [#2482](https://github.com/angular-ui/ui-router/issues/2482))
+
+
+<a name="0.2.16"></a>
+### 0.2.16 (2016-01-24)
+
+
+#### Bug Fixes
+
+* **$state:**
+ * statechangeCancel: Avoid infinite digest in .otherwise/redirect case. Don't clobber url if a new transition has started. Closes #222 ([e00aa695](https://github.com/angular-ui/ui-router/commit/e00aa695e41ddc5ebd5d2b226aa0917a751b11aa), closes [#2238](https://github.com/angular-ui/ui-router/issues/2238))
+ * transitionTo: Allow hash (#) value to be read as toParams['#'] in events. Re-add the saved hash before broadcasting $stateChangeStart event. ([8c1bf30d](https://github.com/angular-ui/ui-router/commit/8c1bf30d2a3b78ba40b330f12d854c885d6cc117))
+* **$stateParams:** Fix for testing: reset service instance between tests ([2aeb0c4b](https://github.com/angular-ui/ui-router/commit/2aeb0c4b205baf6cfa2ef25bb986bb160dc13bf9))
+* **$urlRouter:**
+ * Sort URL rules by specificity. Potential minor BC if apps were relying on rule registration order. ([b5c57c8e](https://github.com/angular-ui/ui-router/commit/b5c57c8ec2e14e17e75104c1424654f126ea4011))
+ * Use $sniffer for pushstate compat check ([c219e801](https://github.com/angular-ui/ui-router/commit/c219e801797f340ef9c5c919ab890ef003a7a042))
+* **UrlMatcher:**
+ * Properly encode/decode slashes in parameters Closes #2172 Closes #2250 Closes #1 ([02e98660](https://github.com/angular-ui/ui-router/commit/02e98660a80dfd1ca4b113dd24ee304af91e9f8c), closes [#2339](https://github.com/angular-ui/ui-router/issues/2339))
+ * Array types: Fix default value for array query parameters. Pass empty arrays through in handler. ([20d6e243](https://github.com/angular-ui/ui-router/commit/20d6e243f1745ddbf257217245a1dc22eabe13da), closes [#2222](https://github.com/angular-ui/ui-router/issues/2222))
+ * Remove trailing slash, if parameter is optional and was squashed from URL ([77fa11bf](https://github.com/angular-ui/ui-router/commit/77fa11bf0787d0f6da97ab0003ab29afb7411391), closes [#1902](https://github.com/angular-ui/ui-router/issues/1902))
+ * Allow a parameter declaration to configure the parameter type by name. closes #2294 ([e4010249](https://github.com/angular-ui/ui-router/commit/e40102492d40fe1cf6ba14d955fcc9f345c16458))
+ * include the slash when recognizing squashed params in url ([b5130bb1](https://github.com/angular-ui/ui-router/commit/b5130bb1215e15f832ea6daa670410b9a950c0d4), closes [#2064](https://github.com/angular-ui/ui-router/issues/2064))
+ * Allow url query param names to contain periods ([d31b3337](https://github.com/angular-ui/ui-router/commit/d31b3337cc2ce71d87c92fdded629e46558d0b49))
+* **reloadOnSearch:** Update `locals.globals.$stateParams` when reloadOnSearch=false ([350d3e87](https://github.com/angular-ui/ui-router/commit/350d3e87783a2263fd7d23913da34f1268c3300b), closes [#2356](https://github.com/angular-ui/ui-router/issues/2356))
+* **ui-view:**
+ * fix $animate usage for ng 1.4+ ([9b6d9a2d](https://github.com/angular-ui/ui-router/commit/9b6d9a2d0ce4ae08384165cb517bddea59b67892))
+ * change $viewContentLoading to pair with $viewContentLoaded ([f9b43d66](https://github.com/angular-ui/ui-router/commit/f9b43d66833f0e17de41fd8d1cc3b491e3ba4a0e), closes [#685](https://github.com/angular-ui/ui-router/issues/685))
+ * $destroy event is triggered before animation ends ([1be13795](https://github.com/angular-ui/ui-router/commit/1be13795686ab78abb2d5094bc8addcacb928975))
+* **uiSref:**
+ * Ensure URL once param checks pass ([9dc31c54](https://github.com/angular-ui/ui-router/commit/9dc31c5465328e5666468b0c2319ce205f4b72f8), closes [#2091](https://github.com/angular-ui/ui-router/issues/2091))
+ * uiSrefActive: update the active classes after linking directive ([7c914030](https://github.com/angular-ui/ui-router/commit/7c914030f13e05e45a941c1b723cb785db729890))
+
+
+#### Features
+
+* **$IncludedByStateFilter:** add parameters to $IncludedByStateFilter ([963f6e71](https://github.com/angular-ui/ui-router/commit/963f6e71633b9c3a266f3991d79089b7d14786b4), closes [#1735](https://github.com/angular-ui/ui-router/issues/1735))
+* **isStateFilter:** Include optional state params. ([71d74699](https://github.com/angular-ui/ui-router/commit/71d7469987ee9ca86a41c8c6393ccd5d8913c3d6))
+* **$state:** make state data inheritance prototypical ([c4fec8c7](https://github.com/angular-ui/ui-router/commit/c4fec8c7998113902af4152d716c42dada6eb465))
+* **$stateChangeStart:** Add options to event ([a1f07559](https://github.com/angular-ui/ui-router/commit/a1f07559ec74e10ff80bc4be81f287e3772b8fcb))
+* **UrlMatcher:** Add param only type names ([6a371f9b](https://github.com/angular-ui/ui-router/commit/6a371f9b70e37a82eb324122879e4473c3f6d526))
+* **uiSrefActive:**
+ * provide a ng-{class,style} like interface ([a9ff6feb](https://github.com/angular-ui/ui-router/commit/a9ff6febb469e0d5cd49054216c4472df7a6259d))
+ * allow active & active-eq on same element ([d9a676ba](https://github.com/angular-ui/ui-router/commit/d9a676ba2c4d9e954be224c60496bcb38f6074e3))
+* **uiState:** add ui-state directive ([3831af1d](https://github.com/angular-ui/ui-router/commit/3831af1dc71b601351e6694af0665a77297f8f7f), closes [#395](https://github.com/angular-ui/ui-router/issues/395), [#900](https://github.com/angular-ui/ui-router/issues/900), [#1932](https://github.com/angular-ui/ui-router/issues/1932))
+* **urlMatcher:** add support for optional spaces in params ([4b7f3046](https://github.com/angular-ui/ui-router/commit/4b7f304617f0b3590b532103b5c2fb526c98a9e4))
+
+
+<a name="0.2.15"></a>
+### 0.2.15 (2015-05-19)
+
+
+#### Bug Fixes
+
+* **$state:** reloadOnSearch should not affect non-search param changes. ([6ca0d770](https://github.com/angular-ui/ui-router/commit/6ca0d7704cf7de9c6e6b7bb64df2f9c68fe081cc), closes [#1079](https://github.com/angular-ui/ui-router/issues/1079))
+* **urlMatcherFactory:** Revert to 0.2.13 behavior where all string parameters are considered optional fi ([495a02c3](https://github.com/angular-ui/ui-router/commit/495a02c3cbde501c1c149bce137806669209bc29), closes [#1963](https://github.com/angular-ui/ui-router/issues/1963))
+* **urlRouter:** allow .when() to redirect, even after a successful $state.go() - This partially ([48aeaff6](https://github.com/angular-ui/ui-router/commit/48aeaff645baf3f42f5a8940ebd97563791ad9f8), closes [#1584](https://github.com/angular-ui/ui-router/issues/1584))
+
+
+#### Features
+
+* **$state:** Inject templateProvider with resolved values ([afa20f22](https://github.com/angular-ui/ui-router/commit/afa20f22373b7176b26daa7e1099750c4254a354))
+
+
+<a name="0.2.14"></a>
+### 0.2.14 (2015-04-23)
+
+
+#### Bug Fixes
+
+* **$StateRefDirective:** resolve missing support for svg anchor elements #1667 ([0149a7bb](https://github.com/angular-ui/ui-router/commit/0149a7bb38b7af99388a1ad7cc9909a7b7c4439d))
+* **$urlMatcherFactory:**
+ * regex params should respect case-sensitivity ([1e10519f](https://github.com/angular-ui/ui-router/commit/1e10519f3be6bbf0cefdcce623cd2ade06e649e5), closes [#1671](https://github.com/angular-ui/ui-router/issues/1671))
+ * unquote all dashes from array params ([06664d33](https://github.com/angular-ui/ui-router/commit/06664d330f882390655dcfa83e10276110d0d0fa))
+ * add Type.$normalize function ([b0c6aa23](https://github.com/angular-ui/ui-router/commit/b0c6aa2350fdd3ce8483144774adc12f5a72b7e9))
+ * make optional params regex grouping optional ([06f73794](https://github.com/angular-ui/ui-router/commit/06f737945e83e668d09cfc3bcffd04a500ff1963), closes [#1576](https://github.com/angular-ui/ui-router/issues/1576))
+* **$state:** allow about.*.** glob patterns ([e39b27a2](https://github.com/angular-ui/ui-router/commit/e39b27a2cb7d88525c446a041f9fbf1553202010))
+* **uiSref:**
+ * use Object's toString instead of Window's toString ([2aa7f4d1](https://github.com/angular-ui/ui-router/commit/2aa7f4d139dbd5b9fcc4afdcf2ab6642c87f5671))
+ * add absolute to allowed transition options ([ae1b3c4e](https://github.com/angular-ui/ui-router/commit/ae1b3c4eedc37983400d830895afb50457c63af4))
+* **uiSrefActive:** Apply active classes on lazy loaded states ([f0ddbe7b](https://github.com/angular-ui/ui-router/commit/f0ddbe7b4a91daf279c3b7d0cee732bb1f3be5b4))
+* **uiView:** add `$element` to locals for view controller ([db68914c](https://github.com/angular-ui/ui-router/commit/db68914cd6c821e7dec8155bd33142a3a97f5453))
+
+
+#### Features
+
+* **$state:**
+ * support URLs with #fragments ([3da0a170](https://github.com/angular-ui/ui-router/commit/3da0a17069e27598c0f9d9164e104dd5ce05cdc6))
+ * inject resolve params into controllerProvider ([b380c223](https://github.com/angular-ui/ui-router/commit/b380c223fe12e2fde7582c0d6b1ed7b15a23579b), closes [#1131](https://github.com/angular-ui/ui-router/issues/1131))
+ * added 'state' to state reload method (feat no.1612) - modiefied options.reload ([b8f04575](https://github.com/angular-ui/ui-router/commit/b8f04575a8557035c1858c4d5c8dbde3e1855aaa))
+ * broadcast $stateChangeCancel event when event.preventDefault() is called in $sta ([ecefb758](https://github.com/angular-ui/ui-router/commit/ecefb758cb445e41620b62a272aafa3638613d7a))
+* **$uiViewScroll:** change function to return promise ([c2a9a311](https://github.com/angular-ui/ui-router/commit/c2a9a311388bb212e5a2e820536d1d739f829ccd), closes [#1702](https://github.com/angular-ui/ui-router/issues/1702))
+* **uiSrefActive:** Added support for multiple nested uiSref directives ([b1844948](https://github.com/angular-ui/ui-router/commit/b18449481d152b50705abfce2493a444eb059fa5))
+
+
+<a name="0.2.13"></a>
+### 0.2.13 (2014-11-20)
+
+This release primarily fixes issues reported against 0.2.12
+
+#### Bug Fixes
+
+* **$state:** fix $state.includes/.is to apply param types before comparisions fix(uiSref): ma ([19715d15](https://github.com/angular-ui/ui-router/commit/19715d15e3cbfff724519e9febedd05b49c75baa), closes [#1513](https://github.com/angular-ui/ui-router/issues/1513))
+ * Avoid re-synchronizing from url after .transitionTo ([b267ecd3](https://github.com/angular-ui/ui-router/commit/b267ecd348e5c415233573ef95ebdbd051875f52), closes [#1573](https://github.com/angular-ui/ui-router/issues/1573))
+* **$urlMatcherFactory:**
+ * Built-in date type uses local time zone ([d726bedc](https://github.com/angular-ui/ui-router/commit/d726bedcbb5f70a5660addf43fd52ec730790293))
+ * make date type fn check .is before running ([aa94ce3b](https://github.com/angular-ui/ui-router/commit/aa94ce3b86632ad05301530a2213099da73a3dc0), closes [#1564](https://github.com/angular-ui/ui-router/issues/1564))
+ * early binding of array handler bypasses type resolution ([ada4bc27](https://github.com/angular-ui/ui-router/commit/ada4bc27df5eff3ba3ab0de94a09bd91b0f7a28c))
+ * add 'any' Type for non-encoding non-url params ([3bfd75ab](https://github.com/angular-ui/ui-router/commit/3bfd75ab445ee2f1dd55275465059ed116b10b27), closes [#1562](https://github.com/angular-ui/ui-router/issues/1562))
+ * fix encoding slashes in params ([0c983a08](https://github.com/angular-ui/ui-router/commit/0c983a08e2947f999683571477debd73038e95cf), closes [#1119](https://github.com/angular-ui/ui-router/issues/1119))
+ * fix mixed path/query params ordering problem ([a479fbd0](https://github.com/angular-ui/ui-router/commit/a479fbd0b8eb393a94320973e5b9a62d83912ee2), closes [#1543](https://github.com/angular-ui/ui-router/issues/1543))
+* **ArrayType:**
+ * specify empty array mapping corner case ([74aa6091](https://github.com/angular-ui/ui-router/commit/74aa60917e996b0b4e27bbb4eb88c3c03832021d), closes [#1511](https://github.com/angular-ui/ui-router/issues/1511))
+ * fix .equals for array types ([5e6783b7](https://github.com/angular-ui/ui-router/commit/5e6783b77af9a90ddff154f990b43dbb17eeda6e), closes [#1538](https://github.com/angular-ui/ui-router/issues/1538))
+* **Param:** fix default value shorthand declaration ([831d812a](https://github.com/angular-ui/ui-router/commit/831d812a524524c71f0ee1c9afaf0487a5a66230), closes [#1554](https://github.com/angular-ui/ui-router/issues/1554))
+* **common:** fixed the _.filter clone to not create sparse arrays ([750f5cf5](https://github.com/angular-ui/ui-router/commit/750f5cf5fd91f9ada96f39e50d39aceb2caf22b6), closes [#1563](https://github.com/angular-ui/ui-router/issues/1563))
+* **ie8:** fix calls to indexOf and filter ([dcb31b84](https://github.com/angular-ui/ui-router/commit/dcb31b843391b3e61dee4de13f368c109541813e), closes [#1556](https://github.com/angular-ui/ui-router/issues/1556))
+
+
+#### Features
+
+* add json parameter Type ([027f1fcf](https://github.com/angular-ui/ui-router/commit/027f1fcf9c0916cea651e88981345da6f9ff214a))
+
+
+<a name="0.2.12"></a>
+### 0.2.12 (2014-11-13)
+
+#### Bug Fixes
+
+* **$resolve:** use resolve fn result, not parent resolved value of same name ([67f5e00c](https://github.com/angular-ui/ui-router/commit/67f5e00cc9aa006ce3fe6cde9dff261c28eab70a), closes [#1317], [#1353])
+* **$state:**
+ * populate default params in .transitionTo. ([3f60fbe6](https://github.com/angular-ui/ui-router/commit/3f60fbe6d65ebeca8d97952c05aa1d269f1b7ba1), closes [#1396])
+ * reload() now reinvokes controllers ([73443420](https://github.com/angular-ui/ui-router/commit/7344342018847902594dc1fc62d30a5c30f01763), closes [#582])
+ * do not emit $viewContentLoading if notify: false ([74255feb](https://github.com/angular-ui/ui-router/commit/74255febdf48ae082a02ca1e735165f2c369a463), closes [#1387](https://github.com/angular-ui/ui-router/issues/1387))
+ * register states at config-time ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a))
+ * handle parent.name when parent is obj ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a))
+* **$urlMatcherFactory:**
+ * register types at config ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a), closes [#1476])
+ * made path params default value "" for backwards compat ([8f998e71](https://github.com/angular-ui/ui-router/commit/8f998e71e43a0b31293331c981f5db0f0097b8ba))
+ * Pre-replace certain param values for better mapping ([6374a3e2](https://github.com/angular-ui/ui-router/commit/6374a3e29ab932014a7c77d2e1ab884cc841a2e3))
+ * fixed ParamSet.$$keys() ordering ([9136fecb](https://github.com/angular-ui/ui-router/commit/9136fecbc2bfd4fda748a9914f0225a46c933860))
+ * empty string policy now respected in Param.value() ([db12c85c](https://github.com/angular-ui/ui-router/commit/db12c85c16f2d105415f9bbbdeb11863f64728e0))
+ * "string" type now encodes/decodes slashes ([3045e415](https://github.com/angular-ui/ui-router/commit/3045e41577a8b8b8afc6039f42adddf5f3c061ec), closes [#1119])
+ * allow arrays in both path and query params ([fdd2f2c1](https://github.com/angular-ui/ui-router/commit/fdd2f2c191c4a67c874fdb9ec9a34f8dde9ad180), closes [#1073], [#1045], [#1486], [#1394])
+ * typed params in search ([8d4cab69](https://github.com/angular-ui/ui-router/commit/8d4cab69dd67058e1a716892cc37b7d80a57037f), closes [#1488](https://github.com/angular-ui/ui-router/issues/1488))
+ * no longer generate unroutable urls ([cb9fd9d8](https://github.com/angular-ui/ui-router/commit/cb9fd9d8943cb26c7223f6990db29c82ae8740f8), closes [#1487](https://github.com/angular-ui/ui-router/issues/1487))
+ * handle optional parameter followed by required parameter in url format. ([efc72106](https://github.com/angular-ui/ui-router/commit/efc72106ddcc4774b48ea176a505ef9e95193b41))
+ * default to parameter string coersion. ([13a468a7](https://github.com/angular-ui/ui-router/commit/13a468a7d54c2fb0751b94c0c1841d580b71e6dc), closes [#1414](https://github.com/angular-ui/ui-router/issues/1414))
+ * concat respects strictMode/caseInsensitive ([dd72e103](https://github.com/angular-ui/ui-router/commit/dd72e103edb342d9cf802816fe127e1bbd68fd5f), closes [#1395])
+* **ui-sref:**
+ * Allow sref state options to take a scope object ([b5f7b596](https://github.com/angular-ui/ui-router/commit/b5f7b59692ce4933e2d63eb5df3f50a4ba68ccc0))
+ * replace raw href modification with attrs. ([08c96782](https://github.com/angular-ui/ui-router/commit/08c96782faf881b0c7ab00afc233ee6729548fa0))
+ * nagivate to state when url is "" fix($state.href): generate href for state with ([656b5aab](https://github.com/angular-ui/ui-router/commit/656b5aab906e5749db9b5a080c6a83b95f50fd91), closes [#1363](https://github.com/angular-ui/ui-router/issues/1363))
+ * Check that state is defined in isMatch() ([92aebc75](https://github.com/angular-ui/ui-router/commit/92aebc7520f88babdc6e266536086e07263514c3), closes [#1314](https://github.com/angular-ui/ui-router/issues/1314), [#1332](https://github.com/angular-ui/ui-router/issues/1332))
+* **uiView:**
+ * allow inteprolated ui-view names ([81f6a19a](https://github.com/angular-ui/ui-router/commit/81f6a19a432dac9198fd33243855bfd3b4fea8c0), closes [#1324](https://github.com/angular-ui/ui-router/issues/1324))
+ * Made anim work with angular 1.3 ([c3bb7ad9](https://github.com/angular-ui/ui-router/commit/c3bb7ad903da1e1f3c91019cfd255be8489ff4ef), closes [#1367](https://github.com/angular-ui/ui-router/issues/1367), [#1345](https://github.com/angular-ui/ui-router/issues/1345))
+* **urlRouter:** html5Mode accepts an object from angular v1.3.0-rc.3 ([7fea1e9d](https://github.com/angular-ui/ui-router/commit/7fea1e9d0d8c6e09cc6c895ecb93d4221e9adf48))
+* **stateFilters:** mark state filters as stateful. ([a00b353e](https://github.com/angular-ui/ui-router/commit/a00b353e3036f64a81245c4e7898646ba218f833), closes [#1479])
+* **ui-router:** re-add IE8 compatibility for map/filter/keys ([8ce69d9f](https://github.com/angular-ui/ui-router/commit/8ce69d9f7c886888ab53eca7e53536f36b428aae), closes [#1518], [#1383])
+* **package:** point 'main' to a valid filename ([ac903350](https://github.com/angular-ui/ui-router/commit/ac9033501debb63364539d91fbf3a0cba4579f8e))
+* **travis:** make CI build faster ([0531de05](https://github.com/angular-ui/ui-router/commit/0531de052e414a8d839fbb4e7635e923e94865b3))
+
+
+#### Features
+
+##### Default and Typed params
+
+This release includes a lot of bug fixes around default/optional and typed parameters. As such, 0.2.12 is the first release where we recommend those features be used.
+
+* **$state:**
+ * add state params validation ([b1379e6a](https://github.com/angular-ui/ui-router/commit/b1379e6a4d38f7ed7436e05873932d7c279af578), closes [#1433](https://github.com/angular-ui/ui-router/issues/1433))
+ * is/includes/get work on relative stateOrName ([232e94b3](https://github.com/angular-ui/ui-router/commit/232e94b3c2ca2c764bb9510046e4b61690c87852))
+ * .reload() returns state transition promise ([639e0565](https://github.com/angular-ui/ui-router/commit/639e0565dece9d5544cc93b3eee6e11c99bd7373))
+* **$templateFactory:** request templateURL as text/html ([ccd60769](https://github.com/angular-ui/ui-router/commit/ccd6076904a4b801d77b47f6e2de4c06ce9962f8), closes [#1287])
+* **$urlMatcherFactory:** Made a Params and ParamSet class ([0cc1e6cc](https://github.com/angular-ui/ui-router/commit/0cc1e6cc461a4640618e2bb594566551c54834e2))
+
+
+
+<a name="0.2.11"></a>
+### 0.2.11 (2014-08-26)
+
+
+#### Bug Fixes
+
+* **$resolve:** Resolves only inherit from immediate parent fixes #702 ([df34e20c](https://github.com/angular-ui/ui-router/commit/df34e20c576299e7a3c8bd4ebc68d42341c0ace9))
+* **$state:**
+ * change $state.href default options.inherit to true ([deea695f](https://github.com/angular-ui/ui-router/commit/deea695f5cacc55de351ab985144fd233c02a769))
+ * sanity-check state lookups ([456fd5ae](https://github.com/angular-ui/ui-router/commit/456fd5aec9ea507518927bfabd62b4afad4cf714), closes [#980](https://github.com/angular-ui/ui-router/issues/980))
+ * didn't comply to inherit parameter ([09836781](https://github.com/angular-ui/ui-router/commit/09836781f126c1c485b06551eb9cfd4fa0f45c35))
+ * allow view content loading broadcast ([7b78edee](https://github.com/angular-ui/ui-router/commit/7b78edeeb52a74abf4d3f00f79534033d5a08d1a))
+* **$urlMatcherFactory:**
+ * detect injected functions ([91f75ae6](https://github.com/angular-ui/ui-router/commit/91f75ae66c4d129f6f69e53bd547594e9661f5d5))
+ * syntax ([1ebed370](https://github.com/angular-ui/ui-router/commit/1ebed37069bae8614d41541d56521f5c45f703f3))
+* **UrlMatcher:**
+ * query param function defaults ([f9c20530](https://github.com/angular-ui/ui-router/commit/f9c205304f10d8a4ebe7efe9025e642016479a51))
+ * don't decode default values ([63607bdb](https://github.com/angular-ui/ui-router/commit/63607bdbbcb432d3fb37856a1cb3da0cd496804e))
+* **travis:** update Node version to fix build ([d6b95ef2](https://github.com/angular-ui/ui-router/commit/d6b95ef23d9dacb4eba08897f5190a0bcddb3a48))
+* **uiSref:**
+ * Generate an href for states with a blank url. closes #1293 ([691745b1](https://github.com/angular-ui/ui-router/commit/691745b12fa05d3700dd28f0c8d25f8a105074ad))
+ * should inherit params by default ([b973dad1](https://github.com/angular-ui/ui-router/commit/b973dad155ad09a7975e1476bd096f7b2c758eeb))
+ * cancel transition if preventDefault() has been called ([2e6d9167](https://github.com/angular-ui/ui-router/commit/2e6d9167d3afbfbca6427e53e012f94fb5fb8022))
+* **uiView:** Fixed infinite loop when is called .go() from a controller. ([e13988b8](https://github.com/angular-ui/ui-router/commit/e13988b8cd6231d75c78876ee9d012cc87f4a8d9), closes [#1194](https://github.com/angular-ui/ui-router/issues/1194))
+* **docs:**
+ * Fixed link to milestones ([6c0ae500](https://github.com/angular-ui/ui-router/commit/6c0ae500cc238ea9fc95adcc15415c55fc9e1f33))
+ * fix bug in decorator example ([4bd00af5](https://github.com/angular-ui/ui-router/commit/4bd00af50b8b88a49d1545a76290731cb8e0feb1))
+ * Removed an incorrect semi-colon ([af97cef8](https://github.com/angular-ui/ui-router/commit/af97cef8b967f2e32177e539ef41450dca131a7d))
+ * Explain return value of rule as function ([5e887890](https://github.com/angular-ui/ui-router/commit/5e8878900a6ffe59a81aed531a3925e34a297377))
+
+
+#### Features
+
+* **$state:**
+ * allow parameters to pass unharmed ([8939d057](https://github.com/angular-ui/ui-router/commit/8939d0572ab1316e458ef016317ecff53131a822))
+ * **BREAKING CHANGE**: state parameters are no longer automatically coerced to strings, and unspecified parameter values are now set to undefined rather than null.
+ * allow prevent syncUrl on failure ([753060b9](https://github.com/angular-ui/ui-router/commit/753060b910d5d2da600a6fa0757976e401c33172))
+* **typescript:** Add typescript definitions for component builds ([521ceb3f](https://github.com/angular-ui/ui-router/commit/521ceb3fd7850646422f411921e21ce5e7d82e0f))
+* **uiSref:** extend syntax for ui-sref ([71cad3d6](https://github.com/angular-ui/ui-router/commit/71cad3d636508b5a9fe004775ad1f1adc0c80c3e))
+* **uiSrefActive:**
+ * Also activate for child states. ([bf163ad6](https://github.com/angular-ui/ui-router/commit/bf163ad6ce176ce28792696c8302d7cdf5c05a01), closes [#818](https://github.com/angular-ui/ui-router/issues/818))
+ * **BREAKING CHANGE** Since ui-sref-active now activates even when child states are active you may need to swap out your ui-sref-active with ui-sref-active-eq, thought typically we think devs want the auto inheritance.
+
+ * uiSrefActiveEq: new directive with old ui-sref-active behavior
+* **$urlRouter:**
+ * defer URL change interception ([c72d8ce1](https://github.com/angular-ui/ui-router/commit/c72d8ce11916d0ac22c81b409c9e61d7048554d7))
+ * force URLs to have valid params ([d48505cd](https://github.com/angular-ui/ui-router/commit/d48505cd328d83e39d5706e085ba319715f999a6))
+ * abstract $location handling ([08b4636b](https://github.com/angular-ui/ui-router/commit/08b4636b294611f08db35f00641eb5211686fb50))
+* **$urlMatcherFactory:**
+ * fail on bad parameters ([d8f124c1](https://github.com/angular-ui/ui-router/commit/d8f124c10d00c7e5dde88c602d966db261aea221))
+ * date type support ([b7f074ff](https://github.com/angular-ui/ui-router/commit/b7f074ff65ca150a3cdbda4d5ad6cb17107300eb))
+ * implement type support ([450b1f0e](https://github.com/angular-ui/ui-router/commit/450b1f0e8e03c738174ff967f688b9a6373290f4))
+* **UrlMatcher:**
+ * handle query string arrays ([9cf764ef](https://github.com/angular-ui/ui-router/commit/9cf764efab45fa9309368688d535ddf6e96d6449), closes [#373](https://github.com/angular-ui/ui-router/issues/373))
+ * injectable functions as defaults ([00966ecd](https://github.com/angular-ui/ui-router/commit/00966ecd91fb745846039160cab707bfca8b3bec))
+ * default values & type decoding for query params ([a472b301](https://github.com/angular-ui/ui-router/commit/a472b301389fbe84d1c1fa9f24852b492a569d11))
+ * allow shorthand definitions ([5b724304](https://github.com/angular-ui/ui-router/commit/5b7243049793505e44b6608ea09878c37c95b1f5))
+ * validates whole interface ([32b27db1](https://github.com/angular-ui/ui-router/commit/32b27db173722e9194ef1d5c0ea7d93f25a98d11))
+ * implement non-strict matching ([a3e21366](https://github.com/angular-ui/ui-router/commit/a3e21366bee0475c9795a1ec76f70eec41c5b4e3))
+ * add per-param config support ([07b3029f](https://github.com/angular-ui/ui-router/commit/07b3029f4d409cf955780113df92e36401b47580))
+ * **BREAKING CHANGE**: the `params` option in state configurations must now be an object keyed by parameter name.
+
+### 0.2.10 (2014-03-12)
+
+
+#### Bug Fixes
+
+* **$state:** use $browser.baseHref() when generating urls with .href() ([cbcc8488](https://github.com/angular-ui/ui-router/commit/cbcc84887d6b6d35258adabb97c714cd9c1e272d))
+* **bower.json:** JS files should not be ignored ([ccdab193](https://github.com/angular-ui/ui-router/commit/ccdab193315f304eb3be5f5b97c47a926c79263e))
+* **dev:** karma:background task is missing, can't run grunt:dev. ([d9f7b898](https://github.com/angular-ui/ui-router/commit/d9f7b898e8e3abb8c846b0faa16a382913d7b22b))
+* **sample:** Contacts menu button not staying active when navigating to detail states. Need t ([2fcb8443](https://github.com/angular-ui/ui-router/commit/2fcb84437cb43ade12682a92b764f13cac77dfe7))
+* **uiSref:** support mock-clicks/events with no data ([717d3ff7](https://github.com/angular-ui/ui-router/commit/717d3ff7d0ba72d239892dee562b401cdf90e418))
+* **uiView:**
+ * Do NOT autoscroll when autoscroll attr is missing ([affe5bd7](https://github.com/angular-ui/ui-router/commit/affe5bd785cdc3f02b7a9f64a52e3900386ec3a0), closes [#807](https://github.com/angular-ui/ui-router/issues/807))
+ * Refactoring uiView directive to copy ngView logic ([548fab6a](https://github.com/angular-ui/ui-router/commit/548fab6ab9debc9904c5865c8bc68b4fc3271dd0), closes [#857](https://github.com/angular-ui/ui-router/issues/857), [#552](https://github.com/angular-ui/ui-router/issues/552))
+
+
+#### Features
+
+* **$state:** includes() allows glob patterns for state matching. ([2d5f6b37](https://github.com/angular-ui/ui-router/commit/2d5f6b37191a3135f4a6d9e8f344c54edcdc065b))
+* **UrlMatcher:** Add support for case insensitive url matching ([642d5247](https://github.com/angular-ui/ui-router/commit/642d524799f604811e680331002feec7199a1fb5))
+* **uiSref:** add support for transition options ([2ed7a728](https://github.com/angular-ui/ui-router/commit/2ed7a728cee6854b38501fbc1df6139d3de5b28a))
+* **uiView:** add controllerAs config with function ([1ee7334a](https://github.com/angular-ui/ui-router/commit/1ee7334a73efeccc9b95340e315cdfd59944762d))
+
+
+### 0.2.9 (2014-01-17)
+
+
+This release is identical to 0.2.8. 0.2.8 was re-tagged in git to fix a problem with bower.
+
+
+### 0.2.8 (2014-01-16)
+
+
+#### Bug Fixes
+
+* **$state:** allow null to be passed as 'params' param ([094dc30e](https://github.com/angular-ui/ui-router/commit/094dc30e883e1bd14e50a475553bafeaade3b178))
+* **$state.go:** param inheritance shouldn't inherit from siblings ([aea872e0](https://github.com/angular-ui/ui-router/commit/aea872e0b983cb433436ce5875df10c838fccedb))
+* **bower.json:** fixes bower.json ([eed3cc4d](https://github.com/angular-ui/ui-router/commit/eed3cc4d4dfef1d3ef84b9fd063127538ebf59d3))
+* **uiSrefActive:** annotate controller injection ([85921422](https://github.com/angular-ui/ui-router/commit/85921422ff7fb0effed358136426d616cce3d583), closes [#671](https://github.com/angular-ui/ui-router/issues/671))
+* **uiView:**
+ * autoscroll tests pass on 1.2.4 & 1.1.5 ([86eacac0](https://github.com/angular-ui/ui-router/commit/86eacac09ca5e9000bd3b9c7ba6e2cc95d883a3a))
+ * don't animate initial load ([83b6634d](https://github.com/angular-ui/ui-router/commit/83b6634d27942ca74766b2b1244a7fc52c5643d9))
+ * test pass against 1.0.8 and 1.2.4 ([a402415a](https://github.com/angular-ui/ui-router/commit/a402415a2a28b360c43b9fe8f4f54c540f6c33de))
+ * it should autoscroll when expr is missing. ([8bb9e27a](https://github.com/angular-ui/ui-router/commit/8bb9e27a2986725f45daf44c4c9f846385095aff))
+
+
+#### Features
+
+* **uiSref:** add target attribute behaviour ([c12bf9a5](https://github.com/angular-ui/ui-router/commit/c12bf9a520d30d70294e3d82de7661900f8e394e))
+* **uiView:**
+ * merge autoscroll expression test. ([b89e0f87](https://github.com/angular-ui/ui-router/commit/b89e0f871d5cc35c10925ede986c10684d5c9252))
+ * cache and test autoscroll expression ([ee262282](https://github.com/angular-ui/ui-router/commit/ee2622828c2ce83807f006a459ac4e11406d9258))
diff --git a/afb-client/bower_components/angular-ui-router/CONTRIBUTING.md b/afb-client/bower_components/angular-ui-router/CONTRIBUTING.md
new file mode 100644
index 0000000..7e4fcb8
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/CONTRIBUTING.md
@@ -0,0 +1,65 @@
+
+# Report an Issue
+
+Help us make UI-Router better! If you think you might have found a bug, or some other weirdness, start by making sure
+it hasn't already been reported. You can [search through existing issues](https://github.com/angular-ui/ui-router/search?q=wat%3F&type=Issues)
+to see if someone's reported one similar to yours.
+
+If not, then [create a plunkr](http://bit.ly/UIR-Plunk) that demonstrates the problem (try to use as little code
+as possible: the more minimalist, the faster we can debug it).
+
+Next, [create a new issue](https://github.com/angular-ui/ui-router/issues/new) that briefly explains the problem,
+and provides a bit of background as to the circumstances that triggered it. Don't forget to include the link to
+that plunkr you created!
+
+**Note**: If you're unsure how a feature is used, or are encountering some unexpected behavior that you aren't sure
+is a bug, it's best to talk it out on
+[StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) before reporting it. This
+keeps development streamlined, and helps us focus on building great software.
+
+
+Issues only! |
+-------------|
+Please keep in mind that the issue tracker is for *issues*. Please do *not* post an issue if you need help or support. Instead, see one of the above-mentioned forums or [IRC](irc://irc.freenode.net/#angularjs). |
+
+####Purple Labels
+A purple label means that **you** need to take some further action.
+ - ![Not Actionable - Need Info](ngdoc_assets/incomplete.png): Your issue is not specific enough, or there is no clear action that we can take. Please clarify and refine your issue.
+ - ![Plunkr Please](ngdoc_assets/example.png): Please [create a plunkr](http://bit.ly/UIR-Plunk)
+ - ![StackOverflow](ngdoc_assets/so.png): We suspect your issue is really a help request, or could be answered by the community. Please ask your question on [StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router). If you determine that is an actual issue, please explain why.
+
+If your issue gets labeled with purple label, no further action will be taken until you respond to the label appropriately.
+
+# Contribute
+
+**(1)** See the **[Developing](#developing)** section below, to get the development version of UI-Router up and running on your local machine.
+
+**(2)** Check out the [roadmap](https://github.com/angular-ui/ui-router/milestones) to see where the project is headed, and if your feature idea fits with where we're headed.
+
+**(3)** If you're not sure, [open an RFC](https://github.com/angular-ui/ui-router/issues/new?title=RFC:%20My%20idea) to get some feedback on your idea.
+
+**(4)** Finally, commit some code and open a pull request. Code & commits should abide by the following rules:
+
+- *Always* have test coverage for new features (or regression tests for bug fixes), and *never* break existing tests
+- Commits should represent one logical change each; if a feature goes through multiple iterations, squash your commits down to one
+- Make sure to follow the [Angular commit message format](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format) so your change will appear in the changelog of the next release.
+- Changes should always respect the coding style of the project
+
+
+
+# Developing
+
+UI-Router uses <code>grunt >= 0.4.x</code>. Make sure to upgrade your environment and read the
+[Migration Guide](http://gruntjs.com/upgrading-from-0.3-to-0.4).
+
+Dependencies for building from source and running tests:
+
+* [grunt-cli](https://github.com/gruntjs/grunt-cli) - run: `$ npm install -g grunt-cli`
+* Then, install the development dependencies by running `$ npm install` from the project directory
+
+There are a number of targets in the gruntfile that are used to generating different builds:
+
+* `grunt`: Perform a normal build, runs jshint and karma tests
+* `grunt build`: Perform a normal build
+* `grunt dist`: Perform a clean build and generate documentation
+* `grunt dev`: Run dev server (sample app) and watch for changes, builds and runs karma tests on changes.
diff --git a/afb-client/bower_components/angular-ui-router/LICENSE b/afb-client/bower_components/angular-ui-router/LICENSE
new file mode 100644
index 0000000..6413b09
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2013-2015 The AngularUI Team, Karsten Sperling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/angular-ui-router/README.md b/afb-client/bower_components/angular-ui-router/README.md
new file mode 100644
index 0000000..ba6c45a
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/README.md
@@ -0,0 +1,252 @@
+# AngularUI Router &nbsp;[![Build Status](https://travis-ci.org/angular-ui/ui-router.svg?branch=master)](https://travis-ci.org/angular-ui/ui-router)
+
+#### The de-facto solution to flexible routing with nested views
+---
+**[Download 0.2.17](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|**
+**[Guide](https://github.com/angular-ui/ui-router/wiki) |**
+**[API](http://angular-ui.github.io/ui-router/site) |**
+**[Sample](http://angular-ui.github.com/ui-router/sample/) ([Src](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) |**
+**[FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) |**
+**[Resources](#resources) |**
+**[Report an Issue](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#report-an-issue) |**
+**[Contribute](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#contribute) |**
+**[Help!](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |**
+**[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router)**
+
+---
+
+*_Please help us out by testing the 1.0 alpha release!_*
+
+[1.0.0alpha0 Announcement](https://github.com/angular-ui/ui-router/releases/tag/1.0.0alpha0) ([Source Code](https://github.com/angular-ui/ui-router/tree/feature-1.0)) | [Sample App](http://ui-router.github.io/sample-app/) ([Source Code](https://github.com/ui-router/sample-app)) | [Known Issues](https://github.com/angular-ui/ui-router/issues?q=is%3Aissue+is%3Aopen+label%3A1.0)
+
+
+---
+
+AngularUI Router is a routing framework for [AngularJS](http://angularjs.org), which allows you to organize the
+parts of your interface into a [*state machine*](https://en.wikipedia.org/wiki/Finite-state_machine). Unlike the
+[`$route` service](http://docs.angularjs.org/api/ngRoute.$route) in the Angular ngRoute module, which is organized around URL
+routes, UI-Router is organized around [*states*](https://github.com/angular-ui/ui-router/wiki),
+which may optionally have routes, as well as other behavior, attached.
+
+States are bound to *named*, *nested* and *parallel views*, allowing you to powerfully manage your application's interface.
+
+Check out the sample app: http://angular-ui.github.io/ui-router/sample/
+
+-
+**Note:** *UI-Router is under active development. As such, while this library is well-tested, the API may change. Consider using it in production applications only if you're comfortable following a changelog and updating your usage accordingly.*
+
+
+## Get Started
+
+**(1)** Get UI-Router in one of the following ways:
+ - clone & [build](CONTRIBUTING.md#developing) this repository
+ - [download the release](http://angular-ui.github.io/ui-router/release/angular-ui-router.js) (or [minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js))
+ - [link to cdn](http://cdnjs.com/libraries/angular-ui-router)
+ - via **[jspm](http://jspm.io/)**: by running `$ jspm install angular-ui-router` from your console
+ - or via **[npm](https://www.npmjs.org/)**: by running `$ npm install angular-ui-router` from your console
+ - or via **[Bower](http://bower.io/)**: by running `$ bower install angular-ui-router` from your console
+ - or via **[Component](https://github.com/component/component)**: by running `$ component install angular-ui/ui-router` from your console
+
+**(2)** Include `angular-ui-router.js` (or `angular-ui-router.min.js`) in your `index.html`, after including Angular itself (For Component users: ignore this step)
+
+**(3)** Add `'ui.router'` to your main module's list of dependencies (For Component users: replace `'ui.router'` with `require('angular-ui-router')`)
+
+When you're done, your setup should look similar to the following:
+
+>
+```html
+<!doctype html>
+<html ng-app="myApp">
+<head>
+ <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
+ <script src="js/angular-ui-router.min.js"></script>
+ <script>
+ var myApp = angular.module('myApp', ['ui.router']);
+ // For Component users, it should look like this:
+ // var myApp = angular.module('myApp', [require('angular-ui-router')]);
+ </script>
+ ...
+</head>
+<body>
+ ...
+</body>
+</html>
+```
+
+### [Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)
+
+The majority of UI-Router's power is in its ability to nest states & views.
+
+**(1)** First, follow the [setup](#get-started) instructions detailed above.
+
+**(2)** Then, add a [`ui-view` directive](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view) to the `<body />` of your app.
+
+>
+```html
+<!-- index.html -->
+<body>
+ <div ui-view></div>
+ <!-- We'll also add some navigation: -->
+ <a ui-sref="state1">State 1</a>
+ <a ui-sref="state2">State 2</a>
+</body>
+```
+
+**(3)** You'll notice we also added some links with [`ui-sref` directives](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref). In addition to managing state transitions, this directive auto-generates the `href` attribute of the `<a />` element it's attached to, if the corresponding state has a URL. Next we'll add some templates. These will plug into the `ui-view` within `index.html`. Notice that they have their own `ui-view` as well! That is the key to nesting states and views.
+
+>
+```html
+<!-- partials/state1.html -->
+<h1>State 1</h1>
+<hr/>
+<a ui-sref="state1.list">Show List</a>
+<div ui-view></div>
+```
+```html
+<!-- partials/state2.html -->
+<h1>State 2</h1>
+<hr/>
+<a ui-sref="state2.list">Show List</a>
+<div ui-view></div>
+```
+
+**(4)** Next, we'll add some child templates. *These* will get plugged into the `ui-view` of their parent state templates.
+
+>
+```html
+<!-- partials/state1.list.html -->
+<h3>List of State 1 Items</h3>
+<ul>
+ <li ng-repeat="item in items">{{ item }}</li>
+</ul>
+```
+
+>
+```html
+<!-- partials/state2.list.html -->
+<h3>List of State 2 Things</h3>
+<ul>
+ <li ng-repeat="thing in things">{{ thing }}</li>
+</ul>
+```
+
+**(5)** Finally, we'll wire it all up with `$stateProvider`. Set up your states in the module config, as in the following:
+
+
+>
+```javascript
+myApp.config(function($stateProvider, $urlRouterProvider) {
+ //
+ // For any unmatched url, redirect to /state1
+ $urlRouterProvider.otherwise("/state1");
+ //
+ // Now set up the states
+ $stateProvider
+ .state('state1', {
+ url: "/state1",
+ templateUrl: "partials/state1.html"
+ })
+ .state('state1.list', {
+ url: "/list",
+ templateUrl: "partials/state1.list.html",
+ controller: function($scope) {
+ $scope.items = ["A", "List", "Of", "Items"];
+ }
+ })
+ .state('state2', {
+ url: "/state2",
+ templateUrl: "partials/state2.html"
+ })
+ .state('state2.list', {
+ url: "/list",
+ templateUrl: "partials/state2.list.html",
+ controller: function($scope) {
+ $scope.things = ["A", "Set", "Of", "Things"];
+ }
+ });
+});
+```
+
+**(6)** See this quick start example in action.
+>**[Go to Quick Start Plunker for Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)**
+
+**(7)** This only scratches the surface
+>**[Dive Deeper!](https://github.com/angular-ui/ui-router/wiki)**
+
+
+### [Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)
+
+Another great feature is the ability to have multiple `ui-view`s view per template.
+
+**Pro Tip:** *While multiple parallel views are a powerful feature, you'll often be able to manage your
+interfaces more effectively by nesting your views, and pairing those views with nested states.*
+
+**(1)** Follow the [setup](#get-started) instructions detailed above.
+
+**(2)** Add one or more `ui-view` to your app, give them names.
+>
+```html
+<!-- index.html -->
+<body>
+ <div ui-view="viewA"></div>
+ <div ui-view="viewB"></div>
+ <!-- Also a way to navigate -->
+ <a ui-sref="route1">Route 1</a>
+ <a ui-sref="route2">Route 2</a>
+</body>
+```
+
+**(3)** Set up your states in the module config:
+>
+```javascript
+myApp.config(function($stateProvider) {
+ $stateProvider
+ .state('index', {
+ url: "",
+ views: {
+ "viewA": { template: "index.viewA" },
+ "viewB": { template: "index.viewB" }
+ }
+ })
+ .state('route1', {
+ url: "/route1",
+ views: {
+ "viewA": { template: "route1.viewA" },
+ "viewB": { template: "route1.viewB" }
+ }
+ })
+ .state('route2', {
+ url: "/route2",
+ views: {
+ "viewA": { template: "route2.viewA" },
+ "viewB": { template: "route2.viewB" }
+ }
+ })
+});
+```
+
+**(4)** See this quick start example in action.
+>**[Go to Quick Start Plunker for Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)**
+
+
+## Resources
+
+* [In-Depth Guide](https://github.com/angular-ui/ui-router/wiki)
+* [API Reference](http://angular-ui.github.io/ui-router/site)
+* [Sample App](http://angular-ui.github.com/ui-router/sample/) ([Source](https://github.com/angular-ui/ui-router/tree/gh-pages/sample))
+* [FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions)
+* [Slides comparing ngRoute to ui-router](http://slid.es/timkindberg/ui-router#/)
+* [UI-Router Extras / Addons](http://christopherthielen.github.io/ui-router-extras/#/home) (@christopherthielen)
+
+### Videos
+
+* [Introduction Video](https://egghead.io/lessons/angularjs-introduction-ui-router) (egghead.io)
+* [Tim Kindberg on Angular UI-Router](https://www.youtube.com/watch?v=lBqiZSemrqg)
+* [Activating States](https://egghead.io/lessons/angularjs-ui-router-activating-states) (egghead.io)
+* [Learn Angular.js using UI-Router](http://youtu.be/QETUuZ27N0w) (LearnCode.academy)
+
+
+
+## Reporting issues and Contributing
+
+Please read our [Contributor guidelines](CONTRIBUTING.md) before reporting an issue or creating a pull request.
diff --git a/afb-client/bower_components/angular-ui-router/bower.json b/afb-client/bower_components/angular-ui-router/bower.json
new file mode 100644
index 0000000..892936f
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/bower.json
@@ -0,0 +1,24 @@
+{
+ "name": "angular-ui-router",
+ "version": "0.2.18",
+ "license" : "MIT",
+ "main": "./release/angular-ui-router.js",
+ "dependencies": {
+ "angular": "^1.0.8"
+ },
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "component.json",
+ "package.json",
+ "lib",
+ "config",
+ "sample",
+ "test",
+ "tests",
+ "ngdoc_assets",
+ "Gruntfile.js",
+ "files.js"
+ ]
+}
diff --git a/afb-client/bower_components/angular-ui-router/release/angular-ui-router.js b/afb-client/bower_components/angular-ui-router/release/angular-ui-router.js
new file mode 100644
index 0000000..26f7657
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/release/angular-ui-router.js
@@ -0,0 +1,4539 @@
+/**
+ * State-based routing for AngularJS
+ * @version v0.2.18
+ * @link http://angular-ui.github.com/
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+
+/* commonjs package manager support (eg componentjs) */
+if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){
+ module.exports = 'ui.router';
+}
+
+(function (window, angular, undefined) {
+/*jshint globalstrict:true*/
+/*global angular:false*/
+'use strict';
+
+var isDefined = angular.isDefined,
+ isFunction = angular.isFunction,
+ isString = angular.isString,
+ isObject = angular.isObject,
+ isArray = angular.isArray,
+ forEach = angular.forEach,
+ extend = angular.extend,
+ copy = angular.copy,
+ toJson = angular.toJson;
+
+function inherit(parent, extra) {
+ return extend(new (extend(function() {}, { prototype: parent }))(), extra);
+}
+
+function merge(dst) {
+ forEach(arguments, function(obj) {
+ if (obj !== dst) {
+ forEach(obj, function(value, key) {
+ if (!dst.hasOwnProperty(key)) dst[key] = value;
+ });
+ }
+ });
+ return dst;
+}
+
+/**
+ * Finds the common ancestor path between two states.
+ *
+ * @param {Object} first The first state.
+ * @param {Object} second The second state.
+ * @return {Array} Returns an array of state names in descending order, not including the root.
+ */
+function ancestors(first, second) {
+ var path = [];
+
+ for (var n in first.path) {
+ if (first.path[n] !== second.path[n]) break;
+ path.push(first.path[n]);
+ }
+ return path;
+}
+
+/**
+ * IE8-safe wrapper for `Object.keys()`.
+ *
+ * @param {Object} object A JavaScript object.
+ * @return {Array} Returns the keys of the object as an array.
+ */
+function objectKeys(object) {
+ if (Object.keys) {
+ return Object.keys(object);
+ }
+ var result = [];
+
+ forEach(object, function(val, key) {
+ result.push(key);
+ });
+ return result;
+}
+
+/**
+ * IE8-safe wrapper for `Array.prototype.indexOf()`.
+ *
+ * @param {Array} array A JavaScript array.
+ * @param {*} value A value to search the array for.
+ * @return {Number} Returns the array index value of `value`, or `-1` if not present.
+ */
+function indexOf(array, value) {
+ if (Array.prototype.indexOf) {
+ return array.indexOf(value, Number(arguments[2]) || 0);
+ }
+ var len = array.length >>> 0, from = Number(arguments[2]) || 0;
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
+
+ if (from < 0) from += len;
+
+ for (; from < len; from++) {
+ if (from in array && array[from] === value) return from;
+ }
+ return -1;
+}
+
+/**
+ * Merges a set of parameters with all parameters inherited between the common parents of the
+ * current state and a given destination state.
+ *
+ * @param {Object} currentParams The value of the current state parameters ($stateParams).
+ * @param {Object} newParams The set of parameters which will be composited with inherited params.
+ * @param {Object} $current Internal definition of object representing the current state.
+ * @param {Object} $to Internal definition of object representing state to transition to.
+ */
+function inheritParams(currentParams, newParams, $current, $to) {
+ var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
+
+ for (var i in parents) {
+ if (!parents[i] || !parents[i].params) continue;
+ parentParams = objectKeys(parents[i].params);
+ if (!parentParams.length) continue;
+
+ for (var j in parentParams) {
+ if (indexOf(inheritList, parentParams[j]) >= 0) continue;
+ inheritList.push(parentParams[j]);
+ inherited[parentParams[j]] = currentParams[parentParams[j]];
+ }
+ }
+ return extend({}, inherited, newParams);
+}
+
+/**
+ * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
+ *
+ * @param {Object} a The first object.
+ * @param {Object} b The second object.
+ * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
+ * it defaults to the list of keys in `a`.
+ * @return {Boolean} Returns `true` if the keys match, otherwise `false`.
+ */
+function equalForKeys(a, b, keys) {
+ if (!keys) {
+ keys = [];
+ for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
+ }
+
+ for (var i=0; i<keys.length; i++) {
+ var k = keys[i];
+ if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
+ }
+ return true;
+}
+
+/**
+ * Returns the subset of an object, based on a list of keys.
+ *
+ * @param {Array} keys
+ * @param {Object} values
+ * @return {Boolean} Returns a subset of `values`.
+ */
+function filterByKeys(keys, values) {
+ var filtered = {};
+
+ forEach(keys, function (name) {
+ filtered[name] = values[name];
+ });
+ return filtered;
+}
+
+// like _.indexBy
+// when you know that your index values will be unique, or you want last-one-in to win
+function indexBy(array, propName) {
+ var result = {};
+ forEach(array, function(item) {
+ result[item[propName]] = item;
+ });
+ return result;
+}
+
+// extracted from underscore.js
+// Return a copy of the object only containing the whitelisted properties.
+function pick(obj) {
+ var copy = {};
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
+ forEach(keys, function(key) {
+ if (key in obj) copy[key] = obj[key];
+ });
+ return copy;
+}
+
+// extracted from underscore.js
+// Return a copy of the object omitting the blacklisted properties.
+function omit(obj) {
+ var copy = {};
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
+ for (var key in obj) {
+ if (indexOf(keys, key) == -1) copy[key] = obj[key];
+ }
+ return copy;
+}
+
+function pluck(collection, key) {
+ var result = isArray(collection) ? [] : {};
+
+ forEach(collection, function(val, i) {
+ result[i] = isFunction(key) ? key(val) : val[key];
+ });
+ return result;
+}
+
+function filter(collection, callback) {
+ var array = isArray(collection);
+ var result = array ? [] : {};
+ forEach(collection, function(val, i) {
+ if (callback(val, i)) {
+ result[array ? result.length : i] = val;
+ }
+ });
+ return result;
+}
+
+function map(collection, callback) {
+ var result = isArray(collection) ? [] : {};
+
+ forEach(collection, function(val, i) {
+ result[i] = callback(val, i);
+ });
+ return result;
+}
+
+/**
+ * @ngdoc overview
+ * @name ui.router.util
+ *
+ * @description
+ * # ui.router.util sub-module
+ *
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ *
+ */
+angular.module('ui.router.util', ['ng']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router.router
+ *
+ * @requires ui.router.util
+ *
+ * @description
+ * # ui.router.router sub-module
+ *
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ */
+angular.module('ui.router.router', ['ui.router.util']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router.state
+ *
+ * @requires ui.router.router
+ * @requires ui.router.util
+ *
+ * @description
+ * # ui.router.state sub-module
+ *
+ * This module is a dependency of the main ui.router module. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ *
+ */
+angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router
+ *
+ * @requires ui.router.state
+ *
+ * @description
+ * # ui.router
+ *
+ * ## The main module for ui.router
+ * There are several sub-modules included with the ui.router module, however only this module is needed
+ * as a dependency within your angular app. The other modules are for organization purposes.
+ *
+ * The modules are:
+ * * ui.router - the main "umbrella" module
+ * * ui.router.router -
+ *
+ * *You'll need to include **only** this module as the dependency within your angular app.*
+ *
+ * <pre>
+ * <!doctype html>
+ * <html ng-app="myApp">
+ * <head>
+ * <script src="js/angular.js"></script>
+ * <!-- Include the ui-router script -->
+ * <script src="js/angular-ui-router.min.js"></script>
+ * <script>
+ * // ...and add 'ui.router' as a dependency
+ * var myApp = angular.module('myApp', ['ui.router']);
+ * </script>
+ * </head>
+ * <body>
+ * </body>
+ * </html>
+ * </pre>
+ */
+angular.module('ui.router', ['ui.router.state']);
+
+angular.module('ui.router.compat', ['ui.router']);
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.$resolve
+ *
+ * @requires $q
+ * @requires $injector
+ *
+ * @description
+ * Manages resolution of (acyclic) graphs of promises.
+ */
+$Resolve.$inject = ['$q', '$injector'];
+function $Resolve( $q, $injector) {
+
+ var VISIT_IN_PROGRESS = 1,
+ VISIT_DONE = 2,
+ NOTHING = {},
+ NO_DEPENDENCIES = [],
+ NO_LOCALS = NOTHING,
+ NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$resolve#study
+ * @methodOf ui.router.util.$resolve
+ *
+ * @description
+ * Studies a set of invocables that are likely to be used multiple times.
+ * <pre>
+ * $resolve.study(invocables)(locals, parent, self)
+ * </pre>
+ * is equivalent to
+ * <pre>
+ * $resolve.resolve(invocables, locals, parent, self)
+ * </pre>
+ * but the former is more efficient (in fact `resolve` just calls `study`
+ * internally).
+ *
+ * @param {object} invocables Invocable objects
+ * @return {function} a function to pass in locals, parent and self
+ */
+ this.study = function (invocables) {
+ if (!isObject(invocables)) throw new Error("'invocables' must be an object");
+ var invocableKeys = objectKeys(invocables || {});
+
+ // Perform a topological sort of invocables to build an ordered plan
+ var plan = [], cycle = [], visited = {};
+ function visit(value, key) {
+ if (visited[key] === VISIT_DONE) return;
+
+ cycle.push(key);
+ if (visited[key] === VISIT_IN_PROGRESS) {
+ cycle.splice(0, indexOf(cycle, key));
+ throw new Error("Cyclic dependency: " + cycle.join(" -> "));
+ }
+ visited[key] = VISIT_IN_PROGRESS;
+
+ if (isString(value)) {
+ plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
+ } else {
+ var params = $injector.annotate(value);
+ forEach(params, function (param) {
+ if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
+ });
+ plan.push(key, value, params);
+ }
+
+ cycle.pop();
+ visited[key] = VISIT_DONE;
+ }
+ forEach(invocables, visit);
+ invocables = cycle = visited = null; // plan is all that's required
+
+ function isResolve(value) {
+ return isObject(value) && value.then && value.$$promises;
+ }
+
+ return function (locals, parent, self) {
+ if (isResolve(locals) && self === undefined) {
+ self = parent; parent = locals; locals = null;
+ }
+ if (!locals) locals = NO_LOCALS;
+ else if (!isObject(locals)) {
+ throw new Error("'locals' must be an object");
+ }
+ if (!parent) parent = NO_PARENT;
+ else if (!isResolve(parent)) {
+ throw new Error("'parent' must be a promise returned by $resolve.resolve()");
+ }
+
+ // To complete the overall resolution, we have to wait for the parent
+ // promise and for the promise for each invokable in our plan.
+ var resolution = $q.defer(),
+ result = resolution.promise,
+ promises = result.$$promises = {},
+ values = extend({}, locals),
+ wait = 1 + plan.length/3,
+ merged = false;
+
+ function done() {
+ // Merge parent values we haven't got yet and publish our own $$values
+ if (!--wait) {
+ if (!merged) merge(values, parent.$$values);
+ result.$$values = values;
+ result.$$promises = result.$$promises || true; // keep for isResolve()
+ delete result.$$inheritedValues;
+ resolution.resolve(values);
+ }
+ }
+
+ function fail(reason) {
+ result.$$failure = reason;
+ resolution.reject(reason);
+ }
+
+ // Short-circuit if parent has already failed
+ if (isDefined(parent.$$failure)) {
+ fail(parent.$$failure);
+ return result;
+ }
+
+ if (parent.$$inheritedValues) {
+ merge(values, omit(parent.$$inheritedValues, invocableKeys));
+ }
+
+ // Merge parent values if the parent has already resolved, or merge
+ // parent promises and wait if the parent resolve is still in progress.
+ extend(promises, parent.$$promises);
+ if (parent.$$values) {
+ merged = merge(values, omit(parent.$$values, invocableKeys));
+ result.$$inheritedValues = omit(parent.$$values, invocableKeys);
+ done();
+ } else {
+ if (parent.$$inheritedValues) {
+ result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);
+ }
+ parent.then(done, fail);
+ }
+
+ // Process each invocable in the plan, but ignore any where a local of the same name exists.
+ for (var i=0, ii=plan.length; i<ii; i+=3) {
+ if (locals.hasOwnProperty(plan[i])) done();
+ else invoke(plan[i], plan[i+1], plan[i+2]);
+ }
+
+ function invoke(key, invocable, params) {
+ // Create a deferred for this invocation. Failures will propagate to the resolution as well.
+ var invocation = $q.defer(), waitParams = 0;
+ function onfailure(reason) {
+ invocation.reject(reason);
+ fail(reason);
+ }
+ // Wait for any parameter that we have a promise for (either from parent or from this
+ // resolve; in that case study() will have made sure it's ordered before us in the plan).
+ forEach(params, function (dep) {
+ if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) {
+ waitParams++;
+ promises[dep].then(function (result) {
+ values[dep] = result;
+ if (!(--waitParams)) proceed();
+ }, onfailure);
+ }
+ });
+ if (!waitParams) proceed();
+ function proceed() {
+ if (isDefined(result.$$failure)) return;
+ try {
+ invocation.resolve($injector.invoke(invocable, self, values));
+ invocation.promise.then(function (result) {
+ values[key] = result;
+ done();
+ }, onfailure);
+ } catch (e) {
+ onfailure(e);
+ }
+ }
+ // Publish promise synchronously; invocations further down in the plan may depend on it.
+ promises[key] = invocation.promise;
+ }
+
+ return result;
+ };
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$resolve#resolve
+ * @methodOf ui.router.util.$resolve
+ *
+ * @description
+ * Resolves a set of invocables. An invocable is a function to be invoked via
+ * `$injector.invoke()`, and can have an arbitrary number of dependencies.
+ * An invocable can either return a value directly,
+ * or a `$q` promise. If a promise is returned it will be resolved and the
+ * resulting value will be used instead. Dependencies of invocables are resolved
+ * (in this order of precedence)
+ *
+ * - from the specified `locals`
+ * - from another invocable that is part of this `$resolve` call
+ * - from an invocable that is inherited from a `parent` call to `$resolve`
+ * (or recursively
+ * - from any ancestor `$resolve` of that parent).
+ *
+ * The return value of `$resolve` is a promise for an object that contains
+ * (in this order of precedence)
+ *
+ * - any `locals` (if specified)
+ * - the resolved return values of all injectables
+ * - any values inherited from a `parent` call to `$resolve` (if specified)
+ *
+ * The promise will resolve after the `parent` promise (if any) and all promises
+ * returned by injectables have been resolved. If any invocable
+ * (or `$injector.invoke`) throws an exception, or if a promise returned by an
+ * invocable is rejected, the `$resolve` promise is immediately rejected with the
+ * same error. A rejection of a `parent` promise (if specified) will likewise be
+ * propagated immediately. Once the `$resolve` promise has been rejected, no
+ * further invocables will be called.
+ *
+ * Cyclic dependencies between invocables are not permitted and will cause `$resolve`
+ * to throw an error. As a special case, an injectable can depend on a parameter
+ * with the same name as the injectable, which will be fulfilled from the `parent`
+ * injectable of the same name. This allows inherited values to be decorated.
+ * Note that in this case any other injectable in the same `$resolve` with the same
+ * dependency would see the decorated value, not the inherited value.
+ *
+ * Note that missing dependencies -- unlike cyclic dependencies -- will cause an
+ * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous)
+ * exception.
+ *
+ * Invocables are invoked eagerly as soon as all dependencies are available.
+ * This is true even for dependencies inherited from a `parent` call to `$resolve`.
+ *
+ * As a special case, an invocable can be a string, in which case it is taken to
+ * be a service name to be passed to `$injector.get()`. This is supported primarily
+ * for backwards-compatibility with the `resolve` property of `$routeProvider`
+ * routes.
+ *
+ * @param {object} invocables functions to invoke or
+ * `$injector` services to fetch.
+ * @param {object} locals values to make available to the injectables
+ * @param {object} parent a promise returned by another call to `$resolve`.
+ * @param {object} self the `this` for the invoked methods
+ * @return {object} Promise for an object that contains the resolved return value
+ * of all invocables, as well as any inherited and local values.
+ */
+ this.resolve = function (invocables, locals, parent, self) {
+ return this.study(invocables)(locals, parent, self);
+ };
+}
+
+angular.module('ui.router.util').service('$resolve', $Resolve);
+
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.$templateFactory
+ *
+ * @requires $http
+ * @requires $templateCache
+ * @requires $injector
+ *
+ * @description
+ * Service. Manages loading of templates.
+ */
+$TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
+function $TemplateFactory( $http, $templateCache, $injector) {
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromConfig
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template from a configuration object.
+ *
+ * @param {object} config Configuration object for which to load a template.
+ * The following properties are search in the specified order, and the first one
+ * that is defined is used to create the template:
+ *
+ * @param {string|object} config.template html string template or function to
+ * load via {@link ui.router.util.$templateFactory#fromString fromString}.
+ * @param {string|object} config.templateUrl url to load or a function returning
+ * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
+ * @param {Function} config.templateProvider function to invoke via
+ * {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
+ * @param {object} params Parameters to pass to the template function.
+ * @param {object} locals Locals to pass to `invoke` if the template is loaded
+ * via a `templateProvider`. Defaults to `{ params: params }`.
+ *
+ * @return {string|object} The template html as a string, or a promise for
+ * that string,or `null` if no template is configured.
+ */
+ this.fromConfig = function (config, params, locals) {
+ return (
+ isDefined(config.template) ? this.fromString(config.template, params) :
+ isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
+ isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
+ null
+ );
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromString
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template from a string or a function returning a string.
+ *
+ * @param {string|object} template html template as a string or function that
+ * returns an html template as a string.
+ * @param {object} params Parameters to pass to the template function.
+ *
+ * @return {string|object} The template html as a string, or a promise for that
+ * string.
+ */
+ this.fromString = function (template, params) {
+ return isFunction(template) ? template(params) : template;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromUrl
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Loads a template from the a URL via `$http` and `$templateCache`.
+ *
+ * @param {string|Function} url url of the template to load, or a function
+ * that returns a url.
+ * @param {Object} params Parameters to pass to the url function.
+ * @return {string|Promise.<string>} The template html as a string, or a promise
+ * for that string.
+ */
+ this.fromUrl = function (url, params) {
+ if (isFunction(url)) url = url(params);
+ if (url == null) return null;
+ else return $http
+ .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }})
+ .then(function(response) { return response.data; });
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromProvider
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template by invoking an injectable provider function.
+ *
+ * @param {Function} provider Function to invoke via `$injector.invoke`
+ * @param {Object} params Parameters for the template.
+ * @param {Object} locals Locals to pass to `invoke`. Defaults to
+ * `{ params: params }`.
+ * @return {string|Promise.<string>} The template html as a string, or a promise
+ * for that string.
+ */
+ this.fromProvider = function (provider, params, locals) {
+ return $injector.invoke(provider, null, locals || { params: params });
+ };
+}
+
+angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
+
+var $$UMFP; // reference to $UrlMatcherFactoryProvider
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Matches URLs against patterns and extracts named parameters from the path or the search
+ * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
+ * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
+ * do not influence whether or not a URL is matched, but their values are passed through into
+ * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.
+ *
+ * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
+ * syntax, which optionally allows a regular expression for the parameter to be specified:
+ *
+ * * `':'` name - colon placeholder
+ * * `'*'` name - catch-all placeholder
+ * * `'{' name '}'` - curly placeholder
+ * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the
+ * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
+ *
+ * Parameter names may contain only word characters (latin letters, digits, and underscore) and
+ * must be unique within the pattern (across both path and search parameters). For colon
+ * placeholders or curly placeholders without an explicit regexp, a path parameter matches any
+ * number of characters other than '/'. For catch-all placeholders the path parameter matches
+ * any number of characters.
+ *
+ * Examples:
+ *
+ * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
+ * trailing slashes, and patterns have to match the entire path, not just a prefix.
+ * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
+ * '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
+ * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
+ * * `'/user/{id:[^/]*}'` - Same as the previous example.
+ * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
+ * parameter consists of 1 to 8 hex digits.
+ * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
+ * path into the parameter 'path'.
+ * * `'/files/*path'` - ditto.
+ * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined
+ * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start
+ *
+ * @param {string} pattern The pattern to compile into a matcher.
+ * @param {Object} config A configuration object hash:
+ * @param {Object=} parentMatcher Used to concatenate the pattern/config onto
+ * an existing UrlMatcher
+ *
+ * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
+ * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
+ *
+ * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any
+ * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns
+ * non-null) will start with this prefix.
+ *
+ * @property {string} source The pattern that was passed into the constructor
+ *
+ * @property {string} sourcePath The path portion of the source property
+ *
+ * @property {string} sourceSearch The search portion of the source property
+ *
+ * @property {string} regex The constructed regex that will be used to match against the url when
+ * it is time to determine which url will match.
+ *
+ * @returns {Object} New `UrlMatcher` object
+ */
+function UrlMatcher(pattern, config, parentMatcher) {
+ config = extend({ params: {} }, isObject(config) ? config : {});
+
+ // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
+ // '*' name
+ // ':' name
+ // '{' name '}'
+ // '{' name ':' regexp '}'
+ // The regular expression is somewhat complicated due to the need to allow curly braces
+ // inside the regular expression. The placeholder regexp breaks down as follows:
+ // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case)
+ // \{([\w\[\]]+)(?:\:\s*( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
+ // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either
+ // [^{}\\]+ - anything other than curly braces or backslash
+ // \\. - a backslash escape
+ // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms
+ var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
+ searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
+ compiled = '^', last = 0, m,
+ segments = this.segments = [],
+ parentParams = parentMatcher ? parentMatcher.params : {},
+ params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(),
+ paramNames = [];
+
+ function addParameter(id, type, config, location) {
+ paramNames.push(id);
+ if (parentParams[id]) return parentParams[id];
+ if (!/^\w+([-.]+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
+ if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
+ params[id] = new $$UMFP.Param(id, type, config, location);
+ return params[id];
+ }
+
+ function quoteRegExp(string, pattern, squash, optional) {
+ var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&");
+ if (!pattern) return result;
+ switch(squash) {
+ case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break;
+ case true:
+ result = result.replace(/\/$/, '');
+ surroundPattern = ['(?:\/(', ')|\/)?'];
+ break;
+ default: surroundPattern = ['(' + squash + "|", ')?']; break;
+ }
+ return result + surroundPattern[0] + pattern + surroundPattern[1];
+ }
+
+ this.source = pattern;
+
+ // Split into static segments separated by path parameter placeholders.
+ // The number of segments is always 1 more than the number of parameters.
+ function matchDetails(m, isSearch) {
+ var id, regexp, segment, type, cfg, arrayMode;
+ id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null
+ cfg = config.params[id];
+ segment = pattern.substring(last, m.index);
+ regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null);
+
+ if (regexp) {
+ type = $$UMFP.type(regexp) || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) });
+ }
+
+ return {
+ id: id, regexp: regexp, segment: segment, type: type, cfg: cfg
+ };
+ }
+
+ var p, param, segment;
+ while ((m = placeholder.exec(pattern))) {
+ p = matchDetails(m, false);
+ if (p.segment.indexOf('?') >= 0) break; // we're into the search part
+
+ param = addParameter(p.id, p.type, p.cfg, "path");
+ compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional);
+ segments.push(p.segment);
+ last = placeholder.lastIndex;
+ }
+ segment = pattern.substring(last);
+
+ // Find any search parameter names and remove them from the last segment
+ var i = segment.indexOf('?');
+
+ if (i >= 0) {
+ var search = this.sourceSearch = segment.substring(i);
+ segment = segment.substring(0, i);
+ this.sourcePath = pattern.substring(0, last + i);
+
+ if (search.length > 0) {
+ last = 0;
+ while ((m = searchPlaceholder.exec(search))) {
+ p = matchDetails(m, true);
+ param = addParameter(p.id, p.type, p.cfg, "search");
+ last = placeholder.lastIndex;
+ // check if ?&
+ }
+ }
+ } else {
+ this.sourcePath = pattern;
+ this.sourceSearch = '';
+ }
+
+ compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$';
+ segments.push(segment);
+
+ this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined);
+ this.prefix = segments[0];
+ this.$$paramNames = paramNames;
+}
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#concat
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Returns a new matcher for a pattern constructed by appending the path part and adding the
+ * search parameters of the specified pattern to this pattern. The current pattern is not
+ * modified. This can be understood as creating a pattern for URLs that are relative to (or
+ * suffixes of) the current pattern.
+ *
+ * @example
+ * The following two matchers are equivalent:
+ * <pre>
+ * new UrlMatcher('/user/{id}?q').concat('/details?date');
+ * new UrlMatcher('/user/{id}/details?q&date');
+ * </pre>
+ *
+ * @param {string} pattern The pattern to append.
+ * @param {Object} config An object hash of the configuration for the matcher.
+ * @returns {UrlMatcher} A matcher for the concatenated pattern.
+ */
+UrlMatcher.prototype.concat = function (pattern, config) {
+ // Because order of search parameters is irrelevant, we can add our own search
+ // parameters to the end of the new pattern. Parse the new pattern by itself
+ // and then join the bits together, but it's much easier to do this on a string level.
+ var defaultConfig = {
+ caseInsensitive: $$UMFP.caseInsensitive(),
+ strict: $$UMFP.strictMode(),
+ squash: $$UMFP.defaultSquashPolicy()
+ };
+ return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);
+};
+
+UrlMatcher.prototype.toString = function () {
+ return this.source;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#exec
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Tests the specified path against this matcher, and returns an object containing the captured
+ * parameter values, or null if the path does not match. The returned object contains the values
+ * of any search parameters that are mentioned in the pattern, but their value may be null if
+ * they are not present in `searchParams`. This means that search parameters are always treated
+ * as optional.
+ *
+ * @example
+ * <pre>
+ * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
+ * x: '1', q: 'hello'
+ * });
+ * // returns { id: 'bob', q: 'hello', r: null }
+ * </pre>
+ *
+ * @param {string} path The URL path to match, e.g. `$location.path()`.
+ * @param {Object} searchParams URL search parameters, e.g. `$location.search()`.
+ * @returns {Object} The captured parameter values.
+ */
+UrlMatcher.prototype.exec = function (path, searchParams) {
+ var m = this.regexp.exec(path);
+ if (!m) return null;
+ searchParams = searchParams || {};
+
+ var paramNames = this.parameters(), nTotal = paramNames.length,
+ nPath = this.segments.length - 1,
+ values = {}, i, j, cfg, paramName;
+
+ if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'");
+
+ function decodePathArray(string) {
+ function reverseString(str) { return str.split("").reverse().join(""); }
+ function unquoteDashes(str) { return str.replace(/\\-/g, "-"); }
+
+ var split = reverseString(string).split(/-(?!\\)/);
+ var allReversed = map(split, reverseString);
+ return map(allReversed, unquoteDashes).reverse();
+ }
+
+ var param, paramVal;
+ for (i = 0; i < nPath; i++) {
+ paramName = paramNames[i];
+ param = this.params[paramName];
+ paramVal = m[i+1];
+ // if the param value matches a pre-replace pair, replace the value before decoding.
+ for (j = 0; j < param.replace.length; j++) {
+ if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
+ }
+ if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);
+ if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
+ values[paramName] = param.value(paramVal);
+ }
+ for (/**/; i < nTotal; i++) {
+ paramName = paramNames[i];
+ values[paramName] = this.params[paramName].value(searchParams[paramName]);
+ param = this.params[paramName];
+ paramVal = searchParams[paramName];
+ for (j = 0; j < param.replace.length; j++) {
+ if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
+ }
+ if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
+ values[paramName] = param.value(paramVal);
+ }
+
+ return values;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#parameters
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Returns the names of all path and search parameters of this pattern in an unspecified order.
+ *
+ * @returns {Array.<string>} An array of parameter names. Must be treated as read-only. If the
+ * pattern has no parameters, an empty array is returned.
+ */
+UrlMatcher.prototype.parameters = function (param) {
+ if (!isDefined(param)) return this.$$paramNames;
+ return this.params[param] || null;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#validates
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Checks an object hash of parameters to validate their correctness according to the parameter
+ * types of this `UrlMatcher`.
+ *
+ * @param {Object} params The object hash of parameters to validate.
+ * @returns {boolean} Returns `true` if `params` validates, otherwise `false`.
+ */
+UrlMatcher.prototype.validates = function (params) {
+ return this.params.$$validates(params);
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#format
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Creates a URL that matches this pattern by substituting the specified values
+ * for the path and search parameters. Null values for path parameters are
+ * treated as empty strings.
+ *
+ * @example
+ * <pre>
+ * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
+ * // returns '/user/bob?q=yes'
+ * </pre>
+ *
+ * @param {Object} values the values to substitute for the parameters in this pattern.
+ * @returns {string} the formatted URL (path and optionally search part).
+ */
+UrlMatcher.prototype.format = function (values) {
+ values = values || {};
+ var segments = this.segments, params = this.parameters(), paramset = this.params;
+ if (!this.validates(values)) return null;
+
+ var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0];
+
+ function encodeDashes(str) { // Replace dashes with encoded "\-"
+ return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); });
+ }
+
+ for (i = 0; i < nTotal; i++) {
+ var isPathParam = i < nPath;
+ var name = params[i], param = paramset[name], value = param.value(values[name]);
+ var isDefaultValue = param.isOptional && param.type.equals(param.value(), value);
+ var squash = isDefaultValue ? param.squash : false;
+ var encoded = param.type.encode(value);
+
+ if (isPathParam) {
+ var nextSegment = segments[i + 1];
+ var isFinalPathParam = i + 1 === nPath;
+
+ if (squash === false) {
+ if (encoded != null) {
+ if (isArray(encoded)) {
+ result += map(encoded, encodeDashes).join("-");
+ } else {
+ result += encodeURIComponent(encoded);
+ }
+ }
+ result += nextSegment;
+ } else if (squash === true) {
+ var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/;
+ result += nextSegment.match(capture)[1];
+ } else if (isString(squash)) {
+ result += squash + nextSegment;
+ }
+
+ if (isFinalPathParam && param.squash === true && result.slice(-1) === '/') result = result.slice(0, -1);
+ } else {
+ if (encoded == null || (isDefaultValue && squash !== false)) continue;
+ if (!isArray(encoded)) encoded = [ encoded ];
+ if (encoded.length === 0) continue;
+ encoded = map(encoded, encodeURIComponent).join('&' + name + '=');
+ result += (search ? '&' : '?') + (name + '=' + encoded);
+ search = true;
+ }
+ }
+
+ return result;
+};
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.type:Type
+ *
+ * @description
+ * Implements an interface to define custom parameter types that can be decoded from and encoded to
+ * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`}
+ * objects when matching or formatting URLs, or comparing or validating parameter values.
+ *
+ * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more
+ * information on registering custom types.
+ *
+ * @param {Object} config A configuration object which contains the custom type definition. The object's
+ * properties will override the default methods and/or pattern in `Type`'s public interface.
+ * @example
+ * <pre>
+ * {
+ * decode: function(val) { return parseInt(val, 10); },
+ * encode: function(val) { return val && val.toString(); },
+ * equals: function(a, b) { return this.is(a) && a === b; },
+ * is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
+ * pattern: /\d+/
+ * }
+ * </pre>
+ *
+ * @property {RegExp} pattern The regular expression pattern used to match values of this type when
+ * coming from a substring of a URL.
+ *
+ * @returns {Object} Returns a new `Type` object.
+ */
+function Type(config) {
+ extend(this, config);
+}
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#is
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Detects whether a value is of a particular type. Accepts a native (decoded) value
+ * and determines whether it matches the current `Type` object.
+ *
+ * @param {*} val The value to check.
+ * @param {string} key Optional. If the type check is happening in the context of a specific
+ * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the
+ * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects.
+ * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`.
+ */
+Type.prototype.is = function(val, key) {
+ return true;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#encode
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the
+ * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
+ * only needs to be a representation of `val` that has been coerced to a string.
+ *
+ * @param {*} val The value to encode.
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
+ * meta-programming of `Type` objects.
+ * @returns {string} Returns a string representation of `val` that can be encoded in a URL.
+ */
+Type.prototype.encode = function(val, key) {
+ return val;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#decode
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Converts a parameter value (from URL string or transition param) to a custom/native value.
+ *
+ * @param {string} val The URL parameter value to decode.
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
+ * meta-programming of `Type` objects.
+ * @returns {*} Returns a custom representation of the URL parameter value.
+ */
+Type.prototype.decode = function(val, key) {
+ return val;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#equals
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Determines whether two decoded values are equivalent.
+ *
+ * @param {*} a A value to compare against.
+ * @param {*} b A value to compare against.
+ * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`.
+ */
+Type.prototype.equals = function(a, b) {
+ return a == b;
+};
+
+Type.prototype.$subPattern = function() {
+ var sub = this.pattern.toString();
+ return sub.substr(1, sub.length - 2);
+};
+
+Type.prototype.pattern = /.*/;
+
+Type.prototype.toString = function() { return "{Type:" + this.name + "}"; };
+
+/** Given an encoded string, or a decoded object, returns a decoded object */
+Type.prototype.$normalize = function(val) {
+ return this.is(val) ? val : this.decode(val);
+};
+
+/*
+ * Wraps an existing custom Type as an array of Type, depending on 'mode'.
+ * e.g.:
+ * - urlmatcher pattern "/path?{queryParam[]:int}"
+ * - url: "/path?queryParam=1&queryParam=2
+ * - $stateParams.queryParam will be [1, 2]
+ * if `mode` is "auto", then
+ * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
+ * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
+ */
+Type.prototype.$asArray = function(mode, isSearch) {
+ if (!mode) return this;
+ if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only");
+
+ function ArrayType(type, mode) {
+ function bindTo(type, callbackName) {
+ return function() {
+ return type[callbackName].apply(type, arguments);
+ };
+ }
+
+ // Wrap non-array value as array
+ function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); }
+ // Unwrap array value for "auto" mode. Return undefined for empty array.
+ function arrayUnwrap(val) {
+ switch(val.length) {
+ case 0: return undefined;
+ case 1: return mode === "auto" ? val[0] : val;
+ default: return val;
+ }
+ }
+ function falsey(val) { return !val; }
+
+ // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
+ function arrayHandler(callback, allTruthyMode) {
+ return function handleArray(val) {
+ if (isArray(val) && val.length === 0) return val;
+ val = arrayWrap(val);
+ var result = map(val, callback);
+ if (allTruthyMode === true)
+ return filter(result, falsey).length === 0;
+ return arrayUnwrap(result);
+ };
+ }
+
+ // Wraps type (.equals) functions to operate on each value of an array
+ function arrayEqualsHandler(callback) {
+ return function handleArray(val1, val2) {
+ var left = arrayWrap(val1), right = arrayWrap(val2);
+ if (left.length !== right.length) return false;
+ for (var i = 0; i < left.length; i++) {
+ if (!callback(left[i], right[i])) return false;
+ }
+ return true;
+ };
+ }
+
+ this.encode = arrayHandler(bindTo(type, 'encode'));
+ this.decode = arrayHandler(bindTo(type, 'decode'));
+ this.is = arrayHandler(bindTo(type, 'is'), true);
+ this.equals = arrayEqualsHandler(bindTo(type, 'equals'));
+ this.pattern = type.pattern;
+ this.$normalize = arrayHandler(bindTo(type, '$normalize'));
+ this.name = type.name;
+ this.$arrayMode = mode;
+ }
+
+ return new ArrayType(this, mode);
+};
+
+
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory
+ * is also available to providers under the name `$urlMatcherFactoryProvider`.
+ */
+function $UrlMatcherFactory() {
+ $$UMFP = this;
+
+ var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false;
+
+ // Use tildes to pre-encode slashes.
+ // If the slashes are simply URLEncoded, the browser can choose to pre-decode them,
+ // and bidirectional encoding/decoding fails.
+ // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character
+ function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; }
+ function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; }
+
+ var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
+ "string": {
+ encode: valToString,
+ decode: valFromString,
+ // TODO: in 1.0, make string .is() return false if value is undefined/null by default.
+ // In 0.2.x, string params are optional by default for backwards compat
+ is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; },
+ pattern: /[^/]*/
+ },
+ "int": {
+ encode: valToString,
+ decode: function(val) { return parseInt(val, 10); },
+ is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; },
+ pattern: /\d+/
+ },
+ "bool": {
+ encode: function(val) { return val ? 1 : 0; },
+ decode: function(val) { return parseInt(val, 10) !== 0; },
+ is: function(val) { return val === true || val === false; },
+ pattern: /0|1/
+ },
+ "date": {
+ encode: function (val) {
+ if (!this.is(val))
+ return undefined;
+ return [ val.getFullYear(),
+ ('0' + (val.getMonth() + 1)).slice(-2),
+ ('0' + val.getDate()).slice(-2)
+ ].join("-");
+ },
+ decode: function (val) {
+ if (this.is(val)) return val;
+ var match = this.capture.exec(val);
+ return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
+ },
+ is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); },
+ equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); },
+ pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
+ capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
+ },
+ "json": {
+ encode: angular.toJson,
+ decode: angular.fromJson,
+ is: angular.isObject,
+ equals: angular.equals,
+ pattern: /[^/]*/
+ },
+ "any": { // does not encode/decode
+ encode: angular.identity,
+ decode: angular.identity,
+ equals: angular.equals,
+ pattern: /.*/
+ }
+ };
+
+ function getDefaultConfig() {
+ return {
+ strict: isStrictMode,
+ caseInsensitive: isCaseInsensitive
+ };
+ }
+
+ function isInjectable(value) {
+ return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));
+ }
+
+ /**
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
+ */
+ $UrlMatcherFactory.$$getDefaultValue = function(config) {
+ if (!isInjectable(config.value)) return config.value;
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
+ return injector.invoke(config.value);
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#caseInsensitive
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Defines whether URL matching should be case sensitive (the default behavior), or not.
+ *
+ * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`;
+ * @returns {boolean} the current value of caseInsensitive
+ */
+ this.caseInsensitive = function(value) {
+ if (isDefined(value))
+ isCaseInsensitive = value;
+ return isCaseInsensitive;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#strictMode
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Defines whether URLs should match trailing slashes, or not (the default behavior).
+ *
+ * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`.
+ * @returns {boolean} the current value of strictMode
+ */
+ this.strictMode = function(value) {
+ if (isDefined(value))
+ isStrictMode = value;
+ return isStrictMode;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Sets the default behavior when generating or matching URLs with default parameter values.
+ *
+ * @param {string} value A string that defines the default parameter URL squashing behavior.
+ * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL
+ * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the
+ * parameter is surrounded by slashes, squash (remove) one slash from the URL
+ * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove)
+ * the parameter value from the URL and replace it with this string.
+ */
+ this.defaultSquashPolicy = function(value) {
+ if (!isDefined(value)) return defaultSquashPolicy;
+ if (value !== true && value !== false && !isString(value))
+ throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string");
+ defaultSquashPolicy = value;
+ return value;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#compile
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern.
+ *
+ * @param {string} pattern The URL pattern.
+ * @param {Object} config The config object hash.
+ * @returns {UrlMatcher} The UrlMatcher.
+ */
+ this.compile = function (pattern, config) {
+ return new UrlMatcher(pattern, extend(getDefaultConfig(), config));
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#isMatcher
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Returns true if the specified object is a `UrlMatcher`, or false otherwise.
+ *
+ * @param {Object} object The object to perform the type check against.
+ * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by
+ * implementing all the same methods.
+ */
+ this.isMatcher = function (o) {
+ if (!isObject(o)) return false;
+ var result = true;
+
+ forEach(UrlMatcher.prototype, function(val, name) {
+ if (isFunction(val)) {
+ result = result && (isDefined(o[name]) && isFunction(o[name]));
+ }
+ });
+ return result;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#type
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to
+ * generate URLs with typed parameters.
+ *
+ * @param {string} name The type name.
+ * @param {Object|Function} definition The type definition. See
+ * {@link ui.router.util.type:Type `Type`} for information on the values accepted.
+ * @param {Object|Function} definitionFn (optional) A function that is injected before the app
+ * runtime starts. The result of this function is merged into the existing `definition`.
+ * See {@link ui.router.util.type:Type `Type`} for information on the values accepted.
+ *
+ * @returns {Object} Returns `$urlMatcherFactoryProvider`.
+ *
+ * @example
+ * This is a simple example of a custom type that encodes and decodes items from an
+ * array, using the array index as the URL-encoded value:
+ *
+ * <pre>
+ * var list = ['John', 'Paul', 'George', 'Ringo'];
+ *
+ * $urlMatcherFactoryProvider.type('listItem', {
+ * encode: function(item) {
+ * // Represent the list item in the URL using its corresponding index
+ * return list.indexOf(item);
+ * },
+ * decode: function(item) {
+ * // Look up the list item by index
+ * return list[parseInt(item, 10)];
+ * },
+ * is: function(item) {
+ * // Ensure the item is valid by checking to see that it appears
+ * // in the list
+ * return list.indexOf(item) > -1;
+ * }
+ * });
+ *
+ * $stateProvider.state('list', {
+ * url: "/list/{item:listItem}",
+ * controller: function($scope, $stateParams) {
+ * console.log($stateParams.item);
+ * }
+ * });
+ *
+ * // ...
+ *
+ * // Changes URL to '/list/3', logs "Ringo" to the console
+ * $state.go('list', { item: "Ringo" });
+ * </pre>
+ *
+ * This is a more complex example of a type that relies on dependency injection to
+ * interact with services, and uses the parameter name from the URL to infer how to
+ * handle encoding and decoding parameter values:
+ *
+ * <pre>
+ * // Defines a custom type that gets a value from a service,
+ * // where each service gets different types of values from
+ * // a backend API:
+ * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
+ *
+ * // Matches up services to URL parameter names
+ * var services = {
+ * user: Users,
+ * post: Posts
+ * };
+ *
+ * return {
+ * encode: function(object) {
+ * // Represent the object in the URL using its unique ID
+ * return object.id;
+ * },
+ * decode: function(value, key) {
+ * // Look up the object by ID, using the parameter
+ * // name (key) to call the correct service
+ * return services[key].findById(value);
+ * },
+ * is: function(object, key) {
+ * // Check that object is a valid dbObject
+ * return angular.isObject(object) && object.id && services[key];
+ * }
+ * equals: function(a, b) {
+ * // Check the equality of decoded objects by comparing
+ * // their unique IDs
+ * return a.id === b.id;
+ * }
+ * };
+ * });
+ *
+ * // In a config() block, you can then attach URLs with
+ * // type-annotated parameters:
+ * $stateProvider.state('users', {
+ * url: "/users",
+ * // ...
+ * }).state('users.item', {
+ * url: "/{user:dbObject}",
+ * controller: function($scope, $stateParams) {
+ * // $stateParams.user will now be an object returned from
+ * // the Users service
+ * },
+ * // ...
+ * });
+ * </pre>
+ */
+ this.type = function (name, definition, definitionFn) {
+ if (!isDefined(definition)) return $types[name];
+ if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined.");
+
+ $types[name] = new Type(extend({ name: name }, definition));
+ if (definitionFn) {
+ typeQueue.push({ name: name, def: definitionFn });
+ if (!enqueue) flushTypeQueue();
+ }
+ return this;
+ };
+
+ // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s
+ function flushTypeQueue() {
+ while(typeQueue.length) {
+ var type = typeQueue.shift();
+ if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime.");
+ angular.extend($types[type.name], injector.invoke(type.def));
+ }
+ }
+
+ // Register default types. Store them in the prototype of $types.
+ forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); });
+ $types = inherit($types, {});
+
+ /* No need to document $get, since it returns this */
+ this.$get = ['$injector', function ($injector) {
+ injector = $injector;
+ enqueue = false;
+ flushTypeQueue();
+
+ forEach(defaultTypes, function(type, name) {
+ if (!$types[name]) $types[name] = new Type(type);
+ });
+ return this;
+ }];
+
+ this.Param = function Param(id, type, config, location) {
+ var self = this;
+ config = unwrapShorthand(config);
+ type = getType(config, type, location);
+ var arrayMode = getArrayMode();
+ type = arrayMode ? type.$asArray(arrayMode, location === "search") : type;
+ if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined)
+ config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to ""
+ var isOptional = config.value !== undefined;
+ var squash = getSquashPolicy(config, isOptional);
+ var replace = getReplace(config, arrayMode, isOptional, squash);
+
+ function unwrapShorthand(config) {
+ var keys = isObject(config) ? objectKeys(config) : [];
+ var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 &&
+ indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1;
+ if (isShorthand) config = { value: config };
+ config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; };
+ return config;
+ }
+
+ function getType(config, urlType, location) {
+ if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
+ if (urlType) return urlType;
+ if (!config.type) return (location === "config" ? $types.any : $types.string);
+
+ if (angular.isString(config.type))
+ return $types[config.type];
+ if (config.type instanceof Type)
+ return config.type;
+ return new Type(config.type);
+ }
+
+ // array config: param name (param[]) overrides default settings. explicit config overrides param name.
+ function getArrayMode() {
+ var arrayDefaults = { array: (location === "search" ? "auto" : false) };
+ var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
+ return extend(arrayDefaults, arrayParamNomenclature, config).array;
+ }
+
+ /**
+ * returns false, true, or the squash value to indicate the "default parameter url squash policy".
+ */
+ function getSquashPolicy(config, isOptional) {
+ var squash = config.squash;
+ if (!isOptional || squash === false) return false;
+ if (!isDefined(squash) || squash == null) return defaultSquashPolicy;
+ if (squash === true || isString(squash)) return squash;
+ throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string");
+ }
+
+ function getReplace(config, arrayMode, isOptional, squash) {
+ var replace, configuredKeys, defaultPolicy = [
+ { from: "", to: (isOptional || arrayMode ? undefined : "") },
+ { from: null, to: (isOptional || arrayMode ? undefined : "") }
+ ];
+ replace = isArray(config.replace) ? config.replace : [];
+ if (isString(squash))
+ replace.push({ from: squash, to: undefined });
+ configuredKeys = map(replace, function(item) { return item.from; } );
+ return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace);
+ }
+
+ /**
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
+ */
+ function $$getDefaultValue() {
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
+ var defaultValue = injector.invoke(config.$$fn);
+ if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue))
+ throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")");
+ return defaultValue;
+ }
+
+ /**
+ * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
+ * default value, which may be the result of an injectable function.
+ */
+ function $value(value) {
+ function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; }
+ function $replace(value) {
+ var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; });
+ return replacement.length ? replacement[0] : value;
+ }
+ value = $replace(value);
+ return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value);
+ }
+
+ function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; }
+
+ extend(this, {
+ id: id,
+ type: type,
+ location: location,
+ array: arrayMode,
+ squash: squash,
+ replace: replace,
+ isOptional: isOptional,
+ value: $value,
+ dynamic: undefined,
+ config: config,
+ toString: toString
+ });
+ };
+
+ function ParamSet(params) {
+ extend(this, params || {});
+ }
+
+ ParamSet.prototype = {
+ $$new: function() {
+ return inherit(this, extend(new ParamSet(), { $$parent: this}));
+ },
+ $$keys: function () {
+ var keys = [], chain = [], parent = this,
+ ignore = objectKeys(ParamSet.prototype);
+ while (parent) { chain.push(parent); parent = parent.$$parent; }
+ chain.reverse();
+ forEach(chain, function(paramset) {
+ forEach(objectKeys(paramset), function(key) {
+ if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key);
+ });
+ });
+ return keys;
+ },
+ $$values: function(paramValues) {
+ var values = {}, self = this;
+ forEach(self.$$keys(), function(key) {
+ values[key] = self[key].value(paramValues && paramValues[key]);
+ });
+ return values;
+ },
+ $$equals: function(paramValues1, paramValues2) {
+ var equal = true, self = this;
+ forEach(self.$$keys(), function(key) {
+ var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key];
+ if (!self[key].type.equals(left, right)) equal = false;
+ });
+ return equal;
+ },
+ $$validates: function $$validate(paramValues) {
+ var keys = this.$$keys(), i, param, rawVal, normalized, encoded;
+ for (i = 0; i < keys.length; i++) {
+ param = this[keys[i]];
+ rawVal = paramValues[keys[i]];
+ if ((rawVal === undefined || rawVal === null) && param.isOptional)
+ break; // There was no parameter value, but the param is optional
+ normalized = param.type.$normalize(rawVal);
+ if (!param.type.is(normalized))
+ return false; // The value was not of the correct Type, and could not be decoded to the correct Type
+ encoded = param.type.encode(normalized);
+ if (angular.isString(encoded) && !param.type.pattern.exec(encoded))
+ return false; // The value was of the correct type, but when encoded, did not match the Type's regexp
+ }
+ return true;
+ },
+ $$parent: undefined
+ };
+
+ this.ParamSet = ParamSet;
+}
+
+// Register as a provider so it's available to other providers
+angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
+angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]);
+
+/**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouterProvider
+ *
+ * @requires ui.router.util.$urlMatcherFactoryProvider
+ * @requires $locationProvider
+ *
+ * @description
+ * `$urlRouterProvider` has the responsibility of watching `$location`.
+ * When `$location` changes it runs through a list of rules one by one until a
+ * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify
+ * a url in a state configuration. All urls are compiled into a UrlMatcher object.
+ *
+ * There are several methods on `$urlRouterProvider` that make it useful to use directly
+ * in your module config.
+ */
+$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];
+function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
+ var rules = [], otherwise = null, interceptDeferred = false, listener;
+
+ // Returns a string that is a prefix of all strings matching the RegExp
+ function regExpPrefix(re) {
+ var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source);
+ return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : '';
+ }
+
+ // Interpolates matched values into a String.replace()-style pattern
+ function interpolate(pattern, match) {
+ return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) {
+ return match[what === '$' ? 0 : Number(what)];
+ });
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#rule
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Defines rules that are used by `$urlRouterProvider` to find matches for
+ * specific URLs.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * // Here's an example of how you might allow case insensitive urls
+ * $urlRouterProvider.rule(function ($injector, $location) {
+ * var path = $location.path(),
+ * normalized = path.toLowerCase();
+ *
+ * if (path !== normalized) {
+ * return normalized;
+ * }
+ * });
+ * });
+ * </pre>
+ *
+ * @param {function} rule Handler function that takes `$injector` and `$location`
+ * services as arguments. You can use them to return a valid path as a string.
+ *
+ * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
+ */
+ this.rule = function (rule) {
+ if (!isFunction(rule)) throw new Error("'rule' must be a function");
+ rules.push(rule);
+ return this;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouterProvider#otherwise
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Defines a path that is used when an invalid route is requested.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * // if the path doesn't match any of the urls you configured
+ * // otherwise will take care of routing the user to the
+ * // specified url
+ * $urlRouterProvider.otherwise('/index');
+ *
+ * // Example of using function rule as param
+ * $urlRouterProvider.otherwise(function ($injector, $location) {
+ * return '/a/valid/url';
+ * });
+ * });
+ * </pre>
+ *
+ * @param {string|function} rule The url path you want to redirect to or a function
+ * rule that returns the url path. The function version is passed two params:
+ * `$injector` and `$location` services, and must return a url string.
+ *
+ * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
+ */
+ this.otherwise = function (rule) {
+ if (isString(rule)) {
+ var redirect = rule;
+ rule = function () { return redirect; };
+ }
+ else if (!isFunction(rule)) throw new Error("'rule' must be a function");
+ otherwise = rule;
+ return this;
+ };
+
+
+ function handleIfMatch($injector, handler, match) {
+ if (!match) return false;
+ var result = $injector.invoke(handler, handler, { $match: match });
+ return isDefined(result) ? result : true;
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#when
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Registers a handler for a given url matching.
+ *
+ * If the handler is a string, it is
+ * treated as a redirect, and is interpolated according to the syntax of match
+ * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
+ *
+ * If the handler is a function, it is injectable. It gets invoked if `$location`
+ * matches. You have the option of inject the match object as `$match`.
+ *
+ * The handler can return
+ *
+ * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
+ * will continue trying to find another one that matches.
+ * - **string** which is treated as a redirect and passed to `$location.url()`
+ * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * $urlRouterProvider.when($state.url, function ($match, $stateParams) {
+ * if ($state.$current.navigable !== state ||
+ * !equalForKeys($match, $stateParams) {
+ * $state.transitionTo(state, $match, false);
+ * }
+ * });
+ * });
+ * </pre>
+ *
+ * @param {string|object} what The incoming path that you want to redirect.
+ * @param {string|function} handler The path you want to redirect your user to.
+ */
+ this.when = function (what, handler) {
+ var redirect, handlerIsString = isString(handler);
+ if (isString(what)) what = $urlMatcherFactory.compile(what);
+
+ if (!handlerIsString && !isFunction(handler) && !isArray(handler))
+ throw new Error("invalid 'handler' in when()");
+
+ var strategies = {
+ matcher: function (what, handler) {
+ if (handlerIsString) {
+ redirect = $urlMatcherFactory.compile(handler);
+ handler = ['$match', function ($match) { return redirect.format($match); }];
+ }
+ return extend(function ($injector, $location) {
+ return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
+ }, {
+ prefix: isString(what.prefix) ? what.prefix : ''
+ });
+ },
+ regex: function (what, handler) {
+ if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
+
+ if (handlerIsString) {
+ redirect = handler;
+ handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
+ }
+ return extend(function ($injector, $location) {
+ return handleIfMatch($injector, handler, what.exec($location.path()));
+ }, {
+ prefix: regExpPrefix(what)
+ });
+ }
+ };
+
+ var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
+
+ for (var n in check) {
+ if (check[n]) return this.rule(strategies[n](what, handler));
+ }
+
+ throw new Error("invalid 'what' in when()");
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#deferIntercept
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Disables (or enables) deferring location change interception.
+ *
+ * If you wish to customize the behavior of syncing the URL (for example, if you wish to
+ * defer a transition but maintain the current URL), call this method at configuration time.
+ * Then, at run time, call `$urlRouter.listen()` after you have configured your own
+ * `$locationChangeSuccess` event handler.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ *
+ * // Prevent $urlRouter from automatically intercepting URL changes;
+ * // this allows you to configure custom behavior in between
+ * // location changes and route synchronization:
+ * $urlRouterProvider.deferIntercept();
+ *
+ * }).run(function ($rootScope, $urlRouter, UserService) {
+ *
+ * $rootScope.$on('$locationChangeSuccess', function(e) {
+ * // UserService is an example service for managing user state
+ * if (UserService.isLoggedIn()) return;
+ *
+ * // Prevent $urlRouter's default handler from firing
+ * e.preventDefault();
+ *
+ * UserService.handleLogin().then(function() {
+ * // Once the user has logged in, sync the current URL
+ * // to the router:
+ * $urlRouter.sync();
+ * });
+ * });
+ *
+ * // Configures $urlRouter's listener *after* your custom listener
+ * $urlRouter.listen();
+ * });
+ * </pre>
+ *
+ * @param {boolean} defer Indicates whether to defer location change interception. Passing
+ no parameter is equivalent to `true`.
+ */
+ this.deferIntercept = function (defer) {
+ if (defer === undefined) defer = true;
+ interceptDeferred = defer;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouter
+ *
+ * @requires $location
+ * @requires $rootScope
+ * @requires $injector
+ * @requires $browser
+ *
+ * @description
+ *
+ */
+ this.$get = $get;
+ $get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer'];
+ function $get( $location, $rootScope, $injector, $browser, $sniffer) {
+
+ var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl;
+
+ function appendBasePath(url, isHtml5, absolute) {
+ if (baseHref === '/') return url;
+ if (isHtml5) return baseHref.slice(0, -1) + url;
+ if (absolute) return baseHref.slice(1) + url;
+ return url;
+ }
+
+ // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree
+ function update(evt) {
+ if (evt && evt.defaultPrevented) return;
+ var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;
+ lastPushedUrl = undefined;
+ // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573
+ //if (ignoreUpdate) return true;
+
+ function check(rule) {
+ var handled = rule($injector, $location);
+
+ if (!handled) return false;
+ if (isString(handled)) $location.replace().url(handled);
+ return true;
+ }
+ var n = rules.length, i;
+
+ for (i = 0; i < n; i++) {
+ if (check(rules[i])) return;
+ }
+ // always check otherwise last to allow dynamic updates to the set of rules
+ if (otherwise) check(otherwise);
+ }
+
+ function listen() {
+ listener = listener || $rootScope.$on('$locationChangeSuccess', update);
+ return listener;
+ }
+
+ if (!interceptDeferred) listen();
+
+ return {
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouter#sync
+ * @methodOf ui.router.router.$urlRouter
+ *
+ * @description
+ * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.
+ * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,
+ * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed
+ * with the transition by calling `$urlRouter.sync()`.
+ *
+ * @example
+ * <pre>
+ * angular.module('app', ['ui.router'])
+ * .run(function($rootScope, $urlRouter) {
+ * $rootScope.$on('$locationChangeSuccess', function(evt) {
+ * // Halt state change from even starting
+ * evt.preventDefault();
+ * // Perform custom logic
+ * var meetsRequirement = ...
+ * // Continue with the update and state transition if logic allows
+ * if (meetsRequirement) $urlRouter.sync();
+ * });
+ * });
+ * </pre>
+ */
+ sync: function() {
+ update();
+ },
+
+ listen: function() {
+ return listen();
+ },
+
+ update: function(read) {
+ if (read) {
+ location = $location.url();
+ return;
+ }
+ if ($location.url() === location) return;
+
+ $location.url(location);
+ $location.replace();
+ },
+
+ push: function(urlMatcher, params, options) {
+ var url = urlMatcher.format(params || {});
+
+ // Handle the special hash param, if needed
+ if (url !== null && params && params['#']) {
+ url += '#' + params['#'];
+ }
+
+ $location.url(url);
+ lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined;
+ if (options && options.replace) $location.replace();
+ },
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouter#href
+ * @methodOf ui.router.router.$urlRouter
+ *
+ * @description
+ * A URL generation method that returns the compiled URL for a given
+ * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters.
+ *
+ * @example
+ * <pre>
+ * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
+ * person: "bob"
+ * });
+ * // $bob == "/about/bob";
+ * </pre>
+ *
+ * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate.
+ * @param {object=} params An object of parameter values to fill the matcher's required parameters.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
+ *
+ * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`
+ */
+ href: function(urlMatcher, params, options) {
+ if (!urlMatcher.validates(params)) return null;
+
+ var isHtml5 = $locationProvider.html5Mode();
+ if (angular.isObject(isHtml5)) {
+ isHtml5 = isHtml5.enabled;
+ }
+
+ isHtml5 = isHtml5 && $sniffer.history;
+
+ var url = urlMatcher.format(params);
+ options = options || {};
+
+ if (!isHtml5 && url !== null) {
+ url = "#" + $locationProvider.hashPrefix() + url;
+ }
+
+ // Handle special hash param, if needed
+ if (url !== null && params && params['#']) {
+ url += '#' + params['#'];
+ }
+
+ url = appendBasePath(url, isHtml5, options.absolute);
+
+ if (!options.absolute || !url) {
+ return url;
+ }
+
+ var slash = (!isHtml5 && url ? '/' : ''), port = $location.port();
+ port = (port === 80 || port === 443 ? '' : ':' + port);
+
+ return [$location.protocol(), '://', $location.host(), port, slash, url].join('');
+ }
+ };
+ }
+}
+
+angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
+
+/**
+ * @ngdoc object
+ * @name ui.router.state.$stateProvider
+ *
+ * @requires ui.router.router.$urlRouterProvider
+ * @requires ui.router.util.$urlMatcherFactoryProvider
+ *
+ * @description
+ * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely
+ * on state.
+ *
+ * A state corresponds to a "place" in the application in terms of the overall UI and
+ * navigation. A state describes (via the controller / template / view properties) what
+ * the UI looks like and does at that place.
+ *
+ * States often have things in common, and the primary way of factoring out these
+ * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
+ * nested states.
+ *
+ * The `$stateProvider` provides interfaces to declare these states for your app.
+ */
+$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];
+function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
+
+ var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
+
+ // Builds state properties from definition passed to registerState()
+ var stateBuilder = {
+
+ // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined.
+ // state.children = [];
+ // if (parent) parent.children.push(state);
+ parent: function(state) {
+ if (isDefined(state.parent) && state.parent) return findState(state.parent);
+ // regex matches any valid composite state name
+ // would match "contact.list" but not "contacts"
+ var compositeName = /^(.+)\.[^.]+$/.exec(state.name);
+ return compositeName ? findState(compositeName[1]) : root;
+ },
+
+ // inherit 'data' from parent and override by own values (if any)
+ data: function(state) {
+ if (state.parent && state.parent.data) {
+ state.data = state.self.data = inherit(state.parent.data, state.data);
+ }
+ return state.data;
+ },
+
+ // Build a URLMatcher if necessary, either via a relative or absolute URL
+ url: function(state) {
+ var url = state.url, config = { params: state.params || {} };
+
+ if (isString(url)) {
+ if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);
+ return (state.parent.navigable || root).url.concat(url, config);
+ }
+
+ if (!url || $urlMatcherFactory.isMatcher(url)) return url;
+ throw new Error("Invalid url '" + url + "' in state '" + state + "'");
+ },
+
+ // Keep track of the closest ancestor state that has a URL (i.e. is navigable)
+ navigable: function(state) {
+ return state.url ? state : (state.parent ? state.parent.navigable : null);
+ },
+
+ // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
+ ownParams: function(state) {
+ var params = state.url && state.url.params || new $$UMFP.ParamSet();
+ forEach(state.params || {}, function(config, id) {
+ if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config");
+ });
+ return params;
+ },
+
+ // Derive parameters for this state and ensure they're a super-set of parent's parameters
+ params: function(state) {
+ var ownParams = pick(state.ownParams, state.ownParams.$$keys());
+ return state.parent && state.parent.params ? extend(state.parent.params.$$new(), ownParams) : new $$UMFP.ParamSet();
+ },
+
+ // If there is no explicit multi-view configuration, make one up so we don't have
+ // to handle both cases in the view directive later. Note that having an explicit
+ // 'views' property will mean the default unnamed view properties are ignored. This
+ // is also a good time to resolve view names to absolute names, so everything is a
+ // straight lookup at link time.
+ views: function(state) {
+ var views = {};
+
+ forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) {
+ if (name.indexOf('@') < 0) name += '@' + state.parent.name;
+ views[name] = view;
+ });
+ return views;
+ },
+
+ // Keep a full path from the root down to this state as this is needed for state activation.
+ path: function(state) {
+ return state.parent ? state.parent.path.concat(state) : []; // exclude root from path
+ },
+
+ // Speed up $state.contains() as it's used a lot
+ includes: function(state) {
+ var includes = state.parent ? extend({}, state.parent.includes) : {};
+ includes[state.name] = true;
+ return includes;
+ },
+
+ $delegates: {}
+ };
+
+ function isRelative(stateName) {
+ return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0;
+ }
+
+ function findState(stateOrName, base) {
+ if (!stateOrName) return undefined;
+
+ var isStr = isString(stateOrName),
+ name = isStr ? stateOrName : stateOrName.name,
+ path = isRelative(name);
+
+ if (path) {
+ if (!base) throw new Error("No reference point given for path '" + name + "'");
+ base = findState(base);
+
+ var rel = name.split("."), i = 0, pathLength = rel.length, current = base;
+
+ for (; i < pathLength; i++) {
+ if (rel[i] === "" && i === 0) {
+ current = base;
+ continue;
+ }
+ if (rel[i] === "^") {
+ if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'");
+ current = current.parent;
+ continue;
+ }
+ break;
+ }
+ rel = rel.slice(i).join(".");
+ name = current.name + (current.name && rel ? "." : "") + rel;
+ }
+ var state = states[name];
+
+ if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {
+ return state;
+ }
+ return undefined;
+ }
+
+ function queueState(parentName, state) {
+ if (!queue[parentName]) {
+ queue[parentName] = [];
+ }
+ queue[parentName].push(state);
+ }
+
+ function flushQueuedChildren(parentName) {
+ var queued = queue[parentName] || [];
+ while(queued.length) {
+ registerState(queued.shift());
+ }
+ }
+
+ function registerState(state) {
+ // Wrap a new object around the state so we can store our private details easily.
+ state = inherit(state, {
+ self: state,
+ resolve: state.resolve || {},
+ toString: function() { return this.name; }
+ });
+
+ var name = state.name;
+ if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name");
+ if (states.hasOwnProperty(name)) throw new Error("State '" + name + "' is already defined");
+
+ // Get parent name
+ var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))
+ : (isString(state.parent)) ? state.parent
+ : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name
+ : '';
+
+ // If parent is not registered yet, add state to queue and register later
+ if (parentName && !states[parentName]) {
+ return queueState(parentName, state.self);
+ }
+
+ for (var key in stateBuilder) {
+ if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]);
+ }
+ states[name] = state;
+
+ // Register the state in the global state list and with $urlRouter if necessary.
+ if (!state[abstractKey] && state.url) {
+ $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
+ if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
+ $state.transitionTo(state, $match, { inherit: true, location: false });
+ }
+ }]);
+ }
+
+ // Register any queued children
+ flushQueuedChildren(name);
+
+ return state;
+ }
+
+ // Checks text to see if it looks like a glob.
+ function isGlob (text) {
+ return text.indexOf('*') > -1;
+ }
+
+ // Returns true if glob matches current $state name.
+ function doesStateMatchGlob (glob) {
+ var globSegments = glob.split('.'),
+ segments = $state.$current.name.split('.');
+
+ //match single stars
+ for (var i = 0, l = globSegments.length; i < l; i++) {
+ if (globSegments[i] === '*') {
+ segments[i] = '*';
+ }
+ }
+
+ //match greedy starts
+ if (globSegments[0] === '**') {
+ segments = segments.slice(indexOf(segments, globSegments[1]));
+ segments.unshift('**');
+ }
+ //match greedy ends
+ if (globSegments[globSegments.length - 1] === '**') {
+ segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
+ segments.push('**');
+ }
+
+ if (globSegments.length != segments.length) {
+ return false;
+ }
+
+ return segments.join('') === globSegments.join('');
+ }
+
+
+ // Implicit root state that is always active
+ root = registerState({
+ name: '',
+ url: '^',
+ views: null,
+ 'abstract': true
+ });
+ root.navigable = null;
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$stateProvider#decorator
+ * @methodOf ui.router.state.$stateProvider
+ *
+ * @description
+ * Allows you to extend (carefully) or override (at your own peril) the
+ * `stateBuilder` object used internally by `$stateProvider`. This can be used
+ * to add custom functionality to ui-router, for example inferring templateUrl
+ * based on the state name.
+ *
+ * When passing only a name, it returns the current (original or decorated) builder
+ * function that matches `name`.
+ *
+ * The builder functions that can be decorated are listed below. Though not all
+ * necessarily have a good use case for decoration, that is up to you to decide.
+ *
+ * In addition, users can attach custom decorators, which will generate new
+ * properties within the state's internal definition. There is currently no clear
+ * use-case for this beyond accessing internal states (i.e. $state.$current),
+ * however, expect this to become increasingly relevant as we introduce additional
+ * meta-programming features.
+ *
+ * **Warning**: Decorators should not be interdependent because the order of
+ * execution of the builder functions in non-deterministic. Builder functions
+ * should only be dependent on the state definition object and super function.
+ *
+ *
+ * Existing builder functions and current return values:
+ *
+ * - **parent** `{object}` - returns the parent state object.
+ * - **data** `{object}` - returns state data, including any inherited data that is not
+ * overridden by own values (if any).
+ * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
+ * or `null`.
+ * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
+ * navigable).
+ * - **params** `{object}` - returns an array of state params that are ensured to
+ * be a super-set of parent's params.
+ * - **views** `{object}` - returns a views object where each key is an absolute view
+ * name (i.e. "viewName@stateName") and each value is the config object
+ * (template, controller) for the view. Even when you don't use the views object
+ * explicitly on a state config, one is still created for you internally.
+ * So by decorating this builder function you have access to decorating template
+ * and controller properties.
+ * - **ownParams** `{object}` - returns an array of params that belong to the state,
+ * not including any params defined by ancestor states.
+ * - **path** `{string}` - returns the full path from the root down to this state.
+ * Needed for state activation.
+ * - **includes** `{object}` - returns an object that includes every state that
+ * would pass a `$state.includes()` test.
+ *
+ * @example
+ * <pre>
+ * // Override the internal 'views' builder with a function that takes the state
+ * // definition, and a reference to the internal function being overridden:
+ * $stateProvider.decorator('views', function (state, parent) {
+ * var result = {},
+ * views = parent(state);
+ *
+ * angular.forEach(views, function (config, name) {
+ * var autoName = (state.name + '.' + name).replace('.', '/');
+ * config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
+ * result[name] = config;
+ * });
+ * return result;
+ * });
+ *
+ * $stateProvider.state('home', {
+ * views: {
+ * 'contact.list': { controller: 'ListController' },
+ * 'contact.item': { controller: 'ItemController' }
+ * }
+ * });
+ *
+ * // ...
+ *
+ * $state.go('home');
+ * // Auto-populates list and item views with /partials/home/contact/list.html,
+ * // and /partials/home/contact/item.html, respectively.
+ * </pre>
+ *
+ * @param {string} name The name of the builder function to decorate.
+ * @param {object} func A function that is responsible for decorating the original
+ * builder function. The function receives two parameters:
+ *
+ * - `{object}` - state - The state config object.
+ * - `{object}` - super - The original builder function.
+ *
+ * @return {object} $stateProvider - $stateProvider instance
+ */
+ this.decorator = decorator;
+ function decorator(name, func) {
+ /*jshint validthis: true */
+ if (isString(name) && !isDefined(func)) {
+ return stateBuilder[name];
+ }
+ if (!isFunction(func) || !isString(name)) {
+ return this;
+ }
+ if (stateBuilder[name] && !stateBuilder.$delegates[name]) {
+ stateBuilder.$delegates[name] = stateBuilder[name];
+ }
+ stateBuilder[name] = func;
+ return this;
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$stateProvider#state
+ * @methodOf ui.router.state.$stateProvider
+ *
+ * @description
+ * Registers a state configuration under a given state name. The stateConfig object
+ * has the following acceptable properties.
+ *
+ * @param {string} name A unique state name, e.g. "home", "about", "contacts".
+ * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
+ * @param {object} stateConfig State configuration object.
+ * @param {string|function=} stateConfig.template
+ * <a id='template'></a>
+ * html template as a string or a function that returns
+ * an html template as a string which should be used by the uiView directives. This property
+ * takes precedence over templateUrl.
+ *
+ * If `template` is a function, it will be called with the following parameters:
+ *
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
+ * applying the current state
+ *
+ * <pre>template:
+ * "<h1>inline template definition</h1>" +
+ * "<div ui-view></div>"</pre>
+ * <pre>template: function(params) {
+ * return "<h1>generated template</h1>"; }</pre>
+ * </div>
+ *
+ * @param {string|function=} stateConfig.templateUrl
+ * <a id='templateUrl'></a>
+ *
+ * path or function that returns a path to an html
+ * template that should be used by uiView.
+ *
+ * If `templateUrl` is a function, it will be called with the following parameters:
+ *
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
+ * applying the current state
+ *
+ * <pre>templateUrl: "home.html"</pre>
+ * <pre>templateUrl: function(params) {
+ * return myTemplates[params.pageId]; }</pre>
+ *
+ * @param {function=} stateConfig.templateProvider
+ * <a id='templateProvider'></a>
+ * Provider function that returns HTML content string.
+ * <pre> templateProvider:
+ * function(MyTemplateService, params) {
+ * return MyTemplateService.getTemplate(params.pageId);
+ * }</pre>
+ *
+ * @param {string|function=} stateConfig.controller
+ * <a id='controller'></a>
+ *
+ * Controller fn that should be associated with newly
+ * related scope or the name of a registered controller if passed as a string.
+ * Optionally, the ControllerAs may be declared here.
+ * <pre>controller: "MyRegisteredController"</pre>
+ * <pre>controller:
+ * "MyRegisteredController as fooCtrl"}</pre>
+ * <pre>controller: function($scope, MyService) {
+ * $scope.data = MyService.getData(); }</pre>
+ *
+ * @param {function=} stateConfig.controllerProvider
+ * <a id='controllerProvider'></a>
+ *
+ * Injectable provider function that returns the actual controller or string.
+ * <pre>controllerProvider:
+ * function(MyResolveData) {
+ * if (MyResolveData.foo)
+ * return "FooCtrl"
+ * else if (MyResolveData.bar)
+ * return "BarCtrl";
+ * else return function($scope) {
+ * $scope.baz = "Qux";
+ * }
+ * }</pre>
+ *
+ * @param {string=} stateConfig.controllerAs
+ * <a id='controllerAs'></a>
+ *
+ * A controller alias name. If present the controller will be
+ * published to scope under the controllerAs name.
+ * <pre>controllerAs: "myCtrl"</pre>
+ *
+ * @param {string|object=} stateConfig.parent
+ * <a id='parent'></a>
+ * Optionally specifies the parent state of this state.
+ *
+ * <pre>parent: 'parentState'</pre>
+ * <pre>parent: parentState // JS variable</pre>
+ *
+ * @param {object=} stateConfig.resolve
+ * <a id='resolve'></a>
+ *
+ * An optional map&lt;string, function&gt; of dependencies which
+ * should be injected into the controller. If any of these dependencies are promises,
+ * the router will wait for them all to be resolved before the controller is instantiated.
+ * If all the promises are resolved successfully, the $stateChangeSuccess event is fired
+ * and the values of the resolved promises are injected into any controllers that reference them.
+ * If any of the promises are rejected the $stateChangeError event is fired.
+ *
+ * The map object is:
+ *
+ * - key - {string}: name of dependency to be injected into controller
+ * - factory - {string|function}: If string then it is alias for service. Otherwise if function,
+ * it is injected and return value it treated as dependency. If result is a promise, it is
+ * resolved before its value is injected into controller.
+ *
+ * <pre>resolve: {
+ * myResolve1:
+ * function($http, $stateParams) {
+ * return $http.get("/api/foos/"+stateParams.fooID);
+ * }
+ * }</pre>
+ *
+ * @param {string=} stateConfig.url
+ * <a id='url'></a>
+ *
+ * A url fragment with optional parameters. When a state is navigated or
+ * transitioned to, the `$stateParams` service will be populated with any
+ * parameters that were passed.
+ *
+ * (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for
+ * more details on acceptable patterns )
+ *
+ * examples:
+ * <pre>url: "/home"
+ * url: "/users/:userid"
+ * url: "/books/{bookid:[a-zA-Z_-]}"
+ * url: "/books/{categoryid:int}"
+ * url: "/books/{publishername:string}/{categoryid:int}"
+ * url: "/messages?before&after"
+ * url: "/messages?{before:date}&{after:date}"
+ * url: "/messages/:mailboxid?{before:date}&{after:date}"
+ * </pre>
+ *
+ * @param {object=} stateConfig.views
+ * <a id='views'></a>
+ * an optional map&lt;string, object&gt; which defined multiple views, or targets views
+ * manually/explicitly.
+ *
+ * Examples:
+ *
+ * Targets three named `ui-view`s in the parent state's template
+ * <pre>views: {
+ * header: {
+ * controller: "headerCtrl",
+ * templateUrl: "header.html"
+ * }, body: {
+ * controller: "bodyCtrl",
+ * templateUrl: "body.html"
+ * }, footer: {
+ * controller: "footCtrl",
+ * templateUrl: "footer.html"
+ * }
+ * }</pre>
+ *
+ * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template.
+ * <pre>views: {
+ * 'header@top': {
+ * controller: "msgHeaderCtrl",
+ * templateUrl: "msgHeader.html"
+ * }, 'body': {
+ * controller: "messagesCtrl",
+ * templateUrl: "messages.html"
+ * }
+ * }</pre>
+ *
+ * @param {boolean=} [stateConfig.abstract=false]
+ * <a id='abstract'></a>
+ * An abstract state will never be directly activated,
+ * but can provide inherited properties to its common children states.
+ * <pre>abstract: true</pre>
+ *
+ * @param {function=} stateConfig.onEnter
+ * <a id='onEnter'></a>
+ *
+ * Callback function for when a state is entered. Good way
+ * to trigger an action or dispatch an event, such as opening a dialog.
+ * If minifying your scripts, make sure to explicitly annotate this function,
+ * because it won't be automatically annotated by your build tools.
+ *
+ * <pre>onEnter: function(MyService, $stateParams) {
+ * MyService.foo($stateParams.myParam);
+ * }</pre>
+ *
+ * @param {function=} stateConfig.onExit
+ * <a id='onExit'></a>
+ *
+ * Callback function for when a state is exited. Good way to
+ * trigger an action or dispatch an event, such as opening a dialog.
+ * If minifying your scripts, make sure to explicitly annotate this function,
+ * because it won't be automatically annotated by your build tools.
+ *
+ * <pre>onExit: function(MyService, $stateParams) {
+ * MyService.cleanup($stateParams.myParam);
+ * }</pre>
+ *
+ * @param {boolean=} [stateConfig.reloadOnSearch=true]
+ * <a id='reloadOnSearch'></a>
+ *
+ * If `false`, will not retrigger the same state
+ * just because a search/query parameter has changed (via $location.search() or $location.hash()).
+ * Useful for when you'd like to modify $location.search() without triggering a reload.
+ * <pre>reloadOnSearch: false</pre>
+ *
+ * @param {object=} stateConfig.data
+ * <a id='data'></a>
+ *
+ * Arbitrary data object, useful for custom configuration. The parent state's `data` is
+ * prototypally inherited. In other words, adding a data property to a state adds it to
+ * the entire subtree via prototypal inheritance.
+ *
+ * <pre>data: {
+ * requiredRole: 'foo'
+ * } </pre>
+ *
+ * @param {object=} stateConfig.params
+ * <a id='params'></a>
+ *
+ * A map which optionally configures parameters declared in the `url`, or
+ * defines additional non-url parameters. For each parameter being
+ * configured, add a configuration object keyed to the name of the parameter.
+ *
+ * Each parameter configuration object may contain the following properties:
+ *
+ * - ** value ** - {object|function=}: specifies the default value for this
+ * parameter. This implicitly sets this parameter as optional.
+ *
+ * When UI-Router routes to a state and no value is
+ * specified for this parameter in the URL or transition, the
+ * default value will be used instead. If `value` is a function,
+ * it will be injected and invoked, and the return value used.
+ *
+ * *Note*: `undefined` is treated as "no default value" while `null`
+ * is treated as "the default value is `null`".
+ *
+ * *Shorthand*: If you only need to configure the default value of the
+ * parameter, you may use a shorthand syntax. In the **`params`**
+ * map, instead mapping the param name to a full parameter configuration
+ * object, simply set map it to the default parameter value, e.g.:
+ *
+ * <pre>// define a parameter's default value
+ * params: {
+ * param1: { value: "defaultValue" }
+ * }
+ * // shorthand default values
+ * params: {
+ * param1: "defaultValue",
+ * param2: "param2Default"
+ * }</pre>
+ *
+ * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be
+ * treated as an array of values. If you specified a Type, the value will be
+ * treated as an array of the specified Type. Note: query parameter values
+ * default to a special `"auto"` mode.
+ *
+ * For query parameters in `"auto"` mode, if multiple values for a single parameter
+ * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values
+ * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if
+ * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single
+ * value (e.g.: `{ foo: '1' }`).
+ *
+ * <pre>params: {
+ * param1: { array: true }
+ * }</pre>
+ *
+ * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when
+ * the current parameter value is the same as the default value. If `squash` is not set, it uses the
+ * configured default squash policy.
+ * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`})
+ *
+ * There are three squash settings:
+ *
+ * - false: The parameter's default value is not squashed. It is encoded and included in the URL
+ * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed
+ * by slashes in the state's `url` declaration, then one of those slashes are omitted.
+ * This can allow for cleaner looking URLs.
+ * - `"<arbitrary string>"`: The parameter's default value is replaced with an arbitrary placeholder of your choice.
+ *
+ * <pre>params: {
+ * param1: {
+ * value: "defaultId",
+ * squash: true
+ * } }
+ * // squash "defaultValue" to "~"
+ * params: {
+ * param1: {
+ * value: "defaultValue",
+ * squash: "~"
+ * } }
+ * </pre>
+ *
+ *
+ * @example
+ * <pre>
+ * // Some state name examples
+ *
+ * // stateName can be a single top-level name (must be unique).
+ * $stateProvider.state("home", {});
+ *
+ * // Or it can be a nested state name. This state is a child of the
+ * // above "home" state.
+ * $stateProvider.state("home.newest", {});
+ *
+ * // Nest states as deeply as needed.
+ * $stateProvider.state("home.newest.abc.xyz.inception", {});
+ *
+ * // state() returns $stateProvider, so you can chain state declarations.
+ * $stateProvider
+ * .state("home", {})
+ * .state("about", {})
+ * .state("contacts", {});
+ * </pre>
+ *
+ */
+ this.state = state;
+ function state(name, definition) {
+ /*jshint validthis: true */
+ if (isObject(name)) definition = name;
+ else definition.name = name;
+ registerState(definition);
+ return this;
+ }
+
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$state
+ *
+ * @requires $rootScope
+ * @requires $q
+ * @requires ui.router.state.$view
+ * @requires $injector
+ * @requires ui.router.util.$resolve
+ * @requires ui.router.state.$stateParams
+ * @requires ui.router.router.$urlRouter
+ *
+ * @property {object} params A param object, e.g. {sectionId: section.id)}, that
+ * you'd like to test against the current active state.
+ * @property {object} current A reference to the state's config object. However
+ * you passed it in. Useful for accessing custom data.
+ * @property {object} transition Currently pending transition. A promise that'll
+ * resolve or reject.
+ *
+ * @description
+ * `$state` service is responsible for representing states as well as transitioning
+ * between them. It also provides interfaces to ask for current state or even states
+ * you're coming from.
+ */
+ this.$get = $get;
+ $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];
+ function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) {
+
+ var TransitionSuperseded = $q.reject(new Error('transition superseded'));
+ var TransitionPrevented = $q.reject(new Error('transition prevented'));
+ var TransitionAborted = $q.reject(new Error('transition aborted'));
+ var TransitionFailed = $q.reject(new Error('transition failed'));
+
+ // Handles the case where a state which is the target of a transition is not found, and the user
+ // can optionally retry or defer the transition
+ function handleRedirect(redirect, state, params, options) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateNotFound
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when a requested state **cannot be found** using the provided state name during transition.
+ * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
+ * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
+ * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
+ * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
+ *
+ * @param {Object} event Event object.
+ * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
+ * @param {State} fromState Current state object.
+ * @param {Object} fromParams Current state params.
+ *
+ * @example
+ *
+ * <pre>
+ * // somewhere, assume lazy.state has not been defined
+ * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
+ *
+ * // somewhere else
+ * $scope.$on('$stateNotFound',
+ * function(event, unfoundState, fromState, fromParams){
+ * console.log(unfoundState.to); // "lazy.state"
+ * console.log(unfoundState.toParams); // {a:1, b:2}
+ * console.log(unfoundState.options); // {inherit:false} + default options
+ * })
+ * </pre>
+ */
+ var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params);
+
+ if (evt.defaultPrevented) {
+ $urlRouter.update();
+ return TransitionAborted;
+ }
+
+ if (!evt.retry) {
+ return null;
+ }
+
+ // Allow the handler to return a promise to defer state lookup retry
+ if (options.$retry) {
+ $urlRouter.update();
+ return TransitionFailed;
+ }
+ var retryTransition = $state.transition = $q.when(evt.retry);
+
+ retryTransition.then(function() {
+ if (retryTransition !== $state.transition) return TransitionSuperseded;
+ redirect.options.$retry = true;
+ return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);
+ }, function() {
+ return TransitionAborted;
+ });
+ $urlRouter.update();
+
+ return retryTransition;
+ }
+
+ root.locals = { resolve: null, globals: { $stateParams: {} } };
+
+ $state = {
+ params: {},
+ current: root.self,
+ $current: root,
+ transition: null
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#reload
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A method that force reloads the current state. All resolves are re-resolved,
+ * controllers reinstantiated, and events re-fired.
+ *
+ * @example
+ * <pre>
+ * var app angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.reload = function(){
+ * $state.reload();
+ * }
+ * });
+ * </pre>
+ *
+ * `reload()` is just an alias for:
+ * <pre>
+ * $state.transitionTo($state.current, $stateParams, {
+ * reload: true, inherit: false, notify: true
+ * });
+ * </pre>
+ *
+ * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved.
+ * @example
+ * <pre>
+ * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item'
+ * //and current state is 'contacts.detail.item'
+ * var app angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.reload = function(){
+ * //will reload 'contact.detail' and 'contact.detail.item' states
+ * $state.reload('contact.detail');
+ * }
+ * });
+ * </pre>
+ *
+ * `reload()` is just an alias for:
+ * <pre>
+ * $state.transitionTo($state.current, $stateParams, {
+ * reload: true, inherit: false, notify: true
+ * });
+ * </pre>
+
+ * @returns {promise} A promise representing the state of the new transition. See
+ * {@link ui.router.state.$state#methods_go $state.go}.
+ */
+ $state.reload = function reload(state) {
+ return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true});
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#go
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Convenience method for transitioning to a new state. `$state.go` calls
+ * `$state.transitionTo` internally but automatically sets options to
+ * `{ location: true, inherit: true, relative: $state.$current, notify: true }`.
+ * This allows you to easily use an absolute or relative to path and specify
+ * only the parameters you'd like to update (while letting unspecified parameters
+ * inherit from the currently active ancestor states).
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.changeState = function () {
+ * $state.go('contact.detail');
+ * };
+ * });
+ * </pre>
+ * <img src='../ngdoc_assets/StateGoExamples.png'/>
+ *
+ * @param {string} to Absolute state name or relative state path. Some examples:
+ *
+ * - `$state.go('contact.detail')` - will go to the `contact.detail` state
+ * - `$state.go('^')` - will go to a parent state
+ * - `$state.go('^.sibling')` - will go to a sibling state
+ * - `$state.go('.child.grandchild')` - will go to grandchild state
+ *
+ * @param {object=} params A map of the parameters that will be sent to the state,
+ * will populate $stateParams. Any parameters that are not specified will be inherited from currently
+ * defined parameters. Only parameters specified in the state definition can be overridden, new
+ * parameters will be ignored. This allows, for example, going to a sibling state that shares parameters
+ * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e.
+ * transitioning to a sibling will get you the parameters for all parents, transitioning to a child
+ * will get you all current parameters, etc.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
+ * - **`reload`** (v0.2.5) - {boolean=false|string|object}, If `true` will force transition even if no state or params
+ * have changed. It will reload the resolves and views of the current state and parent states.
+ * If `reload` is a string (or state object), the state object is fetched (by name, or object reference); and \
+ * the transition reloads the resolves and views for that matched state, and all its children states.
+ *
+ * @returns {promise} A promise representing the state of the new transition.
+ *
+ * Possible success values:
+ *
+ * - $state.current
+ *
+ * <br/>Possible rejection values:
+ *
+ * - 'transition superseded' - when a newer transition has been started after this one
+ * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener
+ * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or
+ * when a `$stateNotFound` `event.retry` promise errors.
+ * - 'transition failed' - when a state has been unsuccessfully found after 2 tries.
+ * - *resolve error* - when an error has occurred with a `resolve`
+ *
+ */
+ $state.go = function go(to, params, options) {
+ return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#transitionTo
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go}
+ * uses `transitionTo` internally. `$state.go` is recommended in most situations.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.changeState = function () {
+ * $state.transitionTo('contact.detail');
+ * };
+ * });
+ * </pre>
+ *
+ * @param {string} to State name.
+ * @param {object=} toParams A map of the parameters that will be sent to the state,
+ * will populate $stateParams.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
+ * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
+ * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params
+ * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
+ * use this when you want to force a reload when *everything* is the same, including search params.
+ * if String, then will reload the state with the name given in reload, and any children.
+ * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children.
+ *
+ * @returns {promise} A promise representing the state of the new transition. See
+ * {@link ui.router.state.$state#methods_go $state.go}.
+ */
+ $state.transitionTo = function transitionTo(to, toParams, options) {
+ toParams = toParams || {};
+ options = extend({
+ location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false
+ }, options || {});
+
+ var from = $state.$current, fromParams = $state.params, fromPath = from.path;
+ var evt, toState = findState(to, options.relative);
+
+ // Store the hash param for later (since it will be stripped out by various methods)
+ var hash = toParams['#'];
+
+ if (!isDefined(toState)) {
+ var redirect = { to: to, toParams: toParams, options: options };
+ var redirectResult = handleRedirect(redirect, from.self, fromParams, options);
+
+ if (redirectResult) {
+ return redirectResult;
+ }
+
+ // Always retry once if the $stateNotFound was not prevented
+ // (handles either redirect changed or state lazy-definition)
+ to = redirect.to;
+ toParams = redirect.toParams;
+ options = redirect.options;
+ toState = findState(to, options.relative);
+
+ if (!isDefined(toState)) {
+ if (!options.relative) throw new Error("No such state '" + to + "'");
+ throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
+ }
+ }
+ if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
+ if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
+ if (!toState.params.$$validates(toParams)) return TransitionFailed;
+
+ toParams = toState.params.$$values(toParams);
+ to = toState;
+
+ var toPath = to.path;
+
+ // Starting from the root of the path, keep all levels that haven't changed
+ var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
+
+ if (!options.reload) {
+ while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
+ locals = toLocals[keep] = state.locals;
+ keep++;
+ state = toPath[keep];
+ }
+ } else if (isString(options.reload) || isObject(options.reload)) {
+ if (isObject(options.reload) && !options.reload.name) {
+ throw new Error('Invalid reload state object');
+ }
+
+ var reloadState = options.reload === true ? fromPath[0] : findState(options.reload);
+ if (options.reload && !reloadState) {
+ throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
+ }
+
+ while (state && state === fromPath[keep] && state !== reloadState) {
+ locals = toLocals[keep] = state.locals;
+ keep++;
+ state = toPath[keep];
+ }
+ }
+
+ // If we're going to the same state and all locals are kept, we've got nothing to do.
+ // But clear 'transition', as we still want to cancel any other pending transitions.
+ // TODO: We may not want to bump 'transition' if we're called from a location change
+ // that we've initiated ourselves, because we might accidentally abort a legitimate
+ // transition initiated from code?
+ if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
+ if (hash) toParams['#'] = hash;
+ $state.params = toParams;
+ copy($state.params, $stateParams);
+ copy(filterByKeys(to.params.$$keys(), $stateParams), to.locals.globals.$stateParams);
+ if (options.location && to.navigable && to.navigable.url) {
+ $urlRouter.push(to.navigable.url, toParams, {
+ $$avoidResync: true, replace: options.location === 'replace'
+ });
+ $urlRouter.update(true);
+ }
+ $state.transition = null;
+ return $q.when($state.current);
+ }
+
+ // Filter parameters before we pass them to event handlers etc.
+ toParams = filterByKeys(to.params.$$keys(), toParams || {});
+
+ // Re-add the saved hash before we start returning things or broadcasting $stateChangeStart
+ if (hash) toParams['#'] = hash;
+
+ // Broadcast start event and cancel the transition if requested
+ if (options.notify) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeStart
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when the state transition **begins**. You can use `event.preventDefault()`
+ * to prevent the transition from happening and then the transition promise will be
+ * rejected with a `'transition prevented'` value.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ *
+ * @example
+ *
+ * <pre>
+ * $rootScope.$on('$stateChangeStart',
+ * function(event, toState, toParams, fromState, fromParams){
+ * event.preventDefault();
+ * // transitionTo() promise will be rejected with
+ * // a 'transition prevented' error
+ * })
+ * </pre>
+ */
+ if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams, options).defaultPrevented) {
+ $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
+ //Don't update and resync url if there's been a new transition started. see issue #2238, #600
+ if ($state.transition == null) $urlRouter.update();
+ return TransitionPrevented;
+ }
+ }
+
+ // Resolve locals for the remaining states, but don't update any global state just
+ // yet -- if anything fails to resolve the current state needs to remain untouched.
+ // We also set up an inheritance chain for the locals here. This allows the view directive
+ // to quickly look up the correct definition for each view in the current state. Even
+ // though we create the locals object itself outside resolveState(), it is initially
+ // empty and gets filled asynchronously. We need to keep track of the promise for the
+ // (fully resolved) current locals, and pass this down the chain.
+ var resolved = $q.when(locals);
+
+ for (var l = keep; l < toPath.length; l++, state = toPath[l]) {
+ locals = toLocals[l] = inherit(locals);
+ resolved = resolveState(state, toParams, state === to, resolved, locals, options);
+ }
+
+ // Once everything is resolved, we are ready to perform the actual transition
+ // and return a promise for the new state. We also keep track of what the
+ // current promise is, so that we can detect overlapping transitions and
+ // keep only the outcome of the last transition.
+ var transition = $state.transition = resolved.then(function () {
+ var l, entering, exiting;
+
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ // Exit 'from' states not kept
+ for (l = fromPath.length - 1; l >= keep; l--) {
+ exiting = fromPath[l];
+ if (exiting.self.onExit) {
+ $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals);
+ }
+ exiting.locals = null;
+ }
+
+ // Enter 'to' states not kept
+ for (l = keep; l < toPath.length; l++) {
+ entering = toPath[l];
+ entering.locals = toLocals[l];
+ if (entering.self.onEnter) {
+ $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals);
+ }
+ }
+
+ // Run it again, to catch any transitions in callbacks
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ // Update globals in $state
+ $state.$current = to;
+ $state.current = to.self;
+ $state.params = toParams;
+ copy($state.params, $stateParams);
+ $state.transition = null;
+
+ if (options.location && to.navigable) {
+ $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, {
+ $$avoidResync: true, replace: options.location === 'replace'
+ });
+ }
+
+ if (options.notify) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeSuccess
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired once the state transition is **complete**.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ */
+ $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);
+ }
+ $urlRouter.update(true);
+
+ return $state.current;
+ }, function (error) {
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ $state.transition = null;
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeError
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when an **error occurs** during transition. It's important to note that if you
+ * have any errors in your resolve functions (javascript errors, non-existent services, etc)
+ * they will not throw traditionally. You must listen for this $stateChangeError event to
+ * catch **ALL** errors.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ * @param {Error} error The resolve error object.
+ */
+ evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
+
+ if (!evt.defaultPrevented) {
+ $urlRouter.update();
+ }
+
+ return $q.reject(error);
+ });
+
+ return transition;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#is
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Similar to {@link ui.router.state.$state#methods_includes $state.includes},
+ * but only checks for the full state name. If params is supplied then it will be
+ * tested for strict equality against the current active params object, so all params
+ * must match with none missing and no extras.
+ *
+ * @example
+ * <pre>
+ * $state.$current.name = 'contacts.details.item';
+ *
+ * // absolute name
+ * $state.is('contact.details.item'); // returns true
+ * $state.is(contactDetailItemStateObject); // returns true
+ *
+ * // relative name (. and ^), typically from a template
+ * // E.g. from the 'contacts.details' template
+ * <div ng-class="{highlighted: $state.is('.item')}">Item</div>
+ * </pre>
+ *
+ * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check.
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
+ * to test against the current active state.
+ * @param {object=} options An options object. The options are:
+ *
+ * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will
+ * test relative to `options.relative` state (or name).
+ *
+ * @returns {boolean} Returns true if it is the state.
+ */
+ $state.is = function is(stateOrName, params, options) {
+ options = extend({ relative: $state.$current }, options || {});
+ var state = findState(stateOrName, options.relative);
+
+ if (!isDefined(state)) { return undefined; }
+ if ($state.$current !== state) { return false; }
+ return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#includes
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A method to determine if the current active state is equal to or is the child of the
+ * state stateName. If any params are passed then they will be tested for a match as well.
+ * Not all the parameters need to be passed, just the ones you'd like to test for equality.
+ *
+ * @example
+ * Partial and relative names
+ * <pre>
+ * $state.$current.name = 'contacts.details.item';
+ *
+ * // Using partial names
+ * $state.includes("contacts"); // returns true
+ * $state.includes("contacts.details"); // returns true
+ * $state.includes("contacts.details.item"); // returns true
+ * $state.includes("contacts.list"); // returns false
+ * $state.includes("about"); // returns false
+ *
+ * // Using relative names (. and ^), typically from a template
+ * // E.g. from the 'contacts.details' template
+ * <div ng-class="{highlighted: $state.includes('.item')}">Item</div>
+ * </pre>
+ *
+ * Basic globbing patterns
+ * <pre>
+ * $state.$current.name = 'contacts.details.item.url';
+ *
+ * $state.includes("*.details.*.*"); // returns true
+ * $state.includes("*.details.**"); // returns true
+ * $state.includes("**.item.**"); // returns true
+ * $state.includes("*.details.item.url"); // returns true
+ * $state.includes("*.details.*.url"); // returns true
+ * $state.includes("*.details.*"); // returns false
+ * $state.includes("item.**"); // returns false
+ * </pre>
+ *
+ * @param {string} stateOrName A partial name, relative name, or glob pattern
+ * to be searched for within the current state name.
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`,
+ * that you'd like to test against the current active state.
+ * @param {object=} options An options object. The options are:
+ *
+ * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set,
+ * .includes will test relative to `options.relative` state (or name).
+ *
+ * @returns {boolean} Returns true if it does include the state
+ */
+ $state.includes = function includes(stateOrName, params, options) {
+ options = extend({ relative: $state.$current }, options || {});
+ if (isString(stateOrName) && isGlob(stateOrName)) {
+ if (!doesStateMatchGlob(stateOrName)) {
+ return false;
+ }
+ stateOrName = $state.$current.name;
+ }
+
+ var state = findState(stateOrName, options.relative);
+ if (!isDefined(state)) { return undefined; }
+ if (!isDefined($state.$current.includes[state.name])) { return false; }
+ return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#href
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A url generation method that returns the compiled url for the given state populated with the given params.
+ *
+ * @example
+ * <pre>
+ * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
+ * </pre>
+ *
+ * @param {string|object} stateOrName The state name or state object you'd like to generate a url from.
+ * @param {object=} params An object of parameter values to fill the state's required parameters.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the
+ * first parameter, then the constructed href url will be built from the first navigable ancestor (aka
+ * ancestor with a valid url).
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
+ *
+ * @returns {string} compiled state url
+ */
+ $state.href = function href(stateOrName, params, options) {
+ options = extend({
+ lossy: true,
+ inherit: true,
+ absolute: false,
+ relative: $state.$current
+ }, options || {});
+
+ var state = findState(stateOrName, options.relative);
+
+ if (!isDefined(state)) return null;
+ if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state);
+
+ var nav = (state && options.lossy) ? state.navigable : state;
+
+ if (!nav || nav.url === undefined || nav.url === null) {
+ return null;
+ }
+ return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), {
+ absolute: options.absolute
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#get
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Returns the state configuration object for any specific state or all states.
+ *
+ * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for
+ * the requested state. If not provided, returns an array of ALL state configs.
+ * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context.
+ * @returns {Object|Array} State configuration object or array of all objects.
+ */
+ $state.get = function (stateOrName, context) {
+ if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; });
+ var state = findState(stateOrName, context || $state.$current);
+ return (state && state.self) ? state.self : null;
+ };
+
+ function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {
+ // Make a restricted $stateParams with only the parameters that apply to this state if
+ // necessary. In addition to being available to the controller and onEnter/onExit callbacks,
+ // we also need $stateParams to be available for any $injector calls we make during the
+ // dependency resolution process.
+ var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
+ var locals = { $stateParams: $stateParams };
+
+ // Resolve 'global' dependencies for the state, i.e. those not specific to a view.
+ // We're also including $stateParams in this; that way the parameters are restricted
+ // to the set that should be visible to the state, and are independent of when we update
+ // the global $state and $stateParams values.
+ dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);
+ var promises = [dst.resolve.then(function (globals) {
+ dst.globals = globals;
+ })];
+ if (inherited) promises.push(inherited);
+
+ function resolveViews() {
+ var viewsPromises = [];
+
+ // Resolve template and dependencies for all views.
+ forEach(state.views, function (view, name) {
+ var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
+ injectables.$template = [ function () {
+ return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || '';
+ }];
+
+ viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) {
+ // References to the controller (only instantiated at link time)
+ if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
+ var injectLocals = angular.extend({}, injectables, dst.globals);
+ result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
+ } else {
+ result.$$controller = view.controller;
+ }
+ // Provide access to the state itself for internal use
+ result.$$state = state;
+ result.$$controllerAs = view.controllerAs;
+ dst[name] = result;
+ }));
+ });
+
+ return $q.all(viewsPromises).then(function(){
+ return dst.globals;
+ });
+ }
+
+ // Wait for all the promises and then return the activation object
+ return $q.all(promises).then(resolveViews).then(function (values) {
+ return dst;
+ });
+ }
+
+ return $state;
+ }
+
+ function shouldSkipReload(to, toParams, from, fromParams, locals, options) {
+ // Return true if there are no differences in non-search (path/object) params, false if there are differences
+ function nonSearchParamsEqual(fromAndToState, fromParams, toParams) {
+ // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params.
+ function notSearchParam(key) {
+ return fromAndToState.params[key].location != "search";
+ }
+ var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam);
+ var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys));
+ var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams);
+ return nonQueryParamSet.$$equals(fromParams, toParams);
+ }
+
+ // If reload was not explicitly requested
+ // and we're transitioning to the same state we're already in
+ // and the locals didn't change
+ // or they changed in a way that doesn't merit reloading
+ // (reloadOnParams:false, or reloadOnSearch.false and only search params changed)
+ // Then return true.
+ if (!options.reload && to === from &&
+ (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) {
+ return true;
+ }
+ }
+}
+
+angular.module('ui.router.state')
+ .factory('$stateParams', function () { return {}; })
+ .provider('$state', $StateProvider);
+
+
+$ViewProvider.$inject = [];
+function $ViewProvider() {
+
+ this.$get = $get;
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$view
+ *
+ * @requires ui.router.util.$templateFactory
+ * @requires $rootScope
+ *
+ * @description
+ *
+ */
+ $get.$inject = ['$rootScope', '$templateFactory'];
+ function $get( $rootScope, $templateFactory) {
+ return {
+ // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$view#load
+ * @methodOf ui.router.state.$view
+ *
+ * @description
+ *
+ * @param {string} name name
+ * @param {object} options option object.
+ */
+ load: function load(name, options) {
+ var result, defaults = {
+ template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}
+ };
+ options = extend(defaults, options);
+
+ if (options.view) {
+ result = $templateFactory.fromConfig(options.view, options.params, options.locals);
+ }
+ return result;
+ }
+ };
+ }
+}
+
+angular.module('ui.router.state').provider('$view', $ViewProvider);
+
+/**
+ * @ngdoc object
+ * @name ui.router.state.$uiViewScrollProvider
+ *
+ * @description
+ * Provider that returns the {@link ui.router.state.$uiViewScroll} service function.
+ */
+function $ViewScrollProvider() {
+
+ var useAnchorScroll = false;
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll
+ * @methodOf ui.router.state.$uiViewScrollProvider
+ *
+ * @description
+ * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for
+ * scrolling based on the url anchor.
+ */
+ this.useAnchorScroll = function () {
+ useAnchorScroll = true;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$uiViewScroll
+ *
+ * @requires $anchorScroll
+ * @requires $timeout
+ *
+ * @description
+ * When called with a jqLite element, it scrolls the element into view (after a
+ * `$timeout` so the DOM has time to refresh).
+ *
+ * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor,
+ * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}.
+ */
+ this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) {
+ if (useAnchorScroll) {
+ return $anchorScroll;
+ }
+
+ return function ($element) {
+ return $timeout(function () {
+ $element[0].scrollIntoView();
+ }, 0, false);
+ };
+ }];
+}
+
+angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
+
+var ngMajorVer = angular.version.major;
+var ngMinorVer = angular.version.minor;
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-view
+ *
+ * @requires ui.router.state.$state
+ * @requires $compile
+ * @requires $controller
+ * @requires $injector
+ * @requires ui.router.state.$uiViewScroll
+ * @requires $document
+ *
+ * @restrict ECA
+ *
+ * @description
+ * The ui-view directive tells $state where to place your templates.
+ *
+ * @param {string=} name A view name. The name should be unique amongst the other views in the
+ * same state. You can have views of the same name that live in different states.
+ *
+ * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window
+ * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll
+ * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
+ * scroll ui-view elements into view when they are populated during a state activation.
+ *
+ * @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
+ * will be applied to the ui-view)
+ *
+ * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
+ * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
+ *
+ * @param {string=} onload Expression to evaluate whenever the view updates.
+ *
+ * @example
+ * A view can be unnamed or named.
+ * <pre>
+ * <!-- Unnamed -->
+ * <div ui-view></div>
+ *
+ * <!-- Named -->
+ * <div ui-view="viewName"></div>
+ * </pre>
+ *
+ * You can only have one unnamed view within any template (or root html). If you are only using a
+ * single view and it is unnamed then you can populate it like so:
+ * <pre>
+ * <div ui-view></div>
+ * $stateProvider.state("home", {
+ * template: "<h1>HELLO!</h1>"
+ * })
+ * </pre>
+ *
+ * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}
+ * config property, by name, in this case an empty name:
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "": {
+ * template: "<h1>HELLO!</h1>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * But typically you'll only use the views property if you name your view or have more than one view
+ * in the same template. There's not really a compelling reason to name a view if its the only one,
+ * but you could if you wanted, like so:
+ * <pre>
+ * <div ui-view="main"></div>
+ * </pre>
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "main": {
+ * template: "<h1>HELLO!</h1>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * Really though, you'll use views to set up multiple views:
+ * <pre>
+ * <div ui-view></div>
+ * <div ui-view="chart"></div>
+ * <div ui-view="data"></div>
+ * </pre>
+ *
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "": {
+ * template: "<h1>HELLO!</h1>"
+ * },
+ * "chart": {
+ * template: "<chart_thing/>"
+ * },
+ * "data": {
+ * template: "<data_thing/>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * Examples for `autoscroll`:
+ *
+ * <pre>
+ * <!-- If autoscroll present with no expression,
+ * then scroll ui-view into view -->
+ * <ui-view autoscroll/>
+ *
+ * <!-- If autoscroll present with valid expression,
+ * then scroll ui-view into view if expression evaluates to true -->
+ * <ui-view autoscroll='true'/>
+ * <ui-view autoscroll='false'/>
+ * <ui-view autoscroll='scopeVariable'/>
+ * </pre>
+ */
+$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];
+function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) {
+
+ function getService() {
+ return ($injector.has) ? function(service) {
+ return $injector.has(service) ? $injector.get(service) : null;
+ } : function(service) {
+ try {
+ return $injector.get(service);
+ } catch (e) {
+ return null;
+ }
+ };
+ }
+
+ var service = getService(),
+ $animator = service('$animator'),
+ $animate = service('$animate');
+
+ // Returns a set of DOM manipulation functions based on which Angular version
+ // it should use
+ function getRenderer(attrs, scope) {
+ var statics = {
+ enter: function (element, target, cb) { target.after(element); cb(); },
+ leave: function (element, cb) { element.remove(); cb(); }
+ };
+
+ if (!!attrs.noanimation) return statics;
+
+ function animEnabled(element) {
+ if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
+ if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
+ return (!!$animator);
+ }
+
+ // ng 1.2+
+ if ($animate) {
+ return {
+ enter: function(element, target, cb) {
+ if (!animEnabled(element)) {
+ statics.enter(element, target, cb);
+ } else if (angular.version.minor > 2) {
+ $animate.enter(element, null, target).then(cb);
+ } else {
+ $animate.enter(element, null, target, cb);
+ }
+ },
+ leave: function(element, cb) {
+ if (!animEnabled(element)) {
+ statics.leave(element, cb);
+ } else if (angular.version.minor > 2) {
+ $animate.leave(element).then(cb);
+ } else {
+ $animate.leave(element, cb);
+ }
+ }
+ };
+ }
+
+ // ng 1.1.5
+ if ($animator) {
+ var animate = $animator && $animator(scope, attrs);
+
+ return {
+ enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
+ leave: function(element, cb) { animate.leave(element); cb(); }
+ };
+ }
+
+ return statics;
+ }
+
+ var directive = {
+ restrict: 'ECA',
+ terminal: true,
+ priority: 400,
+ transclude: 'element',
+ compile: function (tElement, tAttrs, $transclude) {
+ return function (scope, $element, attrs) {
+ var previousEl, currentEl, currentScope, latestLocals,
+ onloadExp = attrs.onload || '',
+ autoScrollExp = attrs.autoscroll,
+ renderer = getRenderer(attrs, scope);
+
+ scope.$on('$stateChangeSuccess', function() {
+ updateView(false);
+ });
+
+ updateView(true);
+
+ function cleanupLastView() {
+ var _previousEl = previousEl;
+ var _currentScope = currentScope;
+
+ if (_currentScope) {
+ _currentScope._willBeDestroyed = true;
+ }
+
+ function cleanOld() {
+ if (_previousEl) {
+ _previousEl.remove();
+ }
+
+ if (_currentScope) {
+ _currentScope.$destroy();
+ }
+ }
+
+ if (currentEl) {
+ renderer.leave(currentEl, function() {
+ cleanOld();
+ previousEl = null;
+ });
+
+ previousEl = currentEl;
+ } else {
+ cleanOld();
+ previousEl = null;
+ }
+
+ currentEl = null;
+ currentScope = null;
+ }
+
+ function updateView(firstTime) {
+ var newScope,
+ name = getUiViewName(scope, attrs, $element, $interpolate),
+ previousLocals = name && $state.$current && $state.$current.locals[name];
+
+ if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
+ newScope = scope.$new();
+ latestLocals = $state.$current.locals[name];
+
+ /**
+ * @ngdoc event
+ * @name ui.router.state.directive:ui-view#$viewContentLoading
+ * @eventOf ui.router.state.directive:ui-view
+ * @eventType emits on ui-view directive scope
+ * @description
+ *
+ * Fired once the view **begins loading**, *before* the DOM is rendered.
+ *
+ * @param {Object} event Event object.
+ * @param {string} viewName Name of the view.
+ */
+ newScope.$emit('$viewContentLoading', name);
+
+ var clone = $transclude(newScope, function(clone) {
+ renderer.enter(clone, $element, function onUiViewEnter() {
+ if(currentScope) {
+ currentScope.$emit('$viewContentAnimationEnded');
+ }
+
+ if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {
+ $uiViewScroll(clone);
+ }
+ });
+ cleanupLastView();
+ });
+
+ currentEl = clone;
+ currentScope = newScope;
+ /**
+ * @ngdoc event
+ * @name ui.router.state.directive:ui-view#$viewContentLoaded
+ * @eventOf ui.router.state.directive:ui-view
+ * @eventType emits on ui-view directive scope
+ * @description
+ * Fired once the view is **loaded**, *after* the DOM is rendered.
+ *
+ * @param {Object} event Event object.
+ * @param {string} viewName Name of the view.
+ */
+ currentScope.$emit('$viewContentLoaded', name);
+ currentScope.$eval(onloadExp);
+ }
+ };
+ }
+ };
+
+ return directive;
+}
+
+$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate'];
+function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ compile: function (tElement) {
+ var initial = tElement.html();
+ return function (scope, $element, attrs) {
+ var current = $state.$current,
+ name = getUiViewName(scope, attrs, $element, $interpolate),
+ locals = current && current.locals[name];
+
+ if (! locals) {
+ return;
+ }
+
+ $element.data('$uiView', { name: name, state: locals.$$state });
+ $element.html(locals.$template ? locals.$template : initial);
+
+ var link = $compile($element.contents());
+
+ if (locals.$$controller) {
+ locals.$scope = scope;
+ locals.$element = $element;
+ var controller = $controller(locals.$$controller, locals);
+ if (locals.$$controllerAs) {
+ scope[locals.$$controllerAs] = controller;
+ }
+ $element.data('$ngControllerController', controller);
+ $element.children().data('$ngControllerController', controller);
+ }
+
+ link(scope);
+ };
+ }
+ };
+}
+
+/**
+ * Shared ui-view code for both directives:
+ * Given scope, element, and its attributes, return the view's name
+ */
+function getUiViewName(scope, attrs, element, $interpolate) {
+ var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
+ var inherited = element.inheritedData('$uiView');
+ return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : ''));
+}
+
+angular.module('ui.router.state').directive('uiView', $ViewDirective);
+angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
+
+function parseStateRef(ref, current) {
+ var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed;
+ if (preparsed) ref = current + '(' + preparsed[1] + ')';
+ parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
+ if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'");
+ return { state: parsed[1], paramExpr: parsed[3] || null };
+}
+
+function stateContext(el) {
+ var stateData = el.parent().inheritedData('$uiView');
+
+ if (stateData && stateData.state && stateData.state.name) {
+ return stateData.state;
+ }
+}
+
+function getTypeInfo(el) {
+ // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
+ var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
+ var isForm = el[0].nodeName === "FORM";
+
+ return {
+ attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'),
+ isAnchor: el.prop("tagName").toUpperCase() === "A",
+ clickable: !isForm
+ };
+}
+
+function clickHook(el, $state, $timeout, type, current) {
+ return function(e) {
+ var button = e.which || e.button, target = current();
+
+ if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
+ // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
+ var transition = $timeout(function() {
+ $state.go(target.state, target.params, target.options);
+ });
+ e.preventDefault();
+
+ // if the state has no URL, ignore one preventDefault from the <a> directive.
+ var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0;
+
+ e.preventDefault = function() {
+ if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition);
+ };
+ }
+ };
+}
+
+function defaultOpts(el, $state) {
+ return { relative: stateContext(el) || $state.$current, inherit: true };
+}
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref
+ *
+ * @requires ui.router.state.$state
+ * @requires $timeout
+ *
+ * @restrict A
+ *
+ * @description
+ * A directive that binds a link (`<a>` tag) to a state. If the state has an associated
+ * URL, the directive will automatically generate & update the `href` attribute via
+ * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking
+ * the link will trigger a state transition with optional parameters.
+ *
+ * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be
+ * handled natively by the browser.
+ *
+ * You can also use relative state paths within ui-sref, just like the relative
+ * paths passed to `$state.go()`. You just need to be aware that the path is relative
+ * to the state that the link lives in, in other words the state that loaded the
+ * template containing the link.
+ *
+ * You can specify options to pass to {@link ui.router.state.$state#go $state.go()}
+ * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
+ * and `reload`.
+ *
+ * @example
+ * Here's an example of how you'd use ui-sref and how it would compile. If you have the
+ * following template:
+ * <pre>
+ * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a>
+ *
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * Then the compiled html would be (assuming Html5Mode is off and current state is contacts):
+ * <pre>
+ * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
+ *
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
+ * </li>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
+ * </li>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
+ * </li>
+ * </ul>
+ *
+ * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
+ * </pre>
+ *
+ * @param {string} ui-sref 'stateName' can be any valid absolute or relative state
+ * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}
+ */
+$StateRefDirective.$inject = ['$state', '$timeout'];
+function $StateRefDirective($state, $timeout) {
+ return {
+ restrict: 'A',
+ require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
+ link: function(scope, element, attrs, uiSrefActive) {
+ var ref = parseStateRef(attrs.uiSref, $state.current.name);
+ var def = { state: ref.state, href: null, params: null };
+ var type = getTypeInfo(element);
+ var active = uiSrefActive[1] || uiSrefActive[0];
+
+ def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});
+
+ var update = function(val) {
+ if (val) def.params = angular.copy(val);
+ def.href = $state.href(ref.state, def.params, def.options);
+
+ if (active) active.$$addStateInfo(ref.state, def.params);
+ if (def.href !== null) attrs.$set(type.attr, def.href);
+ };
+
+ if (ref.paramExpr) {
+ scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true);
+ def.params = angular.copy(scope.$eval(ref.paramExpr));
+ }
+ update();
+
+ if (!type.clickable) return;
+ element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
+ }
+ };
+}
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-state
+ *
+ * @requires ui.router.state.uiSref
+ *
+ * @restrict A
+ *
+ * @description
+ * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition,
+ * params and override options.
+ *
+ * @param {string} ui-state 'stateName' can be any valid absolute or relative state
+ * @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#href $state.href()}
+ * @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#go $state.go()}
+ */
+$StateRefDynamicDirective.$inject = ['$state', '$timeout'];
+function $StateRefDynamicDirective($state, $timeout) {
+ return {
+ restrict: 'A',
+ require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
+ link: function(scope, element, attrs, uiSrefActive) {
+ var type = getTypeInfo(element);
+ var active = uiSrefActive[1] || uiSrefActive[0];
+ var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
+ var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
+ var def = { state: null, params: null, options: null, href: null };
+
+ function runStateRefLink (group) {
+ def.state = group[0]; def.params = group[1]; def.options = group[2];
+ def.href = $state.href(def.state, def.params, def.options);
+
+ if (active) active.$$addStateInfo(def.state, def.params);
+ if (def.href) attrs.$set(type.attr, def.href);
+ }
+
+ scope.$watch(watch, runStateRefLink, true);
+ runStateRefLink(scope.$eval(watch));
+
+ if (!type.clickable) return;
+ element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
+ }
+ };
+}
+
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref-active
+ *
+ * @requires ui.router.state.$state
+ * @requires ui.router.state.$stateParams
+ * @requires $interpolate
+ *
+ * @restrict A
+ *
+ * @description
+ * A directive working alongside ui-sref to add classes to an element when the
+ * related ui-sref directive's state is active, and removing them when it is inactive.
+ * The primary use-case is to simplify the special appearance of navigation menus
+ * relying on `ui-sref`, by having the "active" state's menu button appear different,
+ * distinguishing it from the inactive menu items.
+ *
+ * ui-sref-active can live on the same element as ui-sref or on a parent element. The first
+ * ui-sref-active found at the same level or above the ui-sref will be used.
+ *
+ * Will activate when the ui-sref's target state or any child state is active. If you
+ * need to activate only when the ui-sref target state is active and *not* any of
+ * it's children, then you will use
+ * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq}
+ *
+ * @example
+ * Given the following template:
+ * <pre>
+ * <ul>
+ * <li ui-sref-active="active" class="item">
+ * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ *
+ * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins",
+ * the resulting HTML will appear as (note the 'active' class):
+ * <pre>
+ * <ul>
+ * <li ui-sref-active="active" class="item active">
+ * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * The class name is interpolated **once** during the directives link time (any further changes to the
+ * interpolated value are ignored).
+ *
+ * Multiple classes may be specified in a space-separated format:
+ * <pre>
+ * <ul>
+ * <li ui-sref-active='class1 class2 class3'>
+ * <a ui-sref="app.user">link</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * It is also possible to pass ui-sref-active an expression that evaluates
+ * to an object hash, whose keys represent active class names and whose
+ * values represent the respective state names/globs.
+ * ui-sref-active will match if the current active state **includes** any of
+ * the specified state names/globs, even the abstract ones.
+ *
+ * @Example
+ * Given the following template, with "admin" being an abstract state:
+ * <pre>
+ * <div ui-sref-active="{'active': 'admin.*'}">
+ * <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
+ * </div>
+ * </pre>
+ *
+ * When the current state is "admin.roles" the "active" class will be applied
+ * to both the <div> and <a> elements. It is important to note that the state
+ * names/globs passed to ui-sref-active shadow the state provided by ui-sref.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref-active-eq
+ *
+ * @requires ui.router.state.$state
+ * @requires ui.router.state.$stateParams
+ * @requires $interpolate
+ *
+ * @restrict A
+ *
+ * @description
+ * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate
+ * when the exact target state used in the `ui-sref` is active; no child states.
+ *
+ */
+$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
+function $StateRefActiveDirective($state, $stateParams, $interpolate) {
+ return {
+ restrict: "A",
+ controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {
+ var states = [], activeClasses = {}, activeEqClass, uiSrefActive;
+
+ // There probably isn't much point in $observing this
+ // uiSrefActive and uiSrefActiveEq share the same directive object with some
+ // slight difference in logic routing
+ activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
+
+ try {
+ uiSrefActive = $scope.$eval($attrs.uiSrefActive);
+ } catch (e) {
+ // Do nothing. uiSrefActive is not a valid expression.
+ // Fall back to using $interpolate below
+ }
+ uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
+ if (isObject(uiSrefActive)) {
+ forEach(uiSrefActive, function(stateOrName, activeClass) {
+ if (isString(stateOrName)) {
+ var ref = parseStateRef(stateOrName, $state.current.name);
+ addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
+ }
+ });
+ }
+
+ // Allow uiSref to communicate with uiSrefActive[Equals]
+ this.$$addStateInfo = function (newState, newParams) {
+ // we already got an explicit state provided by ui-sref-active, so we
+ // shadow the one that comes from ui-sref
+ if (isObject(uiSrefActive) && states.length > 0) {
+ return;
+ }
+ addState(newState, newParams, uiSrefActive);
+ update();
+ };
+
+ $scope.$on('$stateChangeSuccess', update);
+
+ function addState(stateName, stateParams, activeClass) {
+ var state = $state.get(stateName, stateContext($element));
+ var stateHash = createStateHash(stateName, stateParams);
+
+ states.push({
+ state: state || { name: stateName },
+ params: stateParams,
+ hash: stateHash
+ });
+
+ activeClasses[stateHash] = activeClass;
+ }
+
+ /**
+ * @param {string} state
+ * @param {Object|string} [params]
+ * @return {string}
+ */
+ function createStateHash(state, params) {
+ if (!isString(state)) {
+ throw new Error('state should be a string');
+ }
+ if (isObject(params)) {
+ return state + toJson(params);
+ }
+ params = $scope.$eval(params);
+ if (isObject(params)) {
+ return state + toJson(params);
+ }
+ return state;
+ }
+
+ // Update route state
+ function update() {
+ for (var i = 0; i < states.length; i++) {
+ if (anyMatch(states[i].state, states[i].params)) {
+ addClass($element, activeClasses[states[i].hash]);
+ } else {
+ removeClass($element, activeClasses[states[i].hash]);
+ }
+
+ if (exactMatch(states[i].state, states[i].params)) {
+ addClass($element, activeEqClass);
+ } else {
+ removeClass($element, activeEqClass);
+ }
+ }
+ }
+
+ function addClass(el, className) { $timeout(function () { el.addClass(className); }); }
+ function removeClass(el, className) { el.removeClass(className); }
+ function anyMatch(state, params) { return $state.includes(state.name, params); }
+ function exactMatch(state, params) { return $state.is(state.name, params); }
+
+ update();
+ }]
+ };
+}
+
+angular.module('ui.router.state')
+ .directive('uiSref', $StateRefDirective)
+ .directive('uiSrefActive', $StateRefActiveDirective)
+ .directive('uiSrefActiveEq', $StateRefActiveDirective)
+ .directive('uiState', $StateRefDynamicDirective);
+
+/**
+ * @ngdoc filter
+ * @name ui.router.state.filter:isState
+ *
+ * @requires ui.router.state.$state
+ *
+ * @description
+ * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}.
+ */
+$IsStateFilter.$inject = ['$state'];
+function $IsStateFilter($state) {
+ var isFilter = function (state, params) {
+ return $state.is(state, params);
+ };
+ isFilter.$stateful = true;
+ return isFilter;
+}
+
+/**
+ * @ngdoc filter
+ * @name ui.router.state.filter:includedByState
+ *
+ * @requires ui.router.state.$state
+ *
+ * @description
+ * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.
+ */
+$IncludedByStateFilter.$inject = ['$state'];
+function $IncludedByStateFilter($state) {
+ var includesFilter = function (state, params, options) {
+ return $state.includes(state, params, options);
+ };
+ includesFilter.$stateful = true;
+ return includesFilter;
+}
+
+angular.module('ui.router.state')
+ .filter('isState', $IsStateFilter)
+ .filter('includedByState', $IncludedByStateFilter);
+})(window, window.angular); \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-router/release/angular-ui-router.min.js b/afb-client/bower_components/angular-ui-router/release/angular-ui-router.min.js
new file mode 100644
index 0000000..f1b0e35
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/release/angular-ui-router.min.js
@@ -0,0 +1,8 @@
+/**
+ * State-based routing for AngularJS
+ * @version v0.2.18
+ * @link http://angular-ui.github.com/
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return R(new(R(function(){},{prototype:a})),b)}function e(a){return Q(arguments,function(b){b!==a&&Q(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return Q(a,function(a,c){b.push(c)}),b}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e<c.length;e++){var f=c[e];if(a[f]!=b[f])return!1}return!0}function k(a,b){var c={};return Q(a,function(a){c[a]=b[a]}),c}function l(a){var b={},c=Array.prototype.concat.apply(Array.prototype,Array.prototype.slice.call(arguments,1));return Q(c,function(c){c in a&&(b[c]=a[c])}),b}function m(a){var b={},c=Array.prototype.concat.apply(Array.prototype,Array.prototype.slice.call(arguments,1));for(var d in a)-1==h(c,d)&&(b[d]=a[d]);return b}function n(a,b){var c=P(a),d=c?[]:{};return Q(a,function(a,e){b(a,e)&&(d[c?d.length:e]=a)}),d}function o(a,b){var c=P(a)?[]:{};return Q(a,function(a,d){c[d]=b(a,d)}),c}function p(a,b){var d=1,f=2,i={},j=[],k=i,l=R(a.when(i),{$$promises:i,$$values:i});this.study=function(i){function n(a,c){if(s[c]!==f){if(r.push(c),s[c]===d)throw r.splice(0,h(r,c)),new Error("Cyclic dependency: "+r.join(" -> "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;d<i.length&&(e=this[i[d]],f=a[i[d]],f!==c&&null!==f||!e.isOptional);d++){if(g=e.type.$normalize(f),!e.type.is(g))return!1;if(h=e.type.encode(g),b.isString(h)&&!e.type.pattern.exec(h))return!1}return!0},$$parent:c},this.ParamSet=k}function u(a,d){function e(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function f(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function g(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return L(d)?d:!0}function h(d,e,f,g,h){function m(a,b,c){return"/"===q?a:b?q.slice(0,-1)+a:c?q.slice(1)+a:a}function n(a){function b(a){var b=a(f,d);return b?(N(b)&&d.replace().url(b),!0):!1}if(!a||!a.defaultPrevented){p&&d.url()===p;p=c;var e,g=j.length;for(e=0;g>e;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K<z.length;K++,F=z[K])G=H[K]=d(G),J=v(F,c,F===b,J,G,f);var M=y.transition=J.then(function(){var d,e,g;if(y.transition!==M)return A;for(d=o.length-1;d>=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d<z.length;d++)e=z[d],e.locals=H[d],e.self.onEnter&&h.invoke(e.self.onEnter,e.self,e.locals.globals);return y.transition!==M?A:(y.$current=b,y.current=b.self,y.params=c,S(y.params,n),y.transition=null,f.location&&b.navigable&&p.push(b.navigable.url,b.navigable.locals.globals.$stateParams,{$$avoidResync:!0,replace:"replace"===f.location}),f.notify&&a.$broadcast("$stateChangeSuccess",b.self,c,j.self,l),p.update(!0),y.current)},function(d){return y.transition!==M?A:(y.transition=null,g=a.$broadcast("$stateChangeError",b.self,c,j.self,l,d),g.defaultPrevented||p.update(),e.reject(d))});return M},y.is=function(a,b,d){d=R({relative:y.$current},d||{});var e=m(a,d.relative);return L(e)?y.$current!==e?!1:b?j(e.params.$$values(b),n):!0:c},y.includes=function(a,b,d){if(d=R({relative:y.$current},d||{}),N(a)&&r(a)){if(!s(a))return!1;a=y.$current.name}var e=m(a,d.relative);return L(e)?L(y.$current.includes[e.name])?b?j(e.params.$$values(b),n,g(b)):!0:!1:c},y.href=function(a,b,d){d=R({lossy:!0,inherit:!0,absolute:!1,relative:y.$current},d||{});var e=m(a,d.relative);if(!L(e))return null;d.inherit&&(b=i(n,b||{},y.$current,e));var f=e&&d.lossy?e.navigable:e;return f&&f.url!==c&&null!==f.url?p.href(f.url,k(e.params.$$keys().concat("#"),b||{}),{absolute:d.absolute}):null},y.get=function(a,b){if(0===arguments.length)return o(g(z),function(a){return z[a].self});var c=m(a,b||y.$current);return c&&c.self?c.self:null},y}function w(a,b,c,d,e,f){function g(a,b,c){function d(b){return"search"!=a.params[b].location}var e=a.params.$$keys().filter(d),f=l.apply({},[a.params].concat(e)),g=new U.ParamSet(f);return g.$$equals(b,c)}return!f.reload&&a===c&&(e===c.locals||a.self.reloadOnSearch===!1&&g(c,d,b))?!0:void 0}var x,y,z={},A={},B="abstract",C={parent:function(a){if(L(a.parent)&&a.parent)return m(a.parent);var b=/^(.+)\.[^.]+$/.exec(a.name);return b?m(b[1]):x},data:function(a){return a.parent&&a.parent.data&&(a.data=a.self.data=d(a.parent.data,a.data)),a.data},url:function(a){var b=a.url,c={params:a.params||{}};if(N(b))return"^"==b.charAt(0)?e.compile(b.substring(1),c):(a.parent.navigable||x).url.concat(b,c);if(!b||e.isMatcher(b))return b;throw new Error("Invalid url '"+b+"' in state '"+a+"'")},navigable:function(a){return a.url?a:a.parent?a.parent.navigable:null},ownParams:function(a){var b=a.url&&a.url.params||new U.ParamSet;return Q(a.params||{},function(a,c){b[c]||(b[c]=new U.Param(c,null,a,"config"))}),b},params:function(a){var b=l(a.ownParams,a.ownParams.$$keys());return a.parent&&a.parent.params?R(a.parent.params.$$new(),b):new U.ParamSet},views:function(a){var b={};return Q(L(a.views)?a.views:{"":a},function(c,d){d.indexOf("@")<0&&(d+="@"+a.parent.name),b[d]=c}),b},path:function(a){return a.parent?a.parent.path.concat(a):[]},includes:function(a){var b=a.parent?R({},a.parent.includes):{};return b[a.name]=!0,b},$delegates:{}};x=q({name:"",url:"^",views:null,"abstract":!0}),x.navigable=null,this.decorator=t,this.state=u,this.$get=v,v.$inject=["$rootScope","$q","$view","$injector","$resolve","$stateParams","$urlRouter","$location","$urlMatcherFactory"]}function w(){function a(a,b){return{load:function(a,c){var d,e={template:null,controller:null,view:null,locals:null,notify:!0,async:!0,params:{}};return c=R(e,c),c.view&&(d=b.fromConfig(c.view,c.params,c.locals)),d}}}this.$get=a,a.$inject=["$rootScope","$templateFactory"]}function x(){var a=!1;this.useAnchorScroll=function(){a=!0},this.$get=["$anchorScroll","$timeout",function(b,c){return a?b:function(a){return c(function(){a[0].scrollIntoView()},0,!1)}}]}function y(a,c,d,e){function f(){return c.has?function(a){return c.has(a)?c.get(a):null}:function(a){try{return c.get(a)}catch(b){return null}}}function g(a,c){function d(a){return 1===V&&W>=4?!!j.enabled(a):1===V&&W>=2?!!j.enabled():!!i}var e={enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}};if(a.noanimation)return e;if(j)return{enter:function(a,c,f){d(a)?b.version.minor>2?j.enter(a,null,c).then(f):j.enter(a,null,c,f):e.enter(a,c,f)},leave:function(a,c){d(a)?b.version.minor>2?j.leave(a).then(c):j.leave(a,c):e.leave(a,c)}};if(i){var f=i&&i(c,a);return{enter:function(a,b,c){f.enter(a,null,b),c()},leave:function(a,b){f.leave(a),b()}}}return e}var h=f(),i=h("$animator"),j=h("$animate"),k={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,f,h){return function(c,f,i){function j(){function a(){b&&b.remove(),c&&c.$destroy()}var b=l,c=n;c&&(c._willBeDestroyed=!0),m?(r.leave(m,function(){a(),l=null}),l=m):(a(),l=null),m=null,n=null}function k(g){var k,l=A(c,i,f,e),s=l&&a.$current&&a.$current.locals[l];if((g||s!==o)&&!c._willBeDestroyed){k=c.$new(),o=a.$current.locals[l],k.$emit("$viewContentLoading",l);var t=h(k,function(a){r.enter(a,f,function(){n&&n.$emit("$viewContentAnimationEnded"),(b.isDefined(q)&&!q||c.$eval(q))&&d(a)}),j()});m=t,n=k,n.$emit("$viewContentLoaded",l),n.$eval(p)}}var l,m,n,o,p=i.onload||"",q=i.autoscroll,r=g(i,c);c.$on("$stateChangeSuccess",function(){k(!1)}),k(!0)}}};return k}function z(a,b,c,d){return{restrict:"ECA",priority:-400,compile:function(e){var f=e.html();return function(e,g,h){var i=c.$current,j=A(e,h,g,d),k=i&&i.locals[j];if(k){g.data("$uiView",{name:j,state:k.$$state}),g.html(k.$template?k.$template:f);var l=a(g.contents());if(k.$$controller){k.$scope=e,k.$element=g;var m=b(k.$$controller,k);k.$$controllerAs&&(e[k.$$controllerAs]=m),g.data("$ngControllerController",m),g.children().data("$ngControllerController",m)}l(e)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h=B(f.uiSref,a.current.name),i={state:h.state,href:null,params:null},j=D(e),k=g[1]||g[0];i.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var l=function(c){c&&(i.params=b.copy(c)),i.href=a.href(h.state,i.params,i.options),k&&k.$$addStateInfo(h.state,i.params),null!==i.href&&f.$set(j.attr,i.href)};h.paramExpr&&(d.$watch(h.paramExpr,function(a){a!==i.params&&l(a)},!0),i.params=b.copy(d.$eval(h.paramExpr))),l(),j.clickable&&e.bind("click",E(e,a,c,j,function(){return i}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){l.state=b[0],l.params=b[1],l.options=b[2],l.href=a.href(l.state,l.params,l.options),i&&i.$$addStateInfo(l.state,l.params),l.href&&e.$set(h.attr,l.href)}var h=D(d),i=f[1]||f[0],j=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],k="["+j.map(function(a){return a||"null"}).join(", ")+"]",l={state:null,params:null,options:null,href:null};c.$watch(k,g,!0),g(c.$eval(k)),h.clickable&&d.bind("click",E(d,a,b,h,function(){return l}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c);p.push({state:f||{name:b},params:c,hash:g}),q[g]=e}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a<p.length;a++)l(p[a].state,p[a].params)?j(d,q[p[a].hash]):k(d,q[p[a].hash]),m(p[a].state,p[a].params)?j(d,n):k(d,n)}function j(a,b){f(function(){a.addClass(b)})}function k(a,b){a.removeClass(b)}function l(b,c){return a.includes(b.name,c)}function m(b,c){return a.is(b.name,c)}var n,o,p=[],q={};n=c(e.uiSrefActiveEq||"",!1)(b);try{o=b.$eval(e.uiSrefActive)}catch(r){}o=o||c(e.uiSrefActive||"",!1)(b),O(o)&&Q(o,function(c,d){if(N(c)){var e=B(c,a.current.name);g(e.state,b.$eval(e.paramExpr),d)}}),this.$$addStateInfo=function(a,b){O(o)&&p.length>0||(g(a,b,o),i())},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;f<l.replace.length;f++)l.replace[f].from===m&&(m=l.replace[f].to);m&&l.array===!0&&(m=c(m)),L(m)&&(m=l.type.decode(m)),k[g]=l.value(m)}for(;i>e;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;f<l.replace.length;f++)l.replace[f].from===m&&(m=l.replace[f].to);L(m)&&(m=l.type.decode(m)),k[g]=l.value(m)}return k},r.prototype.parameters=function(a){return L(a)?this.params[a]||null:this.$$paramNames},r.prototype.validates=function(a){return this.params.$$validates(a)},r.prototype.format=function(a){function b(a){return encodeURIComponent(a).replace(/-/g,function(a){return"%5C%"+a.charCodeAt(0).toString(16).toUpperCase()})}a=a||{};var c=this.segments,d=this.parameters(),e=this.params;if(!this.validates(a))return null;var f,g=!1,h=c.length-1,i=d.length,j=c[0];for(f=0;i>f;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g<d.length;g++)if(!a(d[g],f[g]))return!1;return!0}}this.encode=h(d(a,"encode")),this.decode=h(d(a,"decode")),this.is=h(d(a,"is"),!0),this.equals=i(d(a,"equals")),this.pattern=a.pattern,this.$normalize=h(d(a,"$normalize")),this.name=a.name,this.$arrayMode=b}if(!a)return this;if("auto"===a&&!b)throw new Error("'auto' array mode is for query parameters only");return new d(this,a)},b.module("ui.router.util").provider("$urlMatcherFactory",t),b.module("ui.router.util").run(["$urlMatcherFactory",function(a){}]),u.$inject=["$locationProvider","$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",u),v.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider"],b.module("ui.router.state").factory("$stateParams",function(){return{}}).provider("$state",v),w.$inject=[],b.module("ui.router.state").provider("$view",w),b.module("ui.router.state").provider("$uiViewScroll",x);var V=b.version.major,W=b.version.minor;y.$inject=["$state","$injector","$uiViewScroll","$interpolate"],z.$inject=["$compile","$controller","$state","$interpolate"],b.module("ui.router.state").directive("uiView",y),b.module("ui.router.state").directive("uiView",z),G.$inject=["$state","$timeout"],H.$inject=["$state","$timeout"],I.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",G).directive("uiSrefActive",I).directive("uiSrefActiveEq",I).directive("uiState",H),
+J.$inject=["$state"],K.$inject=["$state"],b.module("ui.router.state").filter("isState",J).filter("includedByState",K)}(window,window.angular); \ No newline at end of file
diff --git a/afb-client/bower_components/angular-ui-router/src/common.js b/afb-client/bower_components/angular-ui-router/src/common.js
new file mode 100644
index 0000000..54c724c
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/common.js
@@ -0,0 +1,293 @@
+/*jshint globalstrict:true*/
+/*global angular:false*/
+'use strict';
+
+var isDefined = angular.isDefined,
+ isFunction = angular.isFunction,
+ isString = angular.isString,
+ isObject = angular.isObject,
+ isArray = angular.isArray,
+ forEach = angular.forEach,
+ extend = angular.extend,
+ copy = angular.copy,
+ toJson = angular.toJson;
+
+function inherit(parent, extra) {
+ return extend(new (extend(function() {}, { prototype: parent }))(), extra);
+}
+
+function merge(dst) {
+ forEach(arguments, function(obj) {
+ if (obj !== dst) {
+ forEach(obj, function(value, key) {
+ if (!dst.hasOwnProperty(key)) dst[key] = value;
+ });
+ }
+ });
+ return dst;
+}
+
+/**
+ * Finds the common ancestor path between two states.
+ *
+ * @param {Object} first The first state.
+ * @param {Object} second The second state.
+ * @return {Array} Returns an array of state names in descending order, not including the root.
+ */
+function ancestors(first, second) {
+ var path = [];
+
+ for (var n in first.path) {
+ if (first.path[n] !== second.path[n]) break;
+ path.push(first.path[n]);
+ }
+ return path;
+}
+
+/**
+ * IE8-safe wrapper for `Object.keys()`.
+ *
+ * @param {Object} object A JavaScript object.
+ * @return {Array} Returns the keys of the object as an array.
+ */
+function objectKeys(object) {
+ if (Object.keys) {
+ return Object.keys(object);
+ }
+ var result = [];
+
+ forEach(object, function(val, key) {
+ result.push(key);
+ });
+ return result;
+}
+
+/**
+ * IE8-safe wrapper for `Array.prototype.indexOf()`.
+ *
+ * @param {Array} array A JavaScript array.
+ * @param {*} value A value to search the array for.
+ * @return {Number} Returns the array index value of `value`, or `-1` if not present.
+ */
+function indexOf(array, value) {
+ if (Array.prototype.indexOf) {
+ return array.indexOf(value, Number(arguments[2]) || 0);
+ }
+ var len = array.length >>> 0, from = Number(arguments[2]) || 0;
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
+
+ if (from < 0) from += len;
+
+ for (; from < len; from++) {
+ if (from in array && array[from] === value) return from;
+ }
+ return -1;
+}
+
+/**
+ * Merges a set of parameters with all parameters inherited between the common parents of the
+ * current state and a given destination state.
+ *
+ * @param {Object} currentParams The value of the current state parameters ($stateParams).
+ * @param {Object} newParams The set of parameters which will be composited with inherited params.
+ * @param {Object} $current Internal definition of object representing the current state.
+ * @param {Object} $to Internal definition of object representing state to transition to.
+ */
+function inheritParams(currentParams, newParams, $current, $to) {
+ var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
+
+ for (var i in parents) {
+ if (!parents[i] || !parents[i].params) continue;
+ parentParams = objectKeys(parents[i].params);
+ if (!parentParams.length) continue;
+
+ for (var j in parentParams) {
+ if (indexOf(inheritList, parentParams[j]) >= 0) continue;
+ inheritList.push(parentParams[j]);
+ inherited[parentParams[j]] = currentParams[parentParams[j]];
+ }
+ }
+ return extend({}, inherited, newParams);
+}
+
+/**
+ * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
+ *
+ * @param {Object} a The first object.
+ * @param {Object} b The second object.
+ * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
+ * it defaults to the list of keys in `a`.
+ * @return {Boolean} Returns `true` if the keys match, otherwise `false`.
+ */
+function equalForKeys(a, b, keys) {
+ if (!keys) {
+ keys = [];
+ for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
+ }
+
+ for (var i=0; i<keys.length; i++) {
+ var k = keys[i];
+ if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
+ }
+ return true;
+}
+
+/**
+ * Returns the subset of an object, based on a list of keys.
+ *
+ * @param {Array} keys
+ * @param {Object} values
+ * @return {Boolean} Returns a subset of `values`.
+ */
+function filterByKeys(keys, values) {
+ var filtered = {};
+
+ forEach(keys, function (name) {
+ filtered[name] = values[name];
+ });
+ return filtered;
+}
+
+// like _.indexBy
+// when you know that your index values will be unique, or you want last-one-in to win
+function indexBy(array, propName) {
+ var result = {};
+ forEach(array, function(item) {
+ result[item[propName]] = item;
+ });
+ return result;
+}
+
+// extracted from underscore.js
+// Return a copy of the object only containing the whitelisted properties.
+function pick(obj) {
+ var copy = {};
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
+ forEach(keys, function(key) {
+ if (key in obj) copy[key] = obj[key];
+ });
+ return copy;
+}
+
+// extracted from underscore.js
+// Return a copy of the object omitting the blacklisted properties.
+function omit(obj) {
+ var copy = {};
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
+ for (var key in obj) {
+ if (indexOf(keys, key) == -1) copy[key] = obj[key];
+ }
+ return copy;
+}
+
+function pluck(collection, key) {
+ var result = isArray(collection) ? [] : {};
+
+ forEach(collection, function(val, i) {
+ result[i] = isFunction(key) ? key(val) : val[key];
+ });
+ return result;
+}
+
+function filter(collection, callback) {
+ var array = isArray(collection);
+ var result = array ? [] : {};
+ forEach(collection, function(val, i) {
+ if (callback(val, i)) {
+ result[array ? result.length : i] = val;
+ }
+ });
+ return result;
+}
+
+function map(collection, callback) {
+ var result = isArray(collection) ? [] : {};
+
+ forEach(collection, function(val, i) {
+ result[i] = callback(val, i);
+ });
+ return result;
+}
+
+/**
+ * @ngdoc overview
+ * @name ui.router.util
+ *
+ * @description
+ * # ui.router.util sub-module
+ *
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ *
+ */
+angular.module('ui.router.util', ['ng']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router.router
+ *
+ * @requires ui.router.util
+ *
+ * @description
+ * # ui.router.router sub-module
+ *
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ */
+angular.module('ui.router.router', ['ui.router.util']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router.state
+ *
+ * @requires ui.router.router
+ * @requires ui.router.util
+ *
+ * @description
+ * # ui.router.state sub-module
+ *
+ * This module is a dependency of the main ui.router module. Do not include this module as a dependency
+ * in your angular app (use {@link ui.router} module instead).
+ *
+ */
+angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
+
+/**
+ * @ngdoc overview
+ * @name ui.router
+ *
+ * @requires ui.router.state
+ *
+ * @description
+ * # ui.router
+ *
+ * ## The main module for ui.router
+ * There are several sub-modules included with the ui.router module, however only this module is needed
+ * as a dependency within your angular app. The other modules are for organization purposes.
+ *
+ * The modules are:
+ * * ui.router - the main "umbrella" module
+ * * ui.router.router -
+ *
+ * *You'll need to include **only** this module as the dependency within your angular app.*
+ *
+ * <pre>
+ * <!doctype html>
+ * <html ng-app="myApp">
+ * <head>
+ * <script src="js/angular.js"></script>
+ * <!-- Include the ui-router script -->
+ * <script src="js/angular-ui-router.min.js"></script>
+ * <script>
+ * // ...and add 'ui.router' as a dependency
+ * var myApp = angular.module('myApp', ['ui.router']);
+ * </script>
+ * </head>
+ * <body>
+ * </body>
+ * </html>
+ * </pre>
+ */
+angular.module('ui.router', ['ui.router.state']);
+
+angular.module('ui.router.compat', ['ui.router']);
diff --git a/afb-client/bower_components/angular-ui-router/src/resolve.js b/afb-client/bower_components/angular-ui-router/src/resolve.js
new file mode 100644
index 0000000..019338d
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/resolve.js
@@ -0,0 +1,252 @@
+/**
+ * @ngdoc object
+ * @name ui.router.util.$resolve
+ *
+ * @requires $q
+ * @requires $injector
+ *
+ * @description
+ * Manages resolution of (acyclic) graphs of promises.
+ */
+$Resolve.$inject = ['$q', '$injector'];
+function $Resolve( $q, $injector) {
+
+ var VISIT_IN_PROGRESS = 1,
+ VISIT_DONE = 2,
+ NOTHING = {},
+ NO_DEPENDENCIES = [],
+ NO_LOCALS = NOTHING,
+ NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$resolve#study
+ * @methodOf ui.router.util.$resolve
+ *
+ * @description
+ * Studies a set of invocables that are likely to be used multiple times.
+ * <pre>
+ * $resolve.study(invocables)(locals, parent, self)
+ * </pre>
+ * is equivalent to
+ * <pre>
+ * $resolve.resolve(invocables, locals, parent, self)
+ * </pre>
+ * but the former is more efficient (in fact `resolve` just calls `study`
+ * internally).
+ *
+ * @param {object} invocables Invocable objects
+ * @return {function} a function to pass in locals, parent and self
+ */
+ this.study = function (invocables) {
+ if (!isObject(invocables)) throw new Error("'invocables' must be an object");
+ var invocableKeys = objectKeys(invocables || {});
+
+ // Perform a topological sort of invocables to build an ordered plan
+ var plan = [], cycle = [], visited = {};
+ function visit(value, key) {
+ if (visited[key] === VISIT_DONE) return;
+
+ cycle.push(key);
+ if (visited[key] === VISIT_IN_PROGRESS) {
+ cycle.splice(0, indexOf(cycle, key));
+ throw new Error("Cyclic dependency: " + cycle.join(" -> "));
+ }
+ visited[key] = VISIT_IN_PROGRESS;
+
+ if (isString(value)) {
+ plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
+ } else {
+ var params = $injector.annotate(value);
+ forEach(params, function (param) {
+ if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
+ });
+ plan.push(key, value, params);
+ }
+
+ cycle.pop();
+ visited[key] = VISIT_DONE;
+ }
+ forEach(invocables, visit);
+ invocables = cycle = visited = null; // plan is all that's required
+
+ function isResolve(value) {
+ return isObject(value) && value.then && value.$$promises;
+ }
+
+ return function (locals, parent, self) {
+ if (isResolve(locals) && self === undefined) {
+ self = parent; parent = locals; locals = null;
+ }
+ if (!locals) locals = NO_LOCALS;
+ else if (!isObject(locals)) {
+ throw new Error("'locals' must be an object");
+ }
+ if (!parent) parent = NO_PARENT;
+ else if (!isResolve(parent)) {
+ throw new Error("'parent' must be a promise returned by $resolve.resolve()");
+ }
+
+ // To complete the overall resolution, we have to wait for the parent
+ // promise and for the promise for each invokable in our plan.
+ var resolution = $q.defer(),
+ result = resolution.promise,
+ promises = result.$$promises = {},
+ values = extend({}, locals),
+ wait = 1 + plan.length/3,
+ merged = false;
+
+ function done() {
+ // Merge parent values we haven't got yet and publish our own $$values
+ if (!--wait) {
+ if (!merged) merge(values, parent.$$values);
+ result.$$values = values;
+ result.$$promises = result.$$promises || true; // keep for isResolve()
+ delete result.$$inheritedValues;
+ resolution.resolve(values);
+ }
+ }
+
+ function fail(reason) {
+ result.$$failure = reason;
+ resolution.reject(reason);
+ }
+
+ // Short-circuit if parent has already failed
+ if (isDefined(parent.$$failure)) {
+ fail(parent.$$failure);
+ return result;
+ }
+
+ if (parent.$$inheritedValues) {
+ merge(values, omit(parent.$$inheritedValues, invocableKeys));
+ }
+
+ // Merge parent values if the parent has already resolved, or merge
+ // parent promises and wait if the parent resolve is still in progress.
+ extend(promises, parent.$$promises);
+ if (parent.$$values) {
+ merged = merge(values, omit(parent.$$values, invocableKeys));
+ result.$$inheritedValues = omit(parent.$$values, invocableKeys);
+ done();
+ } else {
+ if (parent.$$inheritedValues) {
+ result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);
+ }
+ parent.then(done, fail);
+ }
+
+ // Process each invocable in the plan, but ignore any where a local of the same name exists.
+ for (var i=0, ii=plan.length; i<ii; i+=3) {
+ if (locals.hasOwnProperty(plan[i])) done();
+ else invoke(plan[i], plan[i+1], plan[i+2]);
+ }
+
+ function invoke(key, invocable, params) {
+ // Create a deferred for this invocation. Failures will propagate to the resolution as well.
+ var invocation = $q.defer(), waitParams = 0;
+ function onfailure(reason) {
+ invocation.reject(reason);
+ fail(reason);
+ }
+ // Wait for any parameter that we have a promise for (either from parent or from this
+ // resolve; in that case study() will have made sure it's ordered before us in the plan).
+ forEach(params, function (dep) {
+ if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) {
+ waitParams++;
+ promises[dep].then(function (result) {
+ values[dep] = result;
+ if (!(--waitParams)) proceed();
+ }, onfailure);
+ }
+ });
+ if (!waitParams) proceed();
+ function proceed() {
+ if (isDefined(result.$$failure)) return;
+ try {
+ invocation.resolve($injector.invoke(invocable, self, values));
+ invocation.promise.then(function (result) {
+ values[key] = result;
+ done();
+ }, onfailure);
+ } catch (e) {
+ onfailure(e);
+ }
+ }
+ // Publish promise synchronously; invocations further down in the plan may depend on it.
+ promises[key] = invocation.promise;
+ }
+
+ return result;
+ };
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$resolve#resolve
+ * @methodOf ui.router.util.$resolve
+ *
+ * @description
+ * Resolves a set of invocables. An invocable is a function to be invoked via
+ * `$injector.invoke()`, and can have an arbitrary number of dependencies.
+ * An invocable can either return a value directly,
+ * or a `$q` promise. If a promise is returned it will be resolved and the
+ * resulting value will be used instead. Dependencies of invocables are resolved
+ * (in this order of precedence)
+ *
+ * - from the specified `locals`
+ * - from another invocable that is part of this `$resolve` call
+ * - from an invocable that is inherited from a `parent` call to `$resolve`
+ * (or recursively
+ * - from any ancestor `$resolve` of that parent).
+ *
+ * The return value of `$resolve` is a promise for an object that contains
+ * (in this order of precedence)
+ *
+ * - any `locals` (if specified)
+ * - the resolved return values of all injectables
+ * - any values inherited from a `parent` call to `$resolve` (if specified)
+ *
+ * The promise will resolve after the `parent` promise (if any) and all promises
+ * returned by injectables have been resolved. If any invocable
+ * (or `$injector.invoke`) throws an exception, or if a promise returned by an
+ * invocable is rejected, the `$resolve` promise is immediately rejected with the
+ * same error. A rejection of a `parent` promise (if specified) will likewise be
+ * propagated immediately. Once the `$resolve` promise has been rejected, no
+ * further invocables will be called.
+ *
+ * Cyclic dependencies between invocables are not permitted and will cause `$resolve`
+ * to throw an error. As a special case, an injectable can depend on a parameter
+ * with the same name as the injectable, which will be fulfilled from the `parent`
+ * injectable of the same name. This allows inherited values to be decorated.
+ * Note that in this case any other injectable in the same `$resolve` with the same
+ * dependency would see the decorated value, not the inherited value.
+ *
+ * Note that missing dependencies -- unlike cyclic dependencies -- will cause an
+ * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous)
+ * exception.
+ *
+ * Invocables are invoked eagerly as soon as all dependencies are available.
+ * This is true even for dependencies inherited from a `parent` call to `$resolve`.
+ *
+ * As a special case, an invocable can be a string, in which case it is taken to
+ * be a service name to be passed to `$injector.get()`. This is supported primarily
+ * for backwards-compatibility with the `resolve` property of `$routeProvider`
+ * routes.
+ *
+ * @param {object} invocables functions to invoke or
+ * `$injector` services to fetch.
+ * @param {object} locals values to make available to the injectables
+ * @param {object} parent a promise returned by another call to `$resolve`.
+ * @param {object} self the `this` for the invoked methods
+ * @return {object} Promise for an object that contains the resolved return value
+ * of all invocables, as well as any inherited and local values.
+ */
+ this.resolve = function (invocables, locals, parent, self) {
+ return this.study(invocables)(locals, parent, self);
+ };
+}
+
+angular.module('ui.router.util').service('$resolve', $Resolve);
+
diff --git a/afb-client/bower_components/angular-ui-router/src/state.js b/afb-client/bower_components/angular-ui-router/src/state.js
new file mode 100644
index 0000000..34e4f87
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/state.js
@@ -0,0 +1,1470 @@
+/**
+ * @ngdoc object
+ * @name ui.router.state.$stateProvider
+ *
+ * @requires ui.router.router.$urlRouterProvider
+ * @requires ui.router.util.$urlMatcherFactoryProvider
+ *
+ * @description
+ * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely
+ * on state.
+ *
+ * A state corresponds to a "place" in the application in terms of the overall UI and
+ * navigation. A state describes (via the controller / template / view properties) what
+ * the UI looks like and does at that place.
+ *
+ * States often have things in common, and the primary way of factoring out these
+ * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
+ * nested states.
+ *
+ * The `$stateProvider` provides interfaces to declare these states for your app.
+ */
+$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];
+function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
+
+ var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
+
+ // Builds state properties from definition passed to registerState()
+ var stateBuilder = {
+
+ // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined.
+ // state.children = [];
+ // if (parent) parent.children.push(state);
+ parent: function(state) {
+ if (isDefined(state.parent) && state.parent) return findState(state.parent);
+ // regex matches any valid composite state name
+ // would match "contact.list" but not "contacts"
+ var compositeName = /^(.+)\.[^.]+$/.exec(state.name);
+ return compositeName ? findState(compositeName[1]) : root;
+ },
+
+ // inherit 'data' from parent and override by own values (if any)
+ data: function(state) {
+ if (state.parent && state.parent.data) {
+ state.data = state.self.data = inherit(state.parent.data, state.data);
+ }
+ return state.data;
+ },
+
+ // Build a URLMatcher if necessary, either via a relative or absolute URL
+ url: function(state) {
+ var url = state.url, config = { params: state.params || {} };
+
+ if (isString(url)) {
+ if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);
+ return (state.parent.navigable || root).url.concat(url, config);
+ }
+
+ if (!url || $urlMatcherFactory.isMatcher(url)) return url;
+ throw new Error("Invalid url '" + url + "' in state '" + state + "'");
+ },
+
+ // Keep track of the closest ancestor state that has a URL (i.e. is navigable)
+ navigable: function(state) {
+ return state.url ? state : (state.parent ? state.parent.navigable : null);
+ },
+
+ // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
+ ownParams: function(state) {
+ var params = state.url && state.url.params || new $$UMFP.ParamSet();
+ forEach(state.params || {}, function(config, id) {
+ if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config");
+ });
+ return params;
+ },
+
+ // Derive parameters for this state and ensure they're a super-set of parent's parameters
+ params: function(state) {
+ var ownParams = pick(state.ownParams, state.ownParams.$$keys());
+ return state.parent && state.parent.params ? extend(state.parent.params.$$new(), ownParams) : new $$UMFP.ParamSet();
+ },
+
+ // If there is no explicit multi-view configuration, make one up so we don't have
+ // to handle both cases in the view directive later. Note that having an explicit
+ // 'views' property will mean the default unnamed view properties are ignored. This
+ // is also a good time to resolve view names to absolute names, so everything is a
+ // straight lookup at link time.
+ views: function(state) {
+ var views = {};
+
+ forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) {
+ if (name.indexOf('@') < 0) name += '@' + state.parent.name;
+ views[name] = view;
+ });
+ return views;
+ },
+
+ // Keep a full path from the root down to this state as this is needed for state activation.
+ path: function(state) {
+ return state.parent ? state.parent.path.concat(state) : []; // exclude root from path
+ },
+
+ // Speed up $state.contains() as it's used a lot
+ includes: function(state) {
+ var includes = state.parent ? extend({}, state.parent.includes) : {};
+ includes[state.name] = true;
+ return includes;
+ },
+
+ $delegates: {}
+ };
+
+ function isRelative(stateName) {
+ return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0;
+ }
+
+ function findState(stateOrName, base) {
+ if (!stateOrName) return undefined;
+
+ var isStr = isString(stateOrName),
+ name = isStr ? stateOrName : stateOrName.name,
+ path = isRelative(name);
+
+ if (path) {
+ if (!base) throw new Error("No reference point given for path '" + name + "'");
+ base = findState(base);
+
+ var rel = name.split("."), i = 0, pathLength = rel.length, current = base;
+
+ for (; i < pathLength; i++) {
+ if (rel[i] === "" && i === 0) {
+ current = base;
+ continue;
+ }
+ if (rel[i] === "^") {
+ if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'");
+ current = current.parent;
+ continue;
+ }
+ break;
+ }
+ rel = rel.slice(i).join(".");
+ name = current.name + (current.name && rel ? "." : "") + rel;
+ }
+ var state = states[name];
+
+ if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {
+ return state;
+ }
+ return undefined;
+ }
+
+ function queueState(parentName, state) {
+ if (!queue[parentName]) {
+ queue[parentName] = [];
+ }
+ queue[parentName].push(state);
+ }
+
+ function flushQueuedChildren(parentName) {
+ var queued = queue[parentName] || [];
+ while(queued.length) {
+ registerState(queued.shift());
+ }
+ }
+
+ function registerState(state) {
+ // Wrap a new object around the state so we can store our private details easily.
+ state = inherit(state, {
+ self: state,
+ resolve: state.resolve || {},
+ toString: function() { return this.name; }
+ });
+
+ var name = state.name;
+ if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name");
+ if (states.hasOwnProperty(name)) throw new Error("State '" + name + "' is already defined");
+
+ // Get parent name
+ var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))
+ : (isString(state.parent)) ? state.parent
+ : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name
+ : '';
+
+ // If parent is not registered yet, add state to queue and register later
+ if (parentName && !states[parentName]) {
+ return queueState(parentName, state.self);
+ }
+
+ for (var key in stateBuilder) {
+ if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]);
+ }
+ states[name] = state;
+
+ // Register the state in the global state list and with $urlRouter if necessary.
+ if (!state[abstractKey] && state.url) {
+ $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
+ if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
+ $state.transitionTo(state, $match, { inherit: true, location: false });
+ }
+ }]);
+ }
+
+ // Register any queued children
+ flushQueuedChildren(name);
+
+ return state;
+ }
+
+ // Checks text to see if it looks like a glob.
+ function isGlob (text) {
+ return text.indexOf('*') > -1;
+ }
+
+ // Returns true if glob matches current $state name.
+ function doesStateMatchGlob (glob) {
+ var globSegments = glob.split('.'),
+ segments = $state.$current.name.split('.');
+
+ //match single stars
+ for (var i = 0, l = globSegments.length; i < l; i++) {
+ if (globSegments[i] === '*') {
+ segments[i] = '*';
+ }
+ }
+
+ //match greedy starts
+ if (globSegments[0] === '**') {
+ segments = segments.slice(indexOf(segments, globSegments[1]));
+ segments.unshift('**');
+ }
+ //match greedy ends
+ if (globSegments[globSegments.length - 1] === '**') {
+ segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
+ segments.push('**');
+ }
+
+ if (globSegments.length != segments.length) {
+ return false;
+ }
+
+ return segments.join('') === globSegments.join('');
+ }
+
+
+ // Implicit root state that is always active
+ root = registerState({
+ name: '',
+ url: '^',
+ views: null,
+ 'abstract': true
+ });
+ root.navigable = null;
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$stateProvider#decorator
+ * @methodOf ui.router.state.$stateProvider
+ *
+ * @description
+ * Allows you to extend (carefully) or override (at your own peril) the
+ * `stateBuilder` object used internally by `$stateProvider`. This can be used
+ * to add custom functionality to ui-router, for example inferring templateUrl
+ * based on the state name.
+ *
+ * When passing only a name, it returns the current (original or decorated) builder
+ * function that matches `name`.
+ *
+ * The builder functions that can be decorated are listed below. Though not all
+ * necessarily have a good use case for decoration, that is up to you to decide.
+ *
+ * In addition, users can attach custom decorators, which will generate new
+ * properties within the state's internal definition. There is currently no clear
+ * use-case for this beyond accessing internal states (i.e. $state.$current),
+ * however, expect this to become increasingly relevant as we introduce additional
+ * meta-programming features.
+ *
+ * **Warning**: Decorators should not be interdependent because the order of
+ * execution of the builder functions in non-deterministic. Builder functions
+ * should only be dependent on the state definition object and super function.
+ *
+ *
+ * Existing builder functions and current return values:
+ *
+ * - **parent** `{object}` - returns the parent state object.
+ * - **data** `{object}` - returns state data, including any inherited data that is not
+ * overridden by own values (if any).
+ * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
+ * or `null`.
+ * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
+ * navigable).
+ * - **params** `{object}` - returns an array of state params that are ensured to
+ * be a super-set of parent's params.
+ * - **views** `{object}` - returns a views object where each key is an absolute view
+ * name (i.e. "viewName@stateName") and each value is the config object
+ * (template, controller) for the view. Even when you don't use the views object
+ * explicitly on a state config, one is still created for you internally.
+ * So by decorating this builder function you have access to decorating template
+ * and controller properties.
+ * - **ownParams** `{object}` - returns an array of params that belong to the state,
+ * not including any params defined by ancestor states.
+ * - **path** `{string}` - returns the full path from the root down to this state.
+ * Needed for state activation.
+ * - **includes** `{object}` - returns an object that includes every state that
+ * would pass a `$state.includes()` test.
+ *
+ * @example
+ * <pre>
+ * // Override the internal 'views' builder with a function that takes the state
+ * // definition, and a reference to the internal function being overridden:
+ * $stateProvider.decorator('views', function (state, parent) {
+ * var result = {},
+ * views = parent(state);
+ *
+ * angular.forEach(views, function (config, name) {
+ * var autoName = (state.name + '.' + name).replace('.', '/');
+ * config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
+ * result[name] = config;
+ * });
+ * return result;
+ * });
+ *
+ * $stateProvider.state('home', {
+ * views: {
+ * 'contact.list': { controller: 'ListController' },
+ * 'contact.item': { controller: 'ItemController' }
+ * }
+ * });
+ *
+ * // ...
+ *
+ * $state.go('home');
+ * // Auto-populates list and item views with /partials/home/contact/list.html,
+ * // and /partials/home/contact/item.html, respectively.
+ * </pre>
+ *
+ * @param {string} name The name of the builder function to decorate.
+ * @param {object} func A function that is responsible for decorating the original
+ * builder function. The function receives two parameters:
+ *
+ * - `{object}` - state - The state config object.
+ * - `{object}` - super - The original builder function.
+ *
+ * @return {object} $stateProvider - $stateProvider instance
+ */
+ this.decorator = decorator;
+ function decorator(name, func) {
+ /*jshint validthis: true */
+ if (isString(name) && !isDefined(func)) {
+ return stateBuilder[name];
+ }
+ if (!isFunction(func) || !isString(name)) {
+ return this;
+ }
+ if (stateBuilder[name] && !stateBuilder.$delegates[name]) {
+ stateBuilder.$delegates[name] = stateBuilder[name];
+ }
+ stateBuilder[name] = func;
+ return this;
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$stateProvider#state
+ * @methodOf ui.router.state.$stateProvider
+ *
+ * @description
+ * Registers a state configuration under a given state name. The stateConfig object
+ * has the following acceptable properties.
+ *
+ * @param {string} name A unique state name, e.g. "home", "about", "contacts".
+ * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
+ * @param {object} stateConfig State configuration object.
+ * @param {string|function=} stateConfig.template
+ * <a id='template'></a>
+ * html template as a string or a function that returns
+ * an html template as a string which should be used by the uiView directives. This property
+ * takes precedence over templateUrl.
+ *
+ * If `template` is a function, it will be called with the following parameters:
+ *
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
+ * applying the current state
+ *
+ * <pre>template:
+ * "<h1>inline template definition</h1>" +
+ * "<div ui-view></div>"</pre>
+ * <pre>template: function(params) {
+ * return "<h1>generated template</h1>"; }</pre>
+ * </div>
+ *
+ * @param {string|function=} stateConfig.templateUrl
+ * <a id='templateUrl'></a>
+ *
+ * path or function that returns a path to an html
+ * template that should be used by uiView.
+ *
+ * If `templateUrl` is a function, it will be called with the following parameters:
+ *
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
+ * applying the current state
+ *
+ * <pre>templateUrl: "home.html"</pre>
+ * <pre>templateUrl: function(params) {
+ * return myTemplates[params.pageId]; }</pre>
+ *
+ * @param {function=} stateConfig.templateProvider
+ * <a id='templateProvider'></a>
+ * Provider function that returns HTML content string.
+ * <pre> templateProvider:
+ * function(MyTemplateService, params) {
+ * return MyTemplateService.getTemplate(params.pageId);
+ * }</pre>
+ *
+ * @param {string|function=} stateConfig.controller
+ * <a id='controller'></a>
+ *
+ * Controller fn that should be associated with newly
+ * related scope or the name of a registered controller if passed as a string.
+ * Optionally, the ControllerAs may be declared here.
+ * <pre>controller: "MyRegisteredController"</pre>
+ * <pre>controller:
+ * "MyRegisteredController as fooCtrl"}</pre>
+ * <pre>controller: function($scope, MyService) {
+ * $scope.data = MyService.getData(); }</pre>
+ *
+ * @param {function=} stateConfig.controllerProvider
+ * <a id='controllerProvider'></a>
+ *
+ * Injectable provider function that returns the actual controller or string.
+ * <pre>controllerProvider:
+ * function(MyResolveData) {
+ * if (MyResolveData.foo)
+ * return "FooCtrl"
+ * else if (MyResolveData.bar)
+ * return "BarCtrl";
+ * else return function($scope) {
+ * $scope.baz = "Qux";
+ * }
+ * }</pre>
+ *
+ * @param {string=} stateConfig.controllerAs
+ * <a id='controllerAs'></a>
+ *
+ * A controller alias name. If present the controller will be
+ * published to scope under the controllerAs name.
+ * <pre>controllerAs: "myCtrl"</pre>
+ *
+ * @param {string|object=} stateConfig.parent
+ * <a id='parent'></a>
+ * Optionally specifies the parent state of this state.
+ *
+ * <pre>parent: 'parentState'</pre>
+ * <pre>parent: parentState // JS variable</pre>
+ *
+ * @param {object=} stateConfig.resolve
+ * <a id='resolve'></a>
+ *
+ * An optional map&lt;string, function&gt; of dependencies which
+ * should be injected into the controller. If any of these dependencies are promises,
+ * the router will wait for them all to be resolved before the controller is instantiated.
+ * If all the promises are resolved successfully, the $stateChangeSuccess event is fired
+ * and the values of the resolved promises are injected into any controllers that reference them.
+ * If any of the promises are rejected the $stateChangeError event is fired.
+ *
+ * The map object is:
+ *
+ * - key - {string}: name of dependency to be injected into controller
+ * - factory - {string|function}: If string then it is alias for service. Otherwise if function,
+ * it is injected and return value it treated as dependency. If result is a promise, it is
+ * resolved before its value is injected into controller.
+ *
+ * <pre>resolve: {
+ * myResolve1:
+ * function($http, $stateParams) {
+ * return $http.get("/api/foos/"+stateParams.fooID);
+ * }
+ * }</pre>
+ *
+ * @param {string=} stateConfig.url
+ * <a id='url'></a>
+ *
+ * A url fragment with optional parameters. When a state is navigated or
+ * transitioned to, the `$stateParams` service will be populated with any
+ * parameters that were passed.
+ *
+ * (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for
+ * more details on acceptable patterns )
+ *
+ * examples:
+ * <pre>url: "/home"
+ * url: "/users/:userid"
+ * url: "/books/{bookid:[a-zA-Z_-]}"
+ * url: "/books/{categoryid:int}"
+ * url: "/books/{publishername:string}/{categoryid:int}"
+ * url: "/messages?before&after"
+ * url: "/messages?{before:date}&{after:date}"
+ * url: "/messages/:mailboxid?{before:date}&{after:date}"
+ * </pre>
+ *
+ * @param {object=} stateConfig.views
+ * <a id='views'></a>
+ * an optional map&lt;string, object&gt; which defined multiple views, or targets views
+ * manually/explicitly.
+ *
+ * Examples:
+ *
+ * Targets three named `ui-view`s in the parent state's template
+ * <pre>views: {
+ * header: {
+ * controller: "headerCtrl",
+ * templateUrl: "header.html"
+ * }, body: {
+ * controller: "bodyCtrl",
+ * templateUrl: "body.html"
+ * }, footer: {
+ * controller: "footCtrl",
+ * templateUrl: "footer.html"
+ * }
+ * }</pre>
+ *
+ * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template.
+ * <pre>views: {
+ * 'header@top': {
+ * controller: "msgHeaderCtrl",
+ * templateUrl: "msgHeader.html"
+ * }, 'body': {
+ * controller: "messagesCtrl",
+ * templateUrl: "messages.html"
+ * }
+ * }</pre>
+ *
+ * @param {boolean=} [stateConfig.abstract=false]
+ * <a id='abstract'></a>
+ * An abstract state will never be directly activated,
+ * but can provide inherited properties to its common children states.
+ * <pre>abstract: true</pre>
+ *
+ * @param {function=} stateConfig.onEnter
+ * <a id='onEnter'></a>
+ *
+ * Callback function for when a state is entered. Good way
+ * to trigger an action or dispatch an event, such as opening a dialog.
+ * If minifying your scripts, make sure to explicitly annotate this function,
+ * because it won't be automatically annotated by your build tools.
+ *
+ * <pre>onEnter: function(MyService, $stateParams) {
+ * MyService.foo($stateParams.myParam);
+ * }</pre>
+ *
+ * @param {function=} stateConfig.onExit
+ * <a id='onExit'></a>
+ *
+ * Callback function for when a state is exited. Good way to
+ * trigger an action or dispatch an event, such as opening a dialog.
+ * If minifying your scripts, make sure to explicitly annotate this function,
+ * because it won't be automatically annotated by your build tools.
+ *
+ * <pre>onExit: function(MyService, $stateParams) {
+ * MyService.cleanup($stateParams.myParam);
+ * }</pre>
+ *
+ * @param {boolean=} [stateConfig.reloadOnSearch=true]
+ * <a id='reloadOnSearch'></a>
+ *
+ * If `false`, will not retrigger the same state
+ * just because a search/query parameter has changed (via $location.search() or $location.hash()).
+ * Useful for when you'd like to modify $location.search() without triggering a reload.
+ * <pre>reloadOnSearch: false</pre>
+ *
+ * @param {object=} stateConfig.data
+ * <a id='data'></a>
+ *
+ * Arbitrary data object, useful for custom configuration. The parent state's `data` is
+ * prototypally inherited. In other words, adding a data property to a state adds it to
+ * the entire subtree via prototypal inheritance.
+ *
+ * <pre>data: {
+ * requiredRole: 'foo'
+ * } </pre>
+ *
+ * @param {object=} stateConfig.params
+ * <a id='params'></a>
+ *
+ * A map which optionally configures parameters declared in the `url`, or
+ * defines additional non-url parameters. For each parameter being
+ * configured, add a configuration object keyed to the name of the parameter.
+ *
+ * Each parameter configuration object may contain the following properties:
+ *
+ * - ** value ** - {object|function=}: specifies the default value for this
+ * parameter. This implicitly sets this parameter as optional.
+ *
+ * When UI-Router routes to a state and no value is
+ * specified for this parameter in the URL or transition, the
+ * default value will be used instead. If `value` is a function,
+ * it will be injected and invoked, and the return value used.
+ *
+ * *Note*: `undefined` is treated as "no default value" while `null`
+ * is treated as "the default value is `null`".
+ *
+ * *Shorthand*: If you only need to configure the default value of the
+ * parameter, you may use a shorthand syntax. In the **`params`**
+ * map, instead mapping the param name to a full parameter configuration
+ * object, simply set map it to the default parameter value, e.g.:
+ *
+ * <pre>// define a parameter's default value
+ * params: {
+ * param1: { value: "defaultValue" }
+ * }
+ * // shorthand default values
+ * params: {
+ * param1: "defaultValue",
+ * param2: "param2Default"
+ * }</pre>
+ *
+ * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be
+ * treated as an array of values. If you specified a Type, the value will be
+ * treated as an array of the specified Type. Note: query parameter values
+ * default to a special `"auto"` mode.
+ *
+ * For query parameters in `"auto"` mode, if multiple values for a single parameter
+ * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values
+ * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if
+ * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single
+ * value (e.g.: `{ foo: '1' }`).
+ *
+ * <pre>params: {
+ * param1: { array: true }
+ * }</pre>
+ *
+ * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when
+ * the current parameter value is the same as the default value. If `squash` is not set, it uses the
+ * configured default squash policy.
+ * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`})
+ *
+ * There are three squash settings:
+ *
+ * - false: The parameter's default value is not squashed. It is encoded and included in the URL
+ * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed
+ * by slashes in the state's `url` declaration, then one of those slashes are omitted.
+ * This can allow for cleaner looking URLs.
+ * - `"<arbitrary string>"`: The parameter's default value is replaced with an arbitrary placeholder of your choice.
+ *
+ * <pre>params: {
+ * param1: {
+ * value: "defaultId",
+ * squash: true
+ * } }
+ * // squash "defaultValue" to "~"
+ * params: {
+ * param1: {
+ * value: "defaultValue",
+ * squash: "~"
+ * } }
+ * </pre>
+ *
+ *
+ * @example
+ * <pre>
+ * // Some state name examples
+ *
+ * // stateName can be a single top-level name (must be unique).
+ * $stateProvider.state("home", {});
+ *
+ * // Or it can be a nested state name. This state is a child of the
+ * // above "home" state.
+ * $stateProvider.state("home.newest", {});
+ *
+ * // Nest states as deeply as needed.
+ * $stateProvider.state("home.newest.abc.xyz.inception", {});
+ *
+ * // state() returns $stateProvider, so you can chain state declarations.
+ * $stateProvider
+ * .state("home", {})
+ * .state("about", {})
+ * .state("contacts", {});
+ * </pre>
+ *
+ */
+ this.state = state;
+ function state(name, definition) {
+ /*jshint validthis: true */
+ if (isObject(name)) definition = name;
+ else definition.name = name;
+ registerState(definition);
+ return this;
+ }
+
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$state
+ *
+ * @requires $rootScope
+ * @requires $q
+ * @requires ui.router.state.$view
+ * @requires $injector
+ * @requires ui.router.util.$resolve
+ * @requires ui.router.state.$stateParams
+ * @requires ui.router.router.$urlRouter
+ *
+ * @property {object} params A param object, e.g. {sectionId: section.id)}, that
+ * you'd like to test against the current active state.
+ * @property {object} current A reference to the state's config object. However
+ * you passed it in. Useful for accessing custom data.
+ * @property {object} transition Currently pending transition. A promise that'll
+ * resolve or reject.
+ *
+ * @description
+ * `$state` service is responsible for representing states as well as transitioning
+ * between them. It also provides interfaces to ask for current state or even states
+ * you're coming from.
+ */
+ this.$get = $get;
+ $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];
+ function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) {
+
+ var TransitionSuperseded = $q.reject(new Error('transition superseded'));
+ var TransitionPrevented = $q.reject(new Error('transition prevented'));
+ var TransitionAborted = $q.reject(new Error('transition aborted'));
+ var TransitionFailed = $q.reject(new Error('transition failed'));
+
+ // Handles the case where a state which is the target of a transition is not found, and the user
+ // can optionally retry or defer the transition
+ function handleRedirect(redirect, state, params, options) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateNotFound
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when a requested state **cannot be found** using the provided state name during transition.
+ * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
+ * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
+ * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
+ * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
+ *
+ * @param {Object} event Event object.
+ * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
+ * @param {State} fromState Current state object.
+ * @param {Object} fromParams Current state params.
+ *
+ * @example
+ *
+ * <pre>
+ * // somewhere, assume lazy.state has not been defined
+ * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
+ *
+ * // somewhere else
+ * $scope.$on('$stateNotFound',
+ * function(event, unfoundState, fromState, fromParams){
+ * console.log(unfoundState.to); // "lazy.state"
+ * console.log(unfoundState.toParams); // {a:1, b:2}
+ * console.log(unfoundState.options); // {inherit:false} + default options
+ * })
+ * </pre>
+ */
+ var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params);
+
+ if (evt.defaultPrevented) {
+ $urlRouter.update();
+ return TransitionAborted;
+ }
+
+ if (!evt.retry) {
+ return null;
+ }
+
+ // Allow the handler to return a promise to defer state lookup retry
+ if (options.$retry) {
+ $urlRouter.update();
+ return TransitionFailed;
+ }
+ var retryTransition = $state.transition = $q.when(evt.retry);
+
+ retryTransition.then(function() {
+ if (retryTransition !== $state.transition) return TransitionSuperseded;
+ redirect.options.$retry = true;
+ return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);
+ }, function() {
+ return TransitionAborted;
+ });
+ $urlRouter.update();
+
+ return retryTransition;
+ }
+
+ root.locals = { resolve: null, globals: { $stateParams: {} } };
+
+ $state = {
+ params: {},
+ current: root.self,
+ $current: root,
+ transition: null
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#reload
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A method that force reloads the current state. All resolves are re-resolved,
+ * controllers reinstantiated, and events re-fired.
+ *
+ * @example
+ * <pre>
+ * var app angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.reload = function(){
+ * $state.reload();
+ * }
+ * });
+ * </pre>
+ *
+ * `reload()` is just an alias for:
+ * <pre>
+ * $state.transitionTo($state.current, $stateParams, {
+ * reload: true, inherit: false, notify: true
+ * });
+ * </pre>
+ *
+ * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved.
+ * @example
+ * <pre>
+ * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item'
+ * //and current state is 'contacts.detail.item'
+ * var app angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.reload = function(){
+ * //will reload 'contact.detail' and 'contact.detail.item' states
+ * $state.reload('contact.detail');
+ * }
+ * });
+ * </pre>
+ *
+ * `reload()` is just an alias for:
+ * <pre>
+ * $state.transitionTo($state.current, $stateParams, {
+ * reload: true, inherit: false, notify: true
+ * });
+ * </pre>
+
+ * @returns {promise} A promise representing the state of the new transition. See
+ * {@link ui.router.state.$state#methods_go $state.go}.
+ */
+ $state.reload = function reload(state) {
+ return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true});
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#go
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Convenience method for transitioning to a new state. `$state.go` calls
+ * `$state.transitionTo` internally but automatically sets options to
+ * `{ location: true, inherit: true, relative: $state.$current, notify: true }`.
+ * This allows you to easily use an absolute or relative to path and specify
+ * only the parameters you'd like to update (while letting unspecified parameters
+ * inherit from the currently active ancestor states).
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.changeState = function () {
+ * $state.go('contact.detail');
+ * };
+ * });
+ * </pre>
+ * <img src='../ngdoc_assets/StateGoExamples.png'/>
+ *
+ * @param {string} to Absolute state name or relative state path. Some examples:
+ *
+ * - `$state.go('contact.detail')` - will go to the `contact.detail` state
+ * - `$state.go('^')` - will go to a parent state
+ * - `$state.go('^.sibling')` - will go to a sibling state
+ * - `$state.go('.child.grandchild')` - will go to grandchild state
+ *
+ * @param {object=} params A map of the parameters that will be sent to the state,
+ * will populate $stateParams. Any parameters that are not specified will be inherited from currently
+ * defined parameters. Only parameters specified in the state definition can be overridden, new
+ * parameters will be ignored. This allows, for example, going to a sibling state that shares parameters
+ * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e.
+ * transitioning to a sibling will get you the parameters for all parents, transitioning to a child
+ * will get you all current parameters, etc.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
+ * - **`reload`** (v0.2.5) - {boolean=false|string|object}, If `true` will force transition even if no state or params
+ * have changed. It will reload the resolves and views of the current state and parent states.
+ * If `reload` is a string (or state object), the state object is fetched (by name, or object reference); and \
+ * the transition reloads the resolves and views for that matched state, and all its children states.
+ *
+ * @returns {promise} A promise representing the state of the new transition.
+ *
+ * Possible success values:
+ *
+ * - $state.current
+ *
+ * <br/>Possible rejection values:
+ *
+ * - 'transition superseded' - when a newer transition has been started after this one
+ * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener
+ * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or
+ * when a `$stateNotFound` `event.retry` promise errors.
+ * - 'transition failed' - when a state has been unsuccessfully found after 2 tries.
+ * - *resolve error* - when an error has occurred with a `resolve`
+ *
+ */
+ $state.go = function go(to, params, options) {
+ return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#transitionTo
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go}
+ * uses `transitionTo` internally. `$state.go` is recommended in most situations.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router']);
+ *
+ * app.controller('ctrl', function ($scope, $state) {
+ * $scope.changeState = function () {
+ * $state.transitionTo('contact.detail');
+ * };
+ * });
+ * </pre>
+ *
+ * @param {string} to State name.
+ * @param {object=} toParams A map of the parameters that will be sent to the state,
+ * will populate $stateParams.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
+ * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
+ * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params
+ * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
+ * use this when you want to force a reload when *everything* is the same, including search params.
+ * if String, then will reload the state with the name given in reload, and any children.
+ * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children.
+ *
+ * @returns {promise} A promise representing the state of the new transition. See
+ * {@link ui.router.state.$state#methods_go $state.go}.
+ */
+ $state.transitionTo = function transitionTo(to, toParams, options) {
+ toParams = toParams || {};
+ options = extend({
+ location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false
+ }, options || {});
+
+ var from = $state.$current, fromParams = $state.params, fromPath = from.path;
+ var evt, toState = findState(to, options.relative);
+
+ // Store the hash param for later (since it will be stripped out by various methods)
+ var hash = toParams['#'];
+
+ if (!isDefined(toState)) {
+ var redirect = { to: to, toParams: toParams, options: options };
+ var redirectResult = handleRedirect(redirect, from.self, fromParams, options);
+
+ if (redirectResult) {
+ return redirectResult;
+ }
+
+ // Always retry once if the $stateNotFound was not prevented
+ // (handles either redirect changed or state lazy-definition)
+ to = redirect.to;
+ toParams = redirect.toParams;
+ options = redirect.options;
+ toState = findState(to, options.relative);
+
+ if (!isDefined(toState)) {
+ if (!options.relative) throw new Error("No such state '" + to + "'");
+ throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
+ }
+ }
+ if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
+ if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
+ if (!toState.params.$$validates(toParams)) return TransitionFailed;
+
+ toParams = toState.params.$$values(toParams);
+ to = toState;
+
+ var toPath = to.path;
+
+ // Starting from the root of the path, keep all levels that haven't changed
+ var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
+
+ if (!options.reload) {
+ while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
+ locals = toLocals[keep] = state.locals;
+ keep++;
+ state = toPath[keep];
+ }
+ } else if (isString(options.reload) || isObject(options.reload)) {
+ if (isObject(options.reload) && !options.reload.name) {
+ throw new Error('Invalid reload state object');
+ }
+
+ var reloadState = options.reload === true ? fromPath[0] : findState(options.reload);
+ if (options.reload && !reloadState) {
+ throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
+ }
+
+ while (state && state === fromPath[keep] && state !== reloadState) {
+ locals = toLocals[keep] = state.locals;
+ keep++;
+ state = toPath[keep];
+ }
+ }
+
+ // If we're going to the same state and all locals are kept, we've got nothing to do.
+ // But clear 'transition', as we still want to cancel any other pending transitions.
+ // TODO: We may not want to bump 'transition' if we're called from a location change
+ // that we've initiated ourselves, because we might accidentally abort a legitimate
+ // transition initiated from code?
+ if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
+ if (hash) toParams['#'] = hash;
+ $state.params = toParams;
+ copy($state.params, $stateParams);
+ copy(filterByKeys(to.params.$$keys(), $stateParams), to.locals.globals.$stateParams);
+ if (options.location && to.navigable && to.navigable.url) {
+ $urlRouter.push(to.navigable.url, toParams, {
+ $$avoidResync: true, replace: options.location === 'replace'
+ });
+ $urlRouter.update(true);
+ }
+ $state.transition = null;
+ return $q.when($state.current);
+ }
+
+ // Filter parameters before we pass them to event handlers etc.
+ toParams = filterByKeys(to.params.$$keys(), toParams || {});
+
+ // Re-add the saved hash before we start returning things or broadcasting $stateChangeStart
+ if (hash) toParams['#'] = hash;
+
+ // Broadcast start event and cancel the transition if requested
+ if (options.notify) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeStart
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when the state transition **begins**. You can use `event.preventDefault()`
+ * to prevent the transition from happening and then the transition promise will be
+ * rejected with a `'transition prevented'` value.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ *
+ * @example
+ *
+ * <pre>
+ * $rootScope.$on('$stateChangeStart',
+ * function(event, toState, toParams, fromState, fromParams){
+ * event.preventDefault();
+ * // transitionTo() promise will be rejected with
+ * // a 'transition prevented' error
+ * })
+ * </pre>
+ */
+ if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams, options).defaultPrevented) {
+ $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
+ //Don't update and resync url if there's been a new transition started. see issue #2238, #600
+ if ($state.transition == null) $urlRouter.update();
+ return TransitionPrevented;
+ }
+ }
+
+ // Resolve locals for the remaining states, but don't update any global state just
+ // yet -- if anything fails to resolve the current state needs to remain untouched.
+ // We also set up an inheritance chain for the locals here. This allows the view directive
+ // to quickly look up the correct definition for each view in the current state. Even
+ // though we create the locals object itself outside resolveState(), it is initially
+ // empty and gets filled asynchronously. We need to keep track of the promise for the
+ // (fully resolved) current locals, and pass this down the chain.
+ var resolved = $q.when(locals);
+
+ for (var l = keep; l < toPath.length; l++, state = toPath[l]) {
+ locals = toLocals[l] = inherit(locals);
+ resolved = resolveState(state, toParams, state === to, resolved, locals, options);
+ }
+
+ // Once everything is resolved, we are ready to perform the actual transition
+ // and return a promise for the new state. We also keep track of what the
+ // current promise is, so that we can detect overlapping transitions and
+ // keep only the outcome of the last transition.
+ var transition = $state.transition = resolved.then(function () {
+ var l, entering, exiting;
+
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ // Exit 'from' states not kept
+ for (l = fromPath.length - 1; l >= keep; l--) {
+ exiting = fromPath[l];
+ if (exiting.self.onExit) {
+ $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals);
+ }
+ exiting.locals = null;
+ }
+
+ // Enter 'to' states not kept
+ for (l = keep; l < toPath.length; l++) {
+ entering = toPath[l];
+ entering.locals = toLocals[l];
+ if (entering.self.onEnter) {
+ $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals);
+ }
+ }
+
+ // Run it again, to catch any transitions in callbacks
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ // Update globals in $state
+ $state.$current = to;
+ $state.current = to.self;
+ $state.params = toParams;
+ copy($state.params, $stateParams);
+ $state.transition = null;
+
+ if (options.location && to.navigable) {
+ $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, {
+ $$avoidResync: true, replace: options.location === 'replace'
+ });
+ }
+
+ if (options.notify) {
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeSuccess
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired once the state transition is **complete**.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ */
+ $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);
+ }
+ $urlRouter.update(true);
+
+ return $state.current;
+ }, function (error) {
+ if ($state.transition !== transition) return TransitionSuperseded;
+
+ $state.transition = null;
+ /**
+ * @ngdoc event
+ * @name ui.router.state.$state#$stateChangeError
+ * @eventOf ui.router.state.$state
+ * @eventType broadcast on root scope
+ * @description
+ * Fired when an **error occurs** during transition. It's important to note that if you
+ * have any errors in your resolve functions (javascript errors, non-existent services, etc)
+ * they will not throw traditionally. You must listen for this $stateChangeError event to
+ * catch **ALL** errors.
+ *
+ * @param {Object} event Event object.
+ * @param {State} toState The state being transitioned to.
+ * @param {Object} toParams The params supplied to the `toState`.
+ * @param {State} fromState The current state, pre-transition.
+ * @param {Object} fromParams The params supplied to the `fromState`.
+ * @param {Error} error The resolve error object.
+ */
+ evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
+
+ if (!evt.defaultPrevented) {
+ $urlRouter.update();
+ }
+
+ return $q.reject(error);
+ });
+
+ return transition;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#is
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Similar to {@link ui.router.state.$state#methods_includes $state.includes},
+ * but only checks for the full state name. If params is supplied then it will be
+ * tested for strict equality against the current active params object, so all params
+ * must match with none missing and no extras.
+ *
+ * @example
+ * <pre>
+ * $state.$current.name = 'contacts.details.item';
+ *
+ * // absolute name
+ * $state.is('contact.details.item'); // returns true
+ * $state.is(contactDetailItemStateObject); // returns true
+ *
+ * // relative name (. and ^), typically from a template
+ * // E.g. from the 'contacts.details' template
+ * <div ng-class="{highlighted: $state.is('.item')}">Item</div>
+ * </pre>
+ *
+ * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check.
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
+ * to test against the current active state.
+ * @param {object=} options An options object. The options are:
+ *
+ * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will
+ * test relative to `options.relative` state (or name).
+ *
+ * @returns {boolean} Returns true if it is the state.
+ */
+ $state.is = function is(stateOrName, params, options) {
+ options = extend({ relative: $state.$current }, options || {});
+ var state = findState(stateOrName, options.relative);
+
+ if (!isDefined(state)) { return undefined; }
+ if ($state.$current !== state) { return false; }
+ return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#includes
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A method to determine if the current active state is equal to or is the child of the
+ * state stateName. If any params are passed then they will be tested for a match as well.
+ * Not all the parameters need to be passed, just the ones you'd like to test for equality.
+ *
+ * @example
+ * Partial and relative names
+ * <pre>
+ * $state.$current.name = 'contacts.details.item';
+ *
+ * // Using partial names
+ * $state.includes("contacts"); // returns true
+ * $state.includes("contacts.details"); // returns true
+ * $state.includes("contacts.details.item"); // returns true
+ * $state.includes("contacts.list"); // returns false
+ * $state.includes("about"); // returns false
+ *
+ * // Using relative names (. and ^), typically from a template
+ * // E.g. from the 'contacts.details' template
+ * <div ng-class="{highlighted: $state.includes('.item')}">Item</div>
+ * </pre>
+ *
+ * Basic globbing patterns
+ * <pre>
+ * $state.$current.name = 'contacts.details.item.url';
+ *
+ * $state.includes("*.details.*.*"); // returns true
+ * $state.includes("*.details.**"); // returns true
+ * $state.includes("**.item.**"); // returns true
+ * $state.includes("*.details.item.url"); // returns true
+ * $state.includes("*.details.*.url"); // returns true
+ * $state.includes("*.details.*"); // returns false
+ * $state.includes("item.**"); // returns false
+ * </pre>
+ *
+ * @param {string} stateOrName A partial name, relative name, or glob pattern
+ * to be searched for within the current state name.
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`,
+ * that you'd like to test against the current active state.
+ * @param {object=} options An options object. The options are:
+ *
+ * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set,
+ * .includes will test relative to `options.relative` state (or name).
+ *
+ * @returns {boolean} Returns true if it does include the state
+ */
+ $state.includes = function includes(stateOrName, params, options) {
+ options = extend({ relative: $state.$current }, options || {});
+ if (isString(stateOrName) && isGlob(stateOrName)) {
+ if (!doesStateMatchGlob(stateOrName)) {
+ return false;
+ }
+ stateOrName = $state.$current.name;
+ }
+
+ var state = findState(stateOrName, options.relative);
+ if (!isDefined(state)) { return undefined; }
+ if (!isDefined($state.$current.includes[state.name])) { return false; }
+ return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#href
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * A url generation method that returns the compiled url for the given state populated with the given params.
+ *
+ * @example
+ * <pre>
+ * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
+ * </pre>
+ *
+ * @param {string|object} stateOrName The state name or state object you'd like to generate a url from.
+ * @param {object=} params An object of parameter values to fill the state's required parameters.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the
+ * first parameter, then the constructed href url will be built from the first navigable ancestor (aka
+ * ancestor with a valid url).
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
+ * defines which state to be relative from.
+ * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
+ *
+ * @returns {string} compiled state url
+ */
+ $state.href = function href(stateOrName, params, options) {
+ options = extend({
+ lossy: true,
+ inherit: true,
+ absolute: false,
+ relative: $state.$current
+ }, options || {});
+
+ var state = findState(stateOrName, options.relative);
+
+ if (!isDefined(state)) return null;
+ if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state);
+
+ var nav = (state && options.lossy) ? state.navigable : state;
+
+ if (!nav || nav.url === undefined || nav.url === null) {
+ return null;
+ }
+ return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), {
+ absolute: options.absolute
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$state#get
+ * @methodOf ui.router.state.$state
+ *
+ * @description
+ * Returns the state configuration object for any specific state or all states.
+ *
+ * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for
+ * the requested state. If not provided, returns an array of ALL state configs.
+ * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context.
+ * @returns {Object|Array} State configuration object or array of all objects.
+ */
+ $state.get = function (stateOrName, context) {
+ if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; });
+ var state = findState(stateOrName, context || $state.$current);
+ return (state && state.self) ? state.self : null;
+ };
+
+ function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {
+ // Make a restricted $stateParams with only the parameters that apply to this state if
+ // necessary. In addition to being available to the controller and onEnter/onExit callbacks,
+ // we also need $stateParams to be available for any $injector calls we make during the
+ // dependency resolution process.
+ var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
+ var locals = { $stateParams: $stateParams };
+
+ // Resolve 'global' dependencies for the state, i.e. those not specific to a view.
+ // We're also including $stateParams in this; that way the parameters are restricted
+ // to the set that should be visible to the state, and are independent of when we update
+ // the global $state and $stateParams values.
+ dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);
+ var promises = [dst.resolve.then(function (globals) {
+ dst.globals = globals;
+ })];
+ if (inherited) promises.push(inherited);
+
+ function resolveViews() {
+ var viewsPromises = [];
+
+ // Resolve template and dependencies for all views.
+ forEach(state.views, function (view, name) {
+ var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
+ injectables.$template = [ function () {
+ return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || '';
+ }];
+
+ viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) {
+ // References to the controller (only instantiated at link time)
+ if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
+ var injectLocals = angular.extend({}, injectables, dst.globals);
+ result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
+ } else {
+ result.$$controller = view.controller;
+ }
+ // Provide access to the state itself for internal use
+ result.$$state = state;
+ result.$$controllerAs = view.controllerAs;
+ dst[name] = result;
+ }));
+ });
+
+ return $q.all(viewsPromises).then(function(){
+ return dst.globals;
+ });
+ }
+
+ // Wait for all the promises and then return the activation object
+ return $q.all(promises).then(resolveViews).then(function (values) {
+ return dst;
+ });
+ }
+
+ return $state;
+ }
+
+ function shouldSkipReload(to, toParams, from, fromParams, locals, options) {
+ // Return true if there are no differences in non-search (path/object) params, false if there are differences
+ function nonSearchParamsEqual(fromAndToState, fromParams, toParams) {
+ // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params.
+ function notSearchParam(key) {
+ return fromAndToState.params[key].location != "search";
+ }
+ var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam);
+ var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys));
+ var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams);
+ return nonQueryParamSet.$$equals(fromParams, toParams);
+ }
+
+ // If reload was not explicitly requested
+ // and we're transitioning to the same state we're already in
+ // and the locals didn't change
+ // or they changed in a way that doesn't merit reloading
+ // (reloadOnParams:false, or reloadOnSearch.false and only search params changed)
+ // Then return true.
+ if (!options.reload && to === from &&
+ (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) {
+ return true;
+ }
+ }
+}
+
+angular.module('ui.router.state')
+ .factory('$stateParams', function () { return {}; })
+ .provider('$state', $StateProvider);
diff --git a/afb-client/bower_components/angular-ui-router/src/stateDirectives.js b/afb-client/bower_components/angular-ui-router/src/stateDirectives.js
new file mode 100644
index 0000000..d02add9
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/stateDirectives.js
@@ -0,0 +1,391 @@
+function parseStateRef(ref, current) {
+ var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed;
+ if (preparsed) ref = current + '(' + preparsed[1] + ')';
+ parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
+ if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'");
+ return { state: parsed[1], paramExpr: parsed[3] || null };
+}
+
+function stateContext(el) {
+ var stateData = el.parent().inheritedData('$uiView');
+
+ if (stateData && stateData.state && stateData.state.name) {
+ return stateData.state;
+ }
+}
+
+function getTypeInfo(el) {
+ // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
+ var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
+ var isForm = el[0].nodeName === "FORM";
+
+ return {
+ attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'),
+ isAnchor: el.prop("tagName").toUpperCase() === "A",
+ clickable: !isForm
+ };
+}
+
+function clickHook(el, $state, $timeout, type, current) {
+ return function(e) {
+ var button = e.which || e.button, target = current();
+
+ if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
+ // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
+ var transition = $timeout(function() {
+ $state.go(target.state, target.params, target.options);
+ });
+ e.preventDefault();
+
+ // if the state has no URL, ignore one preventDefault from the <a> directive.
+ var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0;
+
+ e.preventDefault = function() {
+ if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition);
+ };
+ }
+ };
+}
+
+function defaultOpts(el, $state) {
+ return { relative: stateContext(el) || $state.$current, inherit: true };
+}
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref
+ *
+ * @requires ui.router.state.$state
+ * @requires $timeout
+ *
+ * @restrict A
+ *
+ * @description
+ * A directive that binds a link (`<a>` tag) to a state. If the state has an associated
+ * URL, the directive will automatically generate & update the `href` attribute via
+ * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking
+ * the link will trigger a state transition with optional parameters.
+ *
+ * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be
+ * handled natively by the browser.
+ *
+ * You can also use relative state paths within ui-sref, just like the relative
+ * paths passed to `$state.go()`. You just need to be aware that the path is relative
+ * to the state that the link lives in, in other words the state that loaded the
+ * template containing the link.
+ *
+ * You can specify options to pass to {@link ui.router.state.$state#go $state.go()}
+ * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
+ * and `reload`.
+ *
+ * @example
+ * Here's an example of how you'd use ui-sref and how it would compile. If you have the
+ * following template:
+ * <pre>
+ * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a>
+ *
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * Then the compiled html would be (assuming Html5Mode is off and current state is contacts):
+ * <pre>
+ * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
+ *
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
+ * </li>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
+ * </li>
+ * <li ng-repeat="contact in contacts">
+ * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
+ * </li>
+ * </ul>
+ *
+ * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
+ * </pre>
+ *
+ * @param {string} ui-sref 'stateName' can be any valid absolute or relative state
+ * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}
+ */
+$StateRefDirective.$inject = ['$state', '$timeout'];
+function $StateRefDirective($state, $timeout) {
+ return {
+ restrict: 'A',
+ require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
+ link: function(scope, element, attrs, uiSrefActive) {
+ var ref = parseStateRef(attrs.uiSref, $state.current.name);
+ var def = { state: ref.state, href: null, params: null };
+ var type = getTypeInfo(element);
+ var active = uiSrefActive[1] || uiSrefActive[0];
+
+ def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});
+
+ var update = function(val) {
+ if (val) def.params = angular.copy(val);
+ def.href = $state.href(ref.state, def.params, def.options);
+
+ if (active) active.$$addStateInfo(ref.state, def.params);
+ if (def.href !== null) attrs.$set(type.attr, def.href);
+ };
+
+ if (ref.paramExpr) {
+ scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true);
+ def.params = angular.copy(scope.$eval(ref.paramExpr));
+ }
+ update();
+
+ if (!type.clickable) return;
+ element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
+ }
+ };
+}
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-state
+ *
+ * @requires ui.router.state.uiSref
+ *
+ * @restrict A
+ *
+ * @description
+ * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition,
+ * params and override options.
+ *
+ * @param {string} ui-state 'stateName' can be any valid absolute or relative state
+ * @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#href $state.href()}
+ * @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#go $state.go()}
+ */
+$StateRefDynamicDirective.$inject = ['$state', '$timeout'];
+function $StateRefDynamicDirective($state, $timeout) {
+ return {
+ restrict: 'A',
+ require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
+ link: function(scope, element, attrs, uiSrefActive) {
+ var type = getTypeInfo(element);
+ var active = uiSrefActive[1] || uiSrefActive[0];
+ var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
+ var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
+ var def = { state: null, params: null, options: null, href: null };
+
+ function runStateRefLink (group) {
+ def.state = group[0]; def.params = group[1]; def.options = group[2];
+ def.href = $state.href(def.state, def.params, def.options);
+
+ if (active) active.$$addStateInfo(def.state, def.params);
+ if (def.href) attrs.$set(type.attr, def.href);
+ }
+
+ scope.$watch(watch, runStateRefLink, true);
+ runStateRefLink(scope.$eval(watch));
+
+ if (!type.clickable) return;
+ element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
+ }
+ };
+}
+
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref-active
+ *
+ * @requires ui.router.state.$state
+ * @requires ui.router.state.$stateParams
+ * @requires $interpolate
+ *
+ * @restrict A
+ *
+ * @description
+ * A directive working alongside ui-sref to add classes to an element when the
+ * related ui-sref directive's state is active, and removing them when it is inactive.
+ * The primary use-case is to simplify the special appearance of navigation menus
+ * relying on `ui-sref`, by having the "active" state's menu button appear different,
+ * distinguishing it from the inactive menu items.
+ *
+ * ui-sref-active can live on the same element as ui-sref or on a parent element. The first
+ * ui-sref-active found at the same level or above the ui-sref will be used.
+ *
+ * Will activate when the ui-sref's target state or any child state is active. If you
+ * need to activate only when the ui-sref target state is active and *not* any of
+ * it's children, then you will use
+ * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq}
+ *
+ * @example
+ * Given the following template:
+ * <pre>
+ * <ul>
+ * <li ui-sref-active="active" class="item">
+ * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ *
+ * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins",
+ * the resulting HTML will appear as (note the 'active' class):
+ * <pre>
+ * <ul>
+ * <li ui-sref-active="active" class="item active">
+ * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * The class name is interpolated **once** during the directives link time (any further changes to the
+ * interpolated value are ignored).
+ *
+ * Multiple classes may be specified in a space-separated format:
+ * <pre>
+ * <ul>
+ * <li ui-sref-active='class1 class2 class3'>
+ * <a ui-sref="app.user">link</a>
+ * </li>
+ * </ul>
+ * </pre>
+ *
+ * It is also possible to pass ui-sref-active an expression that evaluates
+ * to an object hash, whose keys represent active class names and whose
+ * values represent the respective state names/globs.
+ * ui-sref-active will match if the current active state **includes** any of
+ * the specified state names/globs, even the abstract ones.
+ *
+ * @Example
+ * Given the following template, with "admin" being an abstract state:
+ * <pre>
+ * <div ui-sref-active="{'active': 'admin.*'}">
+ * <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
+ * </div>
+ * </pre>
+ *
+ * When the current state is "admin.roles" the "active" class will be applied
+ * to both the <div> and <a> elements. It is important to note that the state
+ * names/globs passed to ui-sref-active shadow the state provided by ui-sref.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-sref-active-eq
+ *
+ * @requires ui.router.state.$state
+ * @requires ui.router.state.$stateParams
+ * @requires $interpolate
+ *
+ * @restrict A
+ *
+ * @description
+ * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate
+ * when the exact target state used in the `ui-sref` is active; no child states.
+ *
+ */
+$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
+function $StateRefActiveDirective($state, $stateParams, $interpolate) {
+ return {
+ restrict: "A",
+ controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {
+ var states = [], activeClasses = {}, activeEqClass, uiSrefActive;
+
+ // There probably isn't much point in $observing this
+ // uiSrefActive and uiSrefActiveEq share the same directive object with some
+ // slight difference in logic routing
+ activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
+
+ try {
+ uiSrefActive = $scope.$eval($attrs.uiSrefActive);
+ } catch (e) {
+ // Do nothing. uiSrefActive is not a valid expression.
+ // Fall back to using $interpolate below
+ }
+ uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
+ if (isObject(uiSrefActive)) {
+ forEach(uiSrefActive, function(stateOrName, activeClass) {
+ if (isString(stateOrName)) {
+ var ref = parseStateRef(stateOrName, $state.current.name);
+ addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
+ }
+ });
+ }
+
+ // Allow uiSref to communicate with uiSrefActive[Equals]
+ this.$$addStateInfo = function (newState, newParams) {
+ // we already got an explicit state provided by ui-sref-active, so we
+ // shadow the one that comes from ui-sref
+ if (isObject(uiSrefActive) && states.length > 0) {
+ return;
+ }
+ addState(newState, newParams, uiSrefActive);
+ update();
+ };
+
+ $scope.$on('$stateChangeSuccess', update);
+
+ function addState(stateName, stateParams, activeClass) {
+ var state = $state.get(stateName, stateContext($element));
+ var stateHash = createStateHash(stateName, stateParams);
+
+ states.push({
+ state: state || { name: stateName },
+ params: stateParams,
+ hash: stateHash
+ });
+
+ activeClasses[stateHash] = activeClass;
+ }
+
+ /**
+ * @param {string} state
+ * @param {Object|string} [params]
+ * @return {string}
+ */
+ function createStateHash(state, params) {
+ if (!isString(state)) {
+ throw new Error('state should be a string');
+ }
+ if (isObject(params)) {
+ return state + toJson(params);
+ }
+ params = $scope.$eval(params);
+ if (isObject(params)) {
+ return state + toJson(params);
+ }
+ return state;
+ }
+
+ // Update route state
+ function update() {
+ for (var i = 0; i < states.length; i++) {
+ if (anyMatch(states[i].state, states[i].params)) {
+ addClass($element, activeClasses[states[i].hash]);
+ } else {
+ removeClass($element, activeClasses[states[i].hash]);
+ }
+
+ if (exactMatch(states[i].state, states[i].params)) {
+ addClass($element, activeEqClass);
+ } else {
+ removeClass($element, activeEqClass);
+ }
+ }
+ }
+
+ function addClass(el, className) { $timeout(function () { el.addClass(className); }); }
+ function removeClass(el, className) { el.removeClass(className); }
+ function anyMatch(state, params) { return $state.includes(state.name, params); }
+ function exactMatch(state, params) { return $state.is(state.name, params); }
+
+ update();
+ }]
+ };
+}
+
+angular.module('ui.router.state')
+ .directive('uiSref', $StateRefDirective)
+ .directive('uiSrefActive', $StateRefActiveDirective)
+ .directive('uiSrefActiveEq', $StateRefActiveDirective)
+ .directive('uiState', $StateRefDynamicDirective);
diff --git a/afb-client/bower_components/angular-ui-router/src/stateFilters.js b/afb-client/bower_components/angular-ui-router/src/stateFilters.js
new file mode 100644
index 0000000..4ef014a
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/stateFilters.js
@@ -0,0 +1,39 @@
+/**
+ * @ngdoc filter
+ * @name ui.router.state.filter:isState
+ *
+ * @requires ui.router.state.$state
+ *
+ * @description
+ * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}.
+ */
+$IsStateFilter.$inject = ['$state'];
+function $IsStateFilter($state) {
+ var isFilter = function (state, params) {
+ return $state.is(state, params);
+ };
+ isFilter.$stateful = true;
+ return isFilter;
+}
+
+/**
+ * @ngdoc filter
+ * @name ui.router.state.filter:includedByState
+ *
+ * @requires ui.router.state.$state
+ *
+ * @description
+ * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.
+ */
+$IncludedByStateFilter.$inject = ['$state'];
+function $IncludedByStateFilter($state) {
+ var includesFilter = function (state, params, options) {
+ return $state.includes(state, params, options);
+ };
+ includesFilter.$stateful = true;
+ return includesFilter;
+}
+
+angular.module('ui.router.state')
+ .filter('isState', $IsStateFilter)
+ .filter('includedByState', $IncludedByStateFilter);
diff --git a/afb-client/bower_components/angular-ui-router/src/templateFactory.js b/afb-client/bower_components/angular-ui-router/src/templateFactory.js
new file mode 100644
index 0000000..ca491a9
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/templateFactory.js
@@ -0,0 +1,110 @@
+/**
+ * @ngdoc object
+ * @name ui.router.util.$templateFactory
+ *
+ * @requires $http
+ * @requires $templateCache
+ * @requires $injector
+ *
+ * @description
+ * Service. Manages loading of templates.
+ */
+$TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
+function $TemplateFactory( $http, $templateCache, $injector) {
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromConfig
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template from a configuration object.
+ *
+ * @param {object} config Configuration object for which to load a template.
+ * The following properties are search in the specified order, and the first one
+ * that is defined is used to create the template:
+ *
+ * @param {string|object} config.template html string template or function to
+ * load via {@link ui.router.util.$templateFactory#fromString fromString}.
+ * @param {string|object} config.templateUrl url to load or a function returning
+ * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
+ * @param {Function} config.templateProvider function to invoke via
+ * {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
+ * @param {object} params Parameters to pass to the template function.
+ * @param {object} locals Locals to pass to `invoke` if the template is loaded
+ * via a `templateProvider`. Defaults to `{ params: params }`.
+ *
+ * @return {string|object} The template html as a string, or a promise for
+ * that string,or `null` if no template is configured.
+ */
+ this.fromConfig = function (config, params, locals) {
+ return (
+ isDefined(config.template) ? this.fromString(config.template, params) :
+ isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
+ isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
+ null
+ );
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromString
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template from a string or a function returning a string.
+ *
+ * @param {string|object} template html template as a string or function that
+ * returns an html template as a string.
+ * @param {object} params Parameters to pass to the template function.
+ *
+ * @return {string|object} The template html as a string, or a promise for that
+ * string.
+ */
+ this.fromString = function (template, params) {
+ return isFunction(template) ? template(params) : template;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromUrl
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Loads a template from the a URL via `$http` and `$templateCache`.
+ *
+ * @param {string|Function} url url of the template to load, or a function
+ * that returns a url.
+ * @param {Object} params Parameters to pass to the url function.
+ * @return {string|Promise.<string>} The template html as a string, or a promise
+ * for that string.
+ */
+ this.fromUrl = function (url, params) {
+ if (isFunction(url)) url = url(params);
+ if (url == null) return null;
+ else return $http
+ .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }})
+ .then(function(response) { return response.data; });
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$templateFactory#fromProvider
+ * @methodOf ui.router.util.$templateFactory
+ *
+ * @description
+ * Creates a template by invoking an injectable provider function.
+ *
+ * @param {Function} provider Function to invoke via `$injector.invoke`
+ * @param {Object} params Parameters for the template.
+ * @param {Object} locals Locals to pass to `invoke`. Defaults to
+ * `{ params: params }`.
+ * @return {string|Promise.<string>} The template html as a string, or a promise
+ * for that string.
+ */
+ this.fromProvider = function (provider, params, locals) {
+ return $injector.invoke(provider, null, locals || { params: params });
+ };
+}
+
+angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
diff --git a/afb-client/bower_components/angular-ui-router/src/urlMatcherFactory.js b/afb-client/bower_components/angular-ui-router/src/urlMatcherFactory.js
new file mode 100644
index 0000000..bc4e1eb
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/urlMatcherFactory.js
@@ -0,0 +1,1081 @@
+var $$UMFP; // reference to $UrlMatcherFactoryProvider
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Matches URLs against patterns and extracts named parameters from the path or the search
+ * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
+ * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
+ * do not influence whether or not a URL is matched, but their values are passed through into
+ * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.
+ *
+ * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
+ * syntax, which optionally allows a regular expression for the parameter to be specified:
+ *
+ * * `':'` name - colon placeholder
+ * * `'*'` name - catch-all placeholder
+ * * `'{' name '}'` - curly placeholder
+ * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the
+ * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
+ *
+ * Parameter names may contain only word characters (latin letters, digits, and underscore) and
+ * must be unique within the pattern (across both path and search parameters). For colon
+ * placeholders or curly placeholders without an explicit regexp, a path parameter matches any
+ * number of characters other than '/'. For catch-all placeholders the path parameter matches
+ * any number of characters.
+ *
+ * Examples:
+ *
+ * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
+ * trailing slashes, and patterns have to match the entire path, not just a prefix.
+ * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
+ * '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
+ * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
+ * * `'/user/{id:[^/]*}'` - Same as the previous example.
+ * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
+ * parameter consists of 1 to 8 hex digits.
+ * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
+ * path into the parameter 'path'.
+ * * `'/files/*path'` - ditto.
+ * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined
+ * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start
+ *
+ * @param {string} pattern The pattern to compile into a matcher.
+ * @param {Object} config A configuration object hash:
+ * @param {Object=} parentMatcher Used to concatenate the pattern/config onto
+ * an existing UrlMatcher
+ *
+ * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
+ * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
+ *
+ * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any
+ * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns
+ * non-null) will start with this prefix.
+ *
+ * @property {string} source The pattern that was passed into the constructor
+ *
+ * @property {string} sourcePath The path portion of the source property
+ *
+ * @property {string} sourceSearch The search portion of the source property
+ *
+ * @property {string} regex The constructed regex that will be used to match against the url when
+ * it is time to determine which url will match.
+ *
+ * @returns {Object} New `UrlMatcher` object
+ */
+function UrlMatcher(pattern, config, parentMatcher) {
+ config = extend({ params: {} }, isObject(config) ? config : {});
+
+ // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
+ // '*' name
+ // ':' name
+ // '{' name '}'
+ // '{' name ':' regexp '}'
+ // The regular expression is somewhat complicated due to the need to allow curly braces
+ // inside the regular expression. The placeholder regexp breaks down as follows:
+ // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case)
+ // \{([\w\[\]]+)(?:\:\s*( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
+ // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either
+ // [^{}\\]+ - anything other than curly braces or backslash
+ // \\. - a backslash escape
+ // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms
+ var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
+ searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
+ compiled = '^', last = 0, m,
+ segments = this.segments = [],
+ parentParams = parentMatcher ? parentMatcher.params : {},
+ params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(),
+ paramNames = [];
+
+ function addParameter(id, type, config, location) {
+ paramNames.push(id);
+ if (parentParams[id]) return parentParams[id];
+ if (!/^\w+([-.]+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
+ if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
+ params[id] = new $$UMFP.Param(id, type, config, location);
+ return params[id];
+ }
+
+ function quoteRegExp(string, pattern, squash, optional) {
+ var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&");
+ if (!pattern) return result;
+ switch(squash) {
+ case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break;
+ case true:
+ result = result.replace(/\/$/, '');
+ surroundPattern = ['(?:\/(', ')|\/)?'];
+ break;
+ default: surroundPattern = ['(' + squash + "|", ')?']; break;
+ }
+ return result + surroundPattern[0] + pattern + surroundPattern[1];
+ }
+
+ this.source = pattern;
+
+ // Split into static segments separated by path parameter placeholders.
+ // The number of segments is always 1 more than the number of parameters.
+ function matchDetails(m, isSearch) {
+ var id, regexp, segment, type, cfg, arrayMode;
+ id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null
+ cfg = config.params[id];
+ segment = pattern.substring(last, m.index);
+ regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null);
+
+ if (regexp) {
+ type = $$UMFP.type(regexp) || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) });
+ }
+
+ return {
+ id: id, regexp: regexp, segment: segment, type: type, cfg: cfg
+ };
+ }
+
+ var p, param, segment;
+ while ((m = placeholder.exec(pattern))) {
+ p = matchDetails(m, false);
+ if (p.segment.indexOf('?') >= 0) break; // we're into the search part
+
+ param = addParameter(p.id, p.type, p.cfg, "path");
+ compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional);
+ segments.push(p.segment);
+ last = placeholder.lastIndex;
+ }
+ segment = pattern.substring(last);
+
+ // Find any search parameter names and remove them from the last segment
+ var i = segment.indexOf('?');
+
+ if (i >= 0) {
+ var search = this.sourceSearch = segment.substring(i);
+ segment = segment.substring(0, i);
+ this.sourcePath = pattern.substring(0, last + i);
+
+ if (search.length > 0) {
+ last = 0;
+ while ((m = searchPlaceholder.exec(search))) {
+ p = matchDetails(m, true);
+ param = addParameter(p.id, p.type, p.cfg, "search");
+ last = placeholder.lastIndex;
+ // check if ?&
+ }
+ }
+ } else {
+ this.sourcePath = pattern;
+ this.sourceSearch = '';
+ }
+
+ compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$';
+ segments.push(segment);
+
+ this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined);
+ this.prefix = segments[0];
+ this.$$paramNames = paramNames;
+}
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#concat
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Returns a new matcher for a pattern constructed by appending the path part and adding the
+ * search parameters of the specified pattern to this pattern. The current pattern is not
+ * modified. This can be understood as creating a pattern for URLs that are relative to (or
+ * suffixes of) the current pattern.
+ *
+ * @example
+ * The following two matchers are equivalent:
+ * <pre>
+ * new UrlMatcher('/user/{id}?q').concat('/details?date');
+ * new UrlMatcher('/user/{id}/details?q&date');
+ * </pre>
+ *
+ * @param {string} pattern The pattern to append.
+ * @param {Object} config An object hash of the configuration for the matcher.
+ * @returns {UrlMatcher} A matcher for the concatenated pattern.
+ */
+UrlMatcher.prototype.concat = function (pattern, config) {
+ // Because order of search parameters is irrelevant, we can add our own search
+ // parameters to the end of the new pattern. Parse the new pattern by itself
+ // and then join the bits together, but it's much easier to do this on a string level.
+ var defaultConfig = {
+ caseInsensitive: $$UMFP.caseInsensitive(),
+ strict: $$UMFP.strictMode(),
+ squash: $$UMFP.defaultSquashPolicy()
+ };
+ return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);
+};
+
+UrlMatcher.prototype.toString = function () {
+ return this.source;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#exec
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Tests the specified path against this matcher, and returns an object containing the captured
+ * parameter values, or null if the path does not match. The returned object contains the values
+ * of any search parameters that are mentioned in the pattern, but their value may be null if
+ * they are not present in `searchParams`. This means that search parameters are always treated
+ * as optional.
+ *
+ * @example
+ * <pre>
+ * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
+ * x: '1', q: 'hello'
+ * });
+ * // returns { id: 'bob', q: 'hello', r: null }
+ * </pre>
+ *
+ * @param {string} path The URL path to match, e.g. `$location.path()`.
+ * @param {Object} searchParams URL search parameters, e.g. `$location.search()`.
+ * @returns {Object} The captured parameter values.
+ */
+UrlMatcher.prototype.exec = function (path, searchParams) {
+ var m = this.regexp.exec(path);
+ if (!m) return null;
+ searchParams = searchParams || {};
+
+ var paramNames = this.parameters(), nTotal = paramNames.length,
+ nPath = this.segments.length - 1,
+ values = {}, i, j, cfg, paramName;
+
+ if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'");
+
+ function decodePathArray(string) {
+ function reverseString(str) { return str.split("").reverse().join(""); }
+ function unquoteDashes(str) { return str.replace(/\\-/g, "-"); }
+
+ var split = reverseString(string).split(/-(?!\\)/);
+ var allReversed = map(split, reverseString);
+ return map(allReversed, unquoteDashes).reverse();
+ }
+
+ var param, paramVal;
+ for (i = 0; i < nPath; i++) {
+ paramName = paramNames[i];
+ param = this.params[paramName];
+ paramVal = m[i+1];
+ // if the param value matches a pre-replace pair, replace the value before decoding.
+ for (j = 0; j < param.replace.length; j++) {
+ if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
+ }
+ if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);
+ if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
+ values[paramName] = param.value(paramVal);
+ }
+ for (/**/; i < nTotal; i++) {
+ paramName = paramNames[i];
+ values[paramName] = this.params[paramName].value(searchParams[paramName]);
+ param = this.params[paramName];
+ paramVal = searchParams[paramName];
+ for (j = 0; j < param.replace.length; j++) {
+ if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
+ }
+ if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
+ values[paramName] = param.value(paramVal);
+ }
+
+ return values;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#parameters
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Returns the names of all path and search parameters of this pattern in an unspecified order.
+ *
+ * @returns {Array.<string>} An array of parameter names. Must be treated as read-only. If the
+ * pattern has no parameters, an empty array is returned.
+ */
+UrlMatcher.prototype.parameters = function (param) {
+ if (!isDefined(param)) return this.$$paramNames;
+ return this.params[param] || null;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#validates
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Checks an object hash of parameters to validate their correctness according to the parameter
+ * types of this `UrlMatcher`.
+ *
+ * @param {Object} params The object hash of parameters to validate.
+ * @returns {boolean} Returns `true` if `params` validates, otherwise `false`.
+ */
+UrlMatcher.prototype.validates = function (params) {
+ return this.params.$$validates(params);
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:UrlMatcher#format
+ * @methodOf ui.router.util.type:UrlMatcher
+ *
+ * @description
+ * Creates a URL that matches this pattern by substituting the specified values
+ * for the path and search parameters. Null values for path parameters are
+ * treated as empty strings.
+ *
+ * @example
+ * <pre>
+ * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
+ * // returns '/user/bob?q=yes'
+ * </pre>
+ *
+ * @param {Object} values the values to substitute for the parameters in this pattern.
+ * @returns {string} the formatted URL (path and optionally search part).
+ */
+UrlMatcher.prototype.format = function (values) {
+ values = values || {};
+ var segments = this.segments, params = this.parameters(), paramset = this.params;
+ if (!this.validates(values)) return null;
+
+ var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0];
+
+ function encodeDashes(str) { // Replace dashes with encoded "\-"
+ return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); });
+ }
+
+ for (i = 0; i < nTotal; i++) {
+ var isPathParam = i < nPath;
+ var name = params[i], param = paramset[name], value = param.value(values[name]);
+ var isDefaultValue = param.isOptional && param.type.equals(param.value(), value);
+ var squash = isDefaultValue ? param.squash : false;
+ var encoded = param.type.encode(value);
+
+ if (isPathParam) {
+ var nextSegment = segments[i + 1];
+ var isFinalPathParam = i + 1 === nPath;
+
+ if (squash === false) {
+ if (encoded != null) {
+ if (isArray(encoded)) {
+ result += map(encoded, encodeDashes).join("-");
+ } else {
+ result += encodeURIComponent(encoded);
+ }
+ }
+ result += nextSegment;
+ } else if (squash === true) {
+ var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/;
+ result += nextSegment.match(capture)[1];
+ } else if (isString(squash)) {
+ result += squash + nextSegment;
+ }
+
+ if (isFinalPathParam && param.squash === true && result.slice(-1) === '/') result = result.slice(0, -1);
+ } else {
+ if (encoded == null || (isDefaultValue && squash !== false)) continue;
+ if (!isArray(encoded)) encoded = [ encoded ];
+ if (encoded.length === 0) continue;
+ encoded = map(encoded, encodeURIComponent).join('&' + name + '=');
+ result += (search ? '&' : '?') + (name + '=' + encoded);
+ search = true;
+ }
+ }
+
+ return result;
+};
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.type:Type
+ *
+ * @description
+ * Implements an interface to define custom parameter types that can be decoded from and encoded to
+ * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`}
+ * objects when matching or formatting URLs, or comparing or validating parameter values.
+ *
+ * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more
+ * information on registering custom types.
+ *
+ * @param {Object} config A configuration object which contains the custom type definition. The object's
+ * properties will override the default methods and/or pattern in `Type`'s public interface.
+ * @example
+ * <pre>
+ * {
+ * decode: function(val) { return parseInt(val, 10); },
+ * encode: function(val) { return val && val.toString(); },
+ * equals: function(a, b) { return this.is(a) && a === b; },
+ * is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
+ * pattern: /\d+/
+ * }
+ * </pre>
+ *
+ * @property {RegExp} pattern The regular expression pattern used to match values of this type when
+ * coming from a substring of a URL.
+ *
+ * @returns {Object} Returns a new `Type` object.
+ */
+function Type(config) {
+ extend(this, config);
+}
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#is
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Detects whether a value is of a particular type. Accepts a native (decoded) value
+ * and determines whether it matches the current `Type` object.
+ *
+ * @param {*} val The value to check.
+ * @param {string} key Optional. If the type check is happening in the context of a specific
+ * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the
+ * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects.
+ * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`.
+ */
+Type.prototype.is = function(val, key) {
+ return true;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#encode
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the
+ * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
+ * only needs to be a representation of `val` that has been coerced to a string.
+ *
+ * @param {*} val The value to encode.
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
+ * meta-programming of `Type` objects.
+ * @returns {string} Returns a string representation of `val` that can be encoded in a URL.
+ */
+Type.prototype.encode = function(val, key) {
+ return val;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#decode
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Converts a parameter value (from URL string or transition param) to a custom/native value.
+ *
+ * @param {string} val The URL parameter value to decode.
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
+ * meta-programming of `Type` objects.
+ * @returns {*} Returns a custom representation of the URL parameter value.
+ */
+Type.prototype.decode = function(val, key) {
+ return val;
+};
+
+/**
+ * @ngdoc function
+ * @name ui.router.util.type:Type#equals
+ * @methodOf ui.router.util.type:Type
+ *
+ * @description
+ * Determines whether two decoded values are equivalent.
+ *
+ * @param {*} a A value to compare against.
+ * @param {*} b A value to compare against.
+ * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`.
+ */
+Type.prototype.equals = function(a, b) {
+ return a == b;
+};
+
+Type.prototype.$subPattern = function() {
+ var sub = this.pattern.toString();
+ return sub.substr(1, sub.length - 2);
+};
+
+Type.prototype.pattern = /.*/;
+
+Type.prototype.toString = function() { return "{Type:" + this.name + "}"; };
+
+/** Given an encoded string, or a decoded object, returns a decoded object */
+Type.prototype.$normalize = function(val) {
+ return this.is(val) ? val : this.decode(val);
+};
+
+/*
+ * Wraps an existing custom Type as an array of Type, depending on 'mode'.
+ * e.g.:
+ * - urlmatcher pattern "/path?{queryParam[]:int}"
+ * - url: "/path?queryParam=1&queryParam=2
+ * - $stateParams.queryParam will be [1, 2]
+ * if `mode` is "auto", then
+ * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
+ * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
+ */
+Type.prototype.$asArray = function(mode, isSearch) {
+ if (!mode) return this;
+ if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only");
+
+ function ArrayType(type, mode) {
+ function bindTo(type, callbackName) {
+ return function() {
+ return type[callbackName].apply(type, arguments);
+ };
+ }
+
+ // Wrap non-array value as array
+ function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); }
+ // Unwrap array value for "auto" mode. Return undefined for empty array.
+ function arrayUnwrap(val) {
+ switch(val.length) {
+ case 0: return undefined;
+ case 1: return mode === "auto" ? val[0] : val;
+ default: return val;
+ }
+ }
+ function falsey(val) { return !val; }
+
+ // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
+ function arrayHandler(callback, allTruthyMode) {
+ return function handleArray(val) {
+ if (isArray(val) && val.length === 0) return val;
+ val = arrayWrap(val);
+ var result = map(val, callback);
+ if (allTruthyMode === true)
+ return filter(result, falsey).length === 0;
+ return arrayUnwrap(result);
+ };
+ }
+
+ // Wraps type (.equals) functions to operate on each value of an array
+ function arrayEqualsHandler(callback) {
+ return function handleArray(val1, val2) {
+ var left = arrayWrap(val1), right = arrayWrap(val2);
+ if (left.length !== right.length) return false;
+ for (var i = 0; i < left.length; i++) {
+ if (!callback(left[i], right[i])) return false;
+ }
+ return true;
+ };
+ }
+
+ this.encode = arrayHandler(bindTo(type, 'encode'));
+ this.decode = arrayHandler(bindTo(type, 'decode'));
+ this.is = arrayHandler(bindTo(type, 'is'), true);
+ this.equals = arrayEqualsHandler(bindTo(type, 'equals'));
+ this.pattern = type.pattern;
+ this.$normalize = arrayHandler(bindTo(type, '$normalize'));
+ this.name = type.name;
+ this.$arrayMode = mode;
+ }
+
+ return new ArrayType(this, mode);
+};
+
+
+
+/**
+ * @ngdoc object
+ * @name ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory
+ * is also available to providers under the name `$urlMatcherFactoryProvider`.
+ */
+function $UrlMatcherFactory() {
+ $$UMFP = this;
+
+ var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false;
+
+ // Use tildes to pre-encode slashes.
+ // If the slashes are simply URLEncoded, the browser can choose to pre-decode them,
+ // and bidirectional encoding/decoding fails.
+ // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character
+ function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; }
+ function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; }
+
+ var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
+ "string": {
+ encode: valToString,
+ decode: valFromString,
+ // TODO: in 1.0, make string .is() return false if value is undefined/null by default.
+ // In 0.2.x, string params are optional by default for backwards compat
+ is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; },
+ pattern: /[^/]*/
+ },
+ "int": {
+ encode: valToString,
+ decode: function(val) { return parseInt(val, 10); },
+ is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; },
+ pattern: /\d+/
+ },
+ "bool": {
+ encode: function(val) { return val ? 1 : 0; },
+ decode: function(val) { return parseInt(val, 10) !== 0; },
+ is: function(val) { return val === true || val === false; },
+ pattern: /0|1/
+ },
+ "date": {
+ encode: function (val) {
+ if (!this.is(val))
+ return undefined;
+ return [ val.getFullYear(),
+ ('0' + (val.getMonth() + 1)).slice(-2),
+ ('0' + val.getDate()).slice(-2)
+ ].join("-");
+ },
+ decode: function (val) {
+ if (this.is(val)) return val;
+ var match = this.capture.exec(val);
+ return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
+ },
+ is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); },
+ equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); },
+ pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
+ capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
+ },
+ "json": {
+ encode: angular.toJson,
+ decode: angular.fromJson,
+ is: angular.isObject,
+ equals: angular.equals,
+ pattern: /[^/]*/
+ },
+ "any": { // does not encode/decode
+ encode: angular.identity,
+ decode: angular.identity,
+ equals: angular.equals,
+ pattern: /.*/
+ }
+ };
+
+ function getDefaultConfig() {
+ return {
+ strict: isStrictMode,
+ caseInsensitive: isCaseInsensitive
+ };
+ }
+
+ function isInjectable(value) {
+ return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));
+ }
+
+ /**
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
+ */
+ $UrlMatcherFactory.$$getDefaultValue = function(config) {
+ if (!isInjectable(config.value)) return config.value;
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
+ return injector.invoke(config.value);
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#caseInsensitive
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Defines whether URL matching should be case sensitive (the default behavior), or not.
+ *
+ * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`;
+ * @returns {boolean} the current value of caseInsensitive
+ */
+ this.caseInsensitive = function(value) {
+ if (isDefined(value))
+ isCaseInsensitive = value;
+ return isCaseInsensitive;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#strictMode
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Defines whether URLs should match trailing slashes, or not (the default behavior).
+ *
+ * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`.
+ * @returns {boolean} the current value of strictMode
+ */
+ this.strictMode = function(value) {
+ if (isDefined(value))
+ isStrictMode = value;
+ return isStrictMode;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Sets the default behavior when generating or matching URLs with default parameter values.
+ *
+ * @param {string} value A string that defines the default parameter URL squashing behavior.
+ * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL
+ * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the
+ * parameter is surrounded by slashes, squash (remove) one slash from the URL
+ * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove)
+ * the parameter value from the URL and replace it with this string.
+ */
+ this.defaultSquashPolicy = function(value) {
+ if (!isDefined(value)) return defaultSquashPolicy;
+ if (value !== true && value !== false && !isString(value))
+ throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string");
+ defaultSquashPolicy = value;
+ return value;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#compile
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern.
+ *
+ * @param {string} pattern The URL pattern.
+ * @param {Object} config The config object hash.
+ * @returns {UrlMatcher} The UrlMatcher.
+ */
+ this.compile = function (pattern, config) {
+ return new UrlMatcher(pattern, extend(getDefaultConfig(), config));
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#isMatcher
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Returns true if the specified object is a `UrlMatcher`, or false otherwise.
+ *
+ * @param {Object} object The object to perform the type check against.
+ * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by
+ * implementing all the same methods.
+ */
+ this.isMatcher = function (o) {
+ if (!isObject(o)) return false;
+ var result = true;
+
+ forEach(UrlMatcher.prototype, function(val, name) {
+ if (isFunction(val)) {
+ result = result && (isDefined(o[name]) && isFunction(o[name]));
+ }
+ });
+ return result;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.util.$urlMatcherFactory#type
+ * @methodOf ui.router.util.$urlMatcherFactory
+ *
+ * @description
+ * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to
+ * generate URLs with typed parameters.
+ *
+ * @param {string} name The type name.
+ * @param {Object|Function} definition The type definition. See
+ * {@link ui.router.util.type:Type `Type`} for information on the values accepted.
+ * @param {Object|Function} definitionFn (optional) A function that is injected before the app
+ * runtime starts. The result of this function is merged into the existing `definition`.
+ * See {@link ui.router.util.type:Type `Type`} for information on the values accepted.
+ *
+ * @returns {Object} Returns `$urlMatcherFactoryProvider`.
+ *
+ * @example
+ * This is a simple example of a custom type that encodes and decodes items from an
+ * array, using the array index as the URL-encoded value:
+ *
+ * <pre>
+ * var list = ['John', 'Paul', 'George', 'Ringo'];
+ *
+ * $urlMatcherFactoryProvider.type('listItem', {
+ * encode: function(item) {
+ * // Represent the list item in the URL using its corresponding index
+ * return list.indexOf(item);
+ * },
+ * decode: function(item) {
+ * // Look up the list item by index
+ * return list[parseInt(item, 10)];
+ * },
+ * is: function(item) {
+ * // Ensure the item is valid by checking to see that it appears
+ * // in the list
+ * return list.indexOf(item) > -1;
+ * }
+ * });
+ *
+ * $stateProvider.state('list', {
+ * url: "/list/{item:listItem}",
+ * controller: function($scope, $stateParams) {
+ * console.log($stateParams.item);
+ * }
+ * });
+ *
+ * // ...
+ *
+ * // Changes URL to '/list/3', logs "Ringo" to the console
+ * $state.go('list', { item: "Ringo" });
+ * </pre>
+ *
+ * This is a more complex example of a type that relies on dependency injection to
+ * interact with services, and uses the parameter name from the URL to infer how to
+ * handle encoding and decoding parameter values:
+ *
+ * <pre>
+ * // Defines a custom type that gets a value from a service,
+ * // where each service gets different types of values from
+ * // a backend API:
+ * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
+ *
+ * // Matches up services to URL parameter names
+ * var services = {
+ * user: Users,
+ * post: Posts
+ * };
+ *
+ * return {
+ * encode: function(object) {
+ * // Represent the object in the URL using its unique ID
+ * return object.id;
+ * },
+ * decode: function(value, key) {
+ * // Look up the object by ID, using the parameter
+ * // name (key) to call the correct service
+ * return services[key].findById(value);
+ * },
+ * is: function(object, key) {
+ * // Check that object is a valid dbObject
+ * return angular.isObject(object) && object.id && services[key];
+ * }
+ * equals: function(a, b) {
+ * // Check the equality of decoded objects by comparing
+ * // their unique IDs
+ * return a.id === b.id;
+ * }
+ * };
+ * });
+ *
+ * // In a config() block, you can then attach URLs with
+ * // type-annotated parameters:
+ * $stateProvider.state('users', {
+ * url: "/users",
+ * // ...
+ * }).state('users.item', {
+ * url: "/{user:dbObject}",
+ * controller: function($scope, $stateParams) {
+ * // $stateParams.user will now be an object returned from
+ * // the Users service
+ * },
+ * // ...
+ * });
+ * </pre>
+ */
+ this.type = function (name, definition, definitionFn) {
+ if (!isDefined(definition)) return $types[name];
+ if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined.");
+
+ $types[name] = new Type(extend({ name: name }, definition));
+ if (definitionFn) {
+ typeQueue.push({ name: name, def: definitionFn });
+ if (!enqueue) flushTypeQueue();
+ }
+ return this;
+ };
+
+ // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s
+ function flushTypeQueue() {
+ while(typeQueue.length) {
+ var type = typeQueue.shift();
+ if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime.");
+ angular.extend($types[type.name], injector.invoke(type.def));
+ }
+ }
+
+ // Register default types. Store them in the prototype of $types.
+ forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); });
+ $types = inherit($types, {});
+
+ /* No need to document $get, since it returns this */
+ this.$get = ['$injector', function ($injector) {
+ injector = $injector;
+ enqueue = false;
+ flushTypeQueue();
+
+ forEach(defaultTypes, function(type, name) {
+ if (!$types[name]) $types[name] = new Type(type);
+ });
+ return this;
+ }];
+
+ this.Param = function Param(id, type, config, location) {
+ var self = this;
+ config = unwrapShorthand(config);
+ type = getType(config, type, location);
+ var arrayMode = getArrayMode();
+ type = arrayMode ? type.$asArray(arrayMode, location === "search") : type;
+ if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined)
+ config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to ""
+ var isOptional = config.value !== undefined;
+ var squash = getSquashPolicy(config, isOptional);
+ var replace = getReplace(config, arrayMode, isOptional, squash);
+
+ function unwrapShorthand(config) {
+ var keys = isObject(config) ? objectKeys(config) : [];
+ var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 &&
+ indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1;
+ if (isShorthand) config = { value: config };
+ config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; };
+ return config;
+ }
+
+ function getType(config, urlType, location) {
+ if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
+ if (urlType) return urlType;
+ if (!config.type) return (location === "config" ? $types.any : $types.string);
+
+ if (angular.isString(config.type))
+ return $types[config.type];
+ if (config.type instanceof Type)
+ return config.type;
+ return new Type(config.type);
+ }
+
+ // array config: param name (param[]) overrides default settings. explicit config overrides param name.
+ function getArrayMode() {
+ var arrayDefaults = { array: (location === "search" ? "auto" : false) };
+ var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
+ return extend(arrayDefaults, arrayParamNomenclature, config).array;
+ }
+
+ /**
+ * returns false, true, or the squash value to indicate the "default parameter url squash policy".
+ */
+ function getSquashPolicy(config, isOptional) {
+ var squash = config.squash;
+ if (!isOptional || squash === false) return false;
+ if (!isDefined(squash) || squash == null) return defaultSquashPolicy;
+ if (squash === true || isString(squash)) return squash;
+ throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string");
+ }
+
+ function getReplace(config, arrayMode, isOptional, squash) {
+ var replace, configuredKeys, defaultPolicy = [
+ { from: "", to: (isOptional || arrayMode ? undefined : "") },
+ { from: null, to: (isOptional || arrayMode ? undefined : "") }
+ ];
+ replace = isArray(config.replace) ? config.replace : [];
+ if (isString(squash))
+ replace.push({ from: squash, to: undefined });
+ configuredKeys = map(replace, function(item) { return item.from; } );
+ return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace);
+ }
+
+ /**
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
+ */
+ function $$getDefaultValue() {
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
+ var defaultValue = injector.invoke(config.$$fn);
+ if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue))
+ throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")");
+ return defaultValue;
+ }
+
+ /**
+ * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
+ * default value, which may be the result of an injectable function.
+ */
+ function $value(value) {
+ function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; }
+ function $replace(value) {
+ var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; });
+ return replacement.length ? replacement[0] : value;
+ }
+ value = $replace(value);
+ return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value);
+ }
+
+ function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; }
+
+ extend(this, {
+ id: id,
+ type: type,
+ location: location,
+ array: arrayMode,
+ squash: squash,
+ replace: replace,
+ isOptional: isOptional,
+ value: $value,
+ dynamic: undefined,
+ config: config,
+ toString: toString
+ });
+ };
+
+ function ParamSet(params) {
+ extend(this, params || {});
+ }
+
+ ParamSet.prototype = {
+ $$new: function() {
+ return inherit(this, extend(new ParamSet(), { $$parent: this}));
+ },
+ $$keys: function () {
+ var keys = [], chain = [], parent = this,
+ ignore = objectKeys(ParamSet.prototype);
+ while (parent) { chain.push(parent); parent = parent.$$parent; }
+ chain.reverse();
+ forEach(chain, function(paramset) {
+ forEach(objectKeys(paramset), function(key) {
+ if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key);
+ });
+ });
+ return keys;
+ },
+ $$values: function(paramValues) {
+ var values = {}, self = this;
+ forEach(self.$$keys(), function(key) {
+ values[key] = self[key].value(paramValues && paramValues[key]);
+ });
+ return values;
+ },
+ $$equals: function(paramValues1, paramValues2) {
+ var equal = true, self = this;
+ forEach(self.$$keys(), function(key) {
+ var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key];
+ if (!self[key].type.equals(left, right)) equal = false;
+ });
+ return equal;
+ },
+ $$validates: function $$validate(paramValues) {
+ var keys = this.$$keys(), i, param, rawVal, normalized, encoded;
+ for (i = 0; i < keys.length; i++) {
+ param = this[keys[i]];
+ rawVal = paramValues[keys[i]];
+ if ((rawVal === undefined || rawVal === null) && param.isOptional)
+ break; // There was no parameter value, but the param is optional
+ normalized = param.type.$normalize(rawVal);
+ if (!param.type.is(normalized))
+ return false; // The value was not of the correct Type, and could not be decoded to the correct Type
+ encoded = param.type.encode(normalized);
+ if (angular.isString(encoded) && !param.type.pattern.exec(encoded))
+ return false; // The value was of the correct type, but when encoded, did not match the Type's regexp
+ }
+ return true;
+ },
+ $$parent: undefined
+ };
+
+ this.ParamSet = ParamSet;
+}
+
+// Register as a provider so it's available to other providers
+angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
+angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]);
diff --git a/afb-client/bower_components/angular-ui-router/src/urlRouter.js b/afb-client/bower_components/angular-ui-router/src/urlRouter.js
new file mode 100644
index 0000000..8ec704b
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/urlRouter.js
@@ -0,0 +1,431 @@
+/**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouterProvider
+ *
+ * @requires ui.router.util.$urlMatcherFactoryProvider
+ * @requires $locationProvider
+ *
+ * @description
+ * `$urlRouterProvider` has the responsibility of watching `$location`.
+ * When `$location` changes it runs through a list of rules one by one until a
+ * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify
+ * a url in a state configuration. All urls are compiled into a UrlMatcher object.
+ *
+ * There are several methods on `$urlRouterProvider` that make it useful to use directly
+ * in your module config.
+ */
+$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];
+function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
+ var rules = [], otherwise = null, interceptDeferred = false, listener;
+
+ // Returns a string that is a prefix of all strings matching the RegExp
+ function regExpPrefix(re) {
+ var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source);
+ return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : '';
+ }
+
+ // Interpolates matched values into a String.replace()-style pattern
+ function interpolate(pattern, match) {
+ return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) {
+ return match[what === '$' ? 0 : Number(what)];
+ });
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#rule
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Defines rules that are used by `$urlRouterProvider` to find matches for
+ * specific URLs.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * // Here's an example of how you might allow case insensitive urls
+ * $urlRouterProvider.rule(function ($injector, $location) {
+ * var path = $location.path(),
+ * normalized = path.toLowerCase();
+ *
+ * if (path !== normalized) {
+ * return normalized;
+ * }
+ * });
+ * });
+ * </pre>
+ *
+ * @param {function} rule Handler function that takes `$injector` and `$location`
+ * services as arguments. You can use them to return a valid path as a string.
+ *
+ * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
+ */
+ this.rule = function (rule) {
+ if (!isFunction(rule)) throw new Error("'rule' must be a function");
+ rules.push(rule);
+ return this;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouterProvider#otherwise
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Defines a path that is used when an invalid route is requested.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * // if the path doesn't match any of the urls you configured
+ * // otherwise will take care of routing the user to the
+ * // specified url
+ * $urlRouterProvider.otherwise('/index');
+ *
+ * // Example of using function rule as param
+ * $urlRouterProvider.otherwise(function ($injector, $location) {
+ * return '/a/valid/url';
+ * });
+ * });
+ * </pre>
+ *
+ * @param {string|function} rule The url path you want to redirect to or a function
+ * rule that returns the url path. The function version is passed two params:
+ * `$injector` and `$location` services, and must return a url string.
+ *
+ * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
+ */
+ this.otherwise = function (rule) {
+ if (isString(rule)) {
+ var redirect = rule;
+ rule = function () { return redirect; };
+ }
+ else if (!isFunction(rule)) throw new Error("'rule' must be a function");
+ otherwise = rule;
+ return this;
+ };
+
+
+ function handleIfMatch($injector, handler, match) {
+ if (!match) return false;
+ var result = $injector.invoke(handler, handler, { $match: match });
+ return isDefined(result) ? result : true;
+ }
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#when
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Registers a handler for a given url matching.
+ *
+ * If the handler is a string, it is
+ * treated as a redirect, and is interpolated according to the syntax of match
+ * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
+ *
+ * If the handler is a function, it is injectable. It gets invoked if `$location`
+ * matches. You have the option of inject the match object as `$match`.
+ *
+ * The handler can return
+ *
+ * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
+ * will continue trying to find another one that matches.
+ * - **string** which is treated as a redirect and passed to `$location.url()`
+ * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ * $urlRouterProvider.when($state.url, function ($match, $stateParams) {
+ * if ($state.$current.navigable !== state ||
+ * !equalForKeys($match, $stateParams) {
+ * $state.transitionTo(state, $match, false);
+ * }
+ * });
+ * });
+ * </pre>
+ *
+ * @param {string|object} what The incoming path that you want to redirect.
+ * @param {string|function} handler The path you want to redirect your user to.
+ */
+ this.when = function (what, handler) {
+ var redirect, handlerIsString = isString(handler);
+ if (isString(what)) what = $urlMatcherFactory.compile(what);
+
+ if (!handlerIsString && !isFunction(handler) && !isArray(handler))
+ throw new Error("invalid 'handler' in when()");
+
+ var strategies = {
+ matcher: function (what, handler) {
+ if (handlerIsString) {
+ redirect = $urlMatcherFactory.compile(handler);
+ handler = ['$match', function ($match) { return redirect.format($match); }];
+ }
+ return extend(function ($injector, $location) {
+ return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
+ }, {
+ prefix: isString(what.prefix) ? what.prefix : ''
+ });
+ },
+ regex: function (what, handler) {
+ if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
+
+ if (handlerIsString) {
+ redirect = handler;
+ handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
+ }
+ return extend(function ($injector, $location) {
+ return handleIfMatch($injector, handler, what.exec($location.path()));
+ }, {
+ prefix: regExpPrefix(what)
+ });
+ }
+ };
+
+ var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
+
+ for (var n in check) {
+ if (check[n]) return this.rule(strategies[n](what, handler));
+ }
+
+ throw new Error("invalid 'what' in when()");
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouterProvider#deferIntercept
+ * @methodOf ui.router.router.$urlRouterProvider
+ *
+ * @description
+ * Disables (or enables) deferring location change interception.
+ *
+ * If you wish to customize the behavior of syncing the URL (for example, if you wish to
+ * defer a transition but maintain the current URL), call this method at configuration time.
+ * Then, at run time, call `$urlRouter.listen()` after you have configured your own
+ * `$locationChangeSuccess` event handler.
+ *
+ * @example
+ * <pre>
+ * var app = angular.module('app', ['ui.router.router']);
+ *
+ * app.config(function ($urlRouterProvider) {
+ *
+ * // Prevent $urlRouter from automatically intercepting URL changes;
+ * // this allows you to configure custom behavior in between
+ * // location changes and route synchronization:
+ * $urlRouterProvider.deferIntercept();
+ *
+ * }).run(function ($rootScope, $urlRouter, UserService) {
+ *
+ * $rootScope.$on('$locationChangeSuccess', function(e) {
+ * // UserService is an example service for managing user state
+ * if (UserService.isLoggedIn()) return;
+ *
+ * // Prevent $urlRouter's default handler from firing
+ * e.preventDefault();
+ *
+ * UserService.handleLogin().then(function() {
+ * // Once the user has logged in, sync the current URL
+ * // to the router:
+ * $urlRouter.sync();
+ * });
+ * });
+ *
+ * // Configures $urlRouter's listener *after* your custom listener
+ * $urlRouter.listen();
+ * });
+ * </pre>
+ *
+ * @param {boolean} defer Indicates whether to defer location change interception. Passing
+ no parameter is equivalent to `true`.
+ */
+ this.deferIntercept = function (defer) {
+ if (defer === undefined) defer = true;
+ interceptDeferred = defer;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.router.$urlRouter
+ *
+ * @requires $location
+ * @requires $rootScope
+ * @requires $injector
+ * @requires $browser
+ *
+ * @description
+ *
+ */
+ this.$get = $get;
+ $get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer'];
+ function $get( $location, $rootScope, $injector, $browser, $sniffer) {
+
+ var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl;
+
+ function appendBasePath(url, isHtml5, absolute) {
+ if (baseHref === '/') return url;
+ if (isHtml5) return baseHref.slice(0, -1) + url;
+ if (absolute) return baseHref.slice(1) + url;
+ return url;
+ }
+
+ // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree
+ function update(evt) {
+ if (evt && evt.defaultPrevented) return;
+ var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;
+ lastPushedUrl = undefined;
+ // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573
+ //if (ignoreUpdate) return true;
+
+ function check(rule) {
+ var handled = rule($injector, $location);
+
+ if (!handled) return false;
+ if (isString(handled)) $location.replace().url(handled);
+ return true;
+ }
+ var n = rules.length, i;
+
+ for (i = 0; i < n; i++) {
+ if (check(rules[i])) return;
+ }
+ // always check otherwise last to allow dynamic updates to the set of rules
+ if (otherwise) check(otherwise);
+ }
+
+ function listen() {
+ listener = listener || $rootScope.$on('$locationChangeSuccess', update);
+ return listener;
+ }
+
+ if (!interceptDeferred) listen();
+
+ return {
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouter#sync
+ * @methodOf ui.router.router.$urlRouter
+ *
+ * @description
+ * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.
+ * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,
+ * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed
+ * with the transition by calling `$urlRouter.sync()`.
+ *
+ * @example
+ * <pre>
+ * angular.module('app', ['ui.router'])
+ * .run(function($rootScope, $urlRouter) {
+ * $rootScope.$on('$locationChangeSuccess', function(evt) {
+ * // Halt state change from even starting
+ * evt.preventDefault();
+ * // Perform custom logic
+ * var meetsRequirement = ...
+ * // Continue with the update and state transition if logic allows
+ * if (meetsRequirement) $urlRouter.sync();
+ * });
+ * });
+ * </pre>
+ */
+ sync: function() {
+ update();
+ },
+
+ listen: function() {
+ return listen();
+ },
+
+ update: function(read) {
+ if (read) {
+ location = $location.url();
+ return;
+ }
+ if ($location.url() === location) return;
+
+ $location.url(location);
+ $location.replace();
+ },
+
+ push: function(urlMatcher, params, options) {
+ var url = urlMatcher.format(params || {});
+
+ // Handle the special hash param, if needed
+ if (url !== null && params && params['#']) {
+ url += '#' + params['#'];
+ }
+
+ $location.url(url);
+ lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined;
+ if (options && options.replace) $location.replace();
+ },
+
+ /**
+ * @ngdoc function
+ * @name ui.router.router.$urlRouter#href
+ * @methodOf ui.router.router.$urlRouter
+ *
+ * @description
+ * A URL generation method that returns the compiled URL for a given
+ * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters.
+ *
+ * @example
+ * <pre>
+ * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
+ * person: "bob"
+ * });
+ * // $bob == "/about/bob";
+ * </pre>
+ *
+ * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate.
+ * @param {object=} params An object of parameter values to fill the matcher's required parameters.
+ * @param {object=} options Options object. The options are:
+ *
+ * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
+ *
+ * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`
+ */
+ href: function(urlMatcher, params, options) {
+ if (!urlMatcher.validates(params)) return null;
+
+ var isHtml5 = $locationProvider.html5Mode();
+ if (angular.isObject(isHtml5)) {
+ isHtml5 = isHtml5.enabled;
+ }
+
+ isHtml5 = isHtml5 && $sniffer.history;
+
+ var url = urlMatcher.format(params);
+ options = options || {};
+
+ if (!isHtml5 && url !== null) {
+ url = "#" + $locationProvider.hashPrefix() + url;
+ }
+
+ // Handle special hash param, if needed
+ if (url !== null && params && params['#']) {
+ url += '#' + params['#'];
+ }
+
+ url = appendBasePath(url, isHtml5, options.absolute);
+
+ if (!options.absolute || !url) {
+ return url;
+ }
+
+ var slash = (!isHtml5 && url ? '/' : ''), port = $location.port();
+ port = (port === 80 || port === 443 ? '' : ':' + port);
+
+ return [$location.protocol(), '://', $location.host(), port, slash, url].join('');
+ }
+ };
+ }
+}
+
+angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
diff --git a/afb-client/bower_components/angular-ui-router/src/view.js b/afb-client/bower_components/angular-ui-router/src/view.js
new file mode 100644
index 0000000..94334d3
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/view.js
@@ -0,0 +1,45 @@
+
+$ViewProvider.$inject = [];
+function $ViewProvider() {
+
+ this.$get = $get;
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$view
+ *
+ * @requires ui.router.util.$templateFactory
+ * @requires $rootScope
+ *
+ * @description
+ *
+ */
+ $get.$inject = ['$rootScope', '$templateFactory'];
+ function $get( $rootScope, $templateFactory) {
+ return {
+ // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$view#load
+ * @methodOf ui.router.state.$view
+ *
+ * @description
+ *
+ * @param {string} name name
+ * @param {object} options option object.
+ */
+ load: function load(name, options) {
+ var result, defaults = {
+ template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}
+ };
+ options = extend(defaults, options);
+
+ if (options.view) {
+ result = $templateFactory.fromConfig(options.view, options.params, options.locals);
+ }
+ return result;
+ }
+ };
+ }
+}
+
+angular.module('ui.router.state').provider('$view', $ViewProvider);
diff --git a/afb-client/bower_components/angular-ui-router/src/viewDirective.js b/afb-client/bower_components/angular-ui-router/src/viewDirective.js
new file mode 100644
index 0000000..c2eaa3d
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/viewDirective.js
@@ -0,0 +1,351 @@
+var ngMajorVer = angular.version.major;
+var ngMinorVer = angular.version.minor;
+/**
+ * @ngdoc directive
+ * @name ui.router.state.directive:ui-view
+ *
+ * @requires ui.router.state.$state
+ * @requires $compile
+ * @requires $controller
+ * @requires $injector
+ * @requires ui.router.state.$uiViewScroll
+ * @requires $document
+ *
+ * @restrict ECA
+ *
+ * @description
+ * The ui-view directive tells $state where to place your templates.
+ *
+ * @param {string=} name A view name. The name should be unique amongst the other views in the
+ * same state. You can have views of the same name that live in different states.
+ *
+ * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window
+ * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll
+ * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
+ * scroll ui-view elements into view when they are populated during a state activation.
+ *
+ * @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
+ * will be applied to the ui-view)
+ *
+ * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
+ * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
+ *
+ * @param {string=} onload Expression to evaluate whenever the view updates.
+ *
+ * @example
+ * A view can be unnamed or named.
+ * <pre>
+ * <!-- Unnamed -->
+ * <div ui-view></div>
+ *
+ * <!-- Named -->
+ * <div ui-view="viewName"></div>
+ * </pre>
+ *
+ * You can only have one unnamed view within any template (or root html). If you are only using a
+ * single view and it is unnamed then you can populate it like so:
+ * <pre>
+ * <div ui-view></div>
+ * $stateProvider.state("home", {
+ * template: "<h1>HELLO!</h1>"
+ * })
+ * </pre>
+ *
+ * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}
+ * config property, by name, in this case an empty name:
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "": {
+ * template: "<h1>HELLO!</h1>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * But typically you'll only use the views property if you name your view or have more than one view
+ * in the same template. There's not really a compelling reason to name a view if its the only one,
+ * but you could if you wanted, like so:
+ * <pre>
+ * <div ui-view="main"></div>
+ * </pre>
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "main": {
+ * template: "<h1>HELLO!</h1>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * Really though, you'll use views to set up multiple views:
+ * <pre>
+ * <div ui-view></div>
+ * <div ui-view="chart"></div>
+ * <div ui-view="data"></div>
+ * </pre>
+ *
+ * <pre>
+ * $stateProvider.state("home", {
+ * views: {
+ * "": {
+ * template: "<h1>HELLO!</h1>"
+ * },
+ * "chart": {
+ * template: "<chart_thing/>"
+ * },
+ * "data": {
+ * template: "<data_thing/>"
+ * }
+ * }
+ * })
+ * </pre>
+ *
+ * Examples for `autoscroll`:
+ *
+ * <pre>
+ * <!-- If autoscroll present with no expression,
+ * then scroll ui-view into view -->
+ * <ui-view autoscroll/>
+ *
+ * <!-- If autoscroll present with valid expression,
+ * then scroll ui-view into view if expression evaluates to true -->
+ * <ui-view autoscroll='true'/>
+ * <ui-view autoscroll='false'/>
+ * <ui-view autoscroll='scopeVariable'/>
+ * </pre>
+ */
+$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];
+function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) {
+
+ function getService() {
+ return ($injector.has) ? function(service) {
+ return $injector.has(service) ? $injector.get(service) : null;
+ } : function(service) {
+ try {
+ return $injector.get(service);
+ } catch (e) {
+ return null;
+ }
+ };
+ }
+
+ var service = getService(),
+ $animator = service('$animator'),
+ $animate = service('$animate');
+
+ // Returns a set of DOM manipulation functions based on which Angular version
+ // it should use
+ function getRenderer(attrs, scope) {
+ var statics = {
+ enter: function (element, target, cb) { target.after(element); cb(); },
+ leave: function (element, cb) { element.remove(); cb(); }
+ };
+
+ if (!!attrs.noanimation) return statics;
+
+ function animEnabled(element) {
+ if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
+ if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
+ return (!!$animator);
+ }
+
+ // ng 1.2+
+ if ($animate) {
+ return {
+ enter: function(element, target, cb) {
+ if (!animEnabled(element)) {
+ statics.enter(element, target, cb);
+ } else if (angular.version.minor > 2) {
+ $animate.enter(element, null, target).then(cb);
+ } else {
+ $animate.enter(element, null, target, cb);
+ }
+ },
+ leave: function(element, cb) {
+ if (!animEnabled(element)) {
+ statics.leave(element, cb);
+ } else if (angular.version.minor > 2) {
+ $animate.leave(element).then(cb);
+ } else {
+ $animate.leave(element, cb);
+ }
+ }
+ };
+ }
+
+ // ng 1.1.5
+ if ($animator) {
+ var animate = $animator && $animator(scope, attrs);
+
+ return {
+ enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
+ leave: function(element, cb) { animate.leave(element); cb(); }
+ };
+ }
+
+ return statics;
+ }
+
+ var directive = {
+ restrict: 'ECA',
+ terminal: true,
+ priority: 400,
+ transclude: 'element',
+ compile: function (tElement, tAttrs, $transclude) {
+ return function (scope, $element, attrs) {
+ var previousEl, currentEl, currentScope, latestLocals,
+ onloadExp = attrs.onload || '',
+ autoScrollExp = attrs.autoscroll,
+ renderer = getRenderer(attrs, scope);
+
+ scope.$on('$stateChangeSuccess', function() {
+ updateView(false);
+ });
+
+ updateView(true);
+
+ function cleanupLastView() {
+ var _previousEl = previousEl;
+ var _currentScope = currentScope;
+
+ if (_currentScope) {
+ _currentScope._willBeDestroyed = true;
+ }
+
+ function cleanOld() {
+ if (_previousEl) {
+ _previousEl.remove();
+ }
+
+ if (_currentScope) {
+ _currentScope.$destroy();
+ }
+ }
+
+ if (currentEl) {
+ renderer.leave(currentEl, function() {
+ cleanOld();
+ previousEl = null;
+ });
+
+ previousEl = currentEl;
+ } else {
+ cleanOld();
+ previousEl = null;
+ }
+
+ currentEl = null;
+ currentScope = null;
+ }
+
+ function updateView(firstTime) {
+ var newScope,
+ name = getUiViewName(scope, attrs, $element, $interpolate),
+ previousLocals = name && $state.$current && $state.$current.locals[name];
+
+ if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
+ newScope = scope.$new();
+ latestLocals = $state.$current.locals[name];
+
+ /**
+ * @ngdoc event
+ * @name ui.router.state.directive:ui-view#$viewContentLoading
+ * @eventOf ui.router.state.directive:ui-view
+ * @eventType emits on ui-view directive scope
+ * @description
+ *
+ * Fired once the view **begins loading**, *before* the DOM is rendered.
+ *
+ * @param {Object} event Event object.
+ * @param {string} viewName Name of the view.
+ */
+ newScope.$emit('$viewContentLoading', name);
+
+ var clone = $transclude(newScope, function(clone) {
+ renderer.enter(clone, $element, function onUiViewEnter() {
+ if(currentScope) {
+ currentScope.$emit('$viewContentAnimationEnded');
+ }
+
+ if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {
+ $uiViewScroll(clone);
+ }
+ });
+ cleanupLastView();
+ });
+
+ currentEl = clone;
+ currentScope = newScope;
+ /**
+ * @ngdoc event
+ * @name ui.router.state.directive:ui-view#$viewContentLoaded
+ * @eventOf ui.router.state.directive:ui-view
+ * @eventType emits on ui-view directive scope
+ * @description
+ * Fired once the view is **loaded**, *after* the DOM is rendered.
+ *
+ * @param {Object} event Event object.
+ * @param {string} viewName Name of the view.
+ */
+ currentScope.$emit('$viewContentLoaded', name);
+ currentScope.$eval(onloadExp);
+ }
+ };
+ }
+ };
+
+ return directive;
+}
+
+$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate'];
+function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ compile: function (tElement) {
+ var initial = tElement.html();
+ return function (scope, $element, attrs) {
+ var current = $state.$current,
+ name = getUiViewName(scope, attrs, $element, $interpolate),
+ locals = current && current.locals[name];
+
+ if (! locals) {
+ return;
+ }
+
+ $element.data('$uiView', { name: name, state: locals.$$state });
+ $element.html(locals.$template ? locals.$template : initial);
+
+ var link = $compile($element.contents());
+
+ if (locals.$$controller) {
+ locals.$scope = scope;
+ locals.$element = $element;
+ var controller = $controller(locals.$$controller, locals);
+ if (locals.$$controllerAs) {
+ scope[locals.$$controllerAs] = controller;
+ }
+ $element.data('$ngControllerController', controller);
+ $element.children().data('$ngControllerController', controller);
+ }
+
+ link(scope);
+ };
+ }
+ };
+}
+
+/**
+ * Shared ui-view code for both directives:
+ * Given scope, element, and its attributes, return the view's name
+ */
+function getUiViewName(scope, attrs, element, $interpolate) {
+ var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
+ var inherited = element.inheritedData('$uiView');
+ return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : ''));
+}
+
+angular.module('ui.router.state').directive('uiView', $ViewDirective);
+angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
diff --git a/afb-client/bower_components/angular-ui-router/src/viewScroll.js b/afb-client/bower_components/angular-ui-router/src/viewScroll.js
new file mode 100644
index 0000000..81114e2
--- /dev/null
+++ b/afb-client/bower_components/angular-ui-router/src/viewScroll.js
@@ -0,0 +1,52 @@
+/**
+ * @ngdoc object
+ * @name ui.router.state.$uiViewScrollProvider
+ *
+ * @description
+ * Provider that returns the {@link ui.router.state.$uiViewScroll} service function.
+ */
+function $ViewScrollProvider() {
+
+ var useAnchorScroll = false;
+
+ /**
+ * @ngdoc function
+ * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll
+ * @methodOf ui.router.state.$uiViewScrollProvider
+ *
+ * @description
+ * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for
+ * scrolling based on the url anchor.
+ */
+ this.useAnchorScroll = function () {
+ useAnchorScroll = true;
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.router.state.$uiViewScroll
+ *
+ * @requires $anchorScroll
+ * @requires $timeout
+ *
+ * @description
+ * When called with a jqLite element, it scrolls the element into view (after a
+ * `$timeout` so the DOM has time to refresh).
+ *
+ * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor,
+ * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}.
+ */
+ this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) {
+ if (useAnchorScroll) {
+ return $anchorScroll;
+ }
+
+ return function ($element) {
+ return $timeout(function () {
+ $element[0].scrollIntoView();
+ }, 0, false);
+ };
+ }];
+}
+
+angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
diff --git a/afb-client/bower_components/angular/.bower.json b/afb-client/bower_components/angular/.bower.json
new file mode 100644
index 0000000..1b094cf
--- /dev/null
+++ b/afb-client/bower_components/angular/.bower.json
@@ -0,0 +1,17 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "main": "./angular.js",
+ "ignore": [],
+ "dependencies": {},
+ "homepage": "https://github.com/angular/bower-angular",
+ "_release": "1.3.20",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.3.20",
+ "commit": "0cd10f27471310fe07167b00f8a4242c6bba4df2"
+ },
+ "_source": "git://github.com/angular/bower-angular.git",
+ "_target": "~1.3.4",
+ "_originalSource": "angular"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular/README.md b/afb-client/bower_components/angular/README.md
new file mode 100644
index 0000000..d1bc0ed
--- /dev/null
+++ b/afb-client/bower_components/angular/README.md
@@ -0,0 +1,64 @@
+# packaged angular
+
+This repo is for distribution on `npm` and `bower`. The source for this module is in the
+[main AngularJS repo](https://github.com/angular/angular.js).
+Please file issues and pull requests against that repo.
+
+## Install
+
+You can install this package either with `npm` or with `bower`.
+
+### npm
+
+```shell
+npm install angular
+```
+
+Then add a `<script>` to your `index.html`:
+
+```html
+<script src="/node_modules/angular/angular.js"></script>
+```
+
+Or `require('angular')` from your code.
+
+### bower
+
+```shell
+bower install angular
+```
+
+Then add a `<script>` to your `index.html`:
+
+```html
+<script src="/bower_components/angular/angular.js"></script>
+```
+
+## Documentation
+
+Documentation is available on the
+[AngularJS docs site](http://docs.angularjs.org/).
+
+## License
+
+The MIT License
+
+Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/angular/angular-csp.css b/afb-client/bower_components/angular/angular-csp.css
new file mode 100644
index 0000000..0ce9d86
--- /dev/null
+++ b/afb-client/bower_components/angular/angular-csp.css
@@ -0,0 +1,13 @@
+/* Include this file in your html if you are using the CSP mode. */
+
+@charset "UTF-8";
+
+[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
+.ng-cloak, .x-ng-cloak,
+.ng-hide:not(.ng-hide-animate) {
+ display: none !important;
+}
+
+ng\:form {
+ display: block;
+}
diff --git a/afb-client/bower_components/angular/angular.js b/afb-client/bower_components/angular/angular.js
new file mode 100644
index 0000000..2445ab5
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.js
@@ -0,0 +1,26451 @@
+/**
+ * @license AngularJS v1.3.20
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document, undefined) {'use strict';
+
+/**
+ * @description
+ *
+ * This object provides a utility for producing rich Error messages within
+ * Angular. It can be called as follows:
+ *
+ * var exampleMinErr = minErr('example');
+ * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
+ *
+ * The above creates an instance of minErr in the example namespace. The
+ * resulting error will have a namespaced error code of example.one. The
+ * resulting error will replace {0} with the value of foo, and {1} with the
+ * value of bar. The object is not restricted in the number of arguments it can
+ * take.
+ *
+ * If fewer arguments are specified than necessary for interpolation, the extra
+ * interpolation markers will be preserved in the final string.
+ *
+ * Since data will be parsed statically during a build step, some restrictions
+ * are applied with respect to how minErr instances are created and called.
+ * Instances should have names of the form namespaceMinErr for a minErr created
+ * using minErr('namespace') . Error codes, namespaces and template strings
+ * should all be static strings, not variables or general expressions.
+ *
+ * @param {string} module The namespace to use for the new minErr instance.
+ * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
+ * error from returned function, for cases when a particular type of error is useful.
+ * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
+ */
+
+function minErr(module, ErrorConstructor) {
+ ErrorConstructor = ErrorConstructor || Error;
+ return function() {
+ var code = arguments[0],
+ prefix = '[' + (module ? module + ':' : '') + code + '] ',
+ template = arguments[1],
+ templateArgs = arguments,
+
+ message, i;
+
+ message = prefix + template.replace(/\{\d+\}/g, function(match) {
+ var index = +match.slice(1, -1), arg;
+
+ if (index + 2 < templateArgs.length) {
+ return toDebugString(templateArgs[index + 2]);
+ }
+ return match;
+ });
+
+ message = message + '\nhttp://errors.angularjs.org/1.3.20/' +
+ (module ? module + '/' : '') + code;
+ for (i = 2; i < arguments.length; i++) {
+ message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
+ encodeURIComponent(toDebugString(arguments[i]));
+ }
+ return new ErrorConstructor(message);
+ };
+}
+
+/* We need to tell jshint what variables are being exported */
+/* global angular: true,
+ msie: true,
+ jqLite: true,
+ jQuery: true,
+ slice: true,
+ splice: true,
+ push: true,
+ toString: true,
+ ngMinErr: true,
+ angularModule: true,
+ uid: true,
+ REGEX_STRING_REGEXP: true,
+ VALIDITY_STATE_PROPERTY: true,
+
+ lowercase: true,
+ uppercase: true,
+ manualLowercase: true,
+ manualUppercase: true,
+ nodeName_: true,
+ isArrayLike: true,
+ forEach: true,
+ sortedKeys: true,
+ forEachSorted: true,
+ reverseParams: true,
+ nextUid: true,
+ setHashKey: true,
+ extend: true,
+ int: true,
+ inherit: true,
+ noop: true,
+ identity: true,
+ valueFn: true,
+ isUndefined: true,
+ isDefined: true,
+ isObject: true,
+ isString: true,
+ isNumber: true,
+ isDate: true,
+ isArray: true,
+ isFunction: true,
+ isRegExp: true,
+ isWindow: true,
+ isScope: true,
+ isFile: true,
+ isFormData: true,
+ isBlob: true,
+ isBoolean: true,
+ isPromiseLike: true,
+ trim: true,
+ escapeForRegexp: true,
+ isElement: true,
+ makeMap: true,
+ includes: true,
+ arrayRemove: true,
+ copy: true,
+ shallowCopy: true,
+ equals: true,
+ csp: true,
+ concat: true,
+ sliceArgs: true,
+ bind: true,
+ toJsonReplacer: true,
+ toJson: true,
+ fromJson: true,
+ startingTag: true,
+ tryDecodeURIComponent: true,
+ parseKeyValue: true,
+ toKeyValue: true,
+ encodeUriSegment: true,
+ encodeUriQuery: true,
+ angularInit: true,
+ bootstrap: true,
+ getTestability: true,
+ snake_case: true,
+ bindJQuery: true,
+ assertArg: true,
+ assertArgFn: true,
+ assertNotHasOwnProperty: true,
+ getter: true,
+ getBlockNodes: true,
+ hasOwnProperty: true,
+ createMap: true,
+
+ NODE_TYPE_ELEMENT: true,
+ NODE_TYPE_ATTRIBUTE: true,
+ NODE_TYPE_TEXT: true,
+ NODE_TYPE_COMMENT: true,
+ NODE_TYPE_DOCUMENT: true,
+ NODE_TYPE_DOCUMENT_FRAGMENT: true,
+*/
+
+////////////////////////////////////
+
+/**
+ * @ngdoc module
+ * @name ng
+ * @module ng
+ * @description
+ *
+ * # ng (core module)
+ * The ng module is loaded by default when an AngularJS application is started. The module itself
+ * contains the essential components for an AngularJS application to function. The table below
+ * lists a high level breakdown of each of the services/factories, filters, directives and testing
+ * components available within this core module.
+ *
+ * <div doc-module-components="ng"></div>
+ */
+
+var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
+
+// The name of a form control's ValidityState property.
+// This is used so that it's possible for internal tests to create mock ValidityStates.
+var VALIDITY_STATE_PROPERTY = 'validity';
+
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
+var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
+
+
+var manualLowercase = function(s) {
+ /* jshint bitwise: false */
+ return isString(s)
+ ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
+ : s;
+};
+var manualUppercase = function(s) {
+ /* jshint bitwise: false */
+ return isString(s)
+ ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
+ : s;
+};
+
+
+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
+// with correct but slower alternatives.
+if ('i' !== 'I'.toLowerCase()) {
+ lowercase = manualLowercase;
+ uppercase = manualUppercase;
+}
+
+
+var
+ msie, // holds major version number for IE, or NaN if UA is not IE.
+ jqLite, // delay binding since jQuery could be loaded after us.
+ jQuery, // delay binding
+ slice = [].slice,
+ splice = [].splice,
+ push = [].push,
+ toString = Object.prototype.toString,
+ ngMinErr = minErr('ng'),
+
+ /** @name angular */
+ angular = window.angular || (window.angular = {}),
+ angularModule,
+ uid = 0;
+
+/**
+ * documentMode is an IE-only property
+ * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
+ */
+msie = document.documentMode;
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
+ * String ...)
+ */
+function isArrayLike(obj) {
+ if (obj == null || isWindow(obj)) {
+ return false;
+ }
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // "length" in obj used to prevent JIT error (gh-11508)
+ var length = "length" in Object(obj) && obj.length;
+
+ if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
+ return true;
+ }
+
+ return isString(obj) || isArray(obj) || length === 0 ||
+ typeof length === 'number' && length > 0 && (length - 1) in obj;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.forEach
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+ * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
+ * is the value of an object property or an array element, `key` is the object property key or
+ * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
+ *
+ * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
+ * using the `hasOwnProperty` method.
+ *
+ * Unlike ES262's
+ * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
+ * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
+ * return the value provided.
+ *
+ ```js
+ var values = {name: 'misko', gender: 'male'};
+ var log = [];
+ angular.forEach(values, function(value, key) {
+ this.push(key + ': ' + value);
+ }, log);
+ expect(log).toEqual(['name: misko', 'gender: male']);
+ ```
+ *
+ * @param {Object|Array} obj Object to iterate over.
+ * @param {Function} iterator Iterator function.
+ * @param {Object=} context Object to become context (`this`) for the iterator function.
+ * @returns {Object|Array} Reference to `obj`.
+ */
+
+function forEach(obj, iterator, context) {
+ var key, length;
+ if (obj) {
+ if (isFunction(obj)) {
+ for (key in obj) {
+ // Need to check if hasOwnProperty exists,
+ // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
+ if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (isArray(obj) || isArrayLike(obj)) {
+ var isPrimitive = typeof obj !== 'object';
+ for (key = 0, length = obj.length; key < length; key++) {
+ if (isPrimitive || key in obj) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (obj.forEach && obj.forEach !== forEach) {
+ obj.forEach(iterator, context, obj);
+ } else {
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ }
+ }
+ return obj;
+}
+
+function sortedKeys(obj) {
+ return Object.keys(obj).sort();
+}
+
+function forEachSorted(obj, iterator, context) {
+ var keys = sortedKeys(obj);
+ for (var i = 0; i < keys.length; i++) {
+ iterator.call(context, obj[keys[i]], keys[i]);
+ }
+ return keys;
+}
+
+
+/**
+ * when using forEach the params are value, key, but it is often useful to have key, value.
+ * @param {function(string, *)} iteratorFn
+ * @returns {function(*, string)}
+ */
+function reverseParams(iteratorFn) {
+ return function(value, key) { iteratorFn(key, value); };
+}
+
+/**
+ * A consistent way of creating unique IDs in angular.
+ *
+ * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
+ * we hit number precision issues in JavaScript.
+ *
+ * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
+ *
+ * @returns {number} an unique alpha-numeric string
+ */
+function nextUid() {
+ return ++uid;
+}
+
+
+/**
+ * Set or clear the hashkey for an object.
+ * @param obj object
+ * @param h the hashkey (!truthy to delete the hashkey)
+ */
+function setHashKey(obj, h) {
+ if (h) {
+ obj.$$hashKey = h;
+ } else {
+ delete obj.$$hashKey;
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.extend
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
+ * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
+ * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
+ *
+ * @param {Object} dst Destination object.
+ * @param {...Object} src Source object(s).
+ * @returns {Object} Reference to `dst`.
+ */
+function extend(dst) {
+ var h = dst.$$hashKey;
+
+ for (var i = 1, ii = arguments.length; i < ii; i++) {
+ var obj = arguments[i];
+ if (obj) {
+ var keys = Object.keys(obj);
+ for (var j = 0, jj = keys.length; j < jj; j++) {
+ var key = keys[j];
+ dst[key] = obj[key];
+ }
+ }
+ }
+
+ setHashKey(dst, h);
+ return dst;
+}
+
+function int(str) {
+ return parseInt(str, 10);
+}
+
+
+function inherit(parent, extra) {
+ return extend(Object.create(parent), extra);
+}
+
+/**
+ * @ngdoc function
+ * @name angular.noop
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that performs no operations. This function can be useful when writing code in the
+ * functional style.
+ ```js
+ function foo(callback) {
+ var result = calculateResult();
+ (callback || angular.noop)(result);
+ }
+ ```
+ */
+function noop() {}
+noop.$inject = [];
+
+
+/**
+ * @ngdoc function
+ * @name angular.identity
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that returns its first argument. This function is useful when writing code in the
+ * functional style.
+ *
+ ```js
+ function transformer(transformationFn, value) {
+ return (transformationFn || angular.identity)(value);
+ };
+ ```
+ * @param {*} value to be returned.
+ * @returns {*} the value passed in.
+ */
+function identity($) {return $;}
+identity.$inject = [];
+
+
+function valueFn(value) {return function() {return value;};}
+
+/**
+ * @ngdoc function
+ * @name angular.isUndefined
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is undefined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is undefined.
+ */
+function isUndefined(value) {return typeof value === 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDefined
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is defined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is defined.
+ */
+function isDefined(value) {return typeof value !== 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isObject
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+ * considered to be objects. Note that JavaScript arrays are objects.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Object` but not `null`.
+ */
+function isObject(value) {
+ // http://jsperf.com/isobject4
+ return value !== null && typeof value === 'object';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isString
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `String`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `String`.
+ */
+function isString(value) {return typeof value === 'string';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isNumber
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `Number`.
+ *
+ * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
+ *
+ * If you wish to exclude these then you can use the native
+ * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
+ * method.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Number`.
+ */
+function isNumber(value) {return typeof value === 'number';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDate
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a value is a date.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Date`.
+ */
+function isDate(value) {
+ return toString.call(value) === '[object Date]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isArray
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Array`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Array`.
+ */
+var isArray = Array.isArray;
+
+/**
+ * @ngdoc function
+ * @name angular.isFunction
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `Function`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Function`.
+ */
+function isFunction(value) {return typeof value === 'function';}
+
+
+/**
+ * Determines if a value is a regular expression object.
+ *
+ * @private
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `RegExp`.
+ */
+function isRegExp(value) {
+ return toString.call(value) === '[object RegExp]';
+}
+
+
+/**
+ * Checks if `obj` is a window object.
+ *
+ * @private
+ * @param {*} obj Object to check
+ * @returns {boolean} True if `obj` is a window obj.
+ */
+function isWindow(obj) {
+ return obj && obj.window === obj;
+}
+
+
+function isScope(obj) {
+ return obj && obj.$evalAsync && obj.$watch;
+}
+
+
+function isFile(obj) {
+ return toString.call(obj) === '[object File]';
+}
+
+
+function isFormData(obj) {
+ return toString.call(obj) === '[object FormData]';
+}
+
+
+function isBlob(obj) {
+ return toString.call(obj) === '[object Blob]';
+}
+
+
+function isBoolean(value) {
+ return typeof value === 'boolean';
+}
+
+
+function isPromiseLike(obj) {
+ return obj && isFunction(obj.then);
+}
+
+
+var trim = function(value) {
+ return isString(value) ? value.trim() : value;
+};
+
+// Copied from:
+// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
+// Prereq: s is a string.
+var escapeForRegexp = function(s) {
+ return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
+ replace(/\x08/g, '\\x08');
+};
+
+
+/**
+ * @ngdoc function
+ * @name angular.isElement
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a DOM element (or wrapped jQuery element).
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
+ */
+function isElement(node) {
+ return !!(node &&
+ (node.nodeName // we are a direct element
+ || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
+}
+
+/**
+ * @param str 'key1,key2,...'
+ * @returns {object} in the form of {key1:true, key2:true, ...}
+ */
+function makeMap(str) {
+ var obj = {}, items = str.split(","), i;
+ for (i = 0; i < items.length; i++)
+ obj[items[i]] = true;
+ return obj;
+}
+
+
+function nodeName_(element) {
+ return lowercase(element.nodeName || (element[0] && element[0].nodeName));
+}
+
+function includes(array, obj) {
+ return Array.prototype.indexOf.call(array, obj) != -1;
+}
+
+function arrayRemove(array, value) {
+ var index = array.indexOf(value);
+ if (index >= 0)
+ array.splice(index, 1);
+ return value;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.copy
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Creates a deep copy of `source`, which should be an object or an array.
+ *
+ * * If no destination is supplied, a copy of the object or array is created.
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
+ * are deleted and then all elements/properties from the source are copied to it.
+ * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
+ * * If `source` is identical to 'destination' an exception will be thrown.
+ *
+ * @param {*} source The source that will be used to make a copy.
+ * Can be any type, including primitives, `null`, and `undefined`.
+ * @param {(Object|Array)=} destination Destination into which the source is copied. If
+ * provided, must be of the same type as `source`.
+ * @returns {*} The copy or updated `destination`, if `destination` was specified.
+ *
+ * @example
+ <example module="copyExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form novalidate class="simple-form">
+ Name: <input type="text" ng-model="user.name" /><br />
+ E-mail: <input type="email" ng-model="user.email" /><br />
+ Gender: <input type="radio" ng-model="user.gender" value="male" />male
+ <input type="radio" ng-model="user.gender" value="female" />female<br />
+ <button ng-click="reset()">RESET</button>
+ <button ng-click="update(user)">SAVE</button>
+ </form>
+ <pre>form = {{user | json}}</pre>
+ <pre>master = {{master | json}}</pre>
+ </div>
+
+ <script>
+ angular.module('copyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.master= {};
+
+ $scope.update = function(user) {
+ // Example with 1 argument
+ $scope.master= angular.copy(user);
+ };
+
+ $scope.reset = function() {
+ // Example with 2 arguments
+ angular.copy($scope.master, $scope.user);
+ };
+
+ $scope.reset();
+ }]);
+ </script>
+ </file>
+ </example>
+ */
+function copy(source, destination, stackSource, stackDest) {
+ if (isWindow(source) || isScope(source)) {
+ throw ngMinErr('cpws',
+ "Can't copy! Making copies of Window or Scope instances is not supported.");
+ }
+
+ if (!destination) {
+ destination = source;
+ if (source) {
+ if (isArray(source)) {
+ destination = copy(source, [], stackSource, stackDest);
+ } else if (isDate(source)) {
+ destination = new Date(source.getTime());
+ } else if (isRegExp(source)) {
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ destination.lastIndex = source.lastIndex;
+ } else if (isObject(source)) {
+ var emptyObject = Object.create(Object.getPrototypeOf(source));
+ destination = copy(source, emptyObject, stackSource, stackDest);
+ }
+ }
+ } else {
+ if (source === destination) throw ngMinErr('cpi',
+ "Can't copy! Source and destination are identical.");
+
+ stackSource = stackSource || [];
+ stackDest = stackDest || [];
+
+ if (isObject(source)) {
+ var index = stackSource.indexOf(source);
+ if (index !== -1) return stackDest[index];
+
+ stackSource.push(source);
+ stackDest.push(destination);
+ }
+
+ var result;
+ if (isArray(source)) {
+ destination.length = 0;
+ for (var i = 0; i < source.length; i++) {
+ result = copy(source[i], null, stackSource, stackDest);
+ if (isObject(source[i])) {
+ stackSource.push(source[i]);
+ stackDest.push(result);
+ }
+ destination.push(result);
+ }
+ } else {
+ var h = destination.$$hashKey;
+ if (isArray(destination)) {
+ destination.length = 0;
+ } else {
+ forEach(destination, function(value, key) {
+ delete destination[key];
+ });
+ }
+ for (var key in source) {
+ if (source.hasOwnProperty(key)) {
+ result = copy(source[key], null, stackSource, stackDest);
+ if (isObject(source[key])) {
+ stackSource.push(source[key]);
+ stackDest.push(result);
+ }
+ destination[key] = result;
+ }
+ }
+ setHashKey(destination,h);
+ }
+
+ }
+ return destination;
+}
+
+/**
+ * Creates a shallow copy of an object, an array or a primitive.
+ *
+ * Assumes that there are no proto properties for objects.
+ */
+function shallowCopy(src, dst) {
+ if (isArray(src)) {
+ dst = dst || [];
+
+ for (var i = 0, ii = src.length; i < ii; i++) {
+ dst[i] = src[i];
+ }
+ } else if (isObject(src)) {
+ dst = dst || {};
+
+ for (var key in src) {
+ if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst || src;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.equals
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if two objects or two values are equivalent. Supports value types, regular
+ * expressions, arrays and objects.
+ *
+ * Two objects or values are considered equivalent if at least one of the following is true:
+ *
+ * * Both objects or values pass `===` comparison.
+ * * Both objects or values are of the same type and all of their properties are equal by
+ * comparing them with `angular.equals`.
+ * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
+ * * Both values represent the same regular expression (In JavaScript,
+ * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
+ * representation matches).
+ *
+ * During a property comparison, properties of `function` type and properties with names
+ * that begin with `$` are ignored.
+ *
+ * Scope and DOMWindow objects are being compared only by identify (`===`).
+ *
+ * @param {*} o1 Object or value to compare.
+ * @param {*} o2 Object or value to compare.
+ * @returns {boolean} True if arguments are equal.
+ */
+function equals(o1, o2) {
+ if (o1 === o2) return true;
+ if (o1 === null || o2 === null) return false;
+ if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+ var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+ if (t1 == t2) {
+ if (t1 == 'object') {
+ if (isArray(o1)) {
+ if (!isArray(o2)) return false;
+ if ((length = o1.length) == o2.length) {
+ for (key = 0; key < length; key++) {
+ if (!equals(o1[key], o2[key])) return false;
+ }
+ return true;
+ }
+ } else if (isDate(o1)) {
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
+ } else if (isRegExp(o1)) {
+ return isRegExp(o2) ? o1.toString() == o2.toString() : false;
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
+ keySet = {};
+ for (key in o1) {
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+ if (!equals(o1[key], o2[key])) return false;
+ keySet[key] = true;
+ }
+ for (key in o2) {
+ if (!keySet.hasOwnProperty(key) &&
+ key.charAt(0) !== '$' &&
+ o2[key] !== undefined &&
+ !isFunction(o2[key])) return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+var csp = function() {
+ if (isDefined(csp.isActive_)) return csp.isActive_;
+
+ var active = !!(document.querySelector('[ng-csp]') ||
+ document.querySelector('[data-ng-csp]'));
+
+ if (!active) {
+ try {
+ /* jshint -W031, -W054 */
+ new Function('');
+ /* jshint +W031, +W054 */
+ } catch (e) {
+ active = true;
+ }
+ }
+
+ return (csp.isActive_ = active);
+};
+
+
+
+function concat(array1, array2, index) {
+ return array1.concat(slice.call(array2, index));
+}
+
+function sliceArgs(args, startIndex) {
+ return slice.call(args, startIndex || 0);
+}
+
+
+/* jshint -W101 */
+/**
+ * @ngdoc function
+ * @name angular.bind
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+ * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
+ * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
+ * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
+ *
+ * @param {Object} self Context which `fn` should be evaluated in.
+ * @param {function()} fn Function to be bound.
+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+ */
+/* jshint +W101 */
+function bind(self, fn) {
+ var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+ if (isFunction(fn) && !(fn instanceof RegExp)) {
+ return curryArgs.length
+ ? function() {
+ return arguments.length
+ ? fn.apply(self, concat(curryArgs, arguments, 0))
+ : fn.apply(self, curryArgs);
+ }
+ : function() {
+ return arguments.length
+ ? fn.apply(self, arguments)
+ : fn.call(self);
+ };
+ } else {
+ // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+ return fn;
+ }
+}
+
+
+function toJsonReplacer(key, value) {
+ var val = value;
+
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
+ val = undefined;
+ } else if (isWindow(value)) {
+ val = '$WINDOW';
+ } else if (value && document === value) {
+ val = '$DOCUMENT';
+ } else if (isScope(value)) {
+ val = '$SCOPE';
+ }
+
+ return val;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.toJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
+ * stripped since angular uses this notation internally.
+ *
+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
+ * If set to an integer, the JSON output will contain that many spaces per indentation.
+ * @returns {string|undefined} JSON-ified string representing `obj`.
+ */
+function toJson(obj, pretty) {
+ if (typeof obj === 'undefined') return undefined;
+ if (!isNumber(pretty)) {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.fromJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Deserializes a JSON string.
+ *
+ * @param {string} json JSON string to deserialize.
+ * @returns {Object|Array|string|number} Deserialized JSON string.
+ */
+function fromJson(json) {
+ return isString(json)
+ ? JSON.parse(json)
+ : json;
+}
+
+
+/**
+ * @returns {string} Returns the string representation of the element.
+ */
+function startingTag(element) {
+ element = jqLite(element).clone();
+ try {
+ // turns out IE does not let you set .html() on elements which
+ // are not allowed to have children. So we just ignore it.
+ element.empty();
+ } catch (e) {}
+ var elemHtml = jqLite('<div>').append(element).html();
+ try {
+ return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
+ elemHtml.
+ match(/^(<[^>]+>)/)[1].
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ } catch (e) {
+ return lowercase(elemHtml);
+ }
+
+}
+
+
+/////////////////////////////////////////////////
+
+/**
+ * Tries to decode the URI component without throwing an exception.
+ *
+ * @private
+ * @param str value potential URI component to check.
+ * @returns {boolean} True if `value` can be decoded
+ * with the decodeURIComponent function.
+ */
+function tryDecodeURIComponent(value) {
+ try {
+ return decodeURIComponent(value);
+ } catch (e) {
+ // Ignore any invalid uri component
+ }
+}
+
+
+/**
+ * Parses an escaped url query string into key-value pairs.
+ * @returns {Object.<string,boolean|Array>}
+ */
+function parseKeyValue(/**string*/keyValue) {
+ var obj = {}, key_value, key;
+ forEach((keyValue || "").split('&'), function(keyValue) {
+ if (keyValue) {
+ key_value = keyValue.replace(/\+/g,'%20').split('=');
+ key = tryDecodeURIComponent(key_value[0]);
+ if (isDefined(key)) {
+ var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
+ if (!hasOwnProperty.call(obj, key)) {
+ obj[key] = val;
+ } else if (isArray(obj[key])) {
+ obj[key].push(val);
+ } else {
+ obj[key] = [obj[key],val];
+ }
+ }
+ }
+ });
+ return obj;
+}
+
+function toKeyValue(obj) {
+ var parts = [];
+ forEach(obj, function(value, key) {
+ if (isArray(value)) {
+ forEach(value, function(arrayValue) {
+ parts.push(encodeUriQuery(key, true) +
+ (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
+ });
+ } else {
+ parts.push(encodeUriQuery(key, true) +
+ (value === true ? '' : '=' + encodeUriQuery(value, true)));
+ }
+ });
+ return parts.length ? parts.join('&') : '';
+}
+
+
+/**
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+ * segments:
+ * segment = *pchar
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriSegment(val) {
+ return encodeUriQuery(val, true).
+ replace(/%26/gi, '&').
+ replace(/%3D/gi, '=').
+ replace(/%2B/gi, '+');
+}
+
+
+/**
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+ * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
+ * encoded per http://tools.ietf.org/html/rfc3986:
+ * query = *( pchar / "/" / "?" )
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriQuery(val, pctEncodeSpaces) {
+ return encodeURIComponent(val).
+ replace(/%40/gi, '@').
+ replace(/%3A/gi, ':').
+ replace(/%24/g, '$').
+ replace(/%2C/gi, ',').
+ replace(/%3B/gi, ';').
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
+}
+
+var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
+
+function getNgAttribute(element, ngAttr) {
+ var attr, i, ii = ngAttrPrefixes.length;
+ element = jqLite(element);
+ for (i = 0; i < ii; ++i) {
+ attr = ngAttrPrefixes[i] + ngAttr;
+ if (isString(attr = element.attr(attr))) {
+ return attr;
+ }
+ }
+ return null;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngApp
+ * @module ng
+ *
+ * @element ANY
+ * @param {angular.Module} ngApp an optional application
+ * {@link angular.module module} name to load.
+ * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
+ * tracking down the root of these bugs.
+ *
+ * @description
+ *
+ * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
+ * designates the **root element** of the application and is typically placed near the root element
+ * of the page - e.g. on the `<body>` or `<html>` tags.
+ *
+ * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
+ * found in the document will be used to define the root element to auto-bootstrap as an
+ * application. To run multiple applications in an HTML document you must manually bootstrap them using
+ * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
+ *
+ * You can specify an **AngularJS module** to be used as the root module for the application. This
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
+ * should contain the application code needed or have dependencies on other modules that will
+ * contain the code. See {@link angular.module} for more information.
+ *
+ * In the example below if the `ngApp` directive were not placed on the `html` element then the
+ * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
+ * would not be resolved to `3`.
+ *
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
+ *
+ <example module="ngAppDemo">
+ <file name="index.html">
+ <div ng-controller="ngAppDemoController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ });
+ </file>
+ </example>
+ *
+ * Using `ngStrictDi`, you would see something like this:
+ *
+ <example ng-app-included="true">
+ <file name="index.html">
+ <div ng-app="ngAppStrictDemo" ng-strict-di>
+ <div ng-controller="GoodController1">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style (see
+ script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="GoodController2">
+ Name: <input ng-model="name"><br />
+ Hello, {{name}}!
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style
+ (see script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="BadController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>The controller could not be instantiated, due to relying
+ on automatic function annotations (which are disabled in
+ strict mode). As such, the content of this section is not
+ interpolated, and there should be an error in your web console.
+ </p>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppStrictDemo', [])
+ // BadController will fail to instantiate, due to relying on automatic function annotation,
+ // rather than an explicit annotation
+ .controller('BadController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ })
+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
+ // due to using explicit annotations using the array style and $inject property, respectively.
+ .controller('GoodController1', ['$scope', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ }])
+ .controller('GoodController2', GoodController2);
+ function GoodController2($scope) {
+ $scope.name = "World";
+ }
+ GoodController2.$inject = ['$scope'];
+ </file>
+ <file name="style.css">
+ div[ng-controller] {
+ margin-bottom: 1em;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ border: 1px solid;
+ padding: .5em;
+ }
+ div[ng-controller^=Good] {
+ border-color: #d6e9c6;
+ background-color: #dff0d8;
+ color: #3c763d;
+ }
+ div[ng-controller^=Bad] {
+ border-color: #ebccd1;
+ background-color: #f2dede;
+ color: #a94442;
+ margin-bottom: 0;
+ }
+ </file>
+ </example>
+ */
+function angularInit(element, bootstrap) {
+ var appElement,
+ module,
+ config = {};
+
+ // The element `element` has priority over any other element
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+
+ if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
+ appElement = element;
+ module = element.getAttribute(name);
+ }
+ });
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+ var candidate;
+
+ if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
+ appElement = candidate;
+ module = candidate.getAttribute(name);
+ }
+ });
+ if (appElement) {
+ config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
+ bootstrap(appElement, module ? [module] : [], config);
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.bootstrap
+ * @module ng
+ * @description
+ * Use this function to manually start up angular application.
+ *
+ * See: {@link guide/bootstrap Bootstrap}
+ *
+ * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
+ * They must use {@link ng.directive:ngApp ngApp}.
+ *
+ * Angular will detect if it has been loaded into the browser more than once and only allow the
+ * first loaded script to be bootstrapped and will report a warning to the browser console for
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
+ * multiple instances of Angular try to work on the DOM.
+ *
+ * ```html
+ * <!doctype html>
+ * <html>
+ * <body>
+ * <div ng-controller="WelcomeController">
+ * {{greeting}}
+ * </div>
+ *
+ * <script src="angular.js"></script>
+ * <script>
+ * var app = angular.module('demo', [])
+ * .controller('WelcomeController', function($scope) {
+ * $scope.greeting = 'Welcome!';
+ * });
+ * angular.bootstrap(document, ['demo']);
+ * </script>
+ * </body>
+ * </html>
+ * ```
+ *
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
+ * Each item in the array should be the name of a predefined module or a (DI annotated)
+ * function that will be invoked by the injector as a `config` block.
+ * See: {@link angular.module modules}
+ * @param {Object=} config an object for defining configuration options for the application. The
+ * following keys are supported:
+ *
+ * * `strictDi` - disable automatic function annotation for the application. This is meant to
+ * assist in finding bugs which break minified code. Defaults to `false`.
+ *
+ * @returns {auto.$injector} Returns the newly created injector for this app.
+ */
+function bootstrap(element, modules, config) {
+ if (!isObject(config)) config = {};
+ var defaultConfig = {
+ strictDi: false
+ };
+ config = extend(defaultConfig, config);
+ var doBootstrap = function() {
+ element = jqLite(element);
+
+ if (element.injector()) {
+ var tag = (element[0] === document) ? 'document' : startingTag(element);
+ //Encode angle brackets to prevent input from being sanitized to empty string #8683
+ throw ngMinErr(
+ 'btstrpd',
+ "App Already Bootstrapped with this Element '{0}'",
+ tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
+ }
+
+ modules = modules || [];
+ modules.unshift(['$provide', function($provide) {
+ $provide.value('$rootElement', element);
+ }]);
+
+ if (config.debugInfoEnabled) {
+ // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
+ modules.push(['$compileProvider', function($compileProvider) {
+ $compileProvider.debugInfoEnabled(true);
+ }]);
+ }
+
+ modules.unshift('ng');
+ var injector = createInjector(modules, config.strictDi);
+ injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
+ function bootstrapApply(scope, element, compile, injector) {
+ scope.$apply(function() {
+ element.data('$injector', injector);
+ compile(element)(scope);
+ });
+ }]
+ );
+ return injector;
+ };
+
+ var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
+ var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
+
+ if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
+ config.debugInfoEnabled = true;
+ window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
+ }
+
+ if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
+ return doBootstrap();
+ }
+
+ window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
+ angular.resumeBootstrap = function(extraModules) {
+ forEach(extraModules, function(module) {
+ modules.push(module);
+ });
+ return doBootstrap();
+ };
+
+ if (isFunction(angular.resumeDeferredBootstrap)) {
+ angular.resumeDeferredBootstrap();
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.reloadWithDebugInfo
+ * @module ng
+ * @description
+ * Use this function to reload the current application with debug information turned on.
+ * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
+ *
+ * See {@link ng.$compileProvider#debugInfoEnabled} for more.
+ */
+function reloadWithDebugInfo() {
+ window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
+ window.location.reload();
+}
+
+/**
+ * @name angular.getTestability
+ * @module ng
+ * @description
+ * Get the testability service for the instance of Angular on the given
+ * element.
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ */
+function getTestability(rootElement) {
+ var injector = angular.element(rootElement).injector();
+ if (!injector) {
+ throw ngMinErr('test',
+ 'no injector found for element argument to getTestability');
+ }
+ return injector.get('$$testability');
+}
+
+var SNAKE_CASE_REGEXP = /[A-Z]/g;
+function snake_case(name, separator) {
+ separator = separator || '_';
+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+}
+
+var bindJQueryFired = false;
+var skipDestroyOnNextJQueryCleanData;
+function bindJQuery() {
+ var originalCleanData;
+
+ if (bindJQueryFired) {
+ return;
+ }
+
+ // bind to jQuery if present;
+ jQuery = window.jQuery;
+ // Use jQuery if it exists with proper functionality, otherwise default to us.
+ // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
+ // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
+ // versions. It will not work for sure with jQuery <1.7, though.
+ if (jQuery && jQuery.fn.on) {
+ jqLite = jQuery;
+ extend(jQuery.fn, {
+ scope: JQLitePrototype.scope,
+ isolateScope: JQLitePrototype.isolateScope,
+ controller: JQLitePrototype.controller,
+ injector: JQLitePrototype.injector,
+ inheritedData: JQLitePrototype.inheritedData
+ });
+
+ // All nodes removed from the DOM via various jQuery APIs like .remove()
+ // are passed through jQuery.cleanData. Monkey-patch this method to fire
+ // the $destroy event on all removed nodes.
+ originalCleanData = jQuery.cleanData;
+ jQuery.cleanData = function(elems) {
+ var events;
+ if (!skipDestroyOnNextJQueryCleanData) {
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
+ }
+ }
+ } else {
+ skipDestroyOnNextJQueryCleanData = false;
+ }
+ originalCleanData(elems);
+ };
+ } else {
+ jqLite = JQLite;
+ }
+
+ angular.element = jqLite;
+
+ // Prevent double-proxying.
+ bindJQueryFired = true;
+}
+
+/**
+ * throw error if the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+ if (!arg) {
+ throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
+ }
+ return arg;
+}
+
+function assertArgFn(arg, name, acceptArrayAnnotation) {
+ if (acceptArrayAnnotation && isArray(arg)) {
+ arg = arg[arg.length - 1];
+ }
+
+ assertArg(isFunction(arg), name, 'not a function, got ' +
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
+ return arg;
+}
+
+/**
+ * throw error if the name given is hasOwnProperty
+ * @param {String} name the name to test
+ * @param {String} context the context in which the name is used, such as module or directive
+ */
+function assertNotHasOwnProperty(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
+ }
+}
+
+/**
+ * Return the value accessible from the object by path. Any undefined traversals are ignored
+ * @param {Object} obj starting object
+ * @param {String} path path to traverse
+ * @param {boolean} [bindFnToScope=true]
+ * @returns {Object} value as accessible by path
+ */
+//TODO(misko): this function needs to be removed
+function getter(obj, path, bindFnToScope) {
+ if (!path) return obj;
+ var keys = path.split('.');
+ var key;
+ var lastInstance = obj;
+ var len = keys.length;
+
+ for (var i = 0; i < len; i++) {
+ key = keys[i];
+ if (obj) {
+ obj = (lastInstance = obj)[key];
+ }
+ }
+ if (!bindFnToScope && isFunction(obj)) {
+ return bind(lastInstance, obj);
+ }
+ return obj;
+}
+
+/**
+ * Return the DOM siblings between the first and last node in the given array.
+ * @param {Array} array like object
+ * @returns {jqLite} jqLite collection containing the nodes
+ */
+function getBlockNodes(nodes) {
+ // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
+ // collection, otherwise update the original collection.
+ var node = nodes[0];
+ var endNode = nodes[nodes.length - 1];
+ var blockNodes = [node];
+
+ do {
+ node = node.nextSibling;
+ if (!node) break;
+ blockNodes.push(node);
+ } while (node !== endNode);
+
+ return jqLite(blockNodes);
+}
+
+
+/**
+ * Creates a new object without a prototype. This object is useful for lookup without having to
+ * guard against prototypically inherited properties via hasOwnProperty.
+ *
+ * Related micro-benchmarks:
+ * - http://jsperf.com/object-create2
+ * - http://jsperf.com/proto-map-lookup/2
+ * - http://jsperf.com/for-in-vs-object-keys2
+ *
+ * @returns {Object}
+ */
+function createMap() {
+ return Object.create(null);
+}
+
+var NODE_TYPE_ELEMENT = 1;
+var NODE_TYPE_ATTRIBUTE = 2;
+var NODE_TYPE_TEXT = 3;
+var NODE_TYPE_COMMENT = 8;
+var NODE_TYPE_DOCUMENT = 9;
+var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
+
+/**
+ * @ngdoc type
+ * @name angular.Module
+ * @module ng
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+ var $injectorMinErr = minErr('$injector');
+ var ngMinErr = minErr('ng');
+
+ function ensure(obj, name, factory) {
+ return obj[name] || (obj[name] = factory());
+ }
+
+ var angular = ensure(window, 'angular', Object);
+
+ // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
+ angular.$$minErr = angular.$$minErr || minErr;
+
+ return ensure(angular, 'module', function() {
+ /** @type {Object.<string, angular.Module>} */
+ var modules = {};
+
+ /**
+ * @ngdoc function
+ * @name angular.module
+ * @module ng
+ * @description
+ *
+ * The `angular.module` is a global place for creating, registering and retrieving Angular
+ * modules.
+ * All modules (angular core or 3rd party) that should be available to an application must be
+ * registered using this mechanism.
+ *
+ * When passed two or more arguments, a new module is created. If passed only one argument, an
+ * existing module (the name passed as the first argument to `module`) is retrieved.
+ *
+ *
+ * # Module
+ *
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
+ * `angular.module` is used to configure the {@link auto.$injector $injector}.
+ *
+ * ```js
+ * // Create a new module
+ * var myModule = angular.module('myModule', []);
+ *
+ * // register a new service
+ * myModule.value('appName', 'MyCoolApp');
+ *
+ * // configure existing services inside initialization blocks.
+ * myModule.config(['$locationProvider', function($locationProvider) {
+ * // Configure existing providers
+ * $locationProvider.hashPrefix('!');
+ * }]);
+ * ```
+ *
+ * Then you can create an injector and load your modules like this:
+ *
+ * ```js
+ * var injector = angular.injector(['ng', 'myModule'])
+ * ```
+ *
+ * However it's more likely that you'll just use
+ * {@link ng.directive:ngApp ngApp} or
+ * {@link angular.bootstrap} to simplify this process for you.
+ *
+ * @param {!string} name The name of the module to create or retrieve.
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
+ * unspecified then the module is being retrieved for further configuration.
+ * @param {Function=} configFn Optional configuration function for the module. Same as
+ * {@link angular.Module#config Module#config()}.
+ * @returns {module} new module with the {@link angular.Module} api.
+ */
+ return function module(name, requires, configFn) {
+ var assertNotHasOwnProperty = function(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
+ }
+ };
+
+ assertNotHasOwnProperty(name, 'module');
+ if (requires && modules.hasOwnProperty(name)) {
+ modules[name] = null;
+ }
+ return ensure(modules, name, function() {
+ if (!requires) {
+ throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
+ "the module name or forgot to load it. If registering a module ensure that you " +
+ "specify the dependencies as the second argument.", name);
+ }
+
+ /** @type {!Array.<Array.<*>>} */
+ var invokeQueue = [];
+
+ /** @type {!Array.<Function>} */
+ var configBlocks = [];
+
+ /** @type {!Array.<Function>} */
+ var runBlocks = [];
+
+ var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
+
+ /** @type {angular.Module} */
+ var moduleInstance = {
+ // Private state
+ _invokeQueue: invokeQueue,
+ _configBlocks: configBlocks,
+ _runBlocks: runBlocks,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#requires
+ * @module ng
+ *
+ * @description
+ * Holds the list of modules which the injector will load before the current module is
+ * loaded.
+ */
+ requires: requires,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#name
+ * @module ng
+ *
+ * @description
+ * Name of the module.
+ */
+ name: name,
+
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#provider
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerType Construction function for creating new instance of the
+ * service.
+ * @description
+ * See {@link auto.$provide#provider $provide.provider()}.
+ */
+ provider: invokeLater('$provide', 'provider'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#factory
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerFunction Function for creating new instance of the service.
+ * @description
+ * See {@link auto.$provide#factory $provide.factory()}.
+ */
+ factory: invokeLater('$provide', 'factory'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#service
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} constructor A constructor function that will be instantiated.
+ * @description
+ * See {@link auto.$provide#service $provide.service()}.
+ */
+ service: invokeLater('$provide', 'service'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#value
+ * @module ng
+ * @param {string} name service name
+ * @param {*} object Service instance object.
+ * @description
+ * See {@link auto.$provide#value $provide.value()}.
+ */
+ value: invokeLater('$provide', 'value'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#constant
+ * @module ng
+ * @param {string} name constant name
+ * @param {*} object Constant value.
+ * @description
+ * Because the constant are fixed, they get applied before other provide methods.
+ * See {@link auto.$provide#constant $provide.constant()}.
+ */
+ constant: invokeLater('$provide', 'constant', 'unshift'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#animation
+ * @module ng
+ * @param {string} name animation name
+ * @param {Function} animationFactory Factory function for creating new instance of an
+ * animation.
+ * @description
+ *
+ * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
+ *
+ *
+ * Defines an animation hook that can be later used with
+ * {@link ngAnimate.$animate $animate} service and directives that use this service.
+ *
+ * ```js
+ * module.animation('.animation-name', function($inject1, $inject2) {
+ * return {
+ * eventName : function(element, done) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function cancellationFunction(element) {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ * })
+ * ```
+ *
+ * See {@link ng.$animateProvider#register $animateProvider.register()} and
+ * {@link ngAnimate ngAnimate module} for more information.
+ */
+ animation: invokeLater('$animateProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#filter
+ * @module ng
+ * @param {string} name Filter name - this must be a valid angular expression identifier
+ * @param {Function} filterFactory Factory function for creating new instance of filter.
+ * @description
+ * See {@link ng.$filterProvider#register $filterProvider.register()}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ */
+ filter: invokeLater('$filterProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#controller
+ * @module ng
+ * @param {string|Object} name Controller name, or an object map of controllers where the
+ * keys are the names and the values are the constructors.
+ * @param {Function} constructor Controller constructor function.
+ * @description
+ * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+ */
+ controller: invokeLater('$controllerProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#directive
+ * @module ng
+ * @param {string|Object} name Directive name, or an object map of directives where the
+ * keys are the names and the values are the factories.
+ * @param {Function} directiveFactory Factory function for creating new instance of
+ * directives.
+ * @description
+ * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+ */
+ directive: invokeLater('$compileProvider', 'directive'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#config
+ * @module ng
+ * @param {Function} configFn Execute this function on module load. Useful for service
+ * configuration.
+ * @description
+ * Use this method to register work which needs to be performed on module loading.
+ * For more about how to configure services, see
+ * {@link providers#provider-recipe Provider Recipe}.
+ */
+ config: config,
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#run
+ * @module ng
+ * @param {Function} initializationFn Execute this function after injector creation.
+ * Useful for application initialization.
+ * @description
+ * Use this method to register work which should be performed when the injector is done
+ * loading all modules.
+ */
+ run: function(block) {
+ runBlocks.push(block);
+ return this;
+ }
+ };
+
+ if (configFn) {
+ config(configFn);
+ }
+
+ return moduleInstance;
+
+ /**
+ * @param {string} provider
+ * @param {string} method
+ * @param {String=} insertMethod
+ * @returns {angular.Module}
+ */
+ function invokeLater(provider, method, insertMethod, queue) {
+ if (!queue) queue = invokeQueue;
+ return function() {
+ queue[insertMethod || 'push']([provider, method, arguments]);
+ return moduleInstance;
+ };
+ }
+ });
+ };
+ });
+
+}
+
+/* global: toDebugString: true */
+
+function serializeObject(obj) {
+ var seen = [];
+
+ return JSON.stringify(obj, function(key, val) {
+ val = toJsonReplacer(key, val);
+ if (isObject(val)) {
+
+ if (seen.indexOf(val) >= 0) return '<<already seen>>';
+
+ seen.push(val);
+ }
+ return val;
+ });
+}
+
+function toDebugString(obj) {
+ if (typeof obj === 'function') {
+ return obj.toString().replace(/ \{[\s\S]*$/, '');
+ } else if (typeof obj === 'undefined') {
+ return 'undefined';
+ } else if (typeof obj !== 'string') {
+ return serializeObject(obj);
+ }
+ return obj;
+}
+
+/* global angularModule: true,
+ version: true,
+
+ $LocaleProvider,
+ $CompileProvider,
+
+ htmlAnchorDirective,
+ inputDirective,
+ inputDirective,
+ formDirective,
+ scriptDirective,
+ selectDirective,
+ styleDirective,
+ optionDirective,
+ ngBindDirective,
+ ngBindHtmlDirective,
+ ngBindTemplateDirective,
+ ngClassDirective,
+ ngClassEvenDirective,
+ ngClassOddDirective,
+ ngCspDirective,
+ ngCloakDirective,
+ ngControllerDirective,
+ ngFormDirective,
+ ngHideDirective,
+ ngIfDirective,
+ ngIncludeDirective,
+ ngIncludeFillContentDirective,
+ ngInitDirective,
+ ngNonBindableDirective,
+ ngPluralizeDirective,
+ ngRepeatDirective,
+ ngShowDirective,
+ ngStyleDirective,
+ ngSwitchDirective,
+ ngSwitchWhenDirective,
+ ngSwitchDefaultDirective,
+ ngOptionsDirective,
+ ngTranscludeDirective,
+ ngModelDirective,
+ ngListDirective,
+ ngChangeDirective,
+ patternDirective,
+ patternDirective,
+ requiredDirective,
+ requiredDirective,
+ minlengthDirective,
+ minlengthDirective,
+ maxlengthDirective,
+ maxlengthDirective,
+ ngValueDirective,
+ ngModelOptionsDirective,
+ ngAttributeAliasDirectives,
+ ngEventDirectives,
+
+ $AnchorScrollProvider,
+ $AnimateProvider,
+ $BrowserProvider,
+ $CacheFactoryProvider,
+ $ControllerProvider,
+ $DocumentProvider,
+ $ExceptionHandlerProvider,
+ $FilterProvider,
+ $InterpolateProvider,
+ $IntervalProvider,
+ $HttpProvider,
+ $HttpBackendProvider,
+ $LocationProvider,
+ $LogProvider,
+ $ParseProvider,
+ $RootScopeProvider,
+ $QProvider,
+ $$QProvider,
+ $$SanitizeUriProvider,
+ $SceProvider,
+ $SceDelegateProvider,
+ $SnifferProvider,
+ $TemplateCacheProvider,
+ $TemplateRequestProvider,
+ $$TestabilityProvider,
+ $TimeoutProvider,
+ $$RAFProvider,
+ $$AsyncCallbackProvider,
+ $WindowProvider,
+ $$jqLiteProvider
+*/
+
+
+/**
+ * @ngdoc object
+ * @name angular.version
+ * @module ng
+ * @description
+ * An object that contains information about the current AngularJS version. This object has the
+ * following properties:
+ *
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ */
+var version = {
+ full: '1.3.20', // all of these placeholder strings will be replaced by grunt's
+ major: 1, // package task
+ minor: 3,
+ dot: 20,
+ codeName: 'shallow-translucence'
+};
+
+
+function publishExternalAPI(angular) {
+ extend(angular, {
+ 'bootstrap': bootstrap,
+ 'copy': copy,
+ 'extend': extend,
+ 'equals': equals,
+ 'element': jqLite,
+ 'forEach': forEach,
+ 'injector': createInjector,
+ 'noop': noop,
+ 'bind': bind,
+ 'toJson': toJson,
+ 'fromJson': fromJson,
+ 'identity': identity,
+ 'isUndefined': isUndefined,
+ 'isDefined': isDefined,
+ 'isString': isString,
+ 'isFunction': isFunction,
+ 'isObject': isObject,
+ 'isNumber': isNumber,
+ 'isElement': isElement,
+ 'isArray': isArray,
+ 'version': version,
+ 'isDate': isDate,
+ 'lowercase': lowercase,
+ 'uppercase': uppercase,
+ 'callbacks': {counter: 0},
+ 'getTestability': getTestability,
+ '$$minErr': minErr,
+ '$$csp': csp,
+ 'reloadWithDebugInfo': reloadWithDebugInfo
+ });
+
+ angularModule = setupModuleLoader(window);
+ try {
+ angularModule('ngLocale');
+ } catch (e) {
+ angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+ }
+
+ angularModule('ng', ['ngLocale'], ['$provide',
+ function ngModule($provide) {
+ // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
+ $provide.provider({
+ $$sanitizeUri: $$SanitizeUriProvider
+ });
+ $provide.provider('$compile', $CompileProvider).
+ directive({
+ a: htmlAnchorDirective,
+ input: inputDirective,
+ textarea: inputDirective,
+ form: formDirective,
+ script: scriptDirective,
+ select: selectDirective,
+ style: styleDirective,
+ option: optionDirective,
+ ngBind: ngBindDirective,
+ ngBindHtml: ngBindHtmlDirective,
+ ngBindTemplate: ngBindTemplateDirective,
+ ngClass: ngClassDirective,
+ ngClassEven: ngClassEvenDirective,
+ ngClassOdd: ngClassOddDirective,
+ ngCloak: ngCloakDirective,
+ ngController: ngControllerDirective,
+ ngForm: ngFormDirective,
+ ngHide: ngHideDirective,
+ ngIf: ngIfDirective,
+ ngInclude: ngIncludeDirective,
+ ngInit: ngInitDirective,
+ ngNonBindable: ngNonBindableDirective,
+ ngPluralize: ngPluralizeDirective,
+ ngRepeat: ngRepeatDirective,
+ ngShow: ngShowDirective,
+ ngStyle: ngStyleDirective,
+ ngSwitch: ngSwitchDirective,
+ ngSwitchWhen: ngSwitchWhenDirective,
+ ngSwitchDefault: ngSwitchDefaultDirective,
+ ngOptions: ngOptionsDirective,
+ ngTransclude: ngTranscludeDirective,
+ ngModel: ngModelDirective,
+ ngList: ngListDirective,
+ ngChange: ngChangeDirective,
+ pattern: patternDirective,
+ ngPattern: patternDirective,
+ required: requiredDirective,
+ ngRequired: requiredDirective,
+ minlength: minlengthDirective,
+ ngMinlength: minlengthDirective,
+ maxlength: maxlengthDirective,
+ ngMaxlength: maxlengthDirective,
+ ngValue: ngValueDirective,
+ ngModelOptions: ngModelOptionsDirective
+ }).
+ directive({
+ ngInclude: ngIncludeFillContentDirective
+ }).
+ directive(ngAttributeAliasDirectives).
+ directive(ngEventDirectives);
+ $provide.provider({
+ $anchorScroll: $AnchorScrollProvider,
+ $animate: $AnimateProvider,
+ $browser: $BrowserProvider,
+ $cacheFactory: $CacheFactoryProvider,
+ $controller: $ControllerProvider,
+ $document: $DocumentProvider,
+ $exceptionHandler: $ExceptionHandlerProvider,
+ $filter: $FilterProvider,
+ $interpolate: $InterpolateProvider,
+ $interval: $IntervalProvider,
+ $http: $HttpProvider,
+ $httpBackend: $HttpBackendProvider,
+ $location: $LocationProvider,
+ $log: $LogProvider,
+ $parse: $ParseProvider,
+ $rootScope: $RootScopeProvider,
+ $q: $QProvider,
+ $$q: $$QProvider,
+ $sce: $SceProvider,
+ $sceDelegate: $SceDelegateProvider,
+ $sniffer: $SnifferProvider,
+ $templateCache: $TemplateCacheProvider,
+ $templateRequest: $TemplateRequestProvider,
+ $$testability: $$TestabilityProvider,
+ $timeout: $TimeoutProvider,
+ $window: $WindowProvider,
+ $$rAF: $$RAFProvider,
+ $$asyncCallback: $$AsyncCallbackProvider,
+ $$jqLite: $$jqLiteProvider
+ });
+ }
+ ]);
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* global JQLitePrototype: true,
+ addEventListenerFn: true,
+ removeEventListenerFn: true,
+ BOOLEAN_ATTR: true,
+ ALIASED_ATTR: true,
+*/
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+ *
+ * If jQuery is available, `angular.element` is an alias for the
+ * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
+ * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
+ *
+ * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
+ * commonly needed functionality with the goal of having a very small footprint.</div>
+ *
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
+ *
+ * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
+ * jqLite; they are never raw DOM references.</div>
+ *
+ * ## Angular's jqLite
+ * jqLite provides only the following jQuery methods:
+ *
+ * - [`addClass()`](http://api.jquery.com/addClass/)
+ * - [`after()`](http://api.jquery.com/after/)
+ * - [`append()`](http://api.jquery.com/append/)
+ * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
+ * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
+ * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
+ * - [`clone()`](http://api.jquery.com/clone/)
+ * - [`contents()`](http://api.jquery.com/contents/)
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
+ * - [`data()`](http://api.jquery.com/data/)
+ * - [`detach()`](http://api.jquery.com/detach/)
+ * - [`empty()`](http://api.jquery.com/empty/)
+ * - [`eq()`](http://api.jquery.com/eq/)
+ * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
+ * - [`hasClass()`](http://api.jquery.com/hasClass/)
+ * - [`html()`](http://api.jquery.com/html/)
+ * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
+ * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
+ * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
+ * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
+ * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
+ * - [`prepend()`](http://api.jquery.com/prepend/)
+ * - [`prop()`](http://api.jquery.com/prop/)
+ * - [`ready()`](http://api.jquery.com/ready/)
+ * - [`remove()`](http://api.jquery.com/remove/)
+ * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
+ * - [`removeClass()`](http://api.jquery.com/removeClass/)
+ * - [`removeData()`](http://api.jquery.com/removeData/)
+ * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
+ * - [`text()`](http://api.jquery.com/text/)
+ * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
+ * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
+ * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
+ * - [`val()`](http://api.jquery.com/val/)
+ * - [`wrap()`](http://api.jquery.com/wrap/)
+ *
+ * ## jQuery/jqLite Extras
+ * Angular also provides the following additional methods and events to both jQuery and jqLite:
+ *
+ * ### Events
+ * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
+ * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
+ * element before it is removed.
+ *
+ * ### Methods
+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+ * retrieves controller associated with the `ngController` directive. If `name` is provided as
+ * camelCase directive name, then the controller for this directive will be retrieved (e.g.
+ * `'ngModel'`).
+ * - `injector()` - retrieves the injector of the current element or its parent.
+ * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
+ * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
+ * be enabled.
+ * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
+ * current element. This getter should be used only on elements that contain a directive which starts a new isolate
+ * scope. Calling `scope()` on this element always returns the original non-isolate scope.
+ * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+ * parent element is reached.
+ *
+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+ * @returns {Object} jQuery object.
+ */
+
+JQLite.expando = 'ng339';
+
+var jqCache = JQLite.cache = {},
+ jqId = 1,
+ addEventListenerFn = function(element, type, fn) {
+ element.addEventListener(type, fn, false);
+ },
+ removeEventListenerFn = function(element, type, fn) {
+ element.removeEventListener(type, fn, false);
+ };
+
+/*
+ * !!! This is an undocumented "private" function !!!
+ */
+JQLite._data = function(node) {
+ //jQuery always returns an object on cache miss
+ return this.cache[node[this.expando]] || {};
+};
+
+function jqNextId() { return ++jqId; }
+
+
+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
+var jqLiteMinErr = minErr('jqLite');
+
+/**
+ * Converts snake_case to camelCase.
+ * Also there is special case for Moz prefix starting with upper case letter.
+ * @param name Name to normalize
+ */
+function camelCase(name) {
+ return name.
+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+ return offset ? letter.toUpperCase() : letter;
+ }).
+ replace(MOZ_HACK_REGEXP, 'Moz$1');
+}
+
+var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
+var HTML_REGEXP = /<|&#?\w+;/;
+var TAG_NAME_REGEXP = /<([\w:]+)/;
+var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
+
+var wrapMap = {
+ 'option': [1, '<select multiple="multiple">', '</select>'],
+
+ 'thead': [1, '<table>', '</table>'],
+ 'col': [2, '<table><colgroup>', '</colgroup></table>'],
+ 'tr': [2, '<table><tbody>', '</tbody></table>'],
+ 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
+ '_default': [0, "", ""]
+};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function jqLiteIsTextNode(html) {
+ return !HTML_REGEXP.test(html);
+}
+
+function jqLiteAcceptsData(node) {
+ // The window object can accept data but has no nodeType
+ // Otherwise we are only interested in elements (1) and documents (9)
+ var nodeType = node.nodeType;
+ return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
+}
+
+function jqLiteBuildFragment(html, context) {
+ var tmp, tag, wrap,
+ fragment = context.createDocumentFragment(),
+ nodes = [], i;
+
+ if (jqLiteIsTextNode(html)) {
+ // Convert non-html into a text node
+ nodes.push(context.createTextNode(html));
+ } else {
+ // Convert html into DOM nodes
+ tmp = tmp || fragment.appendChild(context.createElement("div"));
+ tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
+ wrap = wrapMap[tag] || wrapMap._default;
+ tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
+
+ // Descend through wrappers to the right content
+ i = wrap[0];
+ while (i--) {
+ tmp = tmp.lastChild;
+ }
+
+ nodes = concat(nodes, tmp.childNodes);
+
+ tmp = fragment.firstChild;
+ tmp.textContent = "";
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+ fragment.innerHTML = ""; // Clear inner HTML
+ forEach(nodes, function(node) {
+ fragment.appendChild(node);
+ });
+
+ return fragment;
+}
+
+function jqLiteParseHTML(html, context) {
+ context = context || document;
+ var parsed;
+
+ if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
+ return [context.createElement(parsed[1])];
+ }
+
+ if ((parsed = jqLiteBuildFragment(html, context))) {
+ return parsed.childNodes;
+ }
+
+ return [];
+}
+
+/////////////////////////////////////////////
+function JQLite(element) {
+ if (element instanceof JQLite) {
+ return element;
+ }
+
+ var argIsString;
+
+ if (isString(element)) {
+ element = trim(element);
+ argIsString = true;
+ }
+ if (!(this instanceof JQLite)) {
+ if (argIsString && element.charAt(0) != '<') {
+ throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
+ }
+ return new JQLite(element);
+ }
+
+ if (argIsString) {
+ jqLiteAddNodes(this, jqLiteParseHTML(element));
+ } else {
+ jqLiteAddNodes(this, element);
+ }
+}
+
+function jqLiteClone(element) {
+ return element.cloneNode(true);
+}
+
+function jqLiteDealoc(element, onlyDescendants) {
+ if (!onlyDescendants) jqLiteRemoveData(element);
+
+ if (element.querySelectorAll) {
+ var descendants = element.querySelectorAll('*');
+ for (var i = 0, l = descendants.length; i < l; i++) {
+ jqLiteRemoveData(descendants[i]);
+ }
+ }
+}
+
+function jqLiteOff(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
+
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var handle = expandoStore && expandoStore.handle;
+
+ if (!handle) return; //no listeners registered
+
+ if (!type) {
+ for (type in events) {
+ if (type !== '$destroy') {
+ removeEventListenerFn(element, type, handle);
+ }
+ delete events[type];
+ }
+ } else {
+ forEach(type.split(' '), function(type) {
+ if (isDefined(fn)) {
+ var listenerFns = events[type];
+ arrayRemove(listenerFns || [], fn);
+ if (listenerFns && listenerFns.length > 0) {
+ return;
+ }
+ }
+
+ removeEventListenerFn(element, type, handle);
+ delete events[type];
+ });
+ }
+}
+
+function jqLiteRemoveData(element, name) {
+ var expandoId = element.ng339;
+ var expandoStore = expandoId && jqCache[expandoId];
+
+ if (expandoStore) {
+ if (name) {
+ delete expandoStore.data[name];
+ return;
+ }
+
+ if (expandoStore.handle) {
+ if (expandoStore.events.$destroy) {
+ expandoStore.handle({}, '$destroy');
+ }
+ jqLiteOff(element);
+ }
+ delete jqCache[expandoId];
+ element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
+ }
+}
+
+
+function jqLiteExpandoStore(element, createIfNecessary) {
+ var expandoId = element.ng339,
+ expandoStore = expandoId && jqCache[expandoId];
+
+ if (createIfNecessary && !expandoStore) {
+ element.ng339 = expandoId = jqNextId();
+ expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
+ }
+
+ return expandoStore;
+}
+
+
+function jqLiteData(element, key, value) {
+ if (jqLiteAcceptsData(element)) {
+
+ var isSimpleSetter = isDefined(value);
+ var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
+ var massGetter = !key;
+ var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
+ var data = expandoStore && expandoStore.data;
+
+ if (isSimpleSetter) { // data('key', value)
+ data[key] = value;
+ } else {
+ if (massGetter) { // data()
+ return data;
+ } else {
+ if (isSimpleGetter) { // data('key')
+ // don't force creation of expandoStore if it doesn't exist yet
+ return data && data[key];
+ } else { // mass-setter: data({key1: val1, key2: val2})
+ extend(data, key);
+ }
+ }
+ }
+ }
+}
+
+function jqLiteHasClass(element, selector) {
+ if (!element.getAttribute) return false;
+ return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
+ indexOf(" " + selector + " ") > -1);
+}
+
+function jqLiteRemoveClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ forEach(cssClasses.split(' '), function(cssClass) {
+ element.setAttribute('class', trim(
+ (" " + (element.getAttribute('class') || '') + " ")
+ .replace(/[\n\t]/g, " ")
+ .replace(" " + trim(cssClass) + " ", " "))
+ );
+ });
+ }
+}
+
+function jqLiteAddClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
+ .replace(/[\n\t]/g, " ");
+
+ forEach(cssClasses.split(' '), function(cssClass) {
+ cssClass = trim(cssClass);
+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
+ existingClasses += cssClass + ' ';
+ }
+ });
+
+ element.setAttribute('class', trim(existingClasses));
+ }
+}
+
+
+function jqLiteAddNodes(root, elements) {
+ // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
+
+ if (elements) {
+
+ // if a Node (the most common case)
+ if (elements.nodeType) {
+ root[root.length++] = elements;
+ } else {
+ var length = elements.length;
+
+ // if an Array or NodeList and not a Window
+ if (typeof length === 'number' && elements.window !== elements) {
+ if (length) {
+ for (var i = 0; i < length; i++) {
+ root[root.length++] = elements[i];
+ }
+ }
+ } else {
+ root[root.length++] = elements;
+ }
+ }
+ }
+}
+
+
+function jqLiteController(element, name) {
+ return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
+}
+
+function jqLiteInheritedData(element, name, value) {
+ // if element is the document object work with the html element instead
+ // this makes $(document).scope() possible
+ if (element.nodeType == NODE_TYPE_DOCUMENT) {
+ element = element.documentElement;
+ }
+ var names = isArray(name) ? name : [name];
+
+ while (element) {
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ if ((value = jqLite.data(element, names[i])) !== undefined) return value;
+ }
+
+ // If dealing with a document fragment node with a host element, and no parent, use the host
+ // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
+ // to lookup parent controllers.
+ element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
+ }
+}
+
+function jqLiteEmpty(element) {
+ jqLiteDealoc(element, true);
+ while (element.firstChild) {
+ element.removeChild(element.firstChild);
+ }
+}
+
+function jqLiteRemove(element, keepData) {
+ if (!keepData) jqLiteDealoc(element);
+ var parent = element.parentNode;
+ if (parent) parent.removeChild(element);
+}
+
+
+function jqLiteDocumentLoaded(action, win) {
+ win = win || window;
+ if (win.document.readyState === 'complete') {
+ // Force the action to be run async for consistent behaviour
+ // from the action's point of view
+ // i.e. it will definitely not be in a $apply
+ win.setTimeout(action);
+ } else {
+ // No need to unbind this handler as load is only ever called once
+ jqLite(win).on('load', action);
+ }
+}
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = {
+ ready: function(fn) {
+ var fired = false;
+
+ function trigger() {
+ if (fired) return;
+ fired = true;
+ fn();
+ }
+
+ // check if document is already loaded
+ if (document.readyState === 'complete') {
+ setTimeout(trigger);
+ } else {
+ this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
+ // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+ // jshint -W064
+ JQLite(window).on('load', trigger); // fallback to window.onload for others
+ // jshint +W064
+ }
+ },
+ toString: function() {
+ var value = [];
+ forEach(this, function(e) { value.push('' + e);});
+ return '[' + value.join(', ') + ']';
+ },
+
+ eq: function(index) {
+ return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+ },
+
+ length: 0,
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+var BOOLEAN_ATTR = {};
+forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
+ BOOLEAN_ATTR[lowercase(value)] = value;
+});
+var BOOLEAN_ELEMENTS = {};
+forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
+ BOOLEAN_ELEMENTS[value] = true;
+});
+var ALIASED_ATTR = {
+ 'ngMinlength': 'minlength',
+ 'ngMaxlength': 'maxlength',
+ 'ngMin': 'min',
+ 'ngMax': 'max',
+ 'ngPattern': 'pattern'
+};
+
+function getBooleanAttrName(element, name) {
+ // check dom last since we will most likely fail on name
+ var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+ // booleanAttr is here twice to minimize DOM access
+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
+}
+
+function getAliasedAttrName(element, name) {
+ var nodeName = element.nodeName;
+ return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
+}
+
+forEach({
+ data: jqLiteData,
+ removeData: jqLiteRemoveData
+}, function(fn, name) {
+ JQLite[name] = fn;
+});
+
+forEach({
+ data: jqLiteData,
+ inheritedData: jqLiteInheritedData,
+
+ scope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
+ },
+
+ isolateScope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
+ },
+
+ controller: jqLiteController,
+
+ injector: function(element) {
+ return jqLiteInheritedData(element, '$injector');
+ },
+
+ removeAttr: function(element, name) {
+ element.removeAttribute(name);
+ },
+
+ hasClass: jqLiteHasClass,
+
+ css: function(element, name, value) {
+ name = camelCase(name);
+
+ if (isDefined(value)) {
+ element.style[name] = value;
+ } else {
+ return element.style[name];
+ }
+ },
+
+ attr: function(element, name, value) {
+ var nodeType = element.nodeType;
+ if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
+ return;
+ }
+ var lowercasedName = lowercase(name);
+ if (BOOLEAN_ATTR[lowercasedName]) {
+ if (isDefined(value)) {
+ if (!!value) {
+ element[name] = true;
+ element.setAttribute(name, lowercasedName);
+ } else {
+ element[name] = false;
+ element.removeAttribute(lowercasedName);
+ }
+ } else {
+ return (element[name] ||
+ (element.attributes.getNamedItem(name) || noop).specified)
+ ? lowercasedName
+ : undefined;
+ }
+ } else if (isDefined(value)) {
+ element.setAttribute(name, value);
+ } else if (element.getAttribute) {
+ // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+ // some elements (e.g. Document) don't have get attribute, so return undefined
+ var ret = element.getAttribute(name, 2);
+ // normalize non-existing attributes to undefined (as jQuery)
+ return ret === null ? undefined : ret;
+ }
+ },
+
+ prop: function(element, name, value) {
+ if (isDefined(value)) {
+ element[name] = value;
+ } else {
+ return element[name];
+ }
+ },
+
+ text: (function() {
+ getText.$dv = '';
+ return getText;
+
+ function getText(element, value) {
+ if (isUndefined(value)) {
+ var nodeType = element.nodeType;
+ return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
+ }
+ element.textContent = value;
+ }
+ })(),
+
+ val: function(element, value) {
+ if (isUndefined(value)) {
+ if (element.multiple && nodeName_(element) === 'select') {
+ var result = [];
+ forEach(element.options, function(option) {
+ if (option.selected) {
+ result.push(option.value || option.text);
+ }
+ });
+ return result.length === 0 ? null : result;
+ }
+ return element.value;
+ }
+ element.value = value;
+ },
+
+ html: function(element, value) {
+ if (isUndefined(value)) {
+ return element.innerHTML;
+ }
+ jqLiteDealoc(element, true);
+ element.innerHTML = value;
+ },
+
+ empty: jqLiteEmpty
+}, function(fn, name) {
+ /**
+ * Properties: writes return selection, reads return first value
+ */
+ JQLite.prototype[name] = function(arg1, arg2) {
+ var i, key;
+ var nodeCount = this.length;
+
+ // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+ // in a way that survives minification.
+ // jqLiteEmpty takes no arguments but is a setter.
+ if (fn !== jqLiteEmpty &&
+ (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
+ if (isObject(arg1)) {
+
+ // we are a write, but the object properties are the key/values
+ for (i = 0; i < nodeCount; i++) {
+ if (fn === jqLiteData) {
+ // data() takes the whole object in jQuery
+ fn(this[i], arg1);
+ } else {
+ for (key in arg1) {
+ fn(this[i], key, arg1[key]);
+ }
+ }
+ }
+ // return self for chaining
+ return this;
+ } else {
+ // we are a read, so read the first child.
+ // TODO: do we still need this?
+ var value = fn.$dv;
+ // Only if we have $dv do we iterate over all, otherwise it is just the first element.
+ var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
+ for (var j = 0; j < jj; j++) {
+ var nodeValue = fn(this[j], arg1, arg2);
+ value = value ? value + nodeValue : nodeValue;
+ }
+ return value;
+ }
+ } else {
+ // we are a write, so apply to all children
+ for (i = 0; i < nodeCount; i++) {
+ fn(this[i], arg1, arg2);
+ }
+ // return self for chaining
+ return this;
+ }
+ };
+});
+
+function createEventHandler(element, events) {
+ var eventHandler = function(event, type) {
+ // jQuery specific api
+ event.isDefaultPrevented = function() {
+ return event.defaultPrevented;
+ };
+
+ var eventFns = events[type || event.type];
+ var eventFnsLength = eventFns ? eventFns.length : 0;
+
+ if (!eventFnsLength) return;
+
+ if (isUndefined(event.immediatePropagationStopped)) {
+ var originalStopImmediatePropagation = event.stopImmediatePropagation;
+ event.stopImmediatePropagation = function() {
+ event.immediatePropagationStopped = true;
+
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ }
+
+ if (originalStopImmediatePropagation) {
+ originalStopImmediatePropagation.call(event);
+ }
+ };
+ }
+
+ event.isImmediatePropagationStopped = function() {
+ return event.immediatePropagationStopped === true;
+ };
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ if ((eventFnsLength > 1)) {
+ eventFns = shallowCopy(eventFns);
+ }
+
+ for (var i = 0; i < eventFnsLength; i++) {
+ if (!event.isImmediatePropagationStopped()) {
+ eventFns[i].call(element, event);
+ }
+ }
+ };
+
+ // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
+ // events on `element`
+ eventHandler.elem = element;
+ return eventHandler;
+}
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+ removeData: jqLiteRemoveData,
+
+ on: function jqLiteOn(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
+
+ // Do not add event handlers to non-elements because they will not be cleaned up.
+ if (!jqLiteAcceptsData(element)) {
+ return;
+ }
+
+ var expandoStore = jqLiteExpandoStore(element, true);
+ var events = expandoStore.events;
+ var handle = expandoStore.handle;
+
+ if (!handle) {
+ handle = expandoStore.handle = createEventHandler(element, events);
+ }
+
+ // http://jsperf.com/string-indexof-vs-split
+ var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
+ var i = types.length;
+
+ while (i--) {
+ type = types[i];
+ var eventFns = events[type];
+
+ if (!eventFns) {
+ events[type] = [];
+
+ if (type === 'mouseenter' || type === 'mouseleave') {
+ // Refer to jQuery's implementation of mouseenter & mouseleave
+ // Read about mouseenter and mouseleave:
+ // http://www.quirksmode.org/js/events_mouse.html#link8
+
+ jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
+ var target = this, related = event.relatedTarget;
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if (!related || (related !== target && !target.contains(related))) {
+ handle(event, type);
+ }
+ });
+
+ } else {
+ if (type !== '$destroy') {
+ addEventListenerFn(element, type, handle);
+ }
+ }
+ eventFns = events[type];
+ }
+ eventFns.push(fn);
+ }
+ },
+
+ off: jqLiteOff,
+
+ one: function(element, type, fn) {
+ element = jqLite(element);
+
+ //add the listener twice so that when it is called
+ //you can remove the original function and still be
+ //able to call element.off(ev, fn) normally
+ element.on(type, function onFn() {
+ element.off(type, fn);
+ element.off(type, onFn);
+ });
+ element.on(type, fn);
+ },
+
+ replaceWith: function(element, replaceNode) {
+ var index, parent = element.parentNode;
+ jqLiteDealoc(element);
+ forEach(new JQLite(replaceNode), function(node) {
+ if (index) {
+ parent.insertBefore(node, index.nextSibling);
+ } else {
+ parent.replaceChild(node, element);
+ }
+ index = node;
+ });
+ },
+
+ children: function(element) {
+ var children = [];
+ forEach(element.childNodes, function(element) {
+ if (element.nodeType === NODE_TYPE_ELEMENT)
+ children.push(element);
+ });
+ return children;
+ },
+
+ contents: function(element) {
+ return element.contentDocument || element.childNodes || [];
+ },
+
+ append: function(element, node) {
+ var nodeType = element.nodeType;
+ if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
+
+ node = new JQLite(node);
+
+ for (var i = 0, ii = node.length; i < ii; i++) {
+ var child = node[i];
+ element.appendChild(child);
+ }
+ },
+
+ prepend: function(element, node) {
+ if (element.nodeType === NODE_TYPE_ELEMENT) {
+ var index = element.firstChild;
+ forEach(new JQLite(node), function(child) {
+ element.insertBefore(child, index);
+ });
+ }
+ },
+
+ wrap: function(element, wrapNode) {
+ wrapNode = jqLite(wrapNode).eq(0).clone()[0];
+ var parent = element.parentNode;
+ if (parent) {
+ parent.replaceChild(wrapNode, element);
+ }
+ wrapNode.appendChild(element);
+ },
+
+ remove: jqLiteRemove,
+
+ detach: function(element) {
+ jqLiteRemove(element, true);
+ },
+
+ after: function(element, newElement) {
+ var index = element, parent = element.parentNode;
+ newElement = new JQLite(newElement);
+
+ for (var i = 0, ii = newElement.length; i < ii; i++) {
+ var node = newElement[i];
+ parent.insertBefore(node, index.nextSibling);
+ index = node;
+ }
+ },
+
+ addClass: jqLiteAddClass,
+ removeClass: jqLiteRemoveClass,
+
+ toggleClass: function(element, selector, condition) {
+ if (selector) {
+ forEach(selector.split(' '), function(className) {
+ var classCondition = condition;
+ if (isUndefined(classCondition)) {
+ classCondition = !jqLiteHasClass(element, className);
+ }
+ (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
+ });
+ }
+ },
+
+ parent: function(element) {
+ var parent = element.parentNode;
+ return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
+ },
+
+ next: function(element) {
+ return element.nextElementSibling;
+ },
+
+ find: function(element, selector) {
+ if (element.getElementsByTagName) {
+ return element.getElementsByTagName(selector);
+ } else {
+ return [];
+ }
+ },
+
+ clone: jqLiteClone,
+
+ triggerHandler: function(element, event, extraParameters) {
+
+ var dummyEvent, eventFnsCopy, handlerArgs;
+ var eventName = event.type || event;
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var eventFns = events && events[eventName];
+
+ if (eventFns) {
+ // Create a dummy event to pass to the handlers
+ dummyEvent = {
+ preventDefault: function() { this.defaultPrevented = true; },
+ isDefaultPrevented: function() { return this.defaultPrevented === true; },
+ stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
+ isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
+ stopPropagation: noop,
+ type: eventName,
+ target: element
+ };
+
+ // If a custom event was provided then extend our dummy event with it
+ if (event.type) {
+ dummyEvent = extend(dummyEvent, event);
+ }
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ eventFnsCopy = shallowCopy(eventFns);
+ handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
+
+ forEach(eventFnsCopy, function(fn) {
+ if (!dummyEvent.isImmediatePropagationStopped()) {
+ fn.apply(element, handlerArgs);
+ }
+ });
+ }
+ }
+}, function(fn, name) {
+ /**
+ * chaining functions
+ */
+ JQLite.prototype[name] = function(arg1, arg2, arg3) {
+ var value;
+
+ for (var i = 0, ii = this.length; i < ii; i++) {
+ if (isUndefined(value)) {
+ value = fn(this[i], arg1, arg2, arg3);
+ if (isDefined(value)) {
+ // any function which returns a value needs to be wrapped
+ value = jqLite(value);
+ }
+ } else {
+ jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
+ }
+ }
+ return isDefined(value) ? value : this;
+ };
+
+ // bind legacy bind/unbind to on/off
+ JQLite.prototype.bind = JQLite.prototype.on;
+ JQLite.prototype.unbind = JQLite.prototype.off;
+});
+
+
+// Provider for private $$jqLite service
+function $$jqLiteProvider() {
+ this.$get = function $$jqLite() {
+ return extend(JQLite, {
+ hasClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteHasClass(node, classes);
+ },
+ addClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteAddClass(node, classes);
+ },
+ removeClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteRemoveClass(node, classes);
+ }
+ });
+ };
+}
+
+/**
+ * Computes a hash of an 'obj'.
+ * Hash of a:
+ * string is string
+ * number is number as string
+ * object is either result of calling $$hashKey function on the object or uniquely generated id,
+ * that is also assigned to the $$hashKey property of the object.
+ *
+ * @param obj
+ * @returns {string} hash string such that the same input will have the same hash string.
+ * The resulting string key is in 'type:hashKey' format.
+ */
+function hashKey(obj, nextUidFn) {
+ var key = obj && obj.$$hashKey;
+
+ if (key) {
+ if (typeof key === 'function') {
+ key = obj.$$hashKey();
+ }
+ return key;
+ }
+
+ var objType = typeof obj;
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
+ key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
+ } else {
+ key = objType + ':' + obj;
+ }
+
+ return key;
+}
+
+/**
+ * HashMap which can use objects as keys
+ */
+function HashMap(array, isolatedUid) {
+ if (isolatedUid) {
+ var uid = 0;
+ this.nextUid = function() {
+ return ++uid;
+ };
+ }
+ forEach(array, this.put, this);
+}
+HashMap.prototype = {
+ /**
+ * Store key value pair
+ * @param key key to store can be any type
+ * @param value value to store can be any type
+ */
+ put: function(key, value) {
+ this[hashKey(key, this.nextUid)] = value;
+ },
+
+ /**
+ * @param key
+ * @returns {Object} the value for the key
+ */
+ get: function(key) {
+ return this[hashKey(key, this.nextUid)];
+ },
+
+ /**
+ * Remove the key/value pair
+ * @param key
+ */
+ remove: function(key) {
+ var value = this[key = hashKey(key, this.nextUid)];
+ delete this[key];
+ return value;
+ }
+};
+
+/**
+ * @ngdoc function
+ * @module ng
+ * @name angular.injector
+ * @kind function
+ *
+ * @description
+ * Creates an injector object that can be used for retrieving services as well as for
+ * dependency injection (see {@link guide/di dependency injection}).
+ *
+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+ * {@link angular.module}. The `ng` module must be explicitly added.
+ * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
+ * disallows argument name annotation inference.
+ * @returns {injector} Injector object. See {@link auto.$injector $injector}.
+ *
+ * @example
+ * Typical usage
+ * ```js
+ * // create an injector
+ * var $injector = angular.injector(['ng']);
+ *
+ * // use the injector to kick off your application
+ * // use the type inference to auto inject arguments, or use implicit injection
+ * $injector.invoke(function($rootScope, $compile, $document) {
+ * $compile($document)($rootScope);
+ * $rootScope.$digest();
+ * });
+ * ```
+ *
+ * Sometimes you want to get access to the injector of a currently running Angular app
+ * from outside Angular. Perhaps, you want to inject and compile some markup after the
+ * application has been bootstrapped. You can do this using the extra `injector()` added
+ * to JQuery/jqLite elements. See {@link angular.element}.
+ *
+ * *This is fairly rare but could be the case if a third party library is injecting the
+ * markup.*
+ *
+ * In the following example a new block of HTML containing a `ng-controller`
+ * directive is added to the end of the document body by JQuery. We then compile and link
+ * it into the current AngularJS scope.
+ *
+ * ```js
+ * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
+ * $(document.body).append($div);
+ *
+ * angular.element(document).injector().invoke(function($compile) {
+ * var scope = angular.element($div).scope();
+ * $compile($div)(scope);
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc module
+ * @name auto
+ * @description
+ *
+ * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
+ */
+
+var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+var $injectorMinErr = minErr('$injector');
+
+function anonFn(fn) {
+ // For anonymous functions, showing at the very least the function signature can help in
+ // debugging.
+ var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
+ args = fnText.match(FN_ARGS);
+ if (args) {
+ return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
+ }
+ return 'fn';
+}
+
+function annotate(fn, strictDi, name) {
+ var $inject,
+ fnText,
+ argDecl,
+ last;
+
+ if (typeof fn === 'function') {
+ if (!($inject = fn.$inject)) {
+ $inject = [];
+ if (fn.length) {
+ if (strictDi) {
+ if (!isString(name) || !name) {
+ name = fn.name || anonFn(fn);
+ }
+ throw $injectorMinErr('strictdi',
+ '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
+ }
+ fnText = fn.toString().replace(STRIP_COMMENTS, '');
+ argDecl = fnText.match(FN_ARGS);
+ forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
+ arg.replace(FN_ARG, function(all, underscore, name) {
+ $inject.push(name);
+ });
+ });
+ }
+ fn.$inject = $inject;
+ }
+ } else if (isArray(fn)) {
+ last = fn.length - 1;
+ assertArgFn(fn[last], 'fn');
+ $inject = fn.slice(0, last);
+ } else {
+ assertArgFn(fn, 'fn', true);
+ }
+ return $inject;
+}
+
+///////////////////////////////////////
+
+/**
+ * @ngdoc service
+ * @name $injector
+ *
+ * @description
+ *
+ * `$injector` is used to retrieve object instances as defined by
+ * {@link auto.$provide provider}, instantiate types, invoke methods,
+ * and load modules.
+ *
+ * The following always holds true:
+ *
+ * ```js
+ * var $injector = angular.injector();
+ * expect($injector.get('$injector')).toBe($injector);
+ * expect($injector.invoke(function($injector) {
+ * return $injector;
+ * })).toBe($injector);
+ * ```
+ *
+ * # Injection Function Annotation
+ *
+ * JavaScript does not have annotations, and annotations are needed for dependency injection. The
+ * following are all valid ways of annotating function with injection arguments and are equivalent.
+ *
+ * ```js
+ * // inferred (only works if code not minified/obfuscated)
+ * $injector.invoke(function(serviceA){});
+ *
+ * // annotated
+ * function explicit(serviceA) {};
+ * explicit.$inject = ['serviceA'];
+ * $injector.invoke(explicit);
+ *
+ * // inline
+ * $injector.invoke(['serviceA', function(serviceA){}]);
+ * ```
+ *
+ * ## Inference
+ *
+ * In JavaScript calling `toString()` on a function returns the function definition. The definition
+ * can then be parsed and the function arguments can be extracted. This method of discovering
+ * annotations is disallowed when the injector is in strict mode.
+ * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
+ * argument names.
+ *
+ * ## `$inject` Annotation
+ * By adding an `$inject` property onto a function the injection parameters can be specified.
+ *
+ * ## Inline
+ * As an array of injection names, where the last item in the array is the function to call.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#get
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @param {string=} caller An optional string to provide the origin of the function call for error messages.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#invoke
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
+ * injected according to the {@link guide/di $inject Annotation} rules.
+ * @param {Object=} self The `this` for the invoked method.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {*} the value returned by the invoked `fn` function.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#has
+ *
+ * @description
+ * Allows the user to query if the particular service exists.
+ *
+ * @param {string} name Name of the service to query.
+ * @returns {boolean} `true` if injector has given service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#instantiate
+ * @description
+ * Create a new instance of JS type. The method takes a constructor function, invokes the new
+ * operator, and supplies all of the arguments to the constructor function as specified by the
+ * constructor annotation.
+ *
+ * @param {Function} Type Annotated constructor function.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {Object} new instance of `Type`.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#annotate
+ *
+ * @description
+ * Returns an array of service names which the function is requesting for injection. This API is
+ * used by the injector to determine which services need to be injected into the function when the
+ * function is invoked. There are three ways in which the function can be annotated with the needed
+ * dependencies.
+ *
+ * # Argument names
+ *
+ * The simplest form is to extract the dependencies from the arguments of the function. This is done
+ * by converting the function into a string using `toString()` method and extracting the argument
+ * names.
+ * ```js
+ * // Given
+ * function MyController($scope, $route) {
+ * // ...
+ * }
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * ```
+ *
+ * You can disallow this method by using strict injection mode.
+ *
+ * This method does not work with code minification / obfuscation. For this reason the following
+ * annotation strategies are supported.
+ *
+ * # The `$inject` property
+ *
+ * If a function has an `$inject` property and its value is an array of strings, then the strings
+ * represent names of services to be injected into the function.
+ * ```js
+ * // Given
+ * var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ * // ...
+ * }
+ * // Define function dependencies
+ * MyController['$inject'] = ['$scope', '$route'];
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * ```
+ *
+ * # The array notation
+ *
+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property
+ * is very inconvenient. In these situations using the array notation to specify the dependencies in
+ * a way that survives minification is a better choice:
+ *
+ * ```js
+ * // We wish to write this (not minification / obfuscation safe)
+ * injector.invoke(function($compile, $rootScope) {
+ * // ...
+ * });
+ *
+ * // We are forced to write break inlining
+ * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ * // ...
+ * };
+ * tmpFn.$inject = ['$compile', '$rootScope'];
+ * injector.invoke(tmpFn);
+ *
+ * // To better support inline function the inline annotation is supported
+ * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ * // ...
+ * }]);
+ *
+ * // Therefore
+ * expect(injector.annotate(
+ * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
+ * ).toEqual(['$compile', '$rootScope']);
+ * ```
+ *
+ * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
+ * be retrieved as described above.
+ *
+ * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
+ *
+ * @returns {Array.<string>} The names of the services which the function requires.
+ */
+
+
+
+
+/**
+ * @ngdoc service
+ * @name $provide
+ *
+ * @description
+ *
+ * The {@link auto.$provide $provide} service has a number of methods for registering components
+ * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
+ * {@link angular.Module}.
+ *
+ * An Angular **service** is a singleton object created by a **service factory**. These **service
+ * factories** are functions which, in turn, are created by a **service provider**.
+ * The **service providers** are constructor functions. When instantiated they must contain a
+ * property called `$get`, which holds the **service factory** function.
+ *
+ * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
+ * correct **service provider**, instantiating it and then calling its `$get` **service factory**
+ * function to get the instance of the **service**.
+ *
+ * Often services have no configuration options and there is no need to add methods to the service
+ * provider. The provider will be no more than a constructor function with a `$get` property. For
+ * these cases the {@link auto.$provide $provide} service has additional helper methods to register
+ * services without specifying a provider.
+ *
+ * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
+ * {@link auto.$injector $injector}
+ * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
+ * providers and services.
+ * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
+ * services, not providers.
+ * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
+ * that will be wrapped in a **service provider** object, whose `$get` property will contain the
+ * given factory function.
+ * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
+ * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
+ * a new object using the given constructor function.
+ *
+ * See the individual methods for more information and examples.
+ */
+
+/**
+ * @ngdoc method
+ * @name $provide#provider
+ * @description
+ *
+ * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
+ * are constructor functions, whose instances are responsible for "providing" a factory for a
+ * service.
+ *
+ * Service provider names start with the name of the service they provide followed by `Provider`.
+ * For example, the {@link ng.$log $log} service has a provider called
+ * {@link ng.$logProvider $logProvider}.
+ *
+ * Service provider objects can have additional methods which allow configuration of the provider
+ * and its service. Importantly, you can configure what kind of service is created by the `$get`
+ * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
+ * method {@link ng.$logProvider#debugEnabled debugEnabled}
+ * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
+ * console or not.
+ *
+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
+ 'Provider'` key.
+ * @param {(Object|function())} provider If the provider is:
+ *
+ * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
+ * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
+ * - `Constructor`: a new instance of the provider will be created using
+ * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
+ *
+ * @returns {Object} registered provider instance
+
+ * @example
+ *
+ * The following example shows how to create a simple event tracking service and register it using
+ * {@link auto.$provide#provider $provide.provider()}.
+ *
+ * ```js
+ * // Define the eventTracker provider
+ * function EventTrackerProvider() {
+ * var trackingUrl = '/track';
+ *
+ * // A provider method for configuring where the tracked events should been saved
+ * this.setTrackingUrl = function(url) {
+ * trackingUrl = url;
+ * };
+ *
+ * // The service factory function
+ * this.$get = ['$http', function($http) {
+ * var trackedEvents = {};
+ * return {
+ * // Call this to track an event
+ * event: function(event) {
+ * var count = trackedEvents[event] || 0;
+ * count += 1;
+ * trackedEvents[event] = count;
+ * return count;
+ * },
+ * // Call this to save the tracked events to the trackingUrl
+ * save: function() {
+ * $http.post(trackingUrl, trackedEvents);
+ * }
+ * };
+ * }];
+ * }
+ *
+ * describe('eventTracker', function() {
+ * var postSpy;
+ *
+ * beforeEach(module(function($provide) {
+ * // Register the eventTracker provider
+ * $provide.provider('eventTracker', EventTrackerProvider);
+ * }));
+ *
+ * beforeEach(module(function(eventTrackerProvider) {
+ * // Configure eventTracker provider
+ * eventTrackerProvider.setTrackingUrl('/custom-track');
+ * }));
+ *
+ * it('tracks events', inject(function(eventTracker) {
+ * expect(eventTracker.event('login')).toEqual(1);
+ * expect(eventTracker.event('login')).toEqual(2);
+ * }));
+ *
+ * it('saves to the tracking url', inject(function(eventTracker, $http) {
+ * postSpy = spyOn($http, 'post');
+ * eventTracker.event('login');
+ * eventTracker.save();
+ * expect(postSpy).toHaveBeenCalled();
+ * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ * }));
+ * });
+ * ```
+ */
+
+/**
+ * @ngdoc method
+ * @name $provide#factory
+ * @description
+ *
+ * Register a **service factory**, which will be called to return the service instance.
+ * This is short for registering a service where its provider consists of only a `$get` property,
+ * which is the given service factory function.
+ * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
+ * configure your service in a provider.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
+ * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service
+ * ```js
+ * $provide.factory('ping', ['$http', function($http) {
+ * return function ping() {
+ * return $http.send('/ping');
+ * };
+ * }]);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#service
+ * @description
+ *
+ * Register a **service constructor**, which will be invoked with `new` to create the service
+ * instance.
+ * This is short for registering a service where its provider's `$get` property is the service
+ * constructor function that will be used to instantiate the service instance.
+ *
+ * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
+ * as a type/class.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
+ * that will be instantiated.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service using
+ * {@link auto.$provide#service $provide.service(class)}.
+ * ```js
+ * var Ping = function($http) {
+ * this.$http = $http;
+ * };
+ *
+ * Ping.$inject = ['$http'];
+ *
+ * Ping.prototype.send = function() {
+ * return this.$http.get('/ping');
+ * };
+ * $provide.service('ping', Ping);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping.send();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#value
+ * @description
+ *
+ * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
+ * number, an array, an object or a function. This is short for registering a service where its
+ * provider's `$get` property is a factory function that takes no arguments and returns the **value
+ * service**.
+ *
+ * Value services are similar to constant services, except that they cannot be injected into a
+ * module configuration function (see {@link angular.Module#config}) but they can be overridden by
+ * an Angular
+ * {@link auto.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the instance.
+ * @param {*} value The value.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here are some examples of creating value services.
+ * ```js
+ * $provide.value('ADMIN_USER', 'admin');
+ *
+ * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *
+ * $provide.value('halfOf', function(value) {
+ * return value / 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#constant
+ * @description
+ *
+ * Register a **constant service**, such as a string, a number, an array, an object or a function,
+ * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
+ * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
+ * be overridden by an Angular {@link auto.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the constant.
+ * @param {*} value The constant value.
+ * @returns {Object} registered instance
+ *
+ * @example
+ * Here a some examples of creating constants:
+ * ```js
+ * $provide.constant('SHARD_HEIGHT', 306);
+ *
+ * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *
+ * $provide.constant('double', function(value) {
+ * return value * 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#decorator
+ * @description
+ *
+ * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
+ * intercepts the creation of a service, allowing it to override or modify the behaviour of the
+ * service. The object returned by the decorator may be the original service, or a new service
+ * object which replaces or wraps and delegates to the original service.
+ *
+ * @param {string} name The name of the service to decorate.
+ * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance. The function is called using
+ * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
+ * Local injection arguments:
+ *
+ * * `$delegate` - The original service instance, which can be monkey patched, configured,
+ * decorated or delegated to.
+ *
+ * @example
+ * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
+ * calls to {@link ng.$log#error $log.warn()}.
+ * ```js
+ * $provide.decorator('$log', ['$delegate', function($delegate) {
+ * $delegate.warn = $delegate.error;
+ * return $delegate;
+ * }]);
+ * ```
+ */
+
+
+function createInjector(modulesToLoad, strictDi) {
+ strictDi = (strictDi === true);
+ var INSTANTIATING = {},
+ providerSuffix = 'Provider',
+ path = [],
+ loadedModules = new HashMap([], true),
+ providerCache = {
+ $provide: {
+ provider: supportObject(provider),
+ factory: supportObject(factory),
+ service: supportObject(service),
+ value: supportObject(value),
+ constant: supportObject(constant),
+ decorator: decorator
+ }
+ },
+ providerInjector = (providerCache.$injector =
+ createInternalInjector(providerCache, function(serviceName, caller) {
+ if (angular.isString(caller)) {
+ path.push(caller);
+ }
+ throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
+ })),
+ instanceCache = {},
+ instanceInjector = (instanceCache.$injector =
+ createInternalInjector(instanceCache, function(serviceName, caller) {
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
+ }));
+
+
+ forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
+
+ return instanceInjector;
+
+ ////////////////////////////////////
+ // $provider
+ ////////////////////////////////////
+
+ function supportObject(delegate) {
+ return function(key, value) {
+ if (isObject(key)) {
+ forEach(key, reverseParams(delegate));
+ } else {
+ return delegate(key, value);
+ }
+ };
+ }
+
+ function provider(name, provider_) {
+ assertNotHasOwnProperty(name, 'service');
+ if (isFunction(provider_) || isArray(provider_)) {
+ provider_ = providerInjector.instantiate(provider_);
+ }
+ if (!provider_.$get) {
+ throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
+ }
+ return providerCache[name + providerSuffix] = provider_;
+ }
+
+ function enforceReturnValue(name, factory) {
+ return function enforcedReturnValue() {
+ var result = instanceInjector.invoke(factory, this);
+ if (isUndefined(result)) {
+ throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
+ }
+ return result;
+ };
+ }
+
+ function factory(name, factoryFn, enforce) {
+ return provider(name, {
+ $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
+ });
+ }
+
+ function service(name, constructor) {
+ return factory(name, ['$injector', function($injector) {
+ return $injector.instantiate(constructor);
+ }]);
+ }
+
+ function value(name, val) { return factory(name, valueFn(val), false); }
+
+ function constant(name, value) {
+ assertNotHasOwnProperty(name, 'constant');
+ providerCache[name] = value;
+ instanceCache[name] = value;
+ }
+
+ function decorator(serviceName, decorFn) {
+ var origProvider = providerInjector.get(serviceName + providerSuffix),
+ orig$get = origProvider.$get;
+
+ origProvider.$get = function() {
+ var origInstance = instanceInjector.invoke(orig$get, origProvider);
+ return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
+ };
+ }
+
+ ////////////////////////////////////
+ // Module Loading
+ ////////////////////////////////////
+ function loadModules(modulesToLoad) {
+ var runBlocks = [], moduleFn;
+ forEach(modulesToLoad, function(module) {
+ if (loadedModules.get(module)) return;
+ loadedModules.put(module, true);
+
+ function runInvokeQueue(queue) {
+ var i, ii;
+ for (i = 0, ii = queue.length; i < ii; i++) {
+ var invokeArgs = queue[i],
+ provider = providerInjector.get(invokeArgs[0]);
+
+ provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+ }
+ }
+
+ try {
+ if (isString(module)) {
+ moduleFn = angularModule(module);
+ runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+ runInvokeQueue(moduleFn._invokeQueue);
+ runInvokeQueue(moduleFn._configBlocks);
+ } else if (isFunction(module)) {
+ runBlocks.push(providerInjector.invoke(module));
+ } else if (isArray(module)) {
+ runBlocks.push(providerInjector.invoke(module));
+ } else {
+ assertArgFn(module, 'module');
+ }
+ } catch (e) {
+ if (isArray(module)) {
+ module = module[module.length - 1];
+ }
+ if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
+ // Safari & FF's stack traces don't contain error.message content
+ // unlike those of Chrome and IE
+ // So if stack doesn't contain message, we create a new string that contains both.
+ // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
+ /* jshint -W022 */
+ e = e.message + '\n' + e.stack;
+ }
+ throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
+ module, e.stack || e.message || e);
+ }
+ });
+ return runBlocks;
+ }
+
+ ////////////////////////////////////
+ // internal Injector
+ ////////////////////////////////////
+
+ function createInternalInjector(cache, factory) {
+
+ function getService(serviceName, caller) {
+ if (cache.hasOwnProperty(serviceName)) {
+ if (cache[serviceName] === INSTANTIATING) {
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
+ serviceName + ' <- ' + path.join(' <- '));
+ }
+ return cache[serviceName];
+ } else {
+ try {
+ path.unshift(serviceName);
+ cache[serviceName] = INSTANTIATING;
+ return cache[serviceName] = factory(serviceName, caller);
+ } catch (err) {
+ if (cache[serviceName] === INSTANTIATING) {
+ delete cache[serviceName];
+ }
+ throw err;
+ } finally {
+ path.shift();
+ }
+ }
+ }
+
+ function invoke(fn, self, locals, serviceName) {
+ if (typeof locals === 'string') {
+ serviceName = locals;
+ locals = null;
+ }
+
+ var args = [],
+ $inject = createInjector.$$annotate(fn, strictDi, serviceName),
+ length, i,
+ key;
+
+ for (i = 0, length = $inject.length; i < length; i++) {
+ key = $inject[i];
+ if (typeof key !== 'string') {
+ throw $injectorMinErr('itkn',
+ 'Incorrect injection token! Expected service name as string, got {0}', key);
+ }
+ args.push(
+ locals && locals.hasOwnProperty(key)
+ ? locals[key]
+ : getService(key, serviceName)
+ );
+ }
+ if (isArray(fn)) {
+ fn = fn[length];
+ }
+
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
+ }
+
+ function instantiate(Type, locals, serviceName) {
+ // Check if Type is annotated and use just the given function at n-1 as parameter
+ // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
+ // Object creation: http://jsperf.com/create-constructor/2
+ var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
+ var returnedValue = invoke(Type, instance, locals, serviceName);
+
+ return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
+ }
+
+ return {
+ invoke: invoke,
+ instantiate: instantiate,
+ get: getService,
+ annotate: createInjector.$$annotate,
+ has: function(name) {
+ return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
+ }
+ };
+ }
+}
+
+createInjector.$$annotate = annotate;
+
+/**
+ * @ngdoc provider
+ * @name $anchorScrollProvider
+ *
+ * @description
+ * Use `$anchorScrollProvider` to disable automatic scrolling whenever
+ * {@link ng.$location#hash $location.hash()} changes.
+ */
+function $AnchorScrollProvider() {
+
+ var autoScrollingEnabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $anchorScrollProvider#disableAutoScrolling
+ *
+ * @description
+ * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
+ * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
+ * Use this method to disable automatic scrolling.
+ *
+ * If automatic scrolling is disabled, one must explicitly call
+ * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
+ * current hash.
+ */
+ this.disableAutoScrolling = function() {
+ autoScrollingEnabled = false;
+ };
+
+ /**
+ * @ngdoc service
+ * @name $anchorScroll
+ * @kind function
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and
+ * scrolls to the related element, according to the rules specified in the
+ * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
+ *
+ * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
+ * match any anchor whenever it changes. This can be disabled by calling
+ * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
+ *
+ * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
+ * vertical scroll-offset (either fixed or dynamic).
+ *
+ * @property {(number|function|jqLite)} yOffset
+ * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
+ * positioned elements at the top of the page, such as navbars, headers etc.
+ *
+ * `yOffset` can be specified in various ways:
+ * - **number**: A fixed number of pixels to be used as offset.<br /><br />
+ * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
+ * a number representing the offset (in pixels).<br /><br />
+ * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
+ * the top of the page to the element's bottom will be used as offset.<br />
+ * **Note**: The element will be taken into account only as long as its `position` is set to
+ * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
+ * their height and/or positioning according to the viewport's size.
+ *
+ * <br />
+ * <div class="alert alert-warning">
+ * In order for `yOffset` to work properly, scrolling should take place on the document's root and
+ * not some child element.
+ * </div>
+ *
+ * @example
+ <example module="anchorScrollExample">
+ <file name="index.html">
+ <div id="scrollArea" ng-controller="ScrollController">
+ <a ng-click="gotoBottom()">Go to bottom</a>
+ <a id="bottom"></a> You're at the bottom!
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollExample', [])
+ .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
+ function ($scope, $location, $anchorScroll) {
+ $scope.gotoBottom = function() {
+ // set the location.hash to the id of
+ // the element you wish to scroll to.
+ $location.hash('bottom');
+
+ // call $anchorScroll()
+ $anchorScroll();
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ #scrollArea {
+ height: 280px;
+ overflow: auto;
+ }
+
+ #bottom {
+ display: block;
+ margin-top: 2000px;
+ }
+ </file>
+ </example>
+ *
+ * <hr />
+ * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
+ * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
+ *
+ * @example
+ <example module="anchorScrollOffsetExample">
+ <file name="index.html">
+ <div class="fixed-header" ng-controller="headerCtrl">
+ <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
+ Go to anchor {{x}}
+ </a>
+ </div>
+ <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
+ Anchor {{x}} of 5
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollOffsetExample', [])
+ .run(['$anchorScroll', function($anchorScroll) {
+ $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
+ }])
+ .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
+ function ($anchorScroll, $location, $scope) {
+ $scope.gotoAnchor = function(x) {
+ var newHash = 'anchor' + x;
+ if ($location.hash() !== newHash) {
+ // set the $location.hash to `newHash` and
+ // $anchorScroll will automatically scroll to it
+ $location.hash('anchor' + x);
+ } else {
+ // call $anchorScroll() explicitly,
+ // since $location.hash hasn't changed
+ $anchorScroll();
+ }
+ };
+ }
+ ]);
+ </file>
+ <file name="style.css">
+ body {
+ padding-top: 50px;
+ }
+
+ .anchor {
+ border: 2px dashed DarkOrchid;
+ padding: 10px 10px 200px 10px;
+ }
+
+ .fixed-header {
+ background-color: rgba(0, 0, 0, 0.2);
+ height: 50px;
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ }
+
+ .fixed-header > a {
+ display: inline-block;
+ margin: 5px 15px;
+ }
+ </file>
+ </example>
+ */
+ this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
+ var document = $window.document;
+
+ // Helper function to get first anchor from a NodeList
+ // (using `Array#some()` instead of `angular#forEach()` since it's more performant
+ // and working in all supported browsers.)
+ function getFirstAnchor(list) {
+ var result = null;
+ Array.prototype.some.call(list, function(element) {
+ if (nodeName_(element) === 'a') {
+ result = element;
+ return true;
+ }
+ });
+ return result;
+ }
+
+ function getYOffset() {
+
+ var offset = scroll.yOffset;
+
+ if (isFunction(offset)) {
+ offset = offset();
+ } else if (isElement(offset)) {
+ var elem = offset[0];
+ var style = $window.getComputedStyle(elem);
+ if (style.position !== 'fixed') {
+ offset = 0;
+ } else {
+ offset = elem.getBoundingClientRect().bottom;
+ }
+ } else if (!isNumber(offset)) {
+ offset = 0;
+ }
+
+ return offset;
+ }
+
+ function scrollTo(elem) {
+ if (elem) {
+ elem.scrollIntoView();
+
+ var offset = getYOffset();
+
+ if (offset) {
+ // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
+ // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
+ // top of the viewport.
+ //
+ // IF the number of pixels from the top of `elem` to the end of the page's content is less
+ // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
+ // way down the page.
+ //
+ // This is often the case for elements near the bottom of the page.
+ //
+ // In such cases we do not need to scroll the whole `offset` up, just the difference between
+ // the top of the element and the offset, which is enough to align the top of `elem` at the
+ // desired position.
+ var elemTop = elem.getBoundingClientRect().top;
+ $window.scrollBy(0, elemTop - offset);
+ }
+ } else {
+ $window.scrollTo(0, 0);
+ }
+ }
+
+ function scroll() {
+ var hash = $location.hash(), elm;
+
+ // empty hash, scroll to the top of the page
+ if (!hash) scrollTo(null);
+
+ // element with given id
+ else if ((elm = document.getElementById(hash))) scrollTo(elm);
+
+ // first anchor with given name :-D
+ else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
+
+ // no element and hash == 'top', scroll to the top of the page
+ else if (hash === 'top') scrollTo(null);
+ }
+
+ // does not scroll when user clicks on anchor link that is currently on
+ // (no url change, no $location.hash() change), browser native does scroll
+ if (autoScrollingEnabled) {
+ $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
+ function autoScrollWatchAction(newVal, oldVal) {
+ // skip the initial scroll if $location.hash is empty
+ if (newVal === oldVal && newVal === '') return;
+
+ jqLiteDocumentLoaded(function() {
+ $rootScope.$evalAsync(scroll);
+ });
+ });
+ }
+
+ return scroll;
+ }];
+}
+
+var $animateMinErr = minErr('$animate');
+
+/**
+ * @ngdoc provider
+ * @name $animateProvider
+ *
+ * @description
+ * Default implementation of $animate that doesn't perform any animations, instead just
+ * synchronously performs DOM
+ * updates and calls done() callbacks.
+ *
+ * In order to enable animations the ngAnimate module has to be loaded.
+ *
+ * To see the functional implementation check out src/ngAnimate/animate.js
+ */
+var $AnimateProvider = ['$provide', function($provide) {
+
+
+ this.$$selectors = {};
+
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#register
+ *
+ * @description
+ * Registers a new injectable animation factory function. The factory function produces the
+ * animation object which contains callback functions for each event that is expected to be
+ * animated.
+ *
+ * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
+ * must be called once the element animation is complete. If a function is returned then the
+ * animation service will use this function to cancel the animation whenever a cancel event is
+ * triggered.
+ *
+ *
+ * ```js
+ * return {
+ * eventFn : function(element, done) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function cancellationFunction() {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ * ```
+ *
+ * @param {string} name The name of the animation.
+ * @param {Function} factory The factory function that will be executed to return the animation
+ * object.
+ */
+ this.register = function(name, factory) {
+ var key = name + '-animation';
+ if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
+ "Expecting class selector starting with '.' got '{0}'.", name);
+ this.$$selectors[name.substr(1)] = key;
+ $provide.factory(key, factory);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#classNameFilter
+ *
+ * @description
+ * Sets and/or returns the CSS class regular expression that is checked when performing
+ * an animation. Upon bootstrap the classNameFilter value is not set at all and will
+ * therefore enable $animate to attempt to perform an animation on any element.
+ * When setting the classNameFilter value, animations will only be performed on elements
+ * that successfully match the filter expression. This in turn can boost performance
+ * for low-powered devices as well as applications containing a lot of structural operations.
+ * @param {RegExp=} expression The className expression which will be checked against all animations
+ * @return {RegExp} The current CSS className expression value. If null then there is no expression value
+ */
+ this.classNameFilter = function(expression) {
+ if (arguments.length === 1) {
+ this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
+ }
+ return this.$$classNameFilter;
+ };
+
+ this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {
+
+ var currentDefer;
+
+ function runAnimationPostDigest(fn) {
+ var cancelFn, defer = $$q.defer();
+ defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {
+ cancelFn && cancelFn();
+ };
+
+ $rootScope.$$postDigest(function ngAnimatePostDigest() {
+ cancelFn = fn(function ngAnimateNotifyComplete() {
+ defer.resolve();
+ });
+ });
+
+ return defer.promise;
+ }
+
+ function resolveElementClasses(element, classes) {
+ var toAdd = [], toRemove = [];
+
+ var hasClasses = createMap();
+ forEach((element.attr('class') || '').split(/\s+/), function(className) {
+ hasClasses[className] = true;
+ });
+
+ forEach(classes, function(status, className) {
+ var hasClass = hasClasses[className];
+
+ // If the most recent class manipulation (via $animate) was to remove the class, and the
+ // element currently has the class, the class is scheduled for removal. Otherwise, if
+ // the most recent class manipulation (via $animate) was to add the class, and the
+ // element does not currently have the class, the class is scheduled to be added.
+ if (status === false && hasClass) {
+ toRemove.push(className);
+ } else if (status === true && !hasClass) {
+ toAdd.push(className);
+ }
+ });
+
+ return (toAdd.length + toRemove.length) > 0 &&
+ [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];
+ }
+
+ function cachedClassManipulation(cache, classes, op) {
+ for (var i=0, ii = classes.length; i < ii; ++i) {
+ var className = classes[i];
+ cache[className] = op;
+ }
+ }
+
+ function asyncPromise() {
+ // only serve one instance of a promise in order to save CPU cycles
+ if (!currentDefer) {
+ currentDefer = $$q.defer();
+ $$asyncCallback(function() {
+ currentDefer.resolve();
+ currentDefer = null;
+ });
+ }
+ return currentDefer.promise;
+ }
+
+ function applyStyles(element, options) {
+ if (angular.isObject(options)) {
+ var styles = extend(options.from || {}, options.to || {});
+ element.css(styles);
+ }
+ }
+
+ /**
+ *
+ * @ngdoc service
+ * @name $animate
+ * @description The $animate service provides rudimentary DOM manipulation functions to
+ * insert, remove and move elements within the DOM, as well as adding and removing classes.
+ * This service is the core service used by the ngAnimate $animator service which provides
+ * high-level animation hooks for CSS and JavaScript.
+ *
+ * $animate is available in the AngularJS core, however, the ngAnimate module must be included
+ * to enable full out animation support. Otherwise, $animate will only perform simple DOM
+ * manipulation operations.
+ *
+ * To learn more about enabling animation support, click here to visit the {@link ngAnimate
+ * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
+ * page}.
+ */
+ return {
+ animate: function(element, from, to) {
+ applyStyles(element, { from: from, to: to });
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#enter
+ * @kind function
+ * @description Inserts the element into the DOM either after the `after` element or
+ * as the first child within the `parent` element. When the function is called a promise
+ * is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will be inserted into the DOM
+ * @param {DOMElement} parent the parent element which will append the element as
+ * a child (if the after element is not present)
+ * @param {DOMElement} after the sibling element which will append the element
+ * after itself
+ * @param {object=} options an optional collection of styles that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ enter: function(element, parent, after, options) {
+ applyStyles(element, options);
+ after ? after.after(element)
+ : parent.prepend(element);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#leave
+ * @kind function
+ * @description Removes the element from the DOM. When the function is called a promise
+ * is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will be removed from the DOM
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ leave: function(element, options) {
+ applyStyles(element, options);
+ element.remove();
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#move
+ * @kind function
+ * @description Moves the position of the provided element within the DOM to be placed
+ * either after the `after` element or inside of the `parent` element. When the function
+ * is called a promise is returned that will be resolved at a later time.
+ *
+ * @param {DOMElement} element the element which will be moved around within the
+ * DOM
+ * @param {DOMElement} parent the parent element where the element will be
+ * inserted into (if the after element is not present)
+ * @param {DOMElement} after the sibling element where the element will be
+ * positioned next to
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ move: function(element, parent, after, options) {
+ // Do not remove element before insert. Removing will cause data associated with the
+ // element to be dropped. Insert will implicitly do the remove.
+ return this.enter(element, parent, after, options);
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#addClass
+ * @kind function
+ * @description Adds the provided className CSS class value to the provided element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will have the className value
+ * added to it
+ * @param {string} className the CSS class which will be added to the element
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ addClass: function(element, className, options) {
+ return this.setClass(element, className, [], options);
+ },
+
+ $$addClassImmediately: function(element, className, options) {
+ element = jqLite(element);
+ className = !isString(className)
+ ? (isArray(className) ? className.join(' ') : '')
+ : className;
+ forEach(element, function(element) {
+ jqLiteAddClass(element, className);
+ });
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#removeClass
+ * @kind function
+ * @description Removes the provided className CSS class value from the provided element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will have the className value
+ * removed from it
+ * @param {string} className the CSS class which will be removed from the element
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ removeClass: function(element, className, options) {
+ return this.setClass(element, [], className, options);
+ },
+
+ $$removeClassImmediately: function(element, className, options) {
+ element = jqLite(element);
+ className = !isString(className)
+ ? (isArray(className) ? className.join(' ') : '')
+ : className;
+ forEach(element, function(element) {
+ jqLiteRemoveClass(element, className);
+ });
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#setClass
+ * @kind function
+ * @description Adds and/or removes the given CSS classes to and from the element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will have its CSS classes changed
+ * removed from it
+ * @param {string} add the CSS classes which will be added to the element
+ * @param {string} remove the CSS class which will be removed from the element
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ setClass: function(element, add, remove, options) {
+ var self = this;
+ var STORAGE_KEY = '$$animateClasses';
+ var createdCache = false;
+ element = jqLite(element);
+
+ var cache = element.data(STORAGE_KEY);
+ if (!cache) {
+ cache = {
+ classes: {},
+ options: options
+ };
+ createdCache = true;
+ } else if (options && cache.options) {
+ cache.options = angular.extend(cache.options || {}, options);
+ }
+
+ var classes = cache.classes;
+
+ add = isArray(add) ? add : add.split(' ');
+ remove = isArray(remove) ? remove : remove.split(' ');
+ cachedClassManipulation(classes, add, true);
+ cachedClassManipulation(classes, remove, false);
+
+ if (createdCache) {
+ cache.promise = runAnimationPostDigest(function(done) {
+ var cache = element.data(STORAGE_KEY);
+ element.removeData(STORAGE_KEY);
+
+ // in the event that the element is removed before postDigest
+ // is run then the cache will be undefined and there will be
+ // no need anymore to add or remove and of the element classes
+ if (cache) {
+ var classes = resolveElementClasses(element, cache.classes);
+ if (classes) {
+ self.$$setClassImmediately(element, classes[0], classes[1], cache.options);
+ }
+ }
+
+ done();
+ });
+ element.data(STORAGE_KEY, cache);
+ }
+
+ return cache.promise;
+ },
+
+ $$setClassImmediately: function(element, add, remove, options) {
+ add && this.$$addClassImmediately(element, add);
+ remove && this.$$removeClassImmediately(element, remove);
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ enabled: noop,
+ cancel: noop
+ };
+ }];
+}];
+
+function $$AsyncCallbackProvider() {
+ this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
+ return $$rAF.supported
+ ? function(fn) { return $$rAF(fn); }
+ : function(fn) {
+ return $timeout(fn, 0, false);
+ };
+ }];
+}
+
+/* global stripHash: true */
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name $browser
+ * @requires $log
+ * @description
+ * This object has two goals:
+ *
+ * - hide all the global state in the browser caused by the window object
+ * - abstract away all the browser specific features and inconsistencies
+ *
+ * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
+ * service, which can be used for convenient testing of the application without the interaction with
+ * the real browser apis.
+ */
+/**
+ * @param {object} window The global window object.
+ * @param {object} document jQuery wrapped document.
+ * @param {object} $log window.console or an object with the same interface.
+ * @param {object} $sniffer $sniffer service
+ */
+function Browser(window, document, $log, $sniffer) {
+ var self = this,
+ rawDocument = document[0],
+ location = window.location,
+ history = window.history,
+ setTimeout = window.setTimeout,
+ clearTimeout = window.clearTimeout,
+ pendingDeferIds = {};
+
+ self.isMock = false;
+
+ var outstandingRequestCount = 0;
+ var outstandingRequestCallbacks = [];
+
+ // TODO(vojta): remove this temporary api
+ self.$$completeOutstandingRequest = completeOutstandingRequest;
+ self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
+
+ /**
+ * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
+ * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
+ */
+ function completeOutstandingRequest(fn) {
+ try {
+ fn.apply(null, sliceArgs(arguments, 1));
+ } finally {
+ outstandingRequestCount--;
+ if (outstandingRequestCount === 0) {
+ while (outstandingRequestCallbacks.length) {
+ try {
+ outstandingRequestCallbacks.pop()();
+ } catch (e) {
+ $log.error(e);
+ }
+ }
+ }
+ }
+ }
+
+ function getHash(url) {
+ var index = url.indexOf('#');
+ return index === -1 ? '' : url.substr(index);
+ }
+
+ /**
+ * @private
+ * Note: this method is used only by scenario runner
+ * TODO(vojta): prefix this method with $$ ?
+ * @param {function()} callback Function that will be called when no outstanding request
+ */
+ self.notifyWhenNoOutstandingRequests = function(callback) {
+ // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
+ // at some deterministic time in respect to the test runner's actions. Leaving things up to the
+ // regular poller would result in flaky tests.
+ forEach(pollFns, function(pollFn) { pollFn(); });
+
+ if (outstandingRequestCount === 0) {
+ callback();
+ } else {
+ outstandingRequestCallbacks.push(callback);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////
+ // Poll Watcher API
+ //////////////////////////////////////////////////////////////
+ var pollFns = [],
+ pollTimeout;
+
+ /**
+ * @name $browser#addPollFn
+ *
+ * @param {function()} fn Poll function to add
+ *
+ * @description
+ * Adds a function to the list of functions that poller periodically executes,
+ * and starts polling if not started yet.
+ *
+ * @returns {function()} the added function
+ */
+ self.addPollFn = function(fn) {
+ if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
+ pollFns.push(fn);
+ return fn;
+ };
+
+ /**
+ * @param {number} interval How often should browser call poll functions (ms)
+ * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
+ *
+ * @description
+ * Configures the poller to run in the specified intervals, using the specified
+ * setTimeout fn and kicks it off.
+ */
+ function startPoller(interval, setTimeout) {
+ (function check() {
+ forEach(pollFns, function(pollFn) { pollFn(); });
+ pollTimeout = setTimeout(check, interval);
+ })();
+ }
+
+ //////////////////////////////////////////////////////////////
+ // URL API
+ //////////////////////////////////////////////////////////////
+
+ var cachedState, lastHistoryState,
+ lastBrowserUrl = location.href,
+ baseElement = document.find('base'),
+ reloadLocation = null;
+
+ cacheState();
+ lastHistoryState = cachedState;
+
+ /**
+ * @name $browser#url
+ *
+ * @description
+ * GETTER:
+ * Without any argument, this method just returns current value of location.href.
+ *
+ * SETTER:
+ * With at least one argument, this method sets url to new value.
+ * If html5 history api supported, pushState/replaceState is used, otherwise
+ * location.href/location.replace is used.
+ * Returns its own instance to allow chaining
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@link ng.$location $location service} to change url.
+ *
+ * @param {string} url New url (when used as setter)
+ * @param {boolean=} replace Should new url replace current history record?
+ * @param {object=} state object to use with pushState/replaceState
+ */
+ self.url = function(url, replace, state) {
+ // In modern browsers `history.state` is `null` by default; treating it separately
+ // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
+ // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
+ if (isUndefined(state)) {
+ state = null;
+ }
+
+ // Android Browser BFCache causes location, history reference to become stale.
+ if (location !== window.location) location = window.location;
+ if (history !== window.history) history = window.history;
+
+ // setter
+ if (url) {
+ var sameState = lastHistoryState === state;
+
+ // Don't change anything if previous and current URLs and states match. This also prevents
+ // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
+ // See https://github.com/angular/angular.js/commit/ffb2701
+ if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
+ return self;
+ }
+ var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
+ lastBrowserUrl = url;
+ lastHistoryState = state;
+ // Don't use history API if only the hash changed
+ // due to a bug in IE10/IE11 which leads
+ // to not firing a `hashchange` nor `popstate` event
+ // in some cases (see #9143).
+ if ($sniffer.history && (!sameBase || !sameState)) {
+ history[replace ? 'replaceState' : 'pushState'](state, '', url);
+ cacheState();
+ // Do the assignment again so that those two variables are referentially identical.
+ lastHistoryState = cachedState;
+ } else {
+ if (!sameBase || reloadLocation) {
+ reloadLocation = url;
+ }
+ if (replace) {
+ location.replace(url);
+ } else if (!sameBase) {
+ location.href = url;
+ } else {
+ location.hash = getHash(url);
+ }
+ }
+ return self;
+ // getter
+ } else {
+ // - reloadLocation is needed as browsers don't allow to read out
+ // the new location.href if a reload happened.
+ // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
+ return reloadLocation || location.href.replace(/%27/g,"'");
+ }
+ };
+
+ /**
+ * @name $browser#state
+ *
+ * @description
+ * This method is a getter.
+ *
+ * Return history.state or null if history.state is undefined.
+ *
+ * @returns {object} state
+ */
+ self.state = function() {
+ return cachedState;
+ };
+
+ var urlChangeListeners = [],
+ urlChangeInit = false;
+
+ function cacheStateAndFireUrlChange() {
+ cacheState();
+ fireUrlChange();
+ }
+
+ function getCurrentState() {
+ try {
+ return history.state;
+ } catch (e) {
+ // MSIE can reportedly throw when there is no state (UNCONFIRMED).
+ }
+ }
+
+ // This variable should be used *only* inside the cacheState function.
+ var lastCachedState = null;
+ function cacheState() {
+ // This should be the only place in $browser where `history.state` is read.
+ cachedState = getCurrentState();
+ cachedState = isUndefined(cachedState) ? null : cachedState;
+
+ // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
+ if (equals(cachedState, lastCachedState)) {
+ cachedState = lastCachedState;
+ }
+ lastCachedState = cachedState;
+ }
+
+ function fireUrlChange() {
+ if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
+ return;
+ }
+
+ lastBrowserUrl = self.url();
+ lastHistoryState = cachedState;
+ forEach(urlChangeListeners, function(listener) {
+ listener(self.url(), cachedState);
+ });
+ }
+
+ /**
+ * @name $browser#onUrlChange
+ *
+ * @description
+ * Register callback function that will be called, when url changes.
+ *
+ * It's only called when the url is changed from outside of angular:
+ * - user types different url into address bar
+ * - user clicks on history (forward/back) button
+ * - user clicks on a link
+ *
+ * It's not called when url is changed by $browser.url() method
+ *
+ * The listener gets called with new url as parameter.
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@link ng.$location $location service} to monitor url changes in angular apps.
+ *
+ * @param {function(string)} listener Listener function to be called when url changes.
+ * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
+ */
+ self.onUrlChange = function(callback) {
+ // TODO(vojta): refactor to use node's syntax for events
+ if (!urlChangeInit) {
+ // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
+ // don't fire popstate when user change the address bar and don't fire hashchange when url
+ // changed by push/replaceState
+
+ // html5 history api - popstate event
+ if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
+ // hashchange event
+ jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
+
+ urlChangeInit = true;
+ }
+
+ urlChangeListeners.push(callback);
+ return callback;
+ };
+
+ /**
+ * Checks whether the url has changed outside of Angular.
+ * Needs to be exported to be able to check for changes that have been done in sync,
+ * as hashchange/popstate events fire in async.
+ */
+ self.$$checkUrlChange = fireUrlChange;
+
+ //////////////////////////////////////////////////////////////
+ // Misc API
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * @name $browser#baseHref
+ *
+ * @description
+ * Returns current <base href>
+ * (always relative - without domain)
+ *
+ * @returns {string} The current base href
+ */
+ self.baseHref = function() {
+ var href = baseElement.attr('href');
+ return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
+ };
+
+ //////////////////////////////////////////////////////////////
+ // Cookies API
+ //////////////////////////////////////////////////////////////
+ var lastCookies = {};
+ var lastCookieString = '';
+ var cookiePath = self.baseHref();
+
+ function safeDecodeURIComponent(str) {
+ try {
+ return decodeURIComponent(str);
+ } catch (e) {
+ return str;
+ }
+ }
+
+ /**
+ * @name $browser#cookies
+ *
+ * @param {string=} name Cookie name
+ * @param {string=} value Cookie value
+ *
+ * @description
+ * The cookies method provides a 'private' low level access to browser cookies.
+ * It is not meant to be used directly, use the $cookie service instead.
+ *
+ * The return values vary depending on the arguments that the method was called with as follows:
+ *
+ * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
+ * it
+ * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
+ * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
+ * way)
+ *
+ * @returns {Object} Hash of all cookies (if called without any parameter)
+ */
+ self.cookies = function(name, value) {
+ var cookieLength, cookieArray, cookie, i, index;
+
+ if (name) {
+ if (value === undefined) {
+ rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath +
+ ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
+ } else {
+ if (isString(value)) {
+ cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +
+ ';path=' + cookiePath).length + 1;
+
+ // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
+ // - 300 cookies
+ // - 20 cookies per unique domain
+ // - 4096 bytes per cookie
+ if (cookieLength > 4096) {
+ $log.warn("Cookie '" + name +
+ "' possibly not set or overflowed because it was too large (" +
+ cookieLength + " > 4096 bytes)!");
+ }
+ }
+ }
+ } else {
+ if (rawDocument.cookie !== lastCookieString) {
+ lastCookieString = rawDocument.cookie;
+ cookieArray = lastCookieString.split("; ");
+ lastCookies = {};
+
+ for (i = 0; i < cookieArray.length; i++) {
+ cookie = cookieArray[i];
+ index = cookie.indexOf('=');
+ if (index > 0) { //ignore nameless cookies
+ name = safeDecodeURIComponent(cookie.substring(0, index));
+ // the first value that is seen for a cookie is the most
+ // specific one. values for the same cookie name that
+ // follow are for less specific paths.
+ if (lastCookies[name] === undefined) {
+ lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
+ }
+ }
+ }
+ }
+ return lastCookies;
+ }
+ };
+
+
+ /**
+ * @name $browser#defer
+ * @param {function()} fn A function, who's execution should be deferred.
+ * @param {number=} [delay=0] of milliseconds to defer the function execution.
+ * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
+ *
+ * @description
+ * Executes a fn asynchronously via `setTimeout(fn, delay)`.
+ *
+ * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
+ * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
+ * via `$browser.defer.flush()`.
+ *
+ */
+ self.defer = function(fn, delay) {
+ var timeoutId;
+ outstandingRequestCount++;
+ timeoutId = setTimeout(function() {
+ delete pendingDeferIds[timeoutId];
+ completeOutstandingRequest(fn);
+ }, delay || 0);
+ pendingDeferIds[timeoutId] = true;
+ return timeoutId;
+ };
+
+
+ /**
+ * @name $browser#defer.cancel
+ *
+ * @description
+ * Cancels a deferred task identified with `deferId`.
+ *
+ * @param {*} deferId Token returned by the `$browser.defer` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ self.defer.cancel = function(deferId) {
+ if (pendingDeferIds[deferId]) {
+ delete pendingDeferIds[deferId];
+ clearTimeout(deferId);
+ completeOutstandingRequest(noop);
+ return true;
+ }
+ return false;
+ };
+
+}
+
+function $BrowserProvider() {
+ this.$get = ['$window', '$log', '$sniffer', '$document',
+ function($window, $log, $sniffer, $document) {
+ return new Browser($window, $document, $log, $sniffer);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $cacheFactory
+ *
+ * @description
+ * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
+ * them.
+ *
+ * ```js
+ *
+ * var cache = $cacheFactory('cacheId');
+ * expect($cacheFactory.get('cacheId')).toBe(cache);
+ * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
+ *
+ * cache.put("key", "value");
+ * cache.put("another key", "another value");
+ *
+ * // We've specified no options on creation
+ * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ * ```
+ *
+ *
+ * @param {string} cacheId Name or id of the newly created cache.
+ * @param {object=} options Options object that specifies the cache behavior. Properties:
+ *
+ * - `{number=}` `capacity` — turns the cache into LRU cache.
+ *
+ * @returns {object} Newly created cache object with the following set of methods:
+ *
+ * - `{object}` `info()` — Returns id, size, and options of cache.
+ * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
+ * it.
+ * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
+ * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
+ * - `{void}` `removeAll()` — Removes all cached values.
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
+ *
+ * @example
+ <example module="cacheExampleApp">
+ <file name="index.html">
+ <div ng-controller="CacheController">
+ <input ng-model="newCacheKey" placeholder="Key">
+ <input ng-model="newCacheValue" placeholder="Value">
+ <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
+
+ <p ng-if="keys.length">Cached Values</p>
+ <div ng-repeat="key in keys">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="cache.get(key)"></b>
+ </div>
+
+ <p>Cache Info</p>
+ <div ng-repeat="(key, value) in cache.info()">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="value"></b>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cacheExampleApp', []).
+ controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
+ $scope.keys = [];
+ $scope.cache = $cacheFactory('cacheId');
+ $scope.put = function(key, value) {
+ if ($scope.cache.get(key) === undefined) {
+ $scope.keys.push(key);
+ }
+ $scope.cache.put(key, value === undefined ? null : value);
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ p {
+ margin: 10px 0 3px;
+ }
+ </file>
+ </example>
+ */
+function $CacheFactoryProvider() {
+
+ this.$get = function() {
+ var caches = {};
+
+ function cacheFactory(cacheId, options) {
+ if (cacheId in caches) {
+ throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
+ }
+
+ var size = 0,
+ stats = extend({}, options, {id: cacheId}),
+ data = {},
+ capacity = (options && options.capacity) || Number.MAX_VALUE,
+ lruHash = {},
+ freshEnd = null,
+ staleEnd = null;
+
+ /**
+ * @ngdoc type
+ * @name $cacheFactory.Cache
+ *
+ * @description
+ * A cache object used to store and retrieve data, primarily used by
+ * {@link $http $http} and the {@link ng.directive:script script} directive to cache
+ * templates and other data.
+ *
+ * ```js
+ * angular.module('superCache')
+ * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
+ * return $cacheFactory('super-cache');
+ * }]);
+ * ```
+ *
+ * Example test:
+ *
+ * ```js
+ * it('should behave like a cache', inject(function(superCache) {
+ * superCache.put('key', 'value');
+ * superCache.put('another key', 'another value');
+ *
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 2
+ * });
+ *
+ * superCache.remove('another key');
+ * expect(superCache.get('another key')).toBeUndefined();
+ *
+ * superCache.removeAll();
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 0
+ * });
+ * }));
+ * ```
+ */
+ return caches[cacheId] = {
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#put
+ * @kind function
+ *
+ * @description
+ * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
+ * retrieved later, and incrementing the size of the cache if the key was not already
+ * present in the cache. If behaving like an LRU cache, it will also remove stale
+ * entries from the set.
+ *
+ * It will not insert undefined values into the cache.
+ *
+ * @param {string} key the key under which the cached data is stored.
+ * @param {*} value the value to store alongside the key. If it is undefined, the key
+ * will not be stored.
+ * @returns {*} the value stored.
+ */
+ put: function(key, value) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
+
+ refresh(lruEntry);
+ }
+
+ if (isUndefined(value)) return;
+ if (!(key in data)) size++;
+ data[key] = value;
+
+ if (size > capacity) {
+ this.remove(staleEnd.key);
+ }
+
+ return value;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#get
+ * @kind function
+ *
+ * @description
+ * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the data to be retrieved
+ * @returns {*} the value stored.
+ */
+ get: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ refresh(lruEntry);
+ }
+
+ return data[key];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#remove
+ * @kind function
+ *
+ * @description
+ * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the entry to be removed
+ */
+ remove: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ if (lruEntry == freshEnd) freshEnd = lruEntry.p;
+ if (lruEntry == staleEnd) staleEnd = lruEntry.n;
+ link(lruEntry.n,lruEntry.p);
+
+ delete lruHash[key];
+ }
+
+ delete data[key];
+ size--;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#removeAll
+ * @kind function
+ *
+ * @description
+ * Clears the cache object of any entries.
+ */
+ removeAll: function() {
+ data = {};
+ size = 0;
+ lruHash = {};
+ freshEnd = staleEnd = null;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#destroy
+ * @kind function
+ *
+ * @description
+ * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
+ * removing it from the {@link $cacheFactory $cacheFactory} set.
+ */
+ destroy: function() {
+ data = null;
+ stats = null;
+ lruHash = null;
+ delete caches[cacheId];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#info
+ * @kind function
+ *
+ * @description
+ * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
+ *
+ * @returns {object} an object with the following properties:
+ * <ul>
+ * <li>**id**: the id of the cache instance</li>
+ * <li>**size**: the number of entries kept in the cache instance</li>
+ * <li>**...**: any additional properties from the options object when creating the
+ * cache.</li>
+ * </ul>
+ */
+ info: function() {
+ return extend({}, stats, {size: size});
+ }
+ };
+
+
+ /**
+ * makes the `entry` the freshEnd of the LRU linked list
+ */
+ function refresh(entry) {
+ if (entry != freshEnd) {
+ if (!staleEnd) {
+ staleEnd = entry;
+ } else if (staleEnd == entry) {
+ staleEnd = entry.n;
+ }
+
+ link(entry.n, entry.p);
+ link(entry, freshEnd);
+ freshEnd = entry;
+ freshEnd.n = null;
+ }
+ }
+
+
+ /**
+ * bidirectionally links two entries of the LRU linked list
+ */
+ function link(nextEntry, prevEntry) {
+ if (nextEntry != prevEntry) {
+ if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
+ if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory#info
+ *
+ * @description
+ * Get information about all the caches that have been created
+ *
+ * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
+ */
+ cacheFactory.info = function() {
+ var info = {};
+ forEach(caches, function(cache, cacheId) {
+ info[cacheId] = cache.info();
+ });
+ return info;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory#get
+ *
+ * @description
+ * Get access to a cache object by the `cacheId` used when it was created.
+ *
+ * @param {string} cacheId Name or id of a cache to access.
+ * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
+ */
+ cacheFactory.get = function(cacheId) {
+ return caches[cacheId];
+ };
+
+
+ return cacheFactory;
+ };
+}
+
+/**
+ * @ngdoc service
+ * @name $templateCache
+ *
+ * @description
+ * The first time a template is used, it is loaded in the template cache for quick retrieval. You
+ * can load templates directly into the cache in a `script` tag, or by consuming the
+ * `$templateCache` service directly.
+ *
+ * Adding via the `script` tag:
+ *
+ * ```html
+ * <script type="text/ng-template" id="templateId.html">
+ * <p>This is the content of the template</p>
+ * </script>
+ * ```
+ *
+ * **Note:** the `script` tag containing the template does not need to be included in the `head` of
+ * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
+ * element with ng-app attribute), otherwise the template will be ignored.
+ *
+ * Adding via the `$templateCache` service:
+ *
+ * ```js
+ * var myApp = angular.module('myApp', []);
+ * myApp.run(function($templateCache) {
+ * $templateCache.put('templateId.html', 'This is the content of the template');
+ * });
+ * ```
+ *
+ * To retrieve the template later, simply use it in your HTML:
+ * ```html
+ * <div ng-include=" 'templateId.html' "></div>
+ * ```
+ *
+ * or get it via Javascript:
+ * ```js
+ * $templateCache.get('templateId.html')
+ * ```
+ *
+ * See {@link ng.$cacheFactory $cacheFactory}.
+ *
+ */
+function $TemplateCacheProvider() {
+ this.$get = ['$cacheFactory', function($cacheFactory) {
+ return $cacheFactory('templates');
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
+ *
+ * DOM-related variables:
+ *
+ * - "node" - DOM Node
+ * - "element" - DOM Element or Node
+ * - "$node" or "$element" - jqLite-wrapped node or element
+ *
+ *
+ * Compiler related stuff:
+ *
+ * - "linkFn" - linking fn of a single directive
+ * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
+ * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
+ * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $compile
+ * @kind function
+ *
+ * @description
+ * Compiles an HTML string or DOM into a template and produces a template function, which
+ * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
+ *
+ * The compilation is a process of walking the DOM tree and matching DOM elements to
+ * {@link ng.$compileProvider#directive directives}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** This document is an in-depth reference of all directive options.
+ * For a gentle introduction to directives with examples of common use cases,
+ * see the {@link guide/directive directive guide}.
+ * </div>
+ *
+ * ## Comprehensive Directive API
+ *
+ * There are many different options for a directive.
+ *
+ * The difference resides in the return value of the factory function.
+ * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
+ * or just the `postLink` function (all other properties will have the default values).
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's recommended to use the "directive definition object" form.
+ * </div>
+ *
+ * Here's an example directive declared with a Directive Definition Object:
+ *
+ * ```js
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * priority: 0,
+ * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
+ * // or
+ * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
+ * transclude: false,
+ * restrict: 'A',
+ * templateNamespace: 'html',
+ * scope: false,
+ * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
+ * controllerAs: 'stringIdentifier',
+ * bindToController: false,
+ * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
+ * compile: function compile(tElement, tAttrs, transclude) {
+ * return {
+ * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * }
+ * // or
+ * // return function postLink( ... ) { ... }
+ * },
+ * // or
+ * // link: {
+ * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * // }
+ * // or
+ * // link: function postLink( ... ) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * });
+ * ```
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Any unspecified options will use the default value. You can see the default values below.
+ * </div>
+ *
+ * Therefore the above can be simplified as:
+ *
+ * ```js
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * link: function postLink(scope, iElement, iAttrs) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * // or
+ * // return function postLink(scope, iElement, iAttrs) { ... }
+ * });
+ * ```
+ *
+ *
+ *
+ * ### Directive Definition Object
+ *
+ * The directive definition object provides instructions to the {@link ng.$compile
+ * compiler}. The attributes are:
+ *
+ * #### `multiElement`
+ * When this property is set to true, the HTML compiler will collect DOM nodes between
+ * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
+ * together as the directive elements. It is recommended that this feature be used on directives
+ * which are not strictly behavioural (such as {@link ngClick}), and which
+ * do not manipulate or replace child nodes (such as {@link ngInclude}).
+ *
+ * #### `priority`
+ * When there are multiple directives defined on a single DOM element, sometimes it
+ * is necessary to specify the order in which the directives are applied. The `priority` is used
+ * to sort the directives before their `compile` functions get called. Priority is defined as a
+ * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
+ * are also run in priority order, but post-link functions are run in reverse order. The order
+ * of directives with the same priority is undefined. The default priority is `0`.
+ *
+ * #### `terminal`
+ * If set to true then the current `priority` will be the last set of directives
+ * which will execute (any directives at the current priority will still execute
+ * as the order of execution on same `priority` is undefined). Note that expressions
+ * and other directives used in the directive's template will also be excluded from execution.
+ *
+ * #### `scope`
+ * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
+ * same element request a new scope, only one new scope is created. The new scope rule does not
+ * apply for the root of the template since the root of the template always gets a new scope.
+ *
+ * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
+ * normal scope in that it does not prototypically inherit from the parent scope. This is useful
+ * when creating reusable components, which should not accidentally read or modify data in the
+ * parent scope.
+ *
+ * The 'isolate' scope takes an object hash which defines a set of local scope properties
+ * derived from the parent scope. These local properties are useful for aliasing values for
+ * templates. Locals definition is a hash of local scope property to its source:
+ *
+ * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
+ * always a string since DOM attributes are strings. If no `attr` name is specified then the
+ * attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="hello {{name}}">` and widget definition
+ * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
+ * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
+ * `localName` property on the widget scope. The `name` is read from the parent scope (not
+ * component scope).
+ *
+ * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
+ * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
+ * name is specified then the attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="parentModel">` and widget definition of
+ * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
+ * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
+ * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
+ * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
+ * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
+ * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
+ * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
+ *
+ * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
+ * If no `attr` name is specified then the attribute name is assumed to be the same as the
+ * local name. Given `<widget my-attr="count = count + value">` and widget definition of
+ * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
+ * a function wrapper for the `count = count + value` expression. Often it's desirable to
+ * pass data from the isolated scope via an expression to the parent scope, this can be
+ * done by passing a map of local variable names and values into the expression wrapper fn.
+ * For example, if the expression is `increment(amount)` then we can specify the amount value
+ * by calling the `localFn` as `localFn({amount: 22})`.
+ *
+ *
+ * #### `bindToController`
+ * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
+ * allow a component to have its properties bound to the controller, rather than to scope. When the controller
+ * is instantiated, the initial values of the isolate scope bindings are already available.
+ *
+ * #### `controller`
+ * Controller constructor function. The controller is instantiated before the
+ * pre-linking phase and it is shared with other directives (see
+ * `require` attribute). This allows the directives to communicate with each other and augment
+ * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
+ *
+ * * `$scope` - Current scope associated with the element
+ * * `$element` - Current element
+ * * `$attrs` - Current attributes object for the element
+ * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ * * `scope`: optional argument to override the scope.
+ * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
+ * * `futureParentElement`:
+ * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
+ * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
+ * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
+ * and when the `cloneLinkinFn` is passed,
+ * as those elements need to created and cloned in a special way when they are defined outside their
+ * usual containers (e.g. like `<svg>`).
+ * * See also the `directive.templateNamespace` property.
+ *
+ *
+ * #### `require`
+ * Require another directive and inject its controller as the fourth argument to the linking function. The
+ * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
+ * injected argument will be an array in corresponding order. If no such directive can be
+ * found, or if the directive does not have a controller, then an error is raised (unless no link function
+ * is specified, in which case error checking is skipped). The name can be prefixed with:
+ *
+ * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
+ * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
+ * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
+ * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
+ * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
+ * `null` to the `link` fn if not found.
+ * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
+ * `null` to the `link` fn if not found.
+ *
+ *
+ * #### `controllerAs`
+ * Controller alias at the directive scope. An alias for the controller so it
+ * can be referenced at the directive template. The directive needs to define a scope for this
+ * configuration to be used. Useful in the case when directive is used as component.
+ *
+ *
+ * #### `restrict`
+ * String of subset of `EACM` which restricts the directive to a specific directive
+ * declaration style. If omitted, the defaults (elements and attributes) are used.
+ *
+ * * `E` - Element name (default): `<my-directive></my-directive>`
+ * * `A` - Attribute (default): `<div my-directive="exp"></div>`
+ * * `C` - Class: `<div class="my-directive: exp;"></div>`
+ * * `M` - Comment: `<!-- directive: my-directive exp -->`
+ *
+ *
+ * #### `templateNamespace`
+ * String representing the document type used by the markup in the template.
+ * AngularJS needs this information as those elements need to be created and cloned
+ * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
+ *
+ * * `html` - All root nodes in the template are HTML. Root nodes may also be
+ * top-level elements such as `<svg>` or `<math>`.
+ * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
+ * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
+ *
+ * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
+ *
+ * #### `template`
+ * HTML markup that may:
+ * * Replace the contents of the directive's element (default).
+ * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
+ * * Wrap the contents of the directive's element (if `transclude` is true).
+ *
+ * Value may be:
+ *
+ * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
+ * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
+ * function api below) and returns a string value.
+ *
+ *
+ * #### `templateUrl`
+ * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
+ *
+ * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
+ * for later when the template has been resolved. In the meantime it will continue to compile and link
+ * sibling and parent elements as though this element had not contained any directives.
+ *
+ * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
+ * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
+ * case when only one deeply nested directive has `templateUrl`.
+ *
+ * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
+ *
+ * You can specify `templateUrl` as a string representing the URL or as a function which takes two
+ * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
+ * a string value representing the url. In either case, the template URL is passed through {@link
+ * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
+ *
+ *
+ * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
+ * specify what the template should replace. Defaults to `false`.
+ *
+ * * `true` - the template will replace the directive's element.
+ * * `false` - the template will replace the contents of the directive's element.
+ *
+ * The replacement process migrates all of the attributes / classes from the old element to the new
+ * one. See the {@link guide/directive#template-expanding-directive
+ * Directives Guide} for an example.
+ *
+ * There are very few scenarios where element replacement is required for the application function,
+ * the main one being reusable custom components that are used within SVG contexts
+ * (because SVG doesn't work with custom elements in the DOM tree).
+ *
+ * #### `transclude`
+ * Extract the contents of the element where the directive appears and make it available to the directive.
+ * The contents are compiled and provided to the directive as a **transclusion function**. See the
+ * {@link $compile#transclusion Transclusion} section below.
+ *
+ * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
+ * directive's element or the entire element:
+ *
+ * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
+ * * `'element'` - transclude the whole of the directive's element including any directives on this
+ * element that defined at a lower priority than this directive. When used, the `template`
+ * property is ignored.
+ *
+ *
+ * #### `compile`
+ *
+ * ```js
+ * function compile(tElement, tAttrs, transclude) { ... }
+ * ```
+ *
+ * The compile function deals with transforming the template DOM. Since most directives do not do
+ * template transformation, it is not used often. The compile function takes the following arguments:
+ *
+ * * `tElement` - template element - The element where the directive has been declared. It is
+ * safe to do template transformation on the element and child elements only.
+ *
+ * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
+ * between all directive compile functions.
+ *
+ * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
+ *
+ * <div class="alert alert-warning">
+ * **Note:** The template instance and the link instance may be different objects if the template has
+ * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
+ * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
+ * should be done in a linking function rather than in a compile function.
+ * </div>
+
+ * <div class="alert alert-warning">
+ * **Note:** The compile function cannot handle directives that recursively use themselves in their
+ * own templates or compile functions. Compiling these directives results in an infinite loop and a
+ * stack overflow errors.
+ *
+ * This can be avoided by manually using $compile in the postLink function to imperatively compile
+ * a directive's template instead of relying on automatic template compilation via `template` or
+ * `templateUrl` declaration or manual compilation inside the compile function.
+ * </div>
+ *
+ * <div class="alert alert-error">
+ * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
+ * e.g. does not know about the right outer scope. Please use the transclude function that is passed
+ * to the link function instead.
+ * </div>
+
+ * A compile function can have a return value which can be either a function or an object.
+ *
+ * * returning a (post-link) function - is equivalent to registering the linking function via the
+ * `link` property of the config object when the compile function is empty.
+ *
+ * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
+ * control when a linking function should be called during the linking phase. See info about
+ * pre-linking and post-linking functions below.
+ *
+ *
+ * #### `link`
+ * This property is used only if the `compile` property is not defined.
+ *
+ * ```js
+ * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
+ * ```
+ *
+ * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
+ * executed after the template has been cloned. This is where most of the directive logic will be
+ * put.
+ *
+ * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
+ * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
+ *
+ * * `iElement` - instance element - The element where the directive is to be used. It is safe to
+ * manipulate the children of the element only in `postLink` function since the children have
+ * already been linked.
+ *
+ * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
+ * between all directive linking functions.
+ *
+ * * `controller` - the directive's required controller instance(s) - Instances are shared
+ * among all directives, which allows the directives to use the controllers as a communication
+ * channel. The exact value depends on the directive's `require` property:
+ * * `string`: the controller instance
+ * * `array`: array of controller instances
+ * * no controller(s) required: `undefined`
+ *
+ * If a required controller cannot be found, and it is optional, the instance is `null`,
+ * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
+ *
+ * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
+ * This is the same as the `$transclude`
+ * parameter of directive controllers, see there for details.
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ *
+ * #### Pre-linking function
+ *
+ * Executed before the child elements are linked. Not safe to do DOM transformation since the
+ * compiler linking function will fail to locate the correct elements for linking.
+ *
+ * #### Post-linking function
+ *
+ * Executed after the child elements are linked.
+ *
+ * Note that child elements that contain `templateUrl` directives will not have been compiled
+ * and linked since they are waiting for their template to load asynchronously and their own
+ * compilation and linking has been suspended until that occurs.
+ *
+ * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
+ * for their async templates to be resolved.
+ *
+ *
+ * ### Transclusion
+ *
+ * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
+ * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
+ * scope from where they were taken.
+ *
+ * Transclusion is used (often with {@link ngTransclude}) to insert the
+ * original contents of a directive's element into a specified place in the template of the directive.
+ * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
+ * content has access to the properties on the scope from which it was taken, even if the directive
+ * has isolated scope.
+ * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
+ *
+ * This makes it possible for the widget to have private state for its template, while the transcluded
+ * content has access to its originating scope.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** When testing an element transclude directive you must not place the directive at the root of the
+ * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
+ * Testing Transclusion Directives}.
+ * </div>
+ *
+ * #### Transclusion Functions
+ *
+ * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
+ * function** to the directive's `link` function and `controller`. This transclusion function is a special
+ * **linking function** that will return the compiled contents linked to a new transclusion scope.
+ *
+ * <div class="alert alert-info">
+ * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
+ * ngTransclude will deal with it for us.
+ * </div>
+ *
+ * If you want to manually control the insertion and removal of the transcluded content in your directive
+ * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
+ * object that contains the compiled DOM, which is linked to the correct transclusion scope.
+ *
+ * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
+ * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
+ * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
+ * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
+ * </div>
+ *
+ * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
+ * attach function**:
+ *
+ * ```js
+ * var transcludedContent, transclusionScope;
+ *
+ * $transclude(function(clone, scope) {
+ * element.append(clone);
+ * transcludedContent = clone;
+ * transclusionScope = scope;
+ * });
+ * ```
+ *
+ * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
+ * associated transclusion scope:
+ *
+ * ```js
+ * transcludedContent.remove();
+ * transclusionScope.$destroy();
+ * ```
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
+ * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),
+ * then you are also responsible for calling `$destroy` on the transclusion scope.
+ * </div>
+ *
+ * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
+ * automatically destroy their transluded clones as necessary so you do not need to worry about this if
+ * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
+ *
+ *
+ * #### Transclusion Scopes
+ *
+ * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
+ * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
+ * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
+ * was taken.
+ *
+ * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
+ * like this:
+ *
+ * ```html
+ * <div ng-app>
+ * <div isolate>
+ * <div transclusion>
+ * </div>
+ * </div>
+ * </div>
+ * ```
+ *
+ * The `$parent` scope hierarchy will look like this:
+ *
+ * ```
+ * - $rootScope
+ * - isolate
+ * - transclusion
+ * ```
+ *
+ * but the scopes will inherit prototypically from different scopes to their `$parent`.
+ *
+ * ```
+ * - $rootScope
+ * - transclusion
+ * - isolate
+ * ```
+ *
+ *
+ * ### Attributes
+ *
+ * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
+ * `link()` or `compile()` functions. It has a variety of uses.
+ *
+ * accessing *Normalized attribute names:*
+ * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
+ * the attributes object allows for normalized access to
+ * the attributes.
+ *
+ * * *Directive inter-communication:* All directives share the same instance of the attributes
+ * object which allows the directives to use the attributes object as inter directive
+ * communication.
+ *
+ * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
+ * allowing other directives to read the interpolated value.
+ *
+ * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
+ * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
+ * the only way to easily get the actual value because during the linking phase the interpolation
+ * hasn't been evaluated yet and so the value is at this time set to `undefined`.
+ *
+ * ```js
+ * function linkingFn(scope, elm, attrs, ctrl) {
+ * // get the attribute value
+ * console.log(attrs.ngModel);
+ *
+ * // change the attribute
+ * attrs.$set('ngModel', 'new value');
+ *
+ * // observe changes to interpolated attribute
+ * attrs.$observe('ngModel', function(value) {
+ * console.log('ngModel has changed value to ' + value);
+ * });
+ * }
+ * ```
+ *
+ * ## Example
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Typically directives are registered with `module.directive`. The example below is
+ * to illustrate how `$compile` works.
+ * </div>
+ *
+ <example module="compileExample">
+ <file name="index.html">
+ <script>
+ angular.module('compileExample', [], function($compileProvider) {
+ // configure new 'compile' directive by passing a directive
+ // factory function. The factory function injects the '$compile'
+ $compileProvider.directive('compile', function($compile) {
+ // directive factory creates a link function
+ return function(scope, element, attrs) {
+ scope.$watch(
+ function(scope) {
+ // watch the 'compile' expression for changes
+ return scope.$eval(attrs.compile);
+ },
+ function(value) {
+ // when the 'compile' expression changes
+ // assign it into the current DOM
+ element.html(value);
+
+ // compile the new DOM and link it to the current
+ // scope.
+ // NOTE: we only compile .childNodes so that
+ // we don't get into infinite loop compiling ourselves
+ $compile(element.contents())(scope);
+ }
+ );
+ };
+ });
+ })
+ .controller('GreeterController', ['$scope', function($scope) {
+ $scope.name = 'Angular';
+ $scope.html = 'Hello {{name}}';
+ }]);
+ </script>
+ <div ng-controller="GreeterController">
+ <input ng-model="name"> <br>
+ <textarea ng-model="html"></textarea> <br>
+ <div compile="html"></div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should auto compile', function() {
+ var textarea = $('textarea');
+ var output = $('div[compile]');
+ // The initial state reads 'Hello Angular'.
+ expect(output.getText()).toBe('Hello Angular');
+ textarea.clear();
+ textarea.sendKeys('{{name}}!');
+ expect(output.getText()).toBe('Angular!');
+ });
+ </file>
+ </example>
+
+ *
+ *
+ * @param {string|DOMElement} element Element or HTML string to compile into a template function.
+ * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
+ *
+ * <div class="alert alert-error">
+ * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
+ * e.g. will not use the right outer scope. Please pass the transclude function as a
+ * `parentBoundTranscludeFn` to the link function instead.
+ * </div>
+ *
+ * @param {number} maxPriority only apply directives lower than given priority (Only effects the
+ * root element(s), not their children)
+ * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
+ * (a DOM element/tree) to a scope. Where:
+ *
+ * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
+ * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
+ * `template` and call the `cloneAttachFn` function allowing the caller to attach the
+ * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
+ * called as: <br> `cloneAttachFn(clonedElement, scope)` where:
+ *
+ * * `clonedElement` - is a clone of the original `element` passed into the compiler.
+ * * `scope` - is the current scope with which the linking function is working with.
+ *
+ * * `options` - An optional object hash with linking options. If `options` is provided, then the following
+ * keys may be used to control linking behavior:
+ *
+ * * `parentBoundTranscludeFn` - the transclude function made available to
+ * directives; if given, it will be passed through to the link functions of
+ * directives found in `element` during compilation.
+ * * `transcludeControllers` - an object hash with keys that map controller names
+ * to controller instances; if given, it will make the controllers
+ * available to directives.
+ * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
+ * the cloned elements; only needed for transcludes that are allowed to contain non html
+ * elements (e.g. SVG elements). See also the directive.controller property.
+ *
+ * Calling the linking function returns the element of the template. It is either the original
+ * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
+ *
+ * After linking the view is not updated until after a call to $digest which typically is done by
+ * Angular automatically.
+ *
+ * If you need access to the bound view, there are two ways to do it:
+ *
+ * - If you are not asking the linking function to clone the template, create the DOM element(s)
+ * before you send them to the compiler and keep this reference around.
+ * ```js
+ * var element = $compile('<p>{{total}}</p>')(scope);
+ * ```
+ *
+ * - if on the other hand, you need the element to be cloned, the view reference from the original
+ * example would not point to the clone, but rather to the original template that was cloned. In
+ * this case, you can access the clone via the cloneAttachFn:
+ * ```js
+ * var templateElement = angular.element('<p>{{total}}</p>'),
+ * scope = ....;
+ *
+ * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
+ * //attach the clone to DOM document at the right place
+ * });
+ *
+ * //now we have reference to the cloned DOM via `clonedElement`
+ * ```
+ *
+ *
+ * For information on how the compiler works, see the
+ * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
+ */
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc provider
+ * @name $compileProvider
+ *
+ * @description
+ */
+$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
+function $CompileProvider($provide, $$sanitizeUriProvider) {
+ var hasDirectives = {},
+ Suffix = 'Directive',
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
+ CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
+ ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
+ REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
+
+ // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
+ // The assumption is that future DOM event attribute names will begin with
+ // 'on' and be composed of only English letters.
+ var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
+
+ function parseIsolateBindings(scope, directiveName) {
+ var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
+
+ var bindings = {};
+
+ forEach(scope, function(definition, scopeName) {
+ var match = definition.match(LOCAL_REGEXP);
+
+ if (!match) {
+ throw $compileMinErr('iscp',
+ "Invalid isolate scope definition for directive '{0}'." +
+ " Definition: {... {1}: '{2}' ...}",
+ directiveName, scopeName, definition);
+ }
+
+ bindings[scopeName] = {
+ mode: match[1][0],
+ collection: match[2] === '*',
+ optional: match[3] === '?',
+ attrName: match[4] || scopeName
+ };
+ });
+
+ return bindings;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#directive
+ * @kind function
+ *
+ * @description
+ * Register a new directive with the compiler.
+ *
+ * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
+ * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
+ * names and the values are the factories.
+ * @param {Function|Array} directiveFactory An injectable directive factory function. See
+ * {@link guide/directive} for more info.
+ * @returns {ng.$compileProvider} Self for chaining.
+ */
+ this.directive = function registerDirective(name, directiveFactory) {
+ assertNotHasOwnProperty(name, 'directive');
+ if (isString(name)) {
+ assertArg(directiveFactory, 'directiveFactory');
+ if (!hasDirectives.hasOwnProperty(name)) {
+ hasDirectives[name] = [];
+ $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
+ function($injector, $exceptionHandler) {
+ var directives = [];
+ forEach(hasDirectives[name], function(directiveFactory, index) {
+ try {
+ var directive = $injector.invoke(directiveFactory);
+ if (isFunction(directive)) {
+ directive = { compile: valueFn(directive) };
+ } else if (!directive.compile && directive.link) {
+ directive.compile = valueFn(directive.link);
+ }
+ directive.priority = directive.priority || 0;
+ directive.index = index;
+ directive.name = directive.name || name;
+ directive.require = directive.require || (directive.controller && directive.name);
+ directive.restrict = directive.restrict || 'EA';
+ if (isObject(directive.scope)) {
+ directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);
+ }
+ directives.push(directive);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ return directives;
+ }]);
+ }
+ hasDirectives[name].push(directiveFactory);
+ } else {
+ forEach(name, reverseParams(registerDirective));
+ }
+ return this;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#aHrefSanitizationWhitelist
+ * @kind function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at preventing XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.aHrefSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#imgSrcSanitizationWhitelist
+ * @kind function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during img[src] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.imgSrcSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#debugInfoEnabled
+ *
+ * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
+ * current debugInfoEnabled state
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ *
+ * @kind function
+ *
+ * @description
+ * Call this method to enable/disable various debug runtime information in the compiler such as adding
+ * binding information and a reference to the current scope on to DOM elements.
+ * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
+ * * `ng-binding` CSS class
+ * * `$binding` data property containing an array of the binding expressions
+ *
+ * You may want to disable this in production for a significant performance boost. See
+ * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
+ *
+ * The default value is true.
+ */
+ var debugInfoEnabled = true;
+ this.debugInfoEnabled = function(enabled) {
+ if (isDefined(enabled)) {
+ debugInfoEnabled = enabled;
+ return this;
+ }
+ return debugInfoEnabled;
+ };
+
+ this.$get = [
+ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
+ '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
+ function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
+ $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
+
+ var Attributes = function(element, attributesToCopy) {
+ if (attributesToCopy) {
+ var keys = Object.keys(attributesToCopy);
+ var i, l, key;
+
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i];
+ this[key] = attributesToCopy[key];
+ }
+ } else {
+ this.$attr = {};
+ }
+
+ this.$$element = element;
+ };
+
+ Attributes.prototype = {
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$normalize
+ * @kind function
+ *
+ * @description
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
+ * `data-`) to its normalized, camelCase form.
+ *
+ * Also there is special case for Moz prefix starting with upper case letter.
+ *
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
+ *
+ * @param {string} name Name to normalize
+ */
+ $normalize: directiveNormalize,
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$addClass
+ * @kind function
+ *
+ * @description
+ * Adds the CSS class value specified by the classVal parameter to the element. If animations
+ * are enabled then an animation will be triggered for the class addition.
+ *
+ * @param {string} classVal The className value that will be added to the element
+ */
+ $addClass: function(classVal) {
+ if (classVal && classVal.length > 0) {
+ $animate.addClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$removeClass
+ * @kind function
+ *
+ * @description
+ * Removes the CSS class value specified by the classVal parameter from the element. If
+ * animations are enabled then an animation will be triggered for the class removal.
+ *
+ * @param {string} classVal The className value that will be removed from the element
+ */
+ $removeClass: function(classVal) {
+ if (classVal && classVal.length > 0) {
+ $animate.removeClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$updateClass
+ * @kind function
+ *
+ * @description
+ * Adds and removes the appropriate CSS class values to the element based on the difference
+ * between the new and old CSS class values (specified as newClasses and oldClasses).
+ *
+ * @param {string} newClasses The current CSS className value
+ * @param {string} oldClasses The former CSS className value
+ */
+ $updateClass: function(newClasses, oldClasses) {
+ var toAdd = tokenDifference(newClasses, oldClasses);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(this.$$element, toAdd);
+ }
+
+ var toRemove = tokenDifference(oldClasses, newClasses);
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(this.$$element, toRemove);
+ }
+ },
+
+ /**
+ * Set a normalized attribute on the element in a way such that all directives
+ * can share the attribute. This function properly handles boolean attributes.
+ * @param {string} key Normalized key. (ie ngAttribute)
+ * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
+ * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
+ * Defaults to true.
+ * @param {string=} attrName Optional none normalized name. Defaults to key.
+ */
+ $set: function(key, value, writeAttr, attrName) {
+ // TODO: decide whether or not to throw an error if "class"
+ //is set through this function since it may cause $updateClass to
+ //become unstable.
+
+ var node = this.$$element[0],
+ booleanKey = getBooleanAttrName(node, key),
+ aliasedKey = getAliasedAttrName(node, key),
+ observer = key,
+ nodeName;
+
+ if (booleanKey) {
+ this.$$element.prop(key, value);
+ attrName = booleanKey;
+ } else if (aliasedKey) {
+ this[aliasedKey] = value;
+ observer = aliasedKey;
+ }
+
+ this[key] = value;
+
+ // translate normalized key to actual key
+ if (attrName) {
+ this.$attr[key] = attrName;
+ } else {
+ attrName = this.$attr[key];
+ if (!attrName) {
+ this.$attr[key] = attrName = snake_case(key, '-');
+ }
+ }
+
+ nodeName = nodeName_(this.$$element);
+
+ if ((nodeName === 'a' && key === 'href') ||
+ (nodeName === 'img' && key === 'src')) {
+ // sanitize a[href] and img[src] values
+ this[key] = value = $$sanitizeUri(value, key === 'src');
+ } else if (nodeName === 'img' && key === 'srcset') {
+ // sanitize img[srcset] values
+ var result = "";
+
+ // first check if there are spaces because it's not the same pattern
+ var trimmedSrcset = trim(value);
+ // ( 999x ,| 999w ,| ,|, )
+ var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
+ var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
+
+ // split srcset into tuple of uri and descriptor except for the last item
+ var rawUris = trimmedSrcset.split(pattern);
+
+ // for each tuples
+ var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
+ for (var i = 0; i < nbrUrisWith2parts; i++) {
+ var innerIdx = i * 2;
+ // sanitize the uri
+ result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
+ // add the descriptor
+ result += (" " + trim(rawUris[innerIdx + 1]));
+ }
+
+ // split the last item into uri and descriptor
+ var lastTuple = trim(rawUris[i * 2]).split(/\s/);
+
+ // sanitize the last uri
+ result += $$sanitizeUri(trim(lastTuple[0]), true);
+
+ // and add the last descriptor if any
+ if (lastTuple.length === 2) {
+ result += (" " + trim(lastTuple[1]));
+ }
+ this[key] = value = result;
+ }
+
+ if (writeAttr !== false) {
+ if (value === null || value === undefined) {
+ this.$$element.removeAttr(attrName);
+ } else {
+ this.$$element.attr(attrName, value);
+ }
+ }
+
+ // fire observers
+ var $$observers = this.$$observers;
+ $$observers && forEach($$observers[observer], function(fn) {
+ try {
+ fn(value);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$observe
+ * @kind function
+ *
+ * @description
+ * Observes an interpolated attribute.
+ *
+ * The observer function will be invoked once during the next `$digest` following
+ * compilation. The observer is then invoked whenever the interpolated value
+ * changes.
+ *
+ * @param {string} key Normalized key. (ie ngAttribute) .
+ * @param {function(interpolatedValue)} fn Function that will be called whenever
+ the interpolated value of the attribute changes.
+ * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
+ * @returns {function()} Returns a deregistration function for this observer.
+ */
+ $observe: function(key, fn) {
+ var attrs = this,
+ $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
+ listeners = ($$observers[key] || ($$observers[key] = []));
+
+ listeners.push(fn);
+ $rootScope.$evalAsync(function() {
+ if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
+ // no one registered attribute interpolation function, so lets call it manually
+ fn(attrs[key]);
+ }
+ });
+
+ return function() {
+ arrayRemove(listeners, fn);
+ };
+ }
+ };
+
+
+ function safeAddClass($element, className) {
+ try {
+ $element.addClass(className);
+ } catch (e) {
+ // ignore, since it means that we are trying to set class on
+ // SVG element, where class name is read-only.
+ }
+ }
+
+
+ var startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
+ ? identity
+ : function denormalizeTemplate(template) {
+ return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
+ },
+ NG_ATTR_BINDING = /^ngAttr[A-Z]/;
+
+ compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
+ var bindings = $element.data('$binding') || [];
+
+ if (isArray(binding)) {
+ bindings = bindings.concat(binding);
+ } else {
+ bindings.push(binding);
+ }
+
+ $element.data('$binding', bindings);
+ } : noop;
+
+ compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
+ safeAddClass($element, 'ng-binding');
+ } : noop;
+
+ compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
+ var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
+ $element.data(dataName, scope);
+ } : noop;
+
+ compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
+ safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
+ } : noop;
+
+ return compile;
+
+ //================================
+
+ function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ if (!($compileNodes instanceof jqLite)) {
+ // jquery always rewraps, whereas we need to preserve the original selector so that we can
+ // modify it.
+ $compileNodes = jqLite($compileNodes);
+ }
+ // We can not compile top level text elements since text nodes can be merged and we will
+ // not be able to attach scope data to them, so we will wrap them in <span>
+ forEach($compileNodes, function(node, index) {
+ if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
+ }
+ });
+ var compositeLinkFn =
+ compileNodes($compileNodes, transcludeFn, $compileNodes,
+ maxPriority, ignoreDirective, previousCompileContext);
+ compile.$$addScopeClass($compileNodes);
+ var namespace = null;
+ return function publicLinkFn(scope, cloneConnectFn, options) {
+ assertArg(scope, 'scope');
+
+ options = options || {};
+ var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
+ transcludeControllers = options.transcludeControllers,
+ futureParentElement = options.futureParentElement;
+
+ // When `parentBoundTranscludeFn` is passed, it is a
+ // `controllersBoundTransclude` function (it was previously passed
+ // as `transclude` to directive.link) so we must unwrap it to get
+ // its `boundTranscludeFn`
+ if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
+ parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
+ }
+
+ if (!namespace) {
+ namespace = detectNamespaceForChildElements(futureParentElement);
+ }
+ var $linkNode;
+ if (namespace !== 'html') {
+ // When using a directive with replace:true and templateUrl the $compileNodes
+ // (or a child element inside of them)
+ // might change, so we need to recreate the namespace adapted compileNodes
+ // for call to the link function.
+ // Note: This will already clone the nodes...
+ $linkNode = jqLite(
+ wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
+ );
+ } else if (cloneConnectFn) {
+ // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
+ // and sometimes changes the structure of the DOM.
+ $linkNode = JQLitePrototype.clone.call($compileNodes);
+ } else {
+ $linkNode = $compileNodes;
+ }
+
+ if (transcludeControllers) {
+ for (var controllerName in transcludeControllers) {
+ $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
+ }
+ }
+
+ compile.$$addScopeInfo($linkNode, scope);
+
+ if (cloneConnectFn) cloneConnectFn($linkNode, scope);
+ if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
+ return $linkNode;
+ };
+ }
+
+ function detectNamespaceForChildElements(parentElement) {
+ // TODO: Make this detect MathML as well...
+ var node = parentElement && parentElement[0];
+ if (!node) {
+ return 'html';
+ } else {
+ return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
+ }
+ }
+
+ /**
+ * Compile function matches each node in nodeList against the directives. Once all directives
+ * for a particular node are collected their compile functions are executed. The compile
+ * functions return values - the linking functions - are combined into a composite linking
+ * function, which is the a linking function for the node.
+ *
+ * @param {NodeList} nodeList an array of nodes or NodeList to compile
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new child of the transcluded parent scope.
+ * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
+ * the rootElement must be set the jqLite collection of the compile root. This is
+ * needed so that the jqLite collection items can be replaced with widgets.
+ * @param {number=} maxPriority Max directive priority.
+ * @returns {Function} A composite linking function of all of the matched directives or null.
+ */
+ function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ var linkFns = [],
+ attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
+
+ for (var i = 0; i < nodeList.length; i++) {
+ attrs = new Attributes();
+
+ // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
+ directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
+ ignoreDirective);
+
+ nodeLinkFn = (directives.length)
+ ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
+ null, [], [], previousCompileContext)
+ : null;
+
+ if (nodeLinkFn && nodeLinkFn.scope) {
+ compile.$$addScopeClass(attrs.$$element);
+ }
+
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
+ !(childNodes = nodeList[i].childNodes) ||
+ !childNodes.length)
+ ? null
+ : compileNodes(childNodes,
+ nodeLinkFn ? (
+ (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
+ && nodeLinkFn.transclude) : transcludeFn);
+
+ if (nodeLinkFn || childLinkFn) {
+ linkFns.push(i, nodeLinkFn, childLinkFn);
+ linkFnFound = true;
+ nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
+ }
+
+ //use the previous context only for the first element in the virtual group
+ previousCompileContext = null;
+ }
+
+ // return a linking function if we have found anything, null otherwise
+ return linkFnFound ? compositeLinkFn : null;
+
+ function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
+ var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
+ var stableNodeList;
+
+
+ if (nodeLinkFnFound) {
+ // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
+ // offsets don't get screwed up
+ var nodeListLength = nodeList.length;
+ stableNodeList = new Array(nodeListLength);
+
+ // create a sparse array by only copying the elements which have a linkFn
+ for (i = 0; i < linkFns.length; i+=3) {
+ idx = linkFns[i];
+ stableNodeList[idx] = nodeList[idx];
+ }
+ } else {
+ stableNodeList = nodeList;
+ }
+
+ for (i = 0, ii = linkFns.length; i < ii;) {
+ node = stableNodeList[linkFns[i++]];
+ nodeLinkFn = linkFns[i++];
+ childLinkFn = linkFns[i++];
+
+ if (nodeLinkFn) {
+ if (nodeLinkFn.scope) {
+ childScope = scope.$new();
+ compile.$$addScopeInfo(jqLite(node), childScope);
+ } else {
+ childScope = scope;
+ }
+
+ if (nodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(
+ scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
+ nodeLinkFn.elementTranscludeOnThisElement);
+
+ } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
+ childBoundTranscludeFn = parentBoundTranscludeFn;
+
+ } else if (!parentBoundTranscludeFn && transcludeFn) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
+
+ } else {
+ childBoundTranscludeFn = null;
+ }
+
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
+
+ } else if (childLinkFn) {
+ childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
+ }
+ }
+ }
+ }
+
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
+
+ var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
+
+ if (!transcludedScope) {
+ transcludedScope = scope.$new(false, containingScope);
+ transcludedScope.$$transcluded = true;
+ }
+
+ return transcludeFn(transcludedScope, cloneFn, {
+ parentBoundTranscludeFn: previousBoundTranscludeFn,
+ transcludeControllers: controllers,
+ futureParentElement: futureParentElement
+ });
+ };
+
+ return boundTranscludeFn;
+ }
+
+ /**
+ * Looks for directives on the given node and adds them to the directive collection which is
+ * sorted.
+ *
+ * @param node Node to search.
+ * @param directives An array to which the directives are added to. This array is sorted before
+ * the function returns.
+ * @param attrs The shared attrs object which is used to populate the normalized attributes.
+ * @param {number=} maxPriority Max directive priority.
+ */
+ function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
+ var nodeType = node.nodeType,
+ attrsMap = attrs.$attr,
+ match,
+ className;
+
+ switch (nodeType) {
+ case NODE_TYPE_ELEMENT: /* Element */
+ // use the node name: <directive>
+ addDirective(directives,
+ directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
+
+ // iterate over the attributes
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
+ j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
+ var attrStartName = false;
+ var attrEndName = false;
+
+ attr = nAttrs[j];
+ name = attr.name;
+ value = trim(attr.value);
+
+ // support ngAttr attribute binding
+ ngAttrName = directiveNormalize(name);
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
+ name = name.replace(PREFIX_REGEXP, '')
+ .substr(8).replace(/_(.)/g, function(match, letter) {
+ return letter.toUpperCase();
+ });
+ }
+
+ var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
+ if (directiveIsMultiElement(directiveNName)) {
+ if (ngAttrName === directiveNName + 'Start') {
+ attrStartName = name;
+ attrEndName = name.substr(0, name.length - 5) + 'end';
+ name = name.substr(0, name.length - 6);
+ }
+ }
+
+ nName = directiveNormalize(name.toLowerCase());
+ attrsMap[nName] = name;
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
+ attrs[nName] = value;
+ if (getBooleanAttrName(node, nName)) {
+ attrs[nName] = true; // presence means true
+ }
+ }
+ addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
+ addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
+ attrEndName);
+ }
+
+ // use class as directive
+ className = node.className;
+ if (isObject(className)) {
+ // Maybe SVGAnimatedString
+ className = className.animVal;
+ }
+ if (isString(className) && className !== '') {
+ while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
+ nName = directiveNormalize(match[2]);
+ if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[3]);
+ }
+ className = className.substr(match.index + match[0].length);
+ }
+ }
+ break;
+ case NODE_TYPE_TEXT: /* Text Node */
+ addTextInterpolateDirective(directives, node.nodeValue);
+ break;
+ case NODE_TYPE_COMMENT: /* Comment */
+ try {
+ match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
+ if (match) {
+ nName = directiveNormalize(match[1]);
+ if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[2]);
+ }
+ }
+ } catch (e) {
+ // turns out that under some circumstances IE9 throws errors when one attempts to read
+ // comment's node value.
+ // Just ignore it and continue. (Can't seem to reproduce in test case.)
+ }
+ break;
+ }
+
+ directives.sort(byPriority);
+ return directives;
+ }
+
+ /**
+ * Given a node with an directive-start it collects all of the siblings until it finds
+ * directive-end.
+ * @param node
+ * @param attrStart
+ * @param attrEnd
+ * @returns {*}
+ */
+ function groupScan(node, attrStart, attrEnd) {
+ var nodes = [];
+ var depth = 0;
+ if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
+ do {
+ if (!node) {
+ throw $compileMinErr('uterdir',
+ "Unterminated attribute, found '{0}' but no matching '{1}' found.",
+ attrStart, attrEnd);
+ }
+ if (node.nodeType == NODE_TYPE_ELEMENT) {
+ if (node.hasAttribute(attrStart)) depth++;
+ if (node.hasAttribute(attrEnd)) depth--;
+ }
+ nodes.push(node);
+ node = node.nextSibling;
+ } while (depth > 0);
+ } else {
+ nodes.push(node);
+ }
+
+ return jqLite(nodes);
+ }
+
+ /**
+ * Wrapper for linking function which converts normal linking function into a grouped
+ * linking function.
+ * @param linkFn
+ * @param attrStart
+ * @param attrEnd
+ * @returns {Function}
+ */
+ function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
+ return function(scope, element, attrs, controllers, transcludeFn) {
+ element = groupScan(element[0], attrStart, attrEnd);
+ return linkFn(scope, element, attrs, controllers, transcludeFn);
+ };
+ }
+
+ /**
+ * Once the directives have been collected, their compile functions are executed. This method
+ * is responsible for inlining directive templates as well as terminating the application
+ * of the directives if the terminal directive has been reached.
+ *
+ * @param {Array} directives Array of collected directives to execute their compile function.
+ * this needs to be pre-sorted by priority order.
+ * @param {Node} compileNode The raw DOM node to apply the compile functions to
+ * @param {Object} templateAttrs The shared attribute function
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new
+ * child of the transcluded parent scope.
+ * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
+ * argument has the root jqLite array so that we can replace nodes
+ * on it.
+ * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
+ * compiling the transclusion.
+ * @param {Array.<Function>} preLinkFns
+ * @param {Array.<Function>} postLinkFns
+ * @param {Object} previousCompileContext Context used for previous compilation of the current
+ * node
+ * @returns {Function} linkFn
+ */
+ function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
+ jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
+ previousCompileContext) {
+ previousCompileContext = previousCompileContext || {};
+
+ var terminalPriority = -Number.MAX_VALUE,
+ newScopeDirective,
+ controllerDirectives = previousCompileContext.controllerDirectives,
+ controllers,
+ newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
+ templateDirective = previousCompileContext.templateDirective,
+ nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
+ hasTranscludeDirective = false,
+ hasTemplate = false,
+ hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
+ $compileNode = templateAttrs.$$element = jqLite(compileNode),
+ directive,
+ directiveName,
+ $template,
+ replaceDirective = originalReplaceDirective,
+ childTranscludeFn = transcludeFn,
+ linkFn,
+ directiveValue;
+
+ // executes all directives on the current element
+ for (var i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ var attrStart = directive.$$start;
+ var attrEnd = directive.$$end;
+
+ // collect multiblock sections
+ if (attrStart) {
+ $compileNode = groupScan(compileNode, attrStart, attrEnd);
+ }
+ $template = undefined;
+
+ if (terminalPriority > directive.priority) {
+ break; // prevent further processing of directives
+ }
+
+ if (directiveValue = directive.scope) {
+
+ // skip the check for directives with async templates, we'll check the derived sync
+ // directive when the template arrives
+ if (!directive.templateUrl) {
+ if (isObject(directiveValue)) {
+ // This directive is trying to add an isolated scope.
+ // Check that there is no scope of any kind already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
+ directive, $compileNode);
+ newIsolateScopeDirective = directive;
+ } else {
+ // This directive is trying to add a child scope.
+ // Check that there is no isolated scope already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
+ $compileNode);
+ }
+ }
+
+ newScopeDirective = newScopeDirective || directive;
+ }
+
+ directiveName = directive.name;
+
+ if (!directive.templateUrl && directive.controller) {
+ directiveValue = directive.controller;
+ controllerDirectives = controllerDirectives || {};
+ assertNoDuplicate("'" + directiveName + "' controller",
+ controllerDirectives[directiveName], directive, $compileNode);
+ controllerDirectives[directiveName] = directive;
+ }
+
+ if (directiveValue = directive.transclude) {
+ hasTranscludeDirective = true;
+
+ // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
+ // This option should only be used by directives that know how to safely handle element transclusion,
+ // where the transcluded nodes are added or replaced after linking.
+ if (!directive.$$tlb) {
+ assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
+ nonTlbTranscludeDirective = directive;
+ }
+
+ if (directiveValue == 'element') {
+ hasElementTranscludeDirective = true;
+ terminalPriority = directive.priority;
+ $template = $compileNode;
+ $compileNode = templateAttrs.$$element =
+ jqLite(document.createComment(' ' + directiveName + ': ' +
+ templateAttrs[directiveName] + ' '));
+ compileNode = $compileNode[0];
+ replaceWith(jqCollection, sliceArgs($template), compileNode);
+
+ childTranscludeFn = compile($template, transcludeFn, terminalPriority,
+ replaceDirective && replaceDirective.name, {
+ // Don't pass in:
+ // - controllerDirectives - otherwise we'll create duplicates controllers
+ // - newIsolateScopeDirective or templateDirective - combining templates with
+ // element transclusion doesn't make sense.
+ //
+ // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
+ // on the same element more than once.
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ } else {
+ $template = jqLite(jqLiteClone(compileNode)).contents();
+ $compileNode.empty(); // clear contents
+ childTranscludeFn = compile($template, transcludeFn);
+ }
+ }
+
+ if (directive.template) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ directiveValue = (isFunction(directive.template))
+ ? directive.template($compileNode, templateAttrs)
+ : directive.template;
+
+ directiveValue = denormalizeTemplate(directiveValue);
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ if (jqLiteIsTextNode(directiveValue)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ directiveName, '');
+ }
+
+ replaceWith(jqCollection, $compileNode, compileNode);
+
+ var newTemplateAttrs = {$attr: {}};
+
+ // combine directives from the original node and from the template:
+ // - take the array of directives for this element
+ // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
+ // - collect directives from the template and sort them by priority
+ // - combine directives as: processed + template + unprocessed
+ var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
+ var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
+
+ if (newIsolateScopeDirective) {
+ markDirectivesAsIsolate(templateDirectives);
+ }
+ directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
+ mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
+
+ ii = directives.length;
+ } else {
+ $compileNode.html(directiveValue);
+ }
+ }
+
+ if (directive.templateUrl) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ }
+
+ nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
+ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
+ controllerDirectives: controllerDirectives,
+ newIsolateScopeDirective: newIsolateScopeDirective,
+ templateDirective: templateDirective,
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ ii = directives.length;
+ } else if (directive.compile) {
+ try {
+ linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
+ if (isFunction(linkFn)) {
+ addLinkFns(null, linkFn, attrStart, attrEnd);
+ } else if (linkFn) {
+ addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
+ }
+ } catch (e) {
+ $exceptionHandler(e, startingTag($compileNode));
+ }
+ }
+
+ if (directive.terminal) {
+ nodeLinkFn.terminal = true;
+ terminalPriority = Math.max(terminalPriority, directive.priority);
+ }
+
+ }
+
+ nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
+ nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
+ nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;
+ nodeLinkFn.templateOnThisElement = hasTemplate;
+ nodeLinkFn.transclude = childTranscludeFn;
+
+ previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
+
+ // might be normal or delayed nodeLinkFn depending on if templateUrl is present
+ return nodeLinkFn;
+
+ ////////////////////
+
+ function addLinkFns(pre, post, attrStart, attrEnd) {
+ if (pre) {
+ if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
+ pre.require = directive.require;
+ pre.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ pre = cloneAndAnnotateFn(pre, {isolateScope: true});
+ }
+ preLinkFns.push(pre);
+ }
+ if (post) {
+ if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
+ post.require = directive.require;
+ post.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ post = cloneAndAnnotateFn(post, {isolateScope: true});
+ }
+ postLinkFns.push(post);
+ }
+ }
+
+
+ function getControllers(directiveName, require, $element, elementControllers) {
+ var value, retrievalMethod = 'data', optional = false;
+ var $searchElement = $element;
+ var match;
+ if (isString(require)) {
+ match = require.match(REQUIRE_PREFIX_REGEXP);
+ require = require.substring(match[0].length);
+
+ if (match[3]) {
+ if (match[1]) match[3] = null;
+ else match[1] = match[3];
+ }
+ if (match[1] === '^') {
+ retrievalMethod = 'inheritedData';
+ } else if (match[1] === '^^') {
+ retrievalMethod = 'inheritedData';
+ $searchElement = $element.parent();
+ }
+ if (match[2] === '?') {
+ optional = true;
+ }
+
+ value = null;
+
+ if (elementControllers && retrievalMethod === 'data') {
+ if (value = elementControllers[require]) {
+ value = value.instance;
+ }
+ }
+ value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');
+
+ if (!value && !optional) {
+ throw $compileMinErr('ctreq',
+ "Controller '{0}', required by directive '{1}', can't be found!",
+ require, directiveName);
+ }
+ return value || null;
+ } else if (isArray(require)) {
+ value = [];
+ forEach(require, function(require) {
+ value.push(getControllers(directiveName, require, $element, elementControllers));
+ });
+ }
+ return value;
+ }
+
+
+ function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
+ var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,
+ attrs;
+
+ if (compileNode === linkNode) {
+ attrs = templateAttrs;
+ $element = templateAttrs.$$element;
+ } else {
+ $element = jqLite(linkNode);
+ attrs = new Attributes($element, templateAttrs);
+ }
+
+ if (newIsolateScopeDirective) {
+ isolateScope = scope.$new(true);
+ }
+
+ if (boundTranscludeFn) {
+ // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
+ // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
+ transcludeFn = controllersBoundTransclude;
+ transcludeFn.$$boundTransclude = boundTranscludeFn;
+ }
+
+ if (controllerDirectives) {
+ // TODO: merge `controllers` and `elementControllers` into single object.
+ controllers = {};
+ elementControllers = {};
+ forEach(controllerDirectives, function(directive) {
+ var locals = {
+ $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
+ $element: $element,
+ $attrs: attrs,
+ $transclude: transcludeFn
+ }, controllerInstance;
+
+ controller = directive.controller;
+ if (controller == '@') {
+ controller = attrs[directive.name];
+ }
+
+ controllerInstance = $controller(controller, locals, true, directive.controllerAs);
+
+ // For directives with element transclusion the element is a comment,
+ // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
+ // clean up (http://bugs.jquery.com/ticket/8335).
+ // Instead, we save the controllers for the element in a local hash and attach to .data
+ // later, once we have the actual element.
+ elementControllers[directive.name] = controllerInstance;
+ if (!hasElementTranscludeDirective) {
+ $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
+ }
+
+ controllers[directive.name] = controllerInstance;
+ });
+ }
+
+ if (newIsolateScopeDirective) {
+ compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
+ templateDirective === newIsolateScopeDirective.$$originalDirective)));
+ compile.$$addScopeClass($element, true);
+
+ var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];
+ var isolateBindingContext = isolateScope;
+ if (isolateScopeController && isolateScopeController.identifier &&
+ newIsolateScopeDirective.bindToController === true) {
+ isolateBindingContext = isolateScopeController.instance;
+ }
+
+ forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {
+ var attrName = definition.attrName,
+ optional = definition.optional,
+ mode = definition.mode, // @, =, or &
+ lastValue,
+ parentGet, parentSet, compare;
+
+ switch (mode) {
+
+ case '@':
+ attrs.$observe(attrName, function(value) {
+ isolateBindingContext[scopeName] = value;
+ });
+ attrs.$$observers[attrName].$$scope = scope;
+ if (attrs[attrName]) {
+ // If the attribute has been provided then we trigger an interpolation to ensure
+ // the value is there for use in the link fn
+ isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
+ }
+ break;
+
+ case '=':
+ if (optional && !attrs[attrName]) {
+ return;
+ }
+ parentGet = $parse(attrs[attrName]);
+ if (parentGet.literal) {
+ compare = equals;
+ } else {
+ compare = function(a, b) { return a === b || (a !== a && b !== b); };
+ }
+ parentSet = parentGet.assign || function() {
+ // reset the change, or we will throw this exception on every $digest
+ lastValue = isolateBindingContext[scopeName] = parentGet(scope);
+ throw $compileMinErr('nonassign',
+ "Expression '{0}' used with directive '{1}' is non-assignable!",
+ attrs[attrName], newIsolateScopeDirective.name);
+ };
+ lastValue = isolateBindingContext[scopeName] = parentGet(scope);
+ var parentValueWatch = function parentValueWatch(parentValue) {
+ if (!compare(parentValue, isolateBindingContext[scopeName])) {
+ // we are out of sync and need to copy
+ if (!compare(parentValue, lastValue)) {
+ // parent changed and it has precedence
+ isolateBindingContext[scopeName] = parentValue;
+ } else {
+ // if the parent can be assigned then do so
+ parentSet(scope, parentValue = isolateBindingContext[scopeName]);
+ }
+ }
+ return lastValue = parentValue;
+ };
+ parentValueWatch.$stateful = true;
+ var unwatch;
+ if (definition.collection) {
+ unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
+ } else {
+ unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
+ }
+ isolateScope.$on('$destroy', unwatch);
+ break;
+
+ case '&':
+ parentGet = $parse(attrs[attrName]);
+ isolateBindingContext[scopeName] = function(locals) {
+ return parentGet(scope, locals);
+ };
+ break;
+ }
+ });
+ }
+ if (controllers) {
+ forEach(controllers, function(controller) {
+ controller();
+ });
+ controllers = null;
+ }
+
+ // PRELINKING
+ for (i = 0, ii = preLinkFns.length; i < ii; i++) {
+ linkFn = preLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // RECURSION
+ // We only pass the isolate scope, if the isolate directive has a template,
+ // otherwise the child elements do not belong to the isolate directive.
+ var scopeToChild = scope;
+ if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
+ scopeToChild = isolateScope;
+ }
+ childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
+
+ // POSTLINKING
+ for (i = postLinkFns.length - 1; i >= 0; i--) {
+ linkFn = postLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // This is the function that is injected as `$transclude`.
+ // Note: all arguments are optional!
+ function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
+ var transcludeControllers;
+
+ // No scope passed in:
+ if (!isScope(scope)) {
+ futureParentElement = cloneAttachFn;
+ cloneAttachFn = scope;
+ scope = undefined;
+ }
+
+ if (hasElementTranscludeDirective) {
+ transcludeControllers = elementControllers;
+ }
+ if (!futureParentElement) {
+ futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
+ }
+ return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
+ }
+ }
+ }
+
+ function markDirectivesAsIsolate(directives) {
+ // mark all directives as needing isolate scope.
+ for (var j = 0, jj = directives.length; j < jj; j++) {
+ directives[j] = inherit(directives[j], {$$isolateScope: true});
+ }
+ }
+
+ /**
+ * looks up the directive and decorates it with exception handling and proper parameters. We
+ * call this the boundDirective.
+ *
+ * @param {string} name name of the directive to look up.
+ * @param {string} location The directive must be found in specific format.
+ * String containing any of theses characters:
+ *
+ * * `E`: element name
+ * * `A': attribute
+ * * `C`: class
+ * * `M`: comment
+ * @returns {boolean} true if directive was added.
+ */
+ function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
+ endAttrName) {
+ if (name === ignoreDirective) return null;
+ var match = null;
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ try {
+ directive = directives[i];
+ if ((maxPriority === undefined || maxPriority > directive.priority) &&
+ directive.restrict.indexOf(location) != -1) {
+ if (startAttrName) {
+ directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
+ }
+ tDirectives.push(directive);
+ match = directive;
+ }
+ } catch (e) { $exceptionHandler(e); }
+ }
+ }
+ return match;
+ }
+
+
+ /**
+ * looks up the directive and returns true if it is a multi-element directive,
+ * and therefore requires DOM nodes between -start and -end markers to be grouped
+ * together.
+ *
+ * @param {string} name name of the directive to look up.
+ * @returns true if directive was registered as multi-element.
+ */
+ function directiveIsMultiElement(name) {
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ if (directive.multiElement) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * When the element is replaced with HTML template then the new attributes
+ * on the template need to be merged with the existing attributes in the DOM.
+ * The desired effect is to have both of the attributes present.
+ *
+ * @param {object} dst destination attributes (original DOM)
+ * @param {object} src source attributes (from the directive template)
+ */
+ function mergeTemplateAttributes(dst, src) {
+ var srcAttr = src.$attr,
+ dstAttr = dst.$attr,
+ $element = dst.$$element;
+
+ // reapply the old attributes to the new element
+ forEach(dst, function(value, key) {
+ if (key.charAt(0) != '$') {
+ if (src[key] && src[key] !== value) {
+ value += (key === 'style' ? ';' : ' ') + src[key];
+ }
+ dst.$set(key, value, true, srcAttr[key]);
+ }
+ });
+
+ // copy the new attributes on the old attrs object
+ forEach(src, function(value, key) {
+ if (key == 'class') {
+ safeAddClass($element, value);
+ dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
+ } else if (key == 'style') {
+ $element.attr('style', $element.attr('style') + ';' + value);
+ dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
+ // `dst` will never contain hasOwnProperty as DOM parser won't let it.
+ // You will get an "InvalidCharacterError: DOM Exception 5" error if you
+ // have an attribute like "has-own-property" or "data-has-own-property", etc.
+ } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
+ dst[key] = value;
+ dstAttr[key] = srcAttr[key];
+ }
+ });
+ }
+
+
+ function compileTemplateUrl(directives, $compileNode, tAttrs,
+ $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
+ var linkQueue = [],
+ afterTemplateNodeLinkFn,
+ afterTemplateChildLinkFn,
+ beforeTemplateCompileNode = $compileNode[0],
+ origAsyncDirective = directives.shift(),
+ derivedSyncDirective = inherit(origAsyncDirective, {
+ templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
+ }),
+ templateUrl = (isFunction(origAsyncDirective.templateUrl))
+ ? origAsyncDirective.templateUrl($compileNode, tAttrs)
+ : origAsyncDirective.templateUrl,
+ templateNamespace = origAsyncDirective.templateNamespace;
+
+ $compileNode.empty();
+
+ $templateRequest(templateUrl)
+ .then(function(content) {
+ var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
+
+ content = denormalizeTemplate(content);
+
+ if (origAsyncDirective.replace) {
+ if (jqLiteIsTextNode(content)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ origAsyncDirective.name, templateUrl);
+ }
+
+ tempTemplateAttrs = {$attr: {}};
+ replaceWith($rootElement, $compileNode, compileNode);
+ var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
+
+ if (isObject(origAsyncDirective.scope)) {
+ markDirectivesAsIsolate(templateDirectives);
+ }
+ directives = templateDirectives.concat(directives);
+ mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
+ } else {
+ compileNode = beforeTemplateCompileNode;
+ $compileNode.html(content);
+ }
+
+ directives.unshift(derivedSyncDirective);
+
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
+ childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
+ previousCompileContext);
+ forEach($rootElement, function(node, i) {
+ if (node == compileNode) {
+ $rootElement[i] = $compileNode[0];
+ }
+ });
+ afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
+
+ while (linkQueue.length) {
+ var scope = linkQueue.shift(),
+ beforeTemplateLinkNode = linkQueue.shift(),
+ linkRootElement = linkQueue.shift(),
+ boundTranscludeFn = linkQueue.shift(),
+ linkNode = $compileNode[0];
+
+ if (scope.$$destroyed) continue;
+
+ if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
+ var oldClasses = beforeTemplateLinkNode.className;
+
+ if (!(previousCompileContext.hasElementTranscludeDirective &&
+ origAsyncDirective.replace)) {
+ // it was cloned therefore we have to clone as well.
+ linkNode = jqLiteClone(compileNode);
+ }
+ replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
+
+ // Copy in CSS classes from original node
+ safeAddClass(jqLite(linkNode), oldClasses);
+ }
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ } else {
+ childBoundTranscludeFn = boundTranscludeFn;
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
+ childBoundTranscludeFn);
+ }
+ linkQueue = null;
+ });
+
+ return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
+ var childBoundTranscludeFn = boundTranscludeFn;
+ if (scope.$$destroyed) return;
+ if (linkQueue) {
+ linkQueue.push(scope,
+ node,
+ rootElement,
+ childBoundTranscludeFn);
+ } else {
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
+ }
+ };
+ }
+
+
+ /**
+ * Sorting function for bound directives.
+ */
+ function byPriority(a, b) {
+ var diff = b.priority - a.priority;
+ if (diff !== 0) return diff;
+ if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
+ return a.index - b.index;
+ }
+
+
+ function assertNoDuplicate(what, previousDirective, directive, element) {
+ if (previousDirective) {
+ throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
+ previousDirective.name, directive.name, what, startingTag(element));
+ }
+ }
+
+
+ function addTextInterpolateDirective(directives, text) {
+ var interpolateFn = $interpolate(text, true);
+ if (interpolateFn) {
+ directives.push({
+ priority: 0,
+ compile: function textInterpolateCompileFn(templateNode) {
+ var templateNodeParent = templateNode.parent(),
+ hasCompileParent = !!templateNodeParent.length;
+
+ // When transcluding a template that has bindings in the root
+ // we don't have a parent and thus need to add the class during linking fn.
+ if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
+
+ return function textInterpolateLinkFn(scope, node) {
+ var parent = node.parent();
+ if (!hasCompileParent) compile.$$addBindingClass(parent);
+ compile.$$addBindingInfo(parent, interpolateFn.expressions);
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
+ node[0].nodeValue = value;
+ });
+ };
+ }
+ });
+ }
+ }
+
+
+ function wrapTemplate(type, template) {
+ type = lowercase(type || 'html');
+ switch (type) {
+ case 'svg':
+ case 'math':
+ var wrapper = document.createElement('div');
+ wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
+ return wrapper.childNodes[0].childNodes;
+ default:
+ return template;
+ }
+ }
+
+
+ function getTrustedContext(node, attrNormalizedName) {
+ if (attrNormalizedName == "srcdoc") {
+ return $sce.HTML;
+ }
+ var tag = nodeName_(node);
+ // maction[xlink:href] can source SVG. It's not limited to <maction>.
+ if (attrNormalizedName == "xlinkHref" ||
+ (tag == "form" && attrNormalizedName == "action") ||
+ (tag != "img" && (attrNormalizedName == "src" ||
+ attrNormalizedName == "ngSrc"))) {
+ return $sce.RESOURCE_URL;
+ }
+ }
+
+
+ function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
+ var trustedContext = getTrustedContext(node, name);
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
+
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
+
+ // no interpolation found -> ignore
+ if (!interpolateFn) return;
+
+
+ if (name === "multiple" && nodeName_(node) === "select") {
+ throw $compileMinErr("selmulti",
+ "Binding to the 'multiple' attribute is not supported. Element: {0}",
+ startingTag(node));
+ }
+
+ directives.push({
+ priority: 100,
+ compile: function() {
+ return {
+ pre: function attrInterpolatePreLinkFn(scope, element, attr) {
+ var $$observers = (attr.$$observers || (attr.$$observers = {}));
+
+ if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
+ throw $compileMinErr('nodomevents',
+ "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
+ "ng- versions (such as ng-click instead of onclick) instead.");
+ }
+
+ // If the attribute has changed since last $interpolate()ed
+ var newValue = attr[name];
+ if (newValue !== value) {
+ // we need to interpolate again since the attribute value has been updated
+ // (e.g. by another directive's compile function)
+ // ensure unset/empty values make interpolateFn falsy
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
+ value = newValue;
+ }
+
+ // if attribute was updated so that there is no interpolation going on we don't want to
+ // register any observers
+ if (!interpolateFn) return;
+
+ // initialize attr object so that it's ready in case we need the value for isolate
+ // scope initialization, otherwise the value would not be available from isolate
+ // directive's linking fn during linking phase
+ attr[name] = interpolateFn(scope);
+
+ ($$observers[name] || ($$observers[name] = [])).$$inter = true;
+ (attr.$$observers && attr.$$observers[name].$$scope || scope).
+ $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
+ //special case for class attribute addition + removal
+ //so that class changes can tap into the animation
+ //hooks provided by the $animate service. Be sure to
+ //skip animations when the first digest occurs (when
+ //both the new and the old values are the same) since
+ //the CSS classes are the non-interpolated values
+ if (name === 'class' && newValue != oldValue) {
+ attr.$updateClass(newValue, oldValue);
+ } else {
+ attr.$set(name, newValue);
+ }
+ });
+ }
+ };
+ }
+ });
+ }
+
+
+ /**
+ * This is a special jqLite.replaceWith, which can replace items which
+ * have no parents, provided that the containing jqLite collection is provided.
+ *
+ * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
+ * in the root of the tree.
+ * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
+ * the shell, but replace its DOM node reference.
+ * @param {Node} newNode The new DOM node.
+ */
+ function replaceWith($rootElement, elementsToRemove, newNode) {
+ var firstElementToRemove = elementsToRemove[0],
+ removeCount = elementsToRemove.length,
+ parent = firstElementToRemove.parentNode,
+ i, ii;
+
+ if ($rootElement) {
+ for (i = 0, ii = $rootElement.length; i < ii; i++) {
+ if ($rootElement[i] == firstElementToRemove) {
+ $rootElement[i++] = newNode;
+ for (var j = i, j2 = j + removeCount - 1,
+ jj = $rootElement.length;
+ j < jj; j++, j2++) {
+ if (j2 < jj) {
+ $rootElement[j] = $rootElement[j2];
+ } else {
+ delete $rootElement[j];
+ }
+ }
+ $rootElement.length -= removeCount - 1;
+
+ // If the replaced element is also the jQuery .context then replace it
+ // .context is a deprecated jQuery api, so we should set it only when jQuery set it
+ // http://api.jquery.com/context/
+ if ($rootElement.context === firstElementToRemove) {
+ $rootElement.context = newNode;
+ }
+ break;
+ }
+ }
+ }
+
+ if (parent) {
+ parent.replaceChild(newNode, firstElementToRemove);
+ }
+
+ // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(firstElementToRemove);
+
+ // Copy over user data (that includes Angular's $scope etc.). Don't copy private
+ // data here because there's no public interface in jQuery to do that and copying over
+ // event listeners (which is the main use of private data) wouldn't work anyway.
+ jqLite(newNode).data(jqLite(firstElementToRemove).data());
+
+ // Remove data of the replaced element. We cannot just call .remove()
+ // on the element it since that would deallocate scope that is needed
+ // for the new node. Instead, remove the data "manually".
+ if (!jQuery) {
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
+ } else {
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
+ // the replaced element. The cleanData version monkey-patched by Angular would cause
+ // the scope to be trashed and we do need the very same scope to work with the new
+ // element. However, we cannot just cache the non-patched version and use it here as
+ // that would break if another library patches the method after Angular does (one
+ // example is jQuery UI). Instead, set a flag indicating scope destroying should be
+ // skipped this one time.
+ skipDestroyOnNextJQueryCleanData = true;
+ jQuery.cleanData([firstElementToRemove]);
+ }
+
+ for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
+ var element = elementsToRemove[k];
+ jqLite(element).remove(); // must do this way to clean up expando
+ fragment.appendChild(element);
+ delete elementsToRemove[k];
+ }
+
+ elementsToRemove[0] = newNode;
+ elementsToRemove.length = 1;
+ }
+
+
+ function cloneAndAnnotateFn(fn, annotation) {
+ return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
+ }
+
+
+ function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
+ try {
+ linkFn(scope, $element, attrs, controllers, transcludeFn);
+ } catch (e) {
+ $exceptionHandler(e, startingTag($element));
+ }
+ }
+ }];
+}
+
+var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
+/**
+ * Converts all accepted directives format into proper directive name.
+ * @param name Name to normalize
+ */
+function directiveNormalize(name) {
+ return camelCase(name.replace(PREFIX_REGEXP, ''));
+}
+
+/**
+ * @ngdoc type
+ * @name $compile.directive.Attributes
+ *
+ * @description
+ * A shared object between directive compile / linking functions which contains normalized DOM
+ * element attributes. The values reflect current binding state `{{ }}`. The normalization is
+ * needed since all of these are treated as equivalent in Angular:
+ *
+ * ```
+ * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
+ * ```
+ */
+
+/**
+ * @ngdoc property
+ * @name $compile.directive.Attributes#$attr
+ *
+ * @description
+ * A map of DOM element attribute names to the normalized name. This is
+ * needed to do reverse lookup from normalized name back to actual name.
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$set
+ * @kind function
+ *
+ * @description
+ * Set DOM element attribute value.
+ *
+ *
+ * @param {string} name Normalized element attribute name of the property to modify. The name is
+ * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
+ * property to the original name.
+ * @param {string} value Value to set the attribute to. The value can be an interpolated string.
+ */
+
+
+
+/**
+ * Closure compiler type information
+ */
+
+function nodesetLinkingFn(
+ /* angular.Scope */ scope,
+ /* NodeList */ nodeList,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function directiveLinkingFn(
+ /* nodesetLinkingFn */ nodesetLinkingFn,
+ /* angular.Scope */ scope,
+ /* Node */ node,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function tokenDifference(str1, str2) {
+ var values = '',
+ tokens1 = str1.split(/\s+/),
+ tokens2 = str2.split(/\s+/);
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values += (values.length > 0 ? ' ' : '') + token;
+ }
+ return values;
+}
+
+function removeComments(jqNodes) {
+ jqNodes = jqLite(jqNodes);
+ var i = jqNodes.length;
+
+ if (i <= 1) {
+ return jqNodes;
+ }
+
+ while (i--) {
+ var node = jqNodes[i];
+ if (node.nodeType === NODE_TYPE_COMMENT) {
+ splice.call(jqNodes, i, 1);
+ }
+ }
+ return jqNodes;
+}
+
+var $controllerMinErr = minErr('$controller');
+
+/**
+ * @ngdoc provider
+ * @name $controllerProvider
+ * @description
+ * The {@link ng.$controller $controller service} is used by Angular to create new
+ * controllers.
+ *
+ * This provider allows controller registration via the
+ * {@link ng.$controllerProvider#register register} method.
+ */
+function $ControllerProvider() {
+ var controllers = {},
+ globals = false,
+ CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
+
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#register
+ * @param {string|Object} name Controller name, or an object map of controllers where the keys are
+ * the names and the values are the constructors.
+ * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
+ * annotations in the array notation).
+ */
+ this.register = function(name, constructor) {
+ assertNotHasOwnProperty(name, 'controller');
+ if (isObject(name)) {
+ extend(controllers, name);
+ } else {
+ controllers[name] = constructor;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#allowGlobals
+ * @description If called, allows `$controller` to find controller constructors on `window`
+ */
+ this.allowGlobals = function() {
+ globals = true;
+ };
+
+
+ this.$get = ['$injector', '$window', function($injector, $window) {
+
+ /**
+ * @ngdoc service
+ * @name $controller
+ * @requires $injector
+ *
+ * @param {Function|string} constructor If called with a function then it's considered to be the
+ * controller constructor function. Otherwise it's considered to be a string which is used
+ * to retrieve the controller constructor using the following steps:
+ *
+ * * check if a controller with given name is registered via `$controllerProvider`
+ * * check if evaluating the string on the current scope returns a constructor
+ * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
+ * `window` object (not recommended)
+ *
+ * The string can use the `controller as property` syntax, where the controller instance is published
+ * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
+ * to work correctly.
+ *
+ * @param {Object} locals Injection locals for Controller.
+ * @return {Object} Instance of given controller.
+ *
+ * @description
+ * `$controller` service is responsible for instantiating controllers.
+ *
+ * It's just a simple call to {@link auto.$injector $injector}, but extracted into
+ * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
+ */
+ return function(expression, locals, later, ident) {
+ // PRIVATE API:
+ // param `later` --- indicates that the controller's constructor is invoked at a later time.
+ // If true, $controller will allocate the object with the correct
+ // prototype chain, but will not invoke the controller until a returned
+ // callback is invoked.
+ // param `ident` --- An optional label which overrides the label parsed from the controller
+ // expression, if any.
+ var instance, match, constructor, identifier;
+ later = later === true;
+ if (ident && isString(ident)) {
+ identifier = ident;
+ }
+
+ if (isString(expression)) {
+ match = expression.match(CNTRL_REG);
+ if (!match) {
+ throw $controllerMinErr('ctrlfmt',
+ "Badly formed controller string '{0}'. " +
+ "Must match `__name__ as __id__` or `__name__`.", expression);
+ }
+ constructor = match[1],
+ identifier = identifier || match[3];
+ expression = controllers.hasOwnProperty(constructor)
+ ? controllers[constructor]
+ : getter(locals.$scope, constructor, true) ||
+ (globals ? getter($window, constructor, true) : undefined);
+
+ assertArgFn(expression, constructor, true);
+ }
+
+ if (later) {
+ // Instantiate controller later:
+ // This machinery is used to create an instance of the object before calling the
+ // controller's constructor itself.
+ //
+ // This allows properties to be added to the controller before the constructor is
+ // invoked. Primarily, this is used for isolate scope bindings in $compile.
+ //
+ // This feature is not intended for use by applications, and is thus not documented
+ // publicly.
+ // Object creation: http://jsperf.com/create-constructor/2
+ var controllerPrototype = (isArray(expression) ?
+ expression[expression.length - 1] : expression).prototype;
+ instance = Object.create(controllerPrototype || null);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ return extend(function() {
+ $injector.invoke(expression, instance, locals, constructor);
+ return instance;
+ }, {
+ instance: instance,
+ identifier: identifier
+ });
+ }
+
+ instance = $injector.instantiate(expression, locals, constructor);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ return instance;
+ };
+
+ function addIdentifier(locals, identifier, instance, name) {
+ if (!(locals && isObject(locals.$scope))) {
+ throw minErr('$controller')('noscp',
+ "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
+ name, identifier);
+ }
+
+ locals.$scope[identifier] = instance;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $document
+ * @requires $window
+ *
+ * @description
+ * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
+ *
+ * @example
+ <example module="documentExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p>$document title: <b ng-bind="title"></b></p>
+ <p>window.document title: <b ng-bind="windowTitle"></b></p>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('documentExample', [])
+ .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
+ $scope.title = $document[0].title;
+ $scope.windowTitle = angular.element(window.document)[0].title;
+ }]);
+ </file>
+ </example>
+ */
+function $DocumentProvider() {
+ this.$get = ['$window', function(window) {
+ return jqLite(window.document);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $exceptionHandler
+ * @requires ng.$log
+ *
+ * @description
+ * Any uncaught exception in angular expressions is delegated to this service.
+ * The default implementation simply delegates to `$log.error` which logs it into
+ * the browser console.
+ *
+ * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
+ * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
+ *
+ * ## Example:
+ *
+ * ```js
+ * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
+ * return function(exception, cause) {
+ * exception.message += ' (caused by "' + cause + '")';
+ * throw exception;
+ * };
+ * });
+ * ```
+ *
+ * This example will override the normal action of `$exceptionHandler`, to make angular
+ * exceptions fail hard when they happen, instead of just logging to the console.
+ *
+ * <hr />
+ * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
+ * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
+ * (unless executed during a digest).
+ *
+ * If you wish, you can manually delegate exceptions, e.g.
+ * `try { ... } catch(e) { $exceptionHandler(e); }`
+ *
+ * @param {Error} exception Exception associated with the error.
+ * @param {string=} cause optional information about the context in which
+ * the error was thrown.
+ *
+ */
+function $ExceptionHandlerProvider() {
+ this.$get = ['$log', function($log) {
+ return function(exception, cause) {
+ $log.error.apply($log, arguments);
+ };
+ }];
+}
+
+var APPLICATION_JSON = 'application/json';
+var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
+var JSON_START = /^\[|^\{(?!\{)/;
+var JSON_ENDS = {
+ '[': /]$/,
+ '{': /}$/
+};
+var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
+
+function defaultHttpResponseTransform(data, headers) {
+ if (isString(data)) {
+ // Strip json vulnerability protection prefix and trim whitespace
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
+
+ if (tempData) {
+ var contentType = headers('Content-Type');
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
+ data = fromJson(tempData);
+ }
+ }
+ }
+
+ return data;
+}
+
+function isJsonLike(str) {
+ var jsonStart = str.match(JSON_START);
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
+}
+
+/**
+ * Parse headers into key value object
+ *
+ * @param {string} headers Raw headers as a string
+ * @returns {Object} Parsed headers as key value object
+ */
+function parseHeaders(headers) {
+ var parsed = createMap(), key, val, i;
+
+ if (!headers) return parsed;
+
+ forEach(headers.split('\n'), function(line) {
+ i = line.indexOf(':');
+ key = lowercase(trim(line.substr(0, i)));
+ val = trim(line.substr(i + 1));
+
+ if (key) {
+ parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
+ }
+ });
+
+ return parsed;
+}
+
+
+/**
+ * Returns a function that provides access to parsed headers.
+ *
+ * Headers are lazy parsed when first requested.
+ * @see parseHeaders
+ *
+ * @param {(string|Object)} headers Headers to provide access to.
+ * @returns {function(string=)} Returns a getter function which if called with:
+ *
+ * - if called with single an argument returns a single header value or null
+ * - if called with no arguments returns an object containing all headers.
+ */
+function headersGetter(headers) {
+ var headersObj = isObject(headers) ? headers : undefined;
+
+ return function(name) {
+ if (!headersObj) headersObj = parseHeaders(headers);
+
+ if (name) {
+ var value = headersObj[lowercase(name)];
+ if (value === void 0) {
+ value = null;
+ }
+ return value;
+ }
+
+ return headersObj;
+ };
+}
+
+
+/**
+ * Chain all given functions
+ *
+ * This function is used for both request and response transforming
+ *
+ * @param {*} data Data to transform.
+ * @param {function(string=)} headers HTTP headers getter fn.
+ * @param {number} status HTTP status code of the response.
+ * @param {(Function|Array.<Function>)} fns Function or an array of functions.
+ * @returns {*} Transformed data.
+ */
+function transformData(data, headers, status, fns) {
+ if (isFunction(fns))
+ return fns(data, headers, status);
+
+ forEach(fns, function(fn) {
+ data = fn(data, headers, status);
+ });
+
+ return data;
+}
+
+
+function isSuccess(status) {
+ return 200 <= status && status < 300;
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $httpProvider
+ * @description
+ * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
+ * */
+function $HttpProvider() {
+ /**
+ * @ngdoc property
+ * @name $httpProvider#defaults
+ * @description
+ *
+ * Object containing default values for all {@link ng.$http $http} requests.
+ *
+ * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
+ * that will provide the cache for all requests who set their `cache` property to `true`.
+ * If you set the `default.cache = false` then only requests that specify their own custom
+ * cache object will be cached. See {@link $http#caching $http Caching} for more information.
+ *
+ * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
+ * Defaults value is `'XSRF-TOKEN'`.
+ *
+ * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
+ * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
+ *
+ * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
+ * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
+ * setting default headers.
+ * - **`defaults.headers.common`**
+ * - **`defaults.headers.post`**
+ * - **`defaults.headers.put`**
+ * - **`defaults.headers.patch`**
+ *
+ **/
+ var defaults = this.defaults = {
+ // transform incoming response data
+ transformResponse: [defaultHttpResponseTransform],
+
+ // transform outgoing request data
+ transformRequest: [function(d) {
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
+ }],
+
+ // default headers
+ headers: {
+ common: {
+ 'Accept': 'application/json, text/plain, */*'
+ },
+ post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
+ },
+
+ xsrfCookieName: 'XSRF-TOKEN',
+ xsrfHeaderName: 'X-XSRF-TOKEN'
+ };
+
+ var useApplyAsync = false;
+ /**
+ * @ngdoc method
+ * @name $httpProvider#useApplyAsync
+ * @description
+ *
+ * Configure $http service to combine processing of multiple http responses received at around
+ * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
+ * significant performance improvement for bigger applications that make many HTTP requests
+ * concurrently (common during application bootstrap).
+ *
+ * Defaults to false. If no value is specifed, returns the current configured value.
+ *
+ * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
+ * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
+ * to load and share the same digest cycle.
+ *
+ * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
+ * otherwise, returns the current configured value.
+ **/
+ this.useApplyAsync = function(value) {
+ if (isDefined(value)) {
+ useApplyAsync = !!value;
+ return this;
+ }
+ return useApplyAsync;
+ };
+
+ /**
+ * @ngdoc property
+ * @name $httpProvider#interceptors
+ * @description
+ *
+ * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
+ * pre-processing of request or postprocessing of responses.
+ *
+ * These service factories are ordered by request, i.e. they are applied in the same order as the
+ * array, on request, but reverse order, on response.
+ *
+ * {@link ng.$http#interceptors Interceptors detailed info}
+ **/
+ var interceptorFactories = this.interceptors = [];
+
+ this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
+ function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
+
+ var defaultCache = $cacheFactory('$http');
+
+ /**
+ * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
+ * The reversal is needed so that we can build up the interception chain around the
+ * server request.
+ */
+ var reversedInterceptors = [];
+
+ forEach(interceptorFactories, function(interceptorFactory) {
+ reversedInterceptors.unshift(isString(interceptorFactory)
+ ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
+ });
+
+ /**
+ * @ngdoc service
+ * @kind function
+ * @name $http
+ * @requires ng.$httpBackend
+ * @requires $cacheFactory
+ * @requires $rootScope
+ * @requires $q
+ * @requires $injector
+ *
+ * @description
+ * The `$http` service is a core Angular service that facilitates communication with the remote
+ * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
+ * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
+ *
+ * For unit testing applications that use `$http` service, see
+ * {@link ngMock.$httpBackend $httpBackend mock}.
+ *
+ * For a higher level of abstraction, please check out the {@link ngResource.$resource
+ * $resource} service.
+ *
+ * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
+ * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
+ * it is important to familiarize yourself with these APIs and the guarantees they provide.
+ *
+ *
+ * ## General usage
+ * The `$http` service is a function which takes a single argument — a configuration object —
+ * that is used to generate an HTTP request and returns a {@link ng.$q promise}
+ * with two $http specific methods: `success` and `error`.
+ *
+ * ```js
+ * // Simple GET request example :
+ * $http.get('/someUrl').
+ * success(function(data, status, headers, config) {
+ * // this callback will be called asynchronously
+ * // when the response is available
+ * }).
+ * error(function(data, status, headers, config) {
+ * // called asynchronously if an error occurs
+ * // or server returns response with an error status.
+ * });
+ * ```
+ *
+ * ```js
+ * // Simple POST request example (passing data) :
+ * $http.post('/someUrl', {msg:'hello word!'}).
+ * success(function(data, status, headers, config) {
+ * // this callback will be called asynchronously
+ * // when the response is available
+ * }).
+ * error(function(data, status, headers, config) {
+ * // called asynchronously if an error occurs
+ * // or server returns response with an error status.
+ * });
+ * ```
+ *
+ *
+ * Since the returned value of calling the $http function is a `promise`, you can also use
+ * the `then` method to register callbacks, and these callbacks will receive a single argument –
+ * an object representing the response. See the API signature and type info below for more
+ * details.
+ *
+ * A response status code between 200 and 299 is considered a success status and
+ * will result in the success callback being called. Note that if the response is a redirect,
+ * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
+ * called for such responses.
+ *
+ * ## Writing Unit Tests that use $http
+ * When unit testing (using {@link ngMock ngMock}), it is necessary to call
+ * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
+ * request using trained responses.
+ *
+ * ```
+ * $httpBackend.expectGET(...);
+ * $http.get(...);
+ * $httpBackend.flush();
+ * ```
+ *
+ * ## Shortcut methods
+ *
+ * Shortcut methods are also available. All shortcut methods require passing in the URL, and
+ * request data must be passed in for POST/PUT requests.
+ *
+ * ```js
+ * $http.get('/someUrl').success(successCallback);
+ * $http.post('/someUrl', data).success(successCallback);
+ * ```
+ *
+ * Complete list of shortcut methods:
+ *
+ * - {@link ng.$http#get $http.get}
+ * - {@link ng.$http#head $http.head}
+ * - {@link ng.$http#post $http.post}
+ * - {@link ng.$http#put $http.put}
+ * - {@link ng.$http#delete $http.delete}
+ * - {@link ng.$http#jsonp $http.jsonp}
+ * - {@link ng.$http#patch $http.patch}
+ *
+ *
+ * ## Setting HTTP Headers
+ *
+ * The $http service will automatically add certain HTTP headers to all requests. These defaults
+ * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
+ * object, which currently contains this default configuration:
+ *
+ * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
+ * - `Accept: application/json, text/plain, * / *`
+ * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
+ * - `Content-Type: application/json`
+ * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
+ * - `Content-Type: application/json`
+ *
+ * To add or overwrite these defaults, simply add or remove a property from these configuration
+ * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
+ * with the lowercased HTTP method name as the key, e.g.
+ * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
+ *
+ * The defaults can also be set at runtime via the `$http.defaults` object in the same
+ * fashion. For example:
+ *
+ * ```
+ * module.run(function($http) {
+ * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
+ * });
+ * ```
+ *
+ * In addition, you can supply a `headers` property in the config object passed when
+ * calling `$http(config)`, which overrides the defaults without changing them globally.
+ *
+ * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
+ * Use the `headers` property, setting the desired header to `undefined`. For example:
+ *
+ * ```js
+ * var req = {
+ * method: 'POST',
+ * url: 'http://example.com',
+ * headers: {
+ * 'Content-Type': undefined
+ * },
+ * data: { test: 'test' }
+ * }
+ *
+ * $http(req).success(function(){...}).error(function(){...});
+ * ```
+ *
+ * ## Transforming Requests and Responses
+ *
+ * Both requests and responses can be transformed using transformation functions: `transformRequest`
+ * and `transformResponse`. These properties can be a single function that returns
+ * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
+ * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
+ *
+ * ### Default Transformations
+ *
+ * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
+ * `defaults.transformResponse` properties. If a request does not provide its own transformations
+ * then these will be applied.
+ *
+ * You can augment or replace the default transformations by modifying these properties by adding to or
+ * replacing the array.
+ *
+ * Angular provides the following default transformations:
+ *
+ * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
+ *
+ * - If the `data` property of the request configuration object contains an object, serialize it
+ * into JSON format.
+ *
+ * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
+ *
+ * - If XSRF prefix is detected, strip it (see Security Considerations section below).
+ * - If JSON response is detected, deserialize it using a JSON parser.
+ *
+ *
+ * ### Overriding the Default Transformations Per Request
+ *
+ * If you wish override the request/response transformations only for a single request then provide
+ * `transformRequest` and/or `transformResponse` properties on the configuration object passed
+ * into `$http`.
+ *
+ * Note that if you provide these properties on the config object the default transformations will be
+ * overwritten. If you wish to augment the default transformations then you must include them in your
+ * local transformation array.
+ *
+ * The following code demonstrates adding a new response transformation to be run after the default response
+ * transformations have been run.
+ *
+ * ```js
+ * function appendTransform(defaults, transform) {
+ *
+ * // We can't guarantee that the default transformation is an array
+ * defaults = angular.isArray(defaults) ? defaults : [defaults];
+ *
+ * // Append the new transformation to the defaults
+ * return defaults.concat(transform);
+ * }
+ *
+ * $http({
+ * url: '...',
+ * method: 'GET',
+ * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
+ * return doTransform(value);
+ * })
+ * });
+ * ```
+ *
+ *
+ * ## Caching
+ *
+ * To enable caching, set the request configuration `cache` property to `true` (to use default
+ * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
+ * When the cache is enabled, `$http` stores the response from the server in the specified
+ * cache. The next time the same request is made, the response is served from the cache without
+ * sending a request to the server.
+ *
+ * Note that even if the response is served from cache, delivery of the data is asynchronous in
+ * the same way that real requests are.
+ *
+ * If there are multiple GET requests for the same URL that should be cached using the same
+ * cache, but the cache is not populated yet, only one request to the server will be made and
+ * the remaining requests will be fulfilled using the response from the first request.
+ *
+ * You can change the default cache to a new object (built with
+ * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
+ * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
+ * their `cache` property to `true` will now use this cache object.
+ *
+ * If you set the default cache to `false` then only requests that specify their own custom
+ * cache object will be cached.
+ *
+ * ## Interceptors
+ *
+ * Before you start creating interceptors, be sure to understand the
+ * {@link ng.$q $q and deferred/promise APIs}.
+ *
+ * For purposes of global error handling, authentication, or any kind of synchronous or
+ * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
+ * able to intercept requests before they are handed to the server and
+ * responses before they are handed over to the application code that
+ * initiated these requests. The interceptors leverage the {@link ng.$q
+ * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
+ *
+ * The interceptors are service factories that are registered with the `$httpProvider` by
+ * adding them to the `$httpProvider.interceptors` array. The factory is called and
+ * injected with dependencies (if specified) and returns the interceptor.
+ *
+ * There are two kinds of interceptors (and two kinds of rejection interceptors):
+ *
+ * * `request`: interceptors get called with a http `config` object. The function is free to
+ * modify the `config` object or create a new one. The function needs to return the `config`
+ * object directly, or a promise containing the `config` or a new `config` object.
+ * * `requestError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ * * `response`: interceptors get called with http `response` object. The function is free to
+ * modify the `response` object or create a new one. The function needs to return the `response`
+ * object directly, or as a promise containing the `response` or a new `response` object.
+ * * `responseError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ *
+ *
+ * ```js
+ * // register the interceptor as a service
+ * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+ * return {
+ * // optional method
+ * 'request': function(config) {
+ * // do something on success
+ * return config;
+ * },
+ *
+ * // optional method
+ * 'requestError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * },
+ *
+ *
+ *
+ * // optional method
+ * 'response': function(response) {
+ * // do something on success
+ * return response;
+ * },
+ *
+ * // optional method
+ * 'responseError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * }
+ * };
+ * });
+ *
+ * $httpProvider.interceptors.push('myHttpInterceptor');
+ *
+ *
+ * // alternatively, register the interceptor via an anonymous factory
+ * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
+ * return {
+ * 'request': function(config) {
+ * // same as above
+ * },
+ *
+ * 'response': function(response) {
+ * // same as above
+ * }
+ * };
+ * });
+ * ```
+ *
+ * ## Security Considerations
+ *
+ * When designing web applications, consider security threats from:
+ *
+ * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
+ *
+ * Both server and the client must cooperate in order to eliminate these threats. Angular comes
+ * pre-configured with strategies that address these issues, but for this to work backend server
+ * cooperation is required.
+ *
+ * ### JSON Vulnerability Protection
+ *
+ * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * allows third party website to turn your JSON resource URL into
+ * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
+ * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
+ * Angular will automatically strip the prefix before processing it as JSON.
+ *
+ * For example if your server needs to return:
+ * ```js
+ * ['one','two']
+ * ```
+ *
+ * which is vulnerable to attack, your server can return:
+ * ```js
+ * )]}',
+ * ['one','two']
+ * ```
+ *
+ * Angular will strip the prefix, before processing the JSON.
+ *
+ *
+ * ### Cross Site Request Forgery (XSRF) Protection
+ *
+ * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
+ * an unauthorized site can gain your user's private data. Angular provides a mechanism
+ * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
+ * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
+ * JavaScript that runs on your domain could read the cookie, your server can be assured that
+ * the XHR came from JavaScript running on your domain. The header will not be set for
+ * cross-domain requests.
+ *
+ * To take advantage of this, your server needs to set a token in a JavaScript readable session
+ * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
+ * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
+ * that only JavaScript running on your domain could have sent the request. The token must be
+ * unique for each user and must be verifiable by the server (to prevent the JavaScript from
+ * making up its own tokens). We recommend that the token is a digest of your site's
+ * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
+ * for added security.
+ *
+ * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
+ * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
+ * or the per-request config object.
+ *
+ *
+ * @param {object} config Object describing the request to be made and how it should be
+ * processed. The object has following properties:
+ *
+ * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
+ * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
+ * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned
+ * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
+ * JSONified.
+ * - **data** – `{string|Object}` – Data to be sent as the request message data.
+ * - **headers** – `{Object}` – Map of strings or functions which return strings representing
+ * HTTP headers to send to the server. If the return value of a function is null, the
+ * header will not be sent.
+ * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
+ * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
+ * - **transformRequest** –
+ * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * request body and headers and returns its transformed (typically serialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default Transformations}
+ * - **transformResponse** –
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * response body, headers and status and returns its transformed (typically deserialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default Transformations}
+ * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
+ * GET request, otherwise if a cache instance built with
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
+ * caching.
+ * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
+ * that should abort the request when resolved.
+ * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
+ * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
+ * for more information.
+ * - **responseType** - `{string}` - see
+ * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
+ *
+ * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
+ * standard `then` method and two http specific methods: `success` and `error`. The `then`
+ * method takes two arguments a success and an error callback which will be called with a
+ * response object. The `success` and `error` methods take a single argument - a function that
+ * will be called when the request succeeds or fails respectively. The arguments passed into
+ * these functions are destructured representation of the response object passed into the
+ * `then` method. The response object has these properties:
+ *
+ * - **data** – `{string|Object}` – The response body transformed with the transform
+ * functions.
+ * - **status** – `{number}` – HTTP status code of the response.
+ * - **headers** – `{function([headerName])}` – Header getter function.
+ * - **config** – `{Object}` – The configuration object that was used to generate the request.
+ * - **statusText** – `{string}` – HTTP status text of the response.
+ *
+ * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
+ * requests. This is primarily meant to be used for debugging purposes.
+ *
+ *
+ * @example
+<example module="httpExample">
+<file name="index.html">
+ <div ng-controller="FetchController">
+ <select ng-model="method">
+ <option>GET</option>
+ <option>JSONP</option>
+ </select>
+ <input type="text" ng-model="url" size="80"/>
+ <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
+ <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
+ <button id="samplejsonpbtn"
+ ng-click="updateModel('JSONP',
+ 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
+ Sample JSONP
+ </button>
+ <button id="invalidjsonpbtn"
+ ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
+ Invalid JSONP
+ </button>
+ <pre>http status code: {{status}}</pre>
+ <pre>http response data: {{data}}</pre>
+ </div>
+</file>
+<file name="script.js">
+ angular.module('httpExample', [])
+ .controller('FetchController', ['$scope', '$http', '$templateCache',
+ function($scope, $http, $templateCache) {
+ $scope.method = 'GET';
+ $scope.url = 'http-hello.html';
+
+ $scope.fetch = function() {
+ $scope.code = null;
+ $scope.response = null;
+
+ $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
+ success(function(data, status) {
+ $scope.status = status;
+ $scope.data = data;
+ }).
+ error(function(data, status) {
+ $scope.data = data || "Request failed";
+ $scope.status = status;
+ });
+ };
+
+ $scope.updateModel = function(method, url) {
+ $scope.method = method;
+ $scope.url = url;
+ };
+ }]);
+</file>
+<file name="http-hello.html">
+ Hello, $http!
+</file>
+<file name="protractor.js" type="protractor">
+ var status = element(by.binding('status'));
+ var data = element(by.binding('data'));
+ var fetchBtn = element(by.id('fetchbtn'));
+ var sampleGetBtn = element(by.id('samplegetbtn'));
+ var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
+ var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
+
+ it('should make an xhr GET request', function() {
+ sampleGetBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('200');
+ expect(data.getText()).toMatch(/Hello, \$http!/);
+ });
+
+// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
+// it('should make a JSONP request to angularjs.org', function() {
+// sampleJsonpBtn.click();
+// fetchBtn.click();
+// expect(status.getText()).toMatch('200');
+// expect(data.getText()).toMatch(/Super Hero!/);
+// });
+
+ it('should make JSONP request to invalid URL and invoke the error handler',
+ function() {
+ invalidJsonpBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('0');
+ expect(data.getText()).toMatch('Request failed');
+ });
+</file>
+</example>
+ */
+ function $http(requestConfig) {
+
+ if (!angular.isObject(requestConfig)) {
+ throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
+ }
+
+ var config = extend({
+ method: 'get',
+ transformRequest: defaults.transformRequest,
+ transformResponse: defaults.transformResponse
+ }, requestConfig);
+
+ config.headers = mergeHeaders(requestConfig);
+ config.method = uppercase(config.method);
+
+ var serverRequest = function(config) {
+ var headers = config.headers;
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
+
+ // strip content-type if data is undefined
+ if (isUndefined(reqData)) {
+ forEach(headers, function(value, header) {
+ if (lowercase(header) === 'content-type') {
+ delete headers[header];
+ }
+ });
+ }
+
+ if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
+ config.withCredentials = defaults.withCredentials;
+ }
+
+ // send request
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
+ };
+
+ var chain = [serverRequest, undefined];
+ var promise = $q.when(config);
+
+ // apply interceptors
+ forEach(reversedInterceptors, function(interceptor) {
+ if (interceptor.request || interceptor.requestError) {
+ chain.unshift(interceptor.request, interceptor.requestError);
+ }
+ if (interceptor.response || interceptor.responseError) {
+ chain.push(interceptor.response, interceptor.responseError);
+ }
+ });
+
+ while (chain.length) {
+ var thenFn = chain.shift();
+ var rejectFn = chain.shift();
+
+ promise = promise.then(thenFn, rejectFn);
+ }
+
+ promise.success = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+
+ promise.error = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(null, function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+
+ return promise;
+
+ function transformResponse(response) {
+ // make a copy since the response must be cacheable
+ var resp = extend({}, response);
+ if (!response.data) {
+ resp.data = response.data;
+ } else {
+ resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
+ }
+ return (isSuccess(response.status))
+ ? resp
+ : $q.reject(resp);
+ }
+
+ function executeHeaderFns(headers) {
+ var headerContent, processedHeaders = {};
+
+ forEach(headers, function(headerFn, header) {
+ if (isFunction(headerFn)) {
+ headerContent = headerFn();
+ if (headerContent != null) {
+ processedHeaders[header] = headerContent;
+ }
+ } else {
+ processedHeaders[header] = headerFn;
+ }
+ });
+
+ return processedHeaders;
+ }
+
+ function mergeHeaders(config) {
+ var defHeaders = defaults.headers,
+ reqHeaders = extend({}, config.headers),
+ defHeaderName, lowercaseDefHeaderName, reqHeaderName;
+
+ defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
+
+ // using for-in instead of forEach to avoid unecessary iteration after header has been found
+ defaultHeadersIteration:
+ for (defHeaderName in defHeaders) {
+ lowercaseDefHeaderName = lowercase(defHeaderName);
+
+ for (reqHeaderName in reqHeaders) {
+ if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
+ continue defaultHeadersIteration;
+ }
+ }
+
+ reqHeaders[defHeaderName] = defHeaders[defHeaderName];
+ }
+
+ // execute if header value is a function for merged headers
+ return executeHeaderFns(reqHeaders);
+ }
+ }
+
+ $http.pendingRequests = [];
+
+ /**
+ * @ngdoc method
+ * @name $http#get
+ *
+ * @description
+ * Shortcut method to perform `GET` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#delete
+ *
+ * @description
+ * Shortcut method to perform `DELETE` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#head
+ *
+ * @description
+ * Shortcut method to perform `HEAD` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#jsonp
+ *
+ * @description
+ * Shortcut method to perform `JSONP` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request.
+ * The name of the callback should be the string `JSON_CALLBACK`.
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethods('get', 'delete', 'head', 'jsonp');
+
+ /**
+ * @ngdoc method
+ * @name $http#post
+ *
+ * @description
+ * Shortcut method to perform `POST` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#put
+ *
+ * @description
+ * Shortcut method to perform `PUT` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#patch
+ *
+ * @description
+ * Shortcut method to perform `PATCH` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethodsWithData('post', 'put', 'patch');
+
+ /**
+ * @ngdoc property
+ * @name $http#defaults
+ *
+ * @description
+ * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
+ * default headers, withCredentials as well as request and response transformations.
+ *
+ * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
+ */
+ $http.defaults = defaults;
+
+
+ return $http;
+
+
+ function createShortMethods(names) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, config) {
+ return $http(extend(config || {}, {
+ method: name,
+ url: url
+ }));
+ };
+ });
+ }
+
+
+ function createShortMethodsWithData(name) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, data, config) {
+ return $http(extend(config || {}, {
+ method: name,
+ url: url,
+ data: data
+ }));
+ };
+ });
+ }
+
+
+ /**
+ * Makes the request.
+ *
+ * !!! ACCESSES CLOSURE VARS:
+ * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
+ */
+ function sendReq(config, reqData) {
+ var deferred = $q.defer(),
+ promise = deferred.promise,
+ cache,
+ cachedResp,
+ reqHeaders = config.headers,
+ url = buildUrl(config.url, config.params);
+
+ $http.pendingRequests.push(config);
+ promise.then(removePendingReq, removePendingReq);
+
+
+ if ((config.cache || defaults.cache) && config.cache !== false &&
+ (config.method === 'GET' || config.method === 'JSONP')) {
+ cache = isObject(config.cache) ? config.cache
+ : isObject(defaults.cache) ? defaults.cache
+ : defaultCache;
+ }
+
+ if (cache) {
+ cachedResp = cache.get(url);
+ if (isDefined(cachedResp)) {
+ if (isPromiseLike(cachedResp)) {
+ // cached request has already been sent, but there is no response yet
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
+ } else {
+ // serving from cache
+ if (isArray(cachedResp)) {
+ resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
+ } else {
+ resolvePromise(cachedResp, 200, {}, 'OK');
+ }
+ }
+ } else {
+ // put the promise for the non-transformed response into cache as a placeholder
+ cache.put(url, promise);
+ }
+ }
+
+
+ // if we won't have the response in cache, set the xsrf headers and
+ // send the request to the backend
+ if (isUndefined(cachedResp)) {
+ var xsrfValue = urlIsSameOrigin(config.url)
+ ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
+ : undefined;
+ if (xsrfValue) {
+ reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
+ }
+
+ $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
+ config.withCredentials, config.responseType);
+ }
+
+ return promise;
+
+
+ /**
+ * Callback registered to $httpBackend():
+ * - caches the response if desired
+ * - resolves the raw $http promise
+ * - calls $apply
+ */
+ function done(status, response, headersString, statusText) {
+ if (cache) {
+ if (isSuccess(status)) {
+ cache.put(url, [status, response, parseHeaders(headersString), statusText]);
+ } else {
+ // remove promise from the cache
+ cache.remove(url);
+ }
+ }
+
+ function resolveHttpPromise() {
+ resolvePromise(response, status, headersString, statusText);
+ }
+
+ if (useApplyAsync) {
+ $rootScope.$applyAsync(resolveHttpPromise);
+ } else {
+ resolveHttpPromise();
+ if (!$rootScope.$$phase) $rootScope.$apply();
+ }
+ }
+
+
+ /**
+ * Resolves the raw $http promise.
+ */
+ function resolvePromise(response, status, headers, statusText) {
+ //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
+ status = status >= -1 ? status : 0;
+
+ (isSuccess(status) ? deferred.resolve : deferred.reject)({
+ data: response,
+ status: status,
+ headers: headersGetter(headers),
+ config: config,
+ statusText: statusText
+ });
+ }
+
+ function resolvePromiseWithResult(result) {
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
+ }
+
+ function removePendingReq() {
+ var idx = $http.pendingRequests.indexOf(config);
+ if (idx !== -1) $http.pendingRequests.splice(idx, 1);
+ }
+ }
+
+
+ function buildUrl(url, params) {
+ if (!params) return url;
+ var parts = [];
+ forEachSorted(params, function(value, key) {
+ if (value === null || isUndefined(value)) return;
+ if (!isArray(value)) value = [value];
+
+ forEach(value, function(v) {
+ if (isObject(v)) {
+ if (isDate(v)) {
+ v = v.toISOString();
+ } else {
+ v = toJson(v);
+ }
+ }
+ parts.push(encodeUriQuery(key) + '=' +
+ encodeUriQuery(v));
+ });
+ });
+ if (parts.length > 0) {
+ url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
+ }
+ return url;
+ }
+ }];
+}
+
+function createXhr() {
+ return new window.XMLHttpRequest();
+}
+
+/**
+ * @ngdoc service
+ * @name $httpBackend
+ * @requires $window
+ * @requires $document
+ *
+ * @description
+ * HTTP backend used by the {@link ng.$http service} that delegates to
+ * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
+ *
+ * You should never need to use this service directly, instead use the higher-level abstractions:
+ * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
+ *
+ * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
+ * $httpBackend} which can be trained with responses.
+ */
+function $HttpBackendProvider() {
+ this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
+ return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
+ }];
+}
+
+function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
+ // TODO(vojta): fix the signature
+ return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
+ $browser.$$incOutstandingRequestCount();
+ url = url || $browser.url();
+
+ if (lowercase(method) == 'jsonp') {
+ var callbackId = '_' + (callbacks.counter++).toString(36);
+ callbacks[callbackId] = function(data) {
+ callbacks[callbackId].data = data;
+ callbacks[callbackId].called = true;
+ };
+
+ var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
+ callbackId, function(status, text) {
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
+ callbacks[callbackId] = noop;
+ });
+ } else {
+
+ var xhr = createXhr();
+
+ xhr.open(method, url, true);
+ forEach(headers, function(value, key) {
+ if (isDefined(value)) {
+ xhr.setRequestHeader(key, value);
+ }
+ });
+
+ xhr.onload = function requestLoaded() {
+ var statusText = xhr.statusText || '';
+
+ // responseText is the old-school way of retrieving response (supported by IE9)
+ // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
+ var response = ('response' in xhr) ? xhr.response : xhr.responseText;
+
+ // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
+ var status = xhr.status === 1223 ? 204 : xhr.status;
+
+ // fix status code when it is 0 (0 status is undocumented).
+ // Occurs when accessing file resources or on Android 4.1 stock browser
+ // while retrieving files from application cache.
+ if (status === 0) {
+ status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
+ }
+
+ completeRequest(callback,
+ status,
+ response,
+ xhr.getAllResponseHeaders(),
+ statusText);
+ };
+
+ var requestError = function() {
+ // The response is always empty
+ // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
+ completeRequest(callback, -1, null, null, '');
+ };
+
+ xhr.onerror = requestError;
+ xhr.onabort = requestError;
+
+ if (withCredentials) {
+ xhr.withCredentials = true;
+ }
+
+ if (responseType) {
+ try {
+ xhr.responseType = responseType;
+ } catch (e) {
+ // WebKit added support for the json responseType value on 09/03/2013
+ // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
+ // known to throw when setting the value "json" as the response type. Other older
+ // browsers implementing the responseType
+ //
+ // The json response type can be ignored if not supported, because JSON payloads are
+ // parsed on the client-side regardless.
+ if (responseType !== 'json') {
+ throw e;
+ }
+ }
+ }
+
+ xhr.send(post || null);
+ }
+
+ if (timeout > 0) {
+ var timeoutId = $browserDefer(timeoutRequest, timeout);
+ } else if (isPromiseLike(timeout)) {
+ timeout.then(timeoutRequest);
+ }
+
+
+ function timeoutRequest() {
+ jsonpDone && jsonpDone();
+ xhr && xhr.abort();
+ }
+
+ function completeRequest(callback, status, response, headersString, statusText) {
+ // cancel timeout and subsequent timeout promise resolution
+ if (timeoutId !== undefined) {
+ $browserDefer.cancel(timeoutId);
+ }
+ jsonpDone = xhr = null;
+
+ callback(status, response, headersString, statusText);
+ $browser.$$completeOutstandingRequest(noop);
+ }
+ };
+
+ function jsonpReq(url, callbackId, done) {
+ // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
+ // - fetches local scripts via XHR and evals them
+ // - adds and immediately removes script elements from the document
+ var script = rawDocument.createElement('script'), callback = null;
+ script.type = "text/javascript";
+ script.src = url;
+ script.async = true;
+
+ callback = function(event) {
+ removeEventListenerFn(script, "load", callback);
+ removeEventListenerFn(script, "error", callback);
+ rawDocument.body.removeChild(script);
+ script = null;
+ var status = -1;
+ var text = "unknown";
+
+ if (event) {
+ if (event.type === "load" && !callbacks[callbackId].called) {
+ event = { type: "error" };
+ }
+ text = event.type;
+ status = event.type === "error" ? 404 : 200;
+ }
+
+ if (done) {
+ done(status, text);
+ }
+ };
+
+ addEventListenerFn(script, "load", callback);
+ addEventListenerFn(script, "error", callback);
+ rawDocument.body.appendChild(script);
+ return callback;
+ }
+}
+
+var $interpolateMinErr = minErr('$interpolate');
+
+/**
+ * @ngdoc provider
+ * @name $interpolateProvider
+ *
+ * @description
+ *
+ * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
+ *
+ * @example
+<example module="customInterpolationApp">
+<file name="index.html">
+<script>
+ var customInterpolationApp = angular.module('customInterpolationApp', []);
+
+ customInterpolationApp.config(function($interpolateProvider) {
+ $interpolateProvider.startSymbol('//');
+ $interpolateProvider.endSymbol('//');
+ });
+
+
+ customInterpolationApp.controller('DemoController', function() {
+ this.label = "This binding is brought you by // interpolation symbols.";
+ });
+</script>
+<div ng-app="App" ng-controller="DemoController as demo">
+ //demo.label//
+</div>
+</file>
+<file name="protractor.js" type="protractor">
+ it('should interpolate binding with custom symbols', function() {
+ expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
+ });
+</file>
+</example>
+ */
+function $InterpolateProvider() {
+ var startSymbol = '{{';
+ var endSymbol = '}}';
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#startSymbol
+ * @description
+ * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * @param {string=} value new value to set the starting symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.startSymbol = function(value) {
+ if (value) {
+ startSymbol = value;
+ return this;
+ } else {
+ return startSymbol;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * @param {string=} value new value to set the ending symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.endSymbol = function(value) {
+ if (value) {
+ endSymbol = value;
+ return this;
+ } else {
+ return endSymbol;
+ }
+ };
+
+
+ this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
+ var startSymbolLength = startSymbol.length,
+ endSymbolLength = endSymbol.length,
+ escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
+ escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
+
+ function escape(ch) {
+ return '\\\\\\' + ch;
+ }
+
+ /**
+ * @ngdoc service
+ * @name $interpolate
+ * @kind function
+ *
+ * @requires $parse
+ * @requires $sce
+ *
+ * @description
+ *
+ * Compiles a string with markup into an interpolation function. This service is used by the
+ * HTML {@link ng.$compile $compile} service for data binding. See
+ * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
+ * interpolation markup.
+ *
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var exp = $interpolate('Hello {{name | uppercase}}!');
+ * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
+ * ```
+ *
+ * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
+ * `true`, the interpolation function will return `undefined` unless all embedded expressions
+ * evaluate to a value other than `undefined`.
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var context = {greeting: 'Hello', name: undefined };
+ *
+ * // default "forgiving" mode
+ * var exp = $interpolate('{{greeting}} {{name}}!');
+ * expect(exp(context)).toEqual('Hello !');
+ *
+ * // "allOrNothing" mode
+ * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
+ * expect(exp(context)).toBeUndefined();
+ * context.name = 'Angular';
+ * expect(exp(context)).toEqual('Hello Angular!');
+ * ```
+ *
+ * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
+ *
+ * ####Escaped Interpolation
+ * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
+ * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
+ * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
+ * or binding.
+ *
+ * This enables web-servers to prevent script injection attacks and defacing attacks, to some
+ * degree, while also enabling code examples to work without relying on the
+ * {@link ng.directive:ngNonBindable ngNonBindable} directive.
+ *
+ * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
+ * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
+ * interpolation start/end markers with their escaped counterparts.**
+ *
+ * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
+ * output when the $interpolate service processes the text. So, for HTML elements interpolated
+ * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
+ * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
+ * this is typically useful only when user-data is used in rendering a template from the server, or
+ * when otherwise untrusted data is used by a directive.
+ *
+ * <example>
+ * <file name="index.html">
+ * <div ng-init="username='A user'">
+ * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
+ * </p>
+ * <p><strong>{{username}}</strong> attempts to inject code which will deface the
+ * application, but fails to accomplish their task, because the server has correctly
+ * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
+ * characters.</p>
+ * <p>Instead, the result of the attempted script injection is visible, and can be removed
+ * from the database by an administrator.</p>
+ * </div>
+ * </file>
+ * </example>
+ *
+ * @param {string} text The text with markup to interpolate.
+ * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
+ * embedded expression in order to return an interpolation function. Strings with no
+ * embedded expression will return null for the interpolation function.
+ * @param {string=} trustedContext when provided, the returned function passes the interpolated
+ * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
+ * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
+ * provides Strict Contextual Escaping for details.
+ * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
+ * unless all embedded expressions evaluate to a value other than `undefined`.
+ * @returns {function(context)} an interpolation function which is used to compute the
+ * interpolated string. The function has these parameters:
+ *
+ * - `context`: evaluation context for all expressions embedded in the interpolated text
+ */
+ function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
+ allOrNothing = !!allOrNothing;
+ var startIndex,
+ endIndex,
+ index = 0,
+ expressions = [],
+ parseFns = [],
+ textLength = text.length,
+ exp,
+ concat = [],
+ expressionPositions = [];
+
+ while (index < textLength) {
+ if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
+ ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
+ if (index !== startIndex) {
+ concat.push(unescapeText(text.substring(index, startIndex)));
+ }
+ exp = text.substring(startIndex + startSymbolLength, endIndex);
+ expressions.push(exp);
+ parseFns.push($parse(exp, parseStringifyInterceptor));
+ index = endIndex + endSymbolLength;
+ expressionPositions.push(concat.length);
+ concat.push('');
+ } else {
+ // we did not find an interpolation, so we have to add the remainder to the separators array
+ if (index !== textLength) {
+ concat.push(unescapeText(text.substring(index)));
+ }
+ break;
+ }
+ }
+
+ // Concatenating expressions makes it hard to reason about whether some combination of
+ // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
+ // single expression be used for iframe[src], object[src], etc., we ensure that the value
+ // that's used is assigned or constructed by some JS code somewhere that is more testable or
+ // make it obvious that you bound the value to some user controlled value. This helps reduce
+ // the load when auditing for XSS issues.
+ if (trustedContext && concat.length > 1) {
+ throw $interpolateMinErr('noconcat',
+ "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
+ "interpolations that concatenate multiple expressions when a trusted value is " +
+ "required. See http://docs.angularjs.org/api/ng.$sce", text);
+ }
+
+ if (!mustHaveExpression || expressions.length) {
+ var compute = function(values) {
+ for (var i = 0, ii = expressions.length; i < ii; i++) {
+ if (allOrNothing && isUndefined(values[i])) return;
+ concat[expressionPositions[i]] = values[i];
+ }
+ return concat.join('');
+ };
+
+ var getValue = function(value) {
+ return trustedContext ?
+ $sce.getTrusted(trustedContext, value) :
+ $sce.valueOf(value);
+ };
+
+ var stringify = function(value) {
+ if (value == null) { // null || undefined
+ return '';
+ }
+ switch (typeof value) {
+ case 'string':
+ break;
+ case 'number':
+ value = '' + value;
+ break;
+ default:
+ value = toJson(value);
+ }
+
+ return value;
+ };
+
+ return extend(function interpolationFn(context) {
+ var i = 0;
+ var ii = expressions.length;
+ var values = new Array(ii);
+
+ try {
+ for (; i < ii; i++) {
+ values[i] = parseFns[i](context);
+ }
+
+ return compute(values);
+ } catch (err) {
+ var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
+ err.toString());
+ $exceptionHandler(newErr);
+ }
+
+ }, {
+ // all of these properties are undocumented for now
+ exp: text, //just for compatibility with regular watchers created via $watch
+ expressions: expressions,
+ $$watchDelegate: function(scope, listener, objectEquality) {
+ var lastValue;
+ return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
+ var currValue = compute(values);
+ if (isFunction(listener)) {
+ listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
+ }
+ lastValue = currValue;
+ }, objectEquality);
+ }
+ });
+ }
+
+ function unescapeText(text) {
+ return text.replace(escapedStartRegexp, startSymbol).
+ replace(escapedEndRegexp, endSymbol);
+ }
+
+ function parseStringifyInterceptor(value) {
+ try {
+ value = getValue(value);
+ return allOrNothing && !isDefined(value) ? value : stringify(value);
+ } catch (err) {
+ var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
+ err.toString());
+ $exceptionHandler(newErr);
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#startSymbol
+ * @description
+ * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} start symbol.
+ */
+ $interpolate.startSymbol = function() {
+ return startSymbol;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} end symbol.
+ */
+ $interpolate.endSymbol = function() {
+ return endSymbol;
+ };
+
+ return $interpolate;
+ }];
+}
+
+function $IntervalProvider() {
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
+ function($rootScope, $window, $q, $$q) {
+ var intervals = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $interval
+ *
+ * @description
+ * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
+ * milliseconds.
+ *
+ * The return value of registering an interval function is a promise. This promise will be
+ * notified upon each tick of the interval, and will be resolved after `count` iterations, or
+ * run indefinitely if `count` is not defined. The value of the notification will be the
+ * number of iterations that have run.
+ * To cancel an interval, call `$interval.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
+ * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
+ * time.
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
+ * with them. In particular they are not automatically destroyed when a controller's scope or a
+ * directive's element are destroyed.
+ * You should take this into consideration and make sure to always cancel the interval at the
+ * appropriate moment. See the example below for more details on how and when to do this.
+ * </div>
+ *
+ * @param {function()} fn A function that should be called repeatedly.
+ * @param {number} delay Number of milliseconds between each function call.
+ * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
+ * indefinitely.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @returns {promise} A promise which will be notified on each iteration.
+ *
+ * @example
+ * <example module="intervalExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('intervalExample', [])
+ * .controller('ExampleController', ['$scope', '$interval',
+ * function($scope, $interval) {
+ * $scope.format = 'M/d/yy h:mm:ss a';
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ *
+ * var stop;
+ * $scope.fight = function() {
+ * // Don't start a new fight if we are already fighting
+ * if ( angular.isDefined(stop) ) return;
+ *
+ * stop = $interval(function() {
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
+ * $scope.blood_1 = $scope.blood_1 - 3;
+ * $scope.blood_2 = $scope.blood_2 - 4;
+ * } else {
+ * $scope.stopFight();
+ * }
+ * }, 100);
+ * };
+ *
+ * $scope.stopFight = function() {
+ * if (angular.isDefined(stop)) {
+ * $interval.cancel(stop);
+ * stop = undefined;
+ * }
+ * };
+ *
+ * $scope.resetFight = function() {
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ * };
+ *
+ * $scope.$on('$destroy', function() {
+ * // Make sure that the interval is destroyed too
+ * $scope.stopFight();
+ * });
+ * }])
+ * // Register the 'myCurrentTime' directive factory method.
+ * // We inject $interval and dateFilter service since the factory method is DI.
+ * .directive('myCurrentTime', ['$interval', 'dateFilter',
+ * function($interval, dateFilter) {
+ * // return the directive link function. (compile function not needed)
+ * return function(scope, element, attrs) {
+ * var format, // date format
+ * stopTime; // so that we can cancel the time updates
+ *
+ * // used to update the UI
+ * function updateTime() {
+ * element.text(dateFilter(new Date(), format));
+ * }
+ *
+ * // watch the expression, and update the UI on change.
+ * scope.$watch(attrs.myCurrentTime, function(value) {
+ * format = value;
+ * updateTime();
+ * });
+ *
+ * stopTime = $interval(updateTime, 1000);
+ *
+ * // listen on DOM destroy (removal) event, and cancel the next UI update
+ * // to prevent updating time after the DOM element was removed.
+ * element.on('$destroy', function() {
+ * $interval.cancel(stopTime);
+ * });
+ * }
+ * }]);
+ * </script>
+ *
+ * <div>
+ * <div ng-controller="ExampleController">
+ * Date format: <input ng-model="format"> <hr/>
+ * Current time is: <span my-current-time="format"></span>
+ * <hr/>
+ * Blood 1 : <font color='red'>{{blood_1}}</font>
+ * Blood 2 : <font color='red'>{{blood_2}}</font>
+ * <button type="button" data-ng-click="fight()">Fight</button>
+ * <button type="button" data-ng-click="stopFight()">StopFight</button>
+ * <button type="button" data-ng-click="resetFight()">resetFight</button>
+ * </div>
+ * </div>
+ *
+ * </file>
+ * </example>
+ */
+ function interval(fn, delay, count, invokeApply) {
+ var setInterval = $window.setInterval,
+ clearInterval = $window.clearInterval,
+ iteration = 0,
+ skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise;
+
+ count = isDefined(count) ? count : 0;
+
+ promise.then(null, null, fn);
+
+ promise.$$intervalId = setInterval(function tick() {
+ deferred.notify(iteration++);
+
+ if (count > 0 && iteration >= count) {
+ deferred.resolve(iteration);
+ clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+
+ }, delay);
+
+ intervals[promise.$$intervalId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interval#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`.
+ *
+ * @param {promise} promise returned by the `$interval` function.
+ * @returns {boolean} Returns `true` if the task was successfully canceled.
+ */
+ interval.cancel = function(promise) {
+ if (promise && promise.$$intervalId in intervals) {
+ intervals[promise.$$intervalId].reject('canceled');
+ $window.clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ return true;
+ }
+ return false;
+ };
+
+ return interval;
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $locale
+ *
+ * @description
+ * $locale service provides localization rules for various Angular components. As of right now the
+ * only public api is:
+ *
+ * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
+ */
+function $LocaleProvider() {
+ this.$get = function() {
+ return {
+ id: 'en-us',
+
+ NUMBER_FORMATS: {
+ DECIMAL_SEP: '.',
+ GROUP_SEP: ',',
+ PATTERNS: [
+ { // Decimal Pattern
+ minInt: 1,
+ minFrac: 0,
+ maxFrac: 3,
+ posPre: '',
+ posSuf: '',
+ negPre: '-',
+ negSuf: '',
+ gSize: 3,
+ lgSize: 3
+ },{ //Currency Pattern
+ minInt: 1,
+ minFrac: 2,
+ maxFrac: 2,
+ posPre: '\u00A4',
+ posSuf: '',
+ negPre: '(\u00A4',
+ negSuf: ')',
+ gSize: 3,
+ lgSize: 3
+ }
+ ],
+ CURRENCY_SYM: '$'
+ },
+
+ DATETIME_FORMATS: {
+ MONTH:
+ 'January,February,March,April,May,June,July,August,September,October,November,December'
+ .split(','),
+ SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
+ DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
+ SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
+ AMPMS: ['AM','PM'],
+ medium: 'MMM d, y h:mm:ss a',
+ 'short': 'M/d/yy h:mm a',
+ fullDate: 'EEEE, MMMM d, y',
+ longDate: 'MMMM d, y',
+ mediumDate: 'MMM d, y',
+ shortDate: 'M/d/yy',
+ mediumTime: 'h:mm:ss a',
+ shortTime: 'h:mm a',
+ ERANAMES: [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ ERAS: [
+ "BC",
+ "AD"
+ ]
+ },
+
+ pluralCat: function(num) {
+ if (num === 1) {
+ return 'one';
+ }
+ return 'other';
+ }
+ };
+ };
+}
+
+var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
+ DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
+var $locationMinErr = minErr('$location');
+
+
+/**
+ * Encode path using encodeUriSegment, ignoring forward slashes
+ *
+ * @param {string} path Path to encode
+ * @returns {string}
+ */
+function encodePath(path) {
+ var segments = path.split('/'),
+ i = segments.length;
+
+ while (i--) {
+ segments[i] = encodeUriSegment(segments[i]);
+ }
+
+ return segments.join('/');
+}
+
+function parseAbsoluteUrl(absoluteUrl, locationObj) {
+ var parsedUrl = urlResolve(absoluteUrl);
+
+ locationObj.$$protocol = parsedUrl.protocol;
+ locationObj.$$host = parsedUrl.hostname;
+ locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
+}
+
+
+function parseAppUrl(relativeUrl, locationObj) {
+ var prefixed = (relativeUrl.charAt(0) !== '/');
+ if (prefixed) {
+ relativeUrl = '/' + relativeUrl;
+ }
+ var match = urlResolve(relativeUrl);
+ locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
+ match.pathname.substring(1) : match.pathname);
+ locationObj.$$search = parseKeyValue(match.search);
+ locationObj.$$hash = decodeURIComponent(match.hash);
+
+ // make sure path starts with '/';
+ if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
+ locationObj.$$path = '/' + locationObj.$$path;
+ }
+}
+
+
+/**
+ *
+ * @param {string} begin
+ * @param {string} whole
+ * @returns {string} returns text from whole after begin or undefined if it does not begin with
+ * expected string.
+ */
+function beginsWith(begin, whole) {
+ if (whole.indexOf(begin) === 0) {
+ return whole.substr(begin.length);
+ }
+}
+
+
+function stripHash(url) {
+ var index = url.indexOf('#');
+ return index == -1 ? url : url.substr(0, index);
+}
+
+function trimEmptyHash(url) {
+ return url.replace(/(#.+)|#$/, '$1');
+}
+
+
+function stripFile(url) {
+ return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
+}
+
+/* return the server only (scheme://host:port) */
+function serverBase(url) {
+ return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
+}
+
+
+/**
+ * LocationHtml5Url represents an url
+ * This object is exposed as $location service when HTML5 mode is enabled and supported
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} basePrefix url path prefix
+ */
+function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
+ this.$$html5 = true;
+ basePrefix = basePrefix || '';
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given html5 (regular) url string into properties
+ * @param {string} url HTML5 url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var pathUrl = beginsWith(appBaseNoFile, url);
+ if (!isString(pathUrl)) {
+ throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
+ appBaseNoFile);
+ }
+
+ parseAppUrl(pathUrl, this);
+
+ if (!this.$$path) {
+ this.$$path = '/';
+ }
+
+ this.$$compose();
+ };
+
+ /**
+ * Compose url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+ var appUrl, prevAppUrl;
+ var rewrittenUrl;
+
+ if ((appUrl = beginsWith(appBase, url)) !== undefined) {
+ prevAppUrl = appUrl;
+ if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
+ rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
+ } else {
+ rewrittenUrl = appBase + prevAppUrl;
+ }
+ } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
+ rewrittenUrl = appBaseNoFile + appUrl;
+ } else if (appBaseNoFile == url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when developer doesn't opt into html5 mode.
+ * It also serves as the base class for html5 mode fallback on legacy browsers.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
+
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given hashbang url into properties
+ * @param {string} url Hashbang url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
+ var withoutHashUrl;
+
+ if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
+
+ // The rest of the url starts with a hash so we have
+ // got either a hashbang path or a plain hash fragment
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
+ if (isUndefined(withoutHashUrl)) {
+ // There was no hashbang prefix so we just have a hash fragment
+ withoutHashUrl = withoutBaseUrl;
+ }
+
+ } else {
+ // There was no hashbang path nor hash fragment:
+ // If we are in HTML5 mode we use what is left as the path;
+ // Otherwise we ignore what is left
+ if (this.$$html5) {
+ withoutHashUrl = withoutBaseUrl;
+ } else {
+ withoutHashUrl = '';
+ if (isUndefined(withoutBaseUrl)) {
+ appBase = url;
+ this.replace();
+ }
+ }
+ }
+
+ parseAppUrl(withoutHashUrl, this);
+
+ this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
+
+ this.$$compose();
+
+ /*
+ * In Windows, on an anchor node on documents loaded from
+ * the filesystem, the browser will return a pathname
+ * prefixed with the drive name ('/C:/path') when a
+ * pathname without a drive is set:
+ * * a.setAttribute('href', '/foo')
+ * * a.pathname === '/C:/foo' //true
+ *
+ * Inside of Angular, we're always using pathnames that
+ * do not include drive names for routing.
+ */
+ function removeWindowsDriveName(path, url, base) {
+ /*
+ Matches paths for file protocol on windows,
+ such as /C:/foo/bar, and captures only /foo/bar.
+ */
+ var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
+
+ var firstPathSegmentMatch;
+
+ //Get the relative path from the input URL.
+ if (url.indexOf(base) === 0) {
+ url = url.replace(base, '');
+ }
+
+ // The input URL intentionally contains a first path segment that ends with a colon.
+ if (windowsFilePathExp.exec(url)) {
+ return path;
+ }
+
+ firstPathSegmentMatch = windowsFilePathExp.exec(path);
+ return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
+ }
+ };
+
+ /**
+ * Compose hashbang url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (stripHash(appBase) == stripHash(url)) {
+ this.$$parse(url);
+ return true;
+ }
+ return false;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when html5 history api is enabled but the browser
+ * does not support it.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
+ this.$$html5 = true;
+ LocationHashbangUrl.apply(this, arguments);
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+
+ var rewrittenUrl;
+ var appUrl;
+
+ if (appBase == stripHash(url)) {
+ rewrittenUrl = url;
+ } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
+ rewrittenUrl = appBase + hashPrefix + appUrl;
+ } else if (appBaseNoFile === url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
+ this.$$absUrl = appBase + hashPrefix + this.$$url;
+ };
+
+}
+
+
+var locationPrototype = {
+
+ /**
+ * Are we in html5 mode?
+ * @private
+ */
+ $$html5: false,
+
+ /**
+ * Has any change been replacing?
+ * @private
+ */
+ $$replace: false,
+
+ /**
+ * @ngdoc method
+ * @name $location#absUrl
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return full url representation with all segments encoded according to rules specified in
+ * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var absUrl = $location.absUrl();
+ * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @return {string} full url
+ */
+ absUrl: locationGetter('$$absUrl'),
+
+ /**
+ * @ngdoc method
+ * @name $location#url
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
+ *
+ * Change path, search and hash, when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var url = $location.url();
+ * // => "/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
+ * @return {string} url
+ */
+ url: function(url) {
+ if (isUndefined(url))
+ return this.$$url;
+
+ var match = PATH_MATCH.exec(url);
+ if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
+ if (match[2] || match[1] || url === '') this.search(match[3] || '');
+ this.hash(match[5] || '');
+
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#protocol
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return protocol of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var protocol = $location.protocol();
+ * // => "http"
+ * ```
+ *
+ * @return {string} protocol of current url
+ */
+ protocol: locationGetter('$$protocol'),
+
+ /**
+ * @ngdoc method
+ * @name $location#host
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return host of current url.
+ *
+ * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var host = $location.host();
+ * // => "example.com"
+ *
+ * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
+ * host = $location.host();
+ * // => "example.com"
+ * host = location.host;
+ * // => "example.com:8080"
+ * ```
+ *
+ * @return {string} host of current url.
+ */
+ host: locationGetter('$$host'),
+
+ /**
+ * @ngdoc method
+ * @name $location#port
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return port of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var port = $location.port();
+ * // => 80
+ * ```
+ *
+ * @return {Number} port
+ */
+ port: locationGetter('$$port'),
+
+ /**
+ * @ngdoc method
+ * @name $location#path
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return path of current url when called without any parameter.
+ *
+ * Change path when called with parameter and return `$location`.
+ *
+ * Note: Path should always begin with forward slash (/), this method will add the forward slash
+ * if it is missing.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var path = $location.path();
+ * // => "/some/path"
+ * ```
+ *
+ * @param {(string|number)=} path New path
+ * @return {string} path
+ */
+ path: locationGetterSetter('$$path', function(path) {
+ path = path !== null ? path.toString() : '';
+ return path.charAt(0) == '/' ? path : '/' + path;
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#search
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return search part (as object) of current url when called without any parameter.
+ *
+ * Change search part when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var searchObject = $location.search();
+ * // => {foo: 'bar', baz: 'xoxo'}
+ *
+ * // set foo to 'yipee'
+ * $location.search('foo', 'yipee');
+ * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
+ * ```
+ *
+ * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
+ * hash object.
+ *
+ * When called with a single argument the method acts as a setter, setting the `search` component
+ * of `$location` to the specified value.
+ *
+ * If the argument is a hash object containing an array of values, these values will be encoded
+ * as duplicate search parameters in the url.
+ *
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
+ * will override only a single search property.
+ *
+ * If `paramValue` is an array, it will override the property of the `search` component of
+ * `$location` specified via the first argument.
+ *
+ * If `paramValue` is `null`, the property specified via the first argument will be deleted.
+ *
+ * If `paramValue` is `true`, the property specified via the first argument will be added with no
+ * value nor trailing equal sign.
+ *
+ * @return {Object} If called with no arguments returns the parsed `search` object. If called with
+ * one or more arguments returns `$location` object itself.
+ */
+ search: function(search, paramValue) {
+ switch (arguments.length) {
+ case 0:
+ return this.$$search;
+ case 1:
+ if (isString(search) || isNumber(search)) {
+ search = search.toString();
+ this.$$search = parseKeyValue(search);
+ } else if (isObject(search)) {
+ search = copy(search, {});
+ // remove object undefined or null properties
+ forEach(search, function(value, key) {
+ if (value == null) delete search[key];
+ });
+
+ this.$$search = search;
+ } else {
+ throw $locationMinErr('isrcharg',
+ 'The first argument of the `$location#search()` call must be a string or an object.');
+ }
+ break;
+ default:
+ if (isUndefined(paramValue) || paramValue === null) {
+ delete this.$$search[search];
+ } else {
+ this.$$search[search] = paramValue;
+ }
+ }
+
+ this.$$compose();
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#hash
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return hash fragment when called without any parameter.
+ *
+ * Change hash fragment when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
+ * var hash = $location.hash();
+ * // => "hashValue"
+ * ```
+ *
+ * @param {(string|number)=} hash New hash fragment
+ * @return {string} hash
+ */
+ hash: locationGetterSetter('$$hash', function(hash) {
+ return hash !== null ? hash.toString() : '';
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#replace
+ *
+ * @description
+ * If called, all changes to $location during current `$digest` will be replacing current history
+ * record, instead of adding new one.
+ */
+ replace: function() {
+ this.$$replace = true;
+ return this;
+ }
+};
+
+forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
+ Location.prototype = Object.create(locationPrototype);
+
+ /**
+ * @ngdoc method
+ * @name $location#state
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return the history state object when called without any parameter.
+ *
+ * Change the history state object when called with one parameter and return `$location`.
+ * The state object is later passed to `pushState` or `replaceState`.
+ *
+ * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
+ * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
+ * older browsers (like IE9 or Android < 4.0), don't use this method.
+ *
+ * @param {object=} state State object for pushState or replaceState
+ * @return {object} state
+ */
+ Location.prototype.state = function(state) {
+ if (!arguments.length)
+ return this.$$state;
+
+ if (Location !== LocationHtml5Url || !this.$$html5) {
+ throw $locationMinErr('nostate', 'History API state support is available only ' +
+ 'in HTML5 mode and only in browsers supporting HTML5 History API');
+ }
+ // The user might modify `stateObject` after invoking `$location.state(stateObject)`
+ // but we're changing the $$state reference to $browser.state() during the $digest
+ // so the modification window is narrow.
+ this.$$state = isUndefined(state) ? null : state;
+
+ return this;
+ };
+});
+
+
+function locationGetter(property) {
+ return function() {
+ return this[property];
+ };
+}
+
+
+function locationGetterSetter(property, preprocess) {
+ return function(value) {
+ if (isUndefined(value))
+ return this[property];
+
+ this[property] = preprocess(value);
+ this.$$compose();
+
+ return this;
+ };
+}
+
+
+/**
+ * @ngdoc service
+ * @name $location
+ *
+ * @requires $rootElement
+ *
+ * @description
+ * The $location service parses the URL in the browser address bar (based on the
+ * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
+ * available to your application. Changes to the URL in the address bar are reflected into
+ * $location service and changes to $location are reflected into the browser address bar.
+ *
+ * **The $location service:**
+ *
+ * - Exposes the current URL in the browser address bar, so you can
+ * - Watch and observe the URL.
+ * - Change the URL.
+ * - Synchronizes the URL with the browser when the user
+ * - Changes the address bar.
+ * - Clicks the back or forward button (or clicks a History link).
+ * - Clicks on a link.
+ * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
+ *
+ * For more information see {@link guide/$location Developer Guide: Using $location}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $locationProvider
+ * @description
+ * Use the `$locationProvider` to configure how the application deep linking paths are stored.
+ */
+function $LocationProvider() {
+ var hashPrefix = '',
+ html5Mode = {
+ enabled: false,
+ requireBase: true,
+ rewriteLinks: true
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#hashPrefix
+ * @description
+ * @param {string=} prefix Prefix for hash part (containing path and search)
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.hashPrefix = function(prefix) {
+ if (isDefined(prefix)) {
+ hashPrefix = prefix;
+ return this;
+ } else {
+ return hashPrefix;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#html5Mode
+ * @description
+ * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
+ * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
+ * properties:
+ * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
+ * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
+ * support `pushState`.
+ * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
+ * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
+ * true, and a base tag is not present, an error will be thrown when `$location` is injected.
+ * See the {@link guide/$location $location guide for more information}
+ * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
+ * enables/disables url rewriting for relative links.
+ *
+ * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
+ */
+ this.html5Mode = function(mode) {
+ if (isBoolean(mode)) {
+ html5Mode.enabled = mode;
+ return this;
+ } else if (isObject(mode)) {
+
+ if (isBoolean(mode.enabled)) {
+ html5Mode.enabled = mode.enabled;
+ }
+
+ if (isBoolean(mode.requireBase)) {
+ html5Mode.requireBase = mode.requireBase;
+ }
+
+ if (isBoolean(mode.rewriteLinks)) {
+ html5Mode.rewriteLinks = mode.rewriteLinks;
+ }
+
+ return this;
+ } else {
+ return html5Mode;
+ }
+ };
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeStart
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted before a URL will change.
+ *
+ * This change can be prevented by calling
+ * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
+ * details about event object. Upon successful change
+ * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeSuccess
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted after a URL was changed.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
+ var $location,
+ LocationMode,
+ baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
+ initialUrl = $browser.url(),
+ appBase;
+
+ if (html5Mode.enabled) {
+ if (!baseHref && html5Mode.requireBase) {
+ throw $locationMinErr('nobase',
+ "$location in HTML5 mode requires a <base> tag to be present!");
+ }
+ appBase = serverBase(initialUrl) + (baseHref || '/');
+ LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
+ } else {
+ appBase = stripHash(initialUrl);
+ LocationMode = LocationHashbangUrl;
+ }
+ var appBaseNoFile = stripFile(appBase);
+
+ $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
+ $location.$$parseLinkUrl(initialUrl, initialUrl);
+
+ $location.$$state = $browser.state();
+
+ var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
+
+ function setBrowserUrlWithFallback(url, replace, state) {
+ var oldUrl = $location.url();
+ var oldState = $location.$$state;
+ try {
+ $browser.url(url, replace, state);
+
+ // Make sure $location.state() returns referentially identical (not just deeply equal)
+ // state object; this makes possible quick checking if the state changed in the digest
+ // loop. Checking deep equality would be too expensive.
+ $location.$$state = $browser.state();
+ } catch (e) {
+ // Restore old values if pushState fails
+ $location.url(oldUrl);
+ $location.$$state = oldState;
+
+ throw e;
+ }
+ }
+
+ $rootElement.on('click', function(event) {
+ // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
+ // currently we open nice url link and redirect then
+
+ if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
+
+ var elm = jqLite(event.target);
+
+ // traverse the DOM up to find first A tag
+ while (nodeName_(elm[0]) !== 'a') {
+ // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
+ if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
+ }
+
+ var absHref = elm.prop('href');
+ // get the actual href attribute - see
+ // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
+ var relHref = elm.attr('href') || elm.attr('xlink:href');
+
+ if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
+ // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
+ // an animation.
+ absHref = urlResolve(absHref.animVal).href;
+ }
+
+ // Ignore when url is started with javascript: or mailto:
+ if (IGNORE_URI_REGEXP.test(absHref)) return;
+
+ if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
+ if ($location.$$parseLinkUrl(absHref, relHref)) {
+ // We do a preventDefault for all urls that are part of the angular application,
+ // in html5mode and also without, so that we are able to abort navigation without
+ // getting double entries in the location history.
+ event.preventDefault();
+ // update location manually
+ if ($location.absUrl() != $browser.url()) {
+ $rootScope.$apply();
+ // hack to work around FF6 bug 684208 when scenario runner clicks on links
+ $window.angular['ff-684208-preventDefault'] = true;
+ }
+ }
+ }
+ });
+
+
+ // rewrite hashbang url <> html5 url
+ if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
+ $browser.url($location.absUrl(), true);
+ }
+
+ var initializing = true;
+
+ // update $location when $browser url changes
+ $browser.onUrlChange(function(newUrl, newState) {
+
+ if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
+ // If we are navigating outside of the app then force a reload
+ $window.location.href = newUrl;
+ return;
+ }
+
+ $rootScope.$evalAsync(function() {
+ var oldUrl = $location.absUrl();
+ var oldState = $location.$$state;
+ var defaultPrevented;
+
+ $location.$$parse(newUrl);
+ $location.$$state = newState;
+
+ defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ newState, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ setBrowserUrlWithFallback(oldUrl, false, oldState);
+ } else {
+ initializing = false;
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ if (!$rootScope.$$phase) $rootScope.$digest();
+ });
+
+ // update browser
+ $rootScope.$watch(function $locationWatch() {
+ var oldUrl = trimEmptyHash($browser.url());
+ var newUrl = trimEmptyHash($location.absUrl());
+ var oldState = $browser.state();
+ var currentReplace = $location.$$replace;
+ var urlOrStateChanged = oldUrl !== newUrl ||
+ ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
+
+ if (initializing || urlOrStateChanged) {
+ initializing = false;
+
+ $rootScope.$evalAsync(function() {
+ var newUrl = $location.absUrl();
+ var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ $location.$$state, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ } else {
+ if (urlOrStateChanged) {
+ setBrowserUrlWithFallback(newUrl, currentReplace,
+ oldState === $location.$$state ? null : $location.$$state);
+ }
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ }
+
+ $location.$$replace = false;
+
+ // we don't need to return anything because $evalAsync will make the digest loop dirty when
+ // there is a change
+ });
+
+ return $location;
+
+ function afterLocationChange(oldUrl, oldState) {
+ $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
+ $location.$$state, oldState);
+ }
+}];
+}
+
+/**
+ * @ngdoc service
+ * @name $log
+ * @requires $window
+ *
+ * @description
+ * Simple service for logging. Default implementation safely writes the message
+ * into the browser's console (if present).
+ *
+ * The main purpose of this service is to simplify debugging and troubleshooting.
+ *
+ * The default is to log `debug` messages. You can use
+ * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
+ *
+ * @example
+ <example module="logExample">
+ <file name="script.js">
+ angular.module('logExample', [])
+ .controller('LogController', ['$scope', '$log', function($scope, $log) {
+ $scope.$log = $log;
+ $scope.message = 'Hello World!';
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="LogController">
+ <p>Reload this page with open console, enter text and hit the log button...</p>
+ Message:
+ <input type="text" ng-model="message"/>
+ <button ng-click="$log.log(message)">log</button>
+ <button ng-click="$log.warn(message)">warn</button>
+ <button ng-click="$log.info(message)">info</button>
+ <button ng-click="$log.error(message)">error</button>
+ <button ng-click="$log.debug(message)">debug</button>
+ </div>
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc provider
+ * @name $logProvider
+ * @description
+ * Use the `$logProvider` to configure how the application logs messages
+ */
+function $LogProvider() {
+ var debug = true,
+ self = this;
+
+ /**
+ * @ngdoc method
+ * @name $logProvider#debugEnabled
+ * @description
+ * @param {boolean=} flag enable or disable debug level messages
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.debugEnabled = function(flag) {
+ if (isDefined(flag)) {
+ debug = flag;
+ return this;
+ } else {
+ return debug;
+ }
+ };
+
+ this.$get = ['$window', function($window) {
+ return {
+ /**
+ * @ngdoc method
+ * @name $log#log
+ *
+ * @description
+ * Write a log message
+ */
+ log: consoleLog('log'),
+
+ /**
+ * @ngdoc method
+ * @name $log#info
+ *
+ * @description
+ * Write an information message
+ */
+ info: consoleLog('info'),
+
+ /**
+ * @ngdoc method
+ * @name $log#warn
+ *
+ * @description
+ * Write a warning message
+ */
+ warn: consoleLog('warn'),
+
+ /**
+ * @ngdoc method
+ * @name $log#error
+ *
+ * @description
+ * Write an error message
+ */
+ error: consoleLog('error'),
+
+ /**
+ * @ngdoc method
+ * @name $log#debug
+ *
+ * @description
+ * Write a debug message
+ */
+ debug: (function() {
+ var fn = consoleLog('debug');
+
+ return function() {
+ if (debug) {
+ fn.apply(self, arguments);
+ }
+ };
+ }())
+ };
+
+ function formatError(arg) {
+ if (arg instanceof Error) {
+ if (arg.stack) {
+ arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
+ ? 'Error: ' + arg.message + '\n' + arg.stack
+ : arg.stack;
+ } else if (arg.sourceURL) {
+ arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
+ }
+ }
+ return arg;
+ }
+
+ function consoleLog(type) {
+ var console = $window.console || {},
+ logFn = console[type] || console.log || noop,
+ hasApply = false;
+
+ // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
+ // The reason behind this is that console.log has type "object" in IE8...
+ try {
+ hasApply = !!logFn.apply;
+ } catch (e) {}
+
+ if (hasApply) {
+ return function() {
+ var args = [];
+ forEach(arguments, function(arg) {
+ args.push(formatError(arg));
+ });
+ return logFn.apply(console, args);
+ };
+ }
+
+ // we are IE which either doesn't have window.console => this is noop and we do nothing,
+ // or we are IE where console.log doesn't have apply so we log at least first 2 args
+ return function(arg1, arg2) {
+ logFn(arg1, arg2 == null ? '' : arg2);
+ };
+ }
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $parseMinErr = minErr('$parse');
+
+// Sandboxing Angular Expressions
+// ------------------------------
+// Angular expressions are generally considered safe because these expressions only have direct
+// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
+// obtaining a reference to native JS functions such as the Function constructor.
+//
+// As an example, consider the following Angular expression:
+//
+// {}.toString.constructor('alert("evil JS code")')
+//
+// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
+// against the expression language, but not to prevent exploits that were enabled by exposing
+// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
+// practice and therefore we are not even trying to protect against interaction with an object
+// explicitly exposed in this way.
+//
+// In general, it is not possible to access a Window object from an angular expression unless a
+// window or some DOM object that has a reference to window is published onto a Scope.
+// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
+// native objects.
+//
+// See https://docs.angularjs.org/guide/security
+
+
+function ensureSafeMemberName(name, fullExpression) {
+ if (name === "__defineGetter__" || name === "__defineSetter__"
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
+ || name === "__proto__") {
+ throw $parseMinErr('isecfld',
+ 'Attempting to access a disallowed field in Angular expressions! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function getStringValue(name, fullExpression) {
+ // From the JavaScript docs:
+ // Property names must be strings. This means that non-string objects cannot be used
+ // as keys in an object. Any non-string object, including a number, is typecasted
+ // into a string via the toString method.
+ //
+ // So, to ensure that we are checking the same `name` that JavaScript would use,
+ // we cast it to a string, if possible.
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
+ // this is, this will handle objects that misbehave.
+ name = name + '';
+ if (!isString(name)) {
+ throw $parseMinErr('iseccst',
+ 'Cannot convert object to primitive value! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function ensureSafeObject(obj, fullExpression) {
+ // nifty check if obj is Function that is fast and works across iframes and other contexts
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isWindow(obj)
+ obj.window === obj) {
+ throw $parseMinErr('isecwindow',
+ 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isElement(obj)
+ obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
+ throw $parseMinErr('isecdom',
+ 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
+ obj === Object) {
+ throw $parseMinErr('isecobj',
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+ return obj;
+}
+
+var CALL = Function.prototype.call;
+var APPLY = Function.prototype.apply;
+var BIND = Function.prototype.bind;
+
+function ensureSafeFunction(obj, fullExpression) {
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (obj === CALL || obj === APPLY || obj === BIND) {
+ throw $parseMinErr('isecff',
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+}
+
+//Keyword constants
+var CONSTANTS = createMap();
+forEach({
+ 'null': function() { return null; },
+ 'true': function() { return true; },
+ 'false': function() { return false; },
+ 'undefined': function() {}
+}, function(constantGetter, name) {
+ constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;
+ CONSTANTS[name] = constantGetter;
+});
+
+//Not quite a constant, but can be lex/parsed the same
+CONSTANTS['this'] = function(self) { return self; };
+CONSTANTS['this'].sharedGetter = true;
+
+
+//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
+var OPERATORS = extend(createMap(), {
+ '+':function(self, locals, a, b) {
+ a=a(self, locals); b=b(self, locals);
+ if (isDefined(a)) {
+ if (isDefined(b)) {
+ return a + b;
+ }
+ return a;
+ }
+ return isDefined(b) ? b : undefined;},
+ '-':function(self, locals, a, b) {
+ a=a(self, locals); b=b(self, locals);
+ return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);
+ },
+ '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},
+ '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},
+ '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},
+ '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},
+ '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},
+ '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},
+ '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},
+ '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},
+ '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},
+ '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},
+ '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},
+ '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},
+ '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},
+ '!':function(self, locals, a) {return !a(self, locals);},
+
+ //Tokenized as operators but parsed as assignment/filters
+ '=':true,
+ '|':true
+});
+var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
+
+
+/////////////////////////////////////////
+
+
+/**
+ * @constructor
+ */
+var Lexer = function(options) {
+ this.options = options;
+};
+
+Lexer.prototype = {
+ constructor: Lexer,
+
+ lex: function(text) {
+ this.text = text;
+ this.index = 0;
+ this.tokens = [];
+
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (ch === '"' || ch === "'") {
+ this.readString(ch);
+ } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
+ this.readNumber();
+ } else if (this.isIdent(ch)) {
+ this.readIdent();
+ } else if (this.is(ch, '(){}[].,;:?')) {
+ this.tokens.push({index: this.index, text: ch});
+ this.index++;
+ } else if (this.isWhitespace(ch)) {
+ this.index++;
+ } else {
+ var ch2 = ch + this.peek();
+ var ch3 = ch2 + this.peek(2);
+ var op1 = OPERATORS[ch];
+ var op2 = OPERATORS[ch2];
+ var op3 = OPERATORS[ch3];
+ if (op1 || op2 || op3) {
+ var token = op3 ? ch3 : (op2 ? ch2 : ch);
+ this.tokens.push({index: this.index, text: token, operator: true});
+ this.index += token.length;
+ } else {
+ this.throwError('Unexpected next character ', this.index, this.index + 1);
+ }
+ }
+ }
+ return this.tokens;
+ },
+
+ is: function(ch, chars) {
+ return chars.indexOf(ch) !== -1;
+ },
+
+ peek: function(i) {
+ var num = i || 1;
+ return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
+ },
+
+ isNumber: function(ch) {
+ return ('0' <= ch && ch <= '9') && typeof ch === "string";
+ },
+
+ isWhitespace: function(ch) {
+ // IE treats non-breaking space as \u00A0
+ return (ch === ' ' || ch === '\r' || ch === '\t' ||
+ ch === '\n' || ch === '\v' || ch === '\u00A0');
+ },
+
+ isIdent: function(ch) {
+ return ('a' <= ch && ch <= 'z' ||
+ 'A' <= ch && ch <= 'Z' ||
+ '_' === ch || ch === '$');
+ },
+
+ isExpOperator: function(ch) {
+ return (ch === '-' || ch === '+' || this.isNumber(ch));
+ },
+
+ throwError: function(error, start, end) {
+ end = end || this.index;
+ var colStr = (isDefined(start)
+ ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
+ : ' ' + end);
+ throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
+ error, colStr, this.text);
+ },
+
+ readNumber: function() {
+ var number = '';
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = lowercase(this.text.charAt(this.index));
+ if (ch == '.' || this.isNumber(ch)) {
+ number += ch;
+ } else {
+ var peekCh = this.peek();
+ if (ch == 'e' && this.isExpOperator(peekCh)) {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ peekCh && this.isNumber(peekCh) &&
+ number.charAt(number.length - 1) == 'e') {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ (!peekCh || !this.isNumber(peekCh)) &&
+ number.charAt(number.length - 1) == 'e') {
+ this.throwError('Invalid exponent');
+ } else {
+ break;
+ }
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: number,
+ constant: true,
+ value: Number(number)
+ });
+ },
+
+ readIdent: function() {
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (!(this.isIdent(ch) || this.isNumber(ch))) {
+ break;
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: this.text.slice(start, this.index),
+ identifier: true
+ });
+ },
+
+ readString: function(quote) {
+ var start = this.index;
+ this.index++;
+ var string = '';
+ var rawString = quote;
+ var escape = false;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ rawString += ch;
+ if (escape) {
+ if (ch === 'u') {
+ var hex = this.text.substring(this.index + 1, this.index + 5);
+ if (!hex.match(/[\da-f]{4}/i))
+ this.throwError('Invalid unicode escape [\\u' + hex + ']');
+ this.index += 4;
+ string += String.fromCharCode(parseInt(hex, 16));
+ } else {
+ var rep = ESCAPE[ch];
+ string = string + (rep || ch);
+ }
+ escape = false;
+ } else if (ch === '\\') {
+ escape = true;
+ } else if (ch === quote) {
+ this.index++;
+ this.tokens.push({
+ index: start,
+ text: rawString,
+ constant: true,
+ value: string
+ });
+ return;
+ } else {
+ string += ch;
+ }
+ this.index++;
+ }
+ this.throwError('Unterminated quote', start);
+ }
+};
+
+
+function isConstant(exp) {
+ return exp.constant;
+}
+
+/**
+ * @constructor
+ */
+var Parser = function(lexer, $filter, options) {
+ this.lexer = lexer;
+ this.$filter = $filter;
+ this.options = options;
+};
+
+Parser.ZERO = extend(function() {
+ return 0;
+}, {
+ sharedGetter: true,
+ constant: true
+});
+
+Parser.prototype = {
+ constructor: Parser,
+
+ parse: function(text) {
+ this.text = text;
+ this.tokens = this.lexer.lex(text);
+
+ var value = this.statements();
+
+ if (this.tokens.length !== 0) {
+ this.throwError('is an unexpected token', this.tokens[0]);
+ }
+
+ value.literal = !!value.literal;
+ value.constant = !!value.constant;
+
+ return value;
+ },
+
+ primary: function() {
+ var primary;
+ if (this.expect('(')) {
+ primary = this.filterChain();
+ this.consume(')');
+ } else if (this.expect('[')) {
+ primary = this.arrayDeclaration();
+ } else if (this.expect('{')) {
+ primary = this.object();
+ } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
+ primary = CONSTANTS[this.consume().text];
+ } else if (this.peek().identifier) {
+ primary = this.identifier();
+ } else if (this.peek().constant) {
+ primary = this.constant();
+ } else {
+ this.throwError('not a primary expression', this.peek());
+ }
+
+ var next, context;
+ while ((next = this.expect('(', '[', '.'))) {
+ if (next.text === '(') {
+ primary = this.functionCall(primary, context);
+ context = null;
+ } else if (next.text === '[') {
+ context = primary;
+ primary = this.objectIndex(primary);
+ } else if (next.text === '.') {
+ context = primary;
+ primary = this.fieldAccess(primary);
+ } else {
+ this.throwError('IMPOSSIBLE');
+ }
+ }
+ return primary;
+ },
+
+ throwError: function(msg, token) {
+ throw $parseMinErr('syntax',
+ 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
+ token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
+ },
+
+ peekToken: function() {
+ if (this.tokens.length === 0)
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ return this.tokens[0];
+ },
+
+ peek: function(e1, e2, e3, e4) {
+ return this.peekAhead(0, e1, e2, e3, e4);
+ },
+ peekAhead: function(i, e1, e2, e3, e4) {
+ if (this.tokens.length > i) {
+ var token = this.tokens[i];
+ var t = token.text;
+ if (t === e1 || t === e2 || t === e3 || t === e4 ||
+ (!e1 && !e2 && !e3 && !e4)) {
+ return token;
+ }
+ }
+ return false;
+ },
+
+ expect: function(e1, e2, e3, e4) {
+ var token = this.peek(e1, e2, e3, e4);
+ if (token) {
+ this.tokens.shift();
+ return token;
+ }
+ return false;
+ },
+
+ consume: function(e1) {
+ if (this.tokens.length === 0) {
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ }
+
+ var token = this.expect(e1);
+ if (!token) {
+ this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
+ }
+ return token;
+ },
+
+ unaryFn: function(op, right) {
+ var fn = OPERATORS[op];
+ return extend(function $parseUnaryFn(self, locals) {
+ return fn(self, locals, right);
+ }, {
+ constant:right.constant,
+ inputs: [right]
+ });
+ },
+
+ binaryFn: function(left, op, right, isBranching) {
+ var fn = OPERATORS[op];
+ return extend(function $parseBinaryFn(self, locals) {
+ return fn(self, locals, left, right);
+ }, {
+ constant: left.constant && right.constant,
+ inputs: !isBranching && [left, right]
+ });
+ },
+
+ identifier: function() {
+ var id = this.consume().text;
+
+ //Continue reading each `.identifier` unless it is a method invocation
+ while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {
+ id += this.consume().text + this.consume().text;
+ }
+
+ return getterFn(id, this.options, this.text);
+ },
+
+ constant: function() {
+ var value = this.consume().value;
+
+ return extend(function $parseConstant() {
+ return value;
+ }, {
+ constant: true,
+ literal: true
+ });
+ },
+
+ statements: function() {
+ var statements = [];
+ while (true) {
+ if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
+ statements.push(this.filterChain());
+ if (!this.expect(';')) {
+ // optimize for the common case where there is only one statement.
+ // TODO(size): maybe we should not support multiple statements?
+ return (statements.length === 1)
+ ? statements[0]
+ : function $parseStatements(self, locals) {
+ var value;
+ for (var i = 0, ii = statements.length; i < ii; i++) {
+ value = statements[i](self, locals);
+ }
+ return value;
+ };
+ }
+ }
+ },
+
+ filterChain: function() {
+ var left = this.expression();
+ var token;
+ while ((token = this.expect('|'))) {
+ left = this.filter(left);
+ }
+ return left;
+ },
+
+ filter: function(inputFn) {
+ var fn = this.$filter(this.consume().text);
+ var argsFn;
+ var args;
+
+ if (this.peek(':')) {
+ argsFn = [];
+ args = []; // we can safely reuse the array
+ while (this.expect(':')) {
+ argsFn.push(this.expression());
+ }
+ }
+
+ var inputs = [inputFn].concat(argsFn || []);
+
+ return extend(function $parseFilter(self, locals) {
+ var input = inputFn(self, locals);
+ if (args) {
+ args[0] = input;
+
+ var i = argsFn.length;
+ while (i--) {
+ args[i + 1] = argsFn[i](self, locals);
+ }
+
+ return fn.apply(undefined, args);
+ }
+
+ return fn(input);
+ }, {
+ constant: !fn.$stateful && inputs.every(isConstant),
+ inputs: !fn.$stateful && inputs
+ });
+ },
+
+ expression: function() {
+ return this.assignment();
+ },
+
+ assignment: function() {
+ var left = this.ternary();
+ var right;
+ var token;
+ if ((token = this.expect('='))) {
+ if (!left.assign) {
+ this.throwError('implies assignment but [' +
+ this.text.substring(0, token.index) + '] can not be assigned to', token);
+ }
+ right = this.ternary();
+ return extend(function $parseAssignment(scope, locals) {
+ return left.assign(scope, right(scope, locals), locals);
+ }, {
+ inputs: [left, right]
+ });
+ }
+ return left;
+ },
+
+ ternary: function() {
+ var left = this.logicalOR();
+ var middle;
+ var token;
+ if ((token = this.expect('?'))) {
+ middle = this.assignment();
+ if (this.consume(':')) {
+ var right = this.assignment();
+
+ return extend(function $parseTernary(self, locals) {
+ return left(self, locals) ? middle(self, locals) : right(self, locals);
+ }, {
+ constant: left.constant && middle.constant && right.constant
+ });
+ }
+ }
+
+ return left;
+ },
+
+ logicalOR: function() {
+ var left = this.logicalAND();
+ var token;
+ while ((token = this.expect('||'))) {
+ left = this.binaryFn(left, token.text, this.logicalAND(), true);
+ }
+ return left;
+ },
+
+ logicalAND: function() {
+ var left = this.equality();
+ var token;
+ while ((token = this.expect('&&'))) {
+ left = this.binaryFn(left, token.text, this.equality(), true);
+ }
+ return left;
+ },
+
+ equality: function() {
+ var left = this.relational();
+ var token;
+ while ((token = this.expect('==','!=','===','!=='))) {
+ left = this.binaryFn(left, token.text, this.relational());
+ }
+ return left;
+ },
+
+ relational: function() {
+ var left = this.additive();
+ var token;
+ while ((token = this.expect('<', '>', '<=', '>='))) {
+ left = this.binaryFn(left, token.text, this.additive());
+ }
+ return left;
+ },
+
+ additive: function() {
+ var left = this.multiplicative();
+ var token;
+ while ((token = this.expect('+','-'))) {
+ left = this.binaryFn(left, token.text, this.multiplicative());
+ }
+ return left;
+ },
+
+ multiplicative: function() {
+ var left = this.unary();
+ var token;
+ while ((token = this.expect('*','/','%'))) {
+ left = this.binaryFn(left, token.text, this.unary());
+ }
+ return left;
+ },
+
+ unary: function() {
+ var token;
+ if (this.expect('+')) {
+ return this.primary();
+ } else if ((token = this.expect('-'))) {
+ return this.binaryFn(Parser.ZERO, token.text, this.unary());
+ } else if ((token = this.expect('!'))) {
+ return this.unaryFn(token.text, this.unary());
+ } else {
+ return this.primary();
+ }
+ },
+
+ fieldAccess: function(object) {
+ var getter = this.identifier();
+
+ return extend(function $parseFieldAccess(scope, locals, self) {
+ var o = self || object(scope, locals);
+ return (o == null) ? undefined : getter(o);
+ }, {
+ assign: function(scope, value, locals) {
+ var o = object(scope, locals);
+ if (!o) object.assign(scope, o = {}, locals);
+ return getter.assign(o, value);
+ }
+ });
+ },
+
+ objectIndex: function(obj) {
+ var expression = this.text;
+
+ var indexFn = this.expression();
+ this.consume(']');
+
+ return extend(function $parseObjectIndex(self, locals) {
+ var o = obj(self, locals),
+ i = getStringValue(indexFn(self, locals), expression),
+ v;
+
+ ensureSafeMemberName(i, expression);
+ if (!o) return undefined;
+ v = ensureSafeObject(o[i], expression);
+ return v;
+ }, {
+ assign: function(self, value, locals) {
+ var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
+ // prevent overwriting of Function.constructor which would break ensureSafeObject check
+ var o = ensureSafeObject(obj(self, locals), expression);
+ if (!o) obj.assign(self, o = {}, locals);
+ return o[key] = value;
+ }
+ });
+ },
+
+ functionCall: function(fnGetter, contextGetter) {
+ var argsFn = [];
+ if (this.peekToken().text !== ')') {
+ do {
+ argsFn.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume(')');
+
+ var expressionText = this.text;
+ // we can safely reuse the array across invocations
+ var args = argsFn.length ? [] : null;
+
+ return function $parseFunctionCall(scope, locals) {
+ var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
+ var fn = fnGetter(scope, locals, context) || noop;
+
+ if (args) {
+ var i = argsFn.length;
+ while (i--) {
+ args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);
+ }
+ }
+
+ ensureSafeObject(context, expressionText);
+ ensureSafeFunction(fn, expressionText);
+
+ // IE doesn't have apply for some native functions
+ var v = fn.apply
+ ? fn.apply(context, args)
+ : fn(args[0], args[1], args[2], args[3], args[4]);
+
+ if (args) {
+ // Free-up the memory (arguments of the last function call).
+ args.length = 0;
+ }
+
+ return ensureSafeObject(v, expressionText);
+ };
+ },
+
+ // This is used with json array declaration
+ arrayDeclaration: function() {
+ var elementFns = [];
+ if (this.peekToken().text !== ']') {
+ do {
+ if (this.peek(']')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ elementFns.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume(']');
+
+ return extend(function $parseArrayLiteral(self, locals) {
+ var array = [];
+ for (var i = 0, ii = elementFns.length; i < ii; i++) {
+ array.push(elementFns[i](self, locals));
+ }
+ return array;
+ }, {
+ literal: true,
+ constant: elementFns.every(isConstant),
+ inputs: elementFns
+ });
+ },
+
+ object: function() {
+ var keys = [], valueFns = [];
+ if (this.peekToken().text !== '}') {
+ do {
+ if (this.peek('}')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ var token = this.consume();
+ if (token.constant) {
+ keys.push(token.value);
+ } else if (token.identifier) {
+ keys.push(token.text);
+ } else {
+ this.throwError("invalid key", token);
+ }
+ this.consume(':');
+ valueFns.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume('}');
+
+ return extend(function $parseObjectLiteral(self, locals) {
+ var object = {};
+ for (var i = 0, ii = valueFns.length; i < ii; i++) {
+ object[keys[i]] = valueFns[i](self, locals);
+ }
+ return object;
+ }, {
+ literal: true,
+ constant: valueFns.every(isConstant),
+ inputs: valueFns
+ });
+ }
+};
+
+
+//////////////////////////////////////////////////
+// Parser helper functions
+//////////////////////////////////////////////////
+
+function setter(obj, locals, path, setValue, fullExp) {
+ ensureSafeObject(obj, fullExp);
+ ensureSafeObject(locals, fullExp);
+
+ var element = path.split('.'), key;
+ for (var i = 0; element.length > 1; i++) {
+ key = ensureSafeMemberName(element.shift(), fullExp);
+ var propertyObj = (i === 0 && locals && locals[key]) || obj[key];
+ if (!propertyObj) {
+ propertyObj = {};
+ obj[key] = propertyObj;
+ }
+ obj = ensureSafeObject(propertyObj, fullExp);
+ }
+ key = ensureSafeMemberName(element.shift(), fullExp);
+ ensureSafeObject(obj[key], fullExp);
+ obj[key] = setValue;
+ return setValue;
+}
+
+var getterFnCacheDefault = createMap();
+var getterFnCacheExpensive = createMap();
+
+function isPossiblyDangerousMemberName(name) {
+ return name == 'constructor';
+}
+
+/**
+ * Implementation of the "Black Hole" variant from:
+ * - http://jsperf.com/angularjs-parse-getter/4
+ * - http://jsperf.com/path-evaluation-simplified/7
+ */
+function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {
+ ensureSafeMemberName(key0, fullExp);
+ ensureSafeMemberName(key1, fullExp);
+ ensureSafeMemberName(key2, fullExp);
+ ensureSafeMemberName(key3, fullExp);
+ ensureSafeMemberName(key4, fullExp);
+ var eso = function(o) {
+ return ensureSafeObject(o, fullExp);
+ };
+ var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;
+ var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;
+ var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;
+ var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;
+ var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;
+
+ return function cspSafeGetter(scope, locals) {
+ var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
+
+ if (pathVal == null) return pathVal;
+ pathVal = eso0(pathVal[key0]);
+
+ if (!key1) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso1(pathVal[key1]);
+
+ if (!key2) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso2(pathVal[key2]);
+
+ if (!key3) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso3(pathVal[key3]);
+
+ if (!key4) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso4(pathVal[key4]);
+
+ return pathVal;
+ };
+}
+
+function getterFnWithEnsureSafeObject(fn, fullExpression) {
+ return function(s, l) {
+ return fn(s, l, ensureSafeObject, fullExpression);
+ };
+}
+
+function getterFn(path, options, fullExp) {
+ var expensiveChecks = options.expensiveChecks;
+ var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);
+ var fn = getterFnCache[path];
+ if (fn) return fn;
+
+
+ var pathKeys = path.split('.'),
+ pathKeysLength = pathKeys.length;
+
+ // http://jsperf.com/angularjs-parse-getter/6
+ if (options.csp) {
+ if (pathKeysLength < 6) {
+ fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);
+ } else {
+ fn = function cspSafeGetter(scope, locals) {
+ var i = 0, val;
+ do {
+ val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
+ pathKeys[i++], fullExp, expensiveChecks)(scope, locals);
+
+ locals = undefined; // clear after first iteration
+ scope = val;
+ } while (i < pathKeysLength);
+ return val;
+ };
+ }
+ } else {
+ var code = '';
+ if (expensiveChecks) {
+ code += 's = eso(s, fe);\nl = eso(l, fe);\n';
+ }
+ var needsEnsureSafeObject = expensiveChecks;
+ forEach(pathKeys, function(key, index) {
+ ensureSafeMemberName(key, fullExp);
+ var lookupJs = (index
+ // we simply dereference 's' on any .dot notation
+ ? 's'
+ // but if we are first then we check locals first, and if so read it first
+ : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key;
+ if (expensiveChecks || isPossiblyDangerousMemberName(key)) {
+ lookupJs = 'eso(' + lookupJs + ', fe)';
+ needsEnsureSafeObject = true;
+ }
+ code += 'if(s == null) return undefined;\n' +
+ 's=' + lookupJs + ';\n';
+ });
+ code += 'return s;';
+
+ /* jshint -W054 */
+ var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject
+ /* jshint +W054 */
+ evaledFnGetter.toString = valueFn(code);
+ if (needsEnsureSafeObject) {
+ evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);
+ }
+ fn = evaledFnGetter;
+ }
+
+ fn.sharedGetter = true;
+ fn.assign = function(self, value, locals) {
+ return setter(self, locals, path, value, path);
+ };
+ getterFnCache[path] = fn;
+ return fn;
+}
+
+var objectValueOf = Object.prototype.valueOf;
+
+function getValueOf(value) {
+ return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
+}
+
+///////////////////////////////////
+
+/**
+ * @ngdoc service
+ * @name $parse
+ * @kind function
+ *
+ * @description
+ *
+ * Converts Angular {@link guide/expression expression} into a function.
+ *
+ * ```js
+ * var getter = $parse('user.name');
+ * var setter = getter.assign;
+ * var context = {user:{name:'angular'}};
+ * var locals = {user:{name:'local'}};
+ *
+ * expect(getter(context)).toEqual('angular');
+ * setter(context, 'newValue');
+ * expect(context.user.name).toEqual('newValue');
+ * expect(getter(context, locals)).toEqual('local');
+ * ```
+ *
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ *
+ * The returned function also has the following properties:
+ * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
+ * literal.
+ * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
+ * constant literals.
+ * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
+ * set to a function to change its value on the given context.
+ *
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $parseProvider
+ *
+ * @description
+ * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
+ * service.
+ */
+function $ParseProvider() {
+ var cacheDefault = createMap();
+ var cacheExpensive = createMap();
+
+
+
+ this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
+ var $parseOptions = {
+ csp: $sniffer.csp,
+ expensiveChecks: false
+ },
+ $parseOptionsExpensive = {
+ csp: $sniffer.csp,
+ expensiveChecks: true
+ };
+
+ function wrapSharedExpression(exp) {
+ var wrapped = exp;
+
+ if (exp.sharedGetter) {
+ wrapped = function $parseWrapper(self, locals) {
+ return exp(self, locals);
+ };
+ wrapped.literal = exp.literal;
+ wrapped.constant = exp.constant;
+ wrapped.assign = exp.assign;
+ }
+
+ return wrapped;
+ }
+
+ return function $parse(exp, interceptorFn, expensiveChecks) {
+ var parsedExpression, oneTime, cacheKey;
+
+ switch (typeof exp) {
+ case 'string':
+ cacheKey = exp = exp.trim();
+
+ var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
+ parsedExpression = cache[cacheKey];
+
+ if (!parsedExpression) {
+ if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
+ oneTime = true;
+ exp = exp.substring(2);
+ }
+
+ var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
+ var lexer = new Lexer(parseOptions);
+ var parser = new Parser(lexer, $filter, parseOptions);
+ parsedExpression = parser.parse(exp);
+
+ if (parsedExpression.constant) {
+ parsedExpression.$$watchDelegate = constantWatchDelegate;
+ } else if (oneTime) {
+ //oneTime is not part of the exp passed to the Parser so we may have to
+ //wrap the parsedExpression before adding a $$watchDelegate
+ parsedExpression = wrapSharedExpression(parsedExpression);
+ parsedExpression.$$watchDelegate = parsedExpression.literal ?
+ oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
+ } else if (parsedExpression.inputs) {
+ parsedExpression.$$watchDelegate = inputsWatchDelegate;
+ }
+
+ cache[cacheKey] = parsedExpression;
+ }
+ return addInterceptor(parsedExpression, interceptorFn);
+
+ case 'function':
+ return addInterceptor(exp, interceptorFn);
+
+ default:
+ return addInterceptor(noop, interceptorFn);
+ }
+ };
+
+ function collectExpressionInputs(inputs, list) {
+ for (var i = 0, ii = inputs.length; i < ii; i++) {
+ var input = inputs[i];
+ if (!input.constant) {
+ if (input.inputs) {
+ collectExpressionInputs(input.inputs, list);
+ } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?
+ list.push(input);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ function expressionInputDirtyCheck(newValue, oldValueOfValue) {
+
+ if (newValue == null || oldValueOfValue == null) { // null/undefined
+ return newValue === oldValueOfValue;
+ }
+
+ if (typeof newValue === 'object') {
+
+ // attempt to convert the value to a primitive type
+ // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
+ // be cheaply dirty-checked
+ newValue = getValueOf(newValue);
+
+ if (typeof newValue === 'object') {
+ // objects/arrays are not supported - deep-watching them would be too expensive
+ return false;
+ }
+
+ // fall-through to the primitive equality check
+ }
+
+ //Primitive or NaN
+ return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
+ }
+
+ function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var inputExpressions = parsedExpression.$$inputs ||
+ (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));
+
+ var lastResult;
+
+ if (inputExpressions.length === 1) {
+ var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ inputExpressions = inputExpressions[0];
+ return scope.$watch(function expressionInputWatch(scope) {
+ var newInputValue = inputExpressions(scope);
+ if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
+ lastResult = parsedExpression(scope);
+ oldInputValue = newInputValue && getValueOf(newInputValue);
+ }
+ return lastResult;
+ }, listener, objectEquality);
+ }
+
+ var oldInputValueOfValues = [];
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ }
+
+ return scope.$watch(function expressionInputsWatch(scope) {
+ var changed = false;
+
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ var newInputValue = inputExpressions[i](scope);
+ if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
+ oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
+ }
+ }
+
+ if (changed) {
+ lastResult = parsedExpression(scope);
+ }
+
+ return lastResult;
+ }, listener, objectEquality);
+ }
+
+ function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ if (isDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isDefined(lastValue)) {
+ unwatch();
+ }
+ });
+ }
+ }, objectEquality);
+ }
+
+ function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.call(this, value, old, scope);
+ }
+ if (isAllDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isAllDefined(lastValue)) unwatch();
+ });
+ }
+ }, objectEquality);
+
+ function isAllDefined(value) {
+ var allDefined = true;
+ forEach(value, function(val) {
+ if (!isDefined(val)) allDefined = false;
+ });
+ return allDefined;
+ }
+ }
+
+ function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch;
+ return unwatch = scope.$watch(function constantWatch(scope) {
+ return parsedExpression(scope);
+ }, function constantListener(value, old, scope) {
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ unwatch();
+ }, objectEquality);
+ }
+
+ function addInterceptor(parsedExpression, interceptorFn) {
+ if (!interceptorFn) return parsedExpression;
+ var watchDelegate = parsedExpression.$$watchDelegate;
+
+ var regularWatch =
+ watchDelegate !== oneTimeLiteralWatchDelegate &&
+ watchDelegate !== oneTimeWatchDelegate;
+
+ var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
+ var value = parsedExpression(scope, locals);
+ return interceptorFn(value, scope, locals);
+ } : function oneTimeInterceptedExpression(scope, locals) {
+ var value = parsedExpression(scope, locals);
+ var result = interceptorFn(value, scope, locals);
+ // we only return the interceptor's result if the
+ // initial value is defined (for bind-once)
+ return isDefined(value) ? result : value;
+ };
+
+ // Propagate $$watchDelegates other then inputsWatchDelegate
+ if (parsedExpression.$$watchDelegate &&
+ parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
+ fn.$$watchDelegate = parsedExpression.$$watchDelegate;
+ } else if (!interceptorFn.$stateful) {
+ // If there is an interceptor, but no watchDelegate then treat the interceptor like
+ // we treat filters - it is assumed to be a pure function unless flagged with $stateful
+ fn.$$watchDelegate = inputsWatchDelegate;
+ fn.inputs = [parsedExpression];
+ }
+
+ return fn;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $q
+ * @requires $rootScope
+ *
+ * @description
+ * A service that helps you run functions asynchronously, and use their return values (or exceptions)
+ * when they are done processing.
+ *
+ * This is an implementation of promises/deferred objects inspired by
+ * [Kris Kowal's Q](https://github.com/kriskowal/q).
+ *
+ * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
+ * implementations, and the other which resembles ES6 promises to some degree.
+ *
+ * # $q constructor
+ *
+ * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
+ * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
+ * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
+ *
+ * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
+ * available yet.
+ *
+ * It can be used like so:
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * // perform some asynchronous operation, resolve or reject the promise when appropriate.
+ * return $q(function(resolve, reject) {
+ * setTimeout(function() {
+ * if (okToGreet(name)) {
+ * resolve('Hello, ' + name + '!');
+ * } else {
+ * reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ * });
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * });
+ * ```
+ *
+ * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
+ *
+ * However, the more traditional CommonJS-style usage is still available, and documented below.
+ *
+ * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
+ * interface for interacting with an object that represents the result of an action that is
+ * performed asynchronously, and may or may not be finished at any given point in time.
+ *
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
+ * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * var deferred = $q.defer();
+ *
+ * setTimeout(function() {
+ * deferred.notify('About to greet ' + name + '.');
+ *
+ * if (okToGreet(name)) {
+ * deferred.resolve('Hello, ' + name + '!');
+ * } else {
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ *
+ * return deferred.promise;
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * }, function(update) {
+ * alert('Got notification: ' + update);
+ * });
+ * ```
+ *
+ * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
+ * comes in the way of guarantees that promise and deferred APIs make, see
+ * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
+ *
+ * Additionally the promise api allows for composition that is very hard to do with the
+ * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
+ * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
+ * section on serial or parallel joining of promises.
+ *
+ * # The Deferred API
+ *
+ * A new instance of deferred is constructed by calling `$q.defer()`.
+ *
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
+ * that can be used for signaling the successful or unsuccessful completion, as well as the status
+ * of the task.
+ *
+ * **Methods**
+ *
+ * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
+ * constructed via `$q.reject`, the promise will be rejected instead.
+ * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
+ * resolving it with a rejection constructed via `$q.reject`.
+ * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
+ * multiple times before the promise is either resolved or rejected.
+ *
+ * **Properties**
+ *
+ * - promise – `{Promise}` – promise object associated with this deferred.
+ *
+ *
+ * # The Promise API
+ *
+ * A new promise instance is created when a deferred instance is created and can be retrieved by
+ * calling `deferred.promise`.
+ *
+ * The purpose of the promise object is to allow for interested parties to get access to the result
+ * of the deferred task when it completes.
+ *
+ * **Methods**
+ *
+ * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
+ * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
+ * as soon as the result is available. The callbacks are called with a single argument: the result
+ * or rejection reason. Additionally, the notify callback may be called zero or more times to
+ * provide a progress indication, before the promise is resolved or rejected.
+ *
+ * This method *returns a new promise* which is resolved or rejected via the return value of the
+ * `successCallback`, `errorCallback`. It also notifies via the return value of the
+ * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
+ * method.
+ *
+ * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
+ *
+ * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
+ * but to do so without modifying the final value. This is useful to release resources or do some
+ * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
+ * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
+ * more information.
+ *
+ * # Chaining promises
+ *
+ * Because calling the `then` method of a promise returns a new derived promise, it is easily
+ * possible to create a chain of promises:
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * return result + 1;
+ * });
+ *
+ * // promiseB will be resolved immediately after promiseA is resolved and its value
+ * // will be the result of promiseA incremented by 1
+ * ```
+ *
+ * It is possible to create chains of any length and since a promise can be resolved with another
+ * promise (which will defer its resolution further), it is possible to pause/defer resolution of
+ * the promises at any point in the chain. This makes it possible to implement powerful APIs like
+ * $http's response interceptors.
+ *
+ *
+ * # Differences between Kris Kowal's Q and $q
+ *
+ * There are two main differences:
+ *
+ * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
+ * mechanism in angular, which means faster propagation of resolution or rejection into your
+ * models and avoiding unnecessary browser repaints, which would result in flickering UI.
+ * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
+ * all the important functionality needed for common async tasks.
+ *
+ * # Testing
+ *
+ * ```js
+ * it('should simulate promise', inject(function($q, $rootScope) {
+ * var deferred = $q.defer();
+ * var promise = deferred.promise;
+ * var resolvedValue;
+ *
+ * promise.then(function(value) { resolvedValue = value; });
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Simulate resolving of promise
+ * deferred.resolve(123);
+ * // Note that the 'then' function does not get called synchronously.
+ * // This is because we want the promise API to always be async, whether or not
+ * // it got called synchronously or asynchronously.
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Propagate promise resolution to 'then' functions using $apply().
+ * $rootScope.$apply();
+ * expect(resolvedValue).toEqual(123);
+ * }));
+ * ```
+ *
+ * @param {function(function, function)} resolver Function which is responsible for resolving or
+ * rejecting the newly created promise. The first parameter is a function which resolves the
+ * promise, the second parameter is a function which rejects the promise.
+ *
+ * @returns {Promise} The newly created promise.
+ */
+function $QProvider() {
+
+ this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $rootScope.$evalAsync(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+function $$QProvider() {
+ this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $browser.defer(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+/**
+ * Constructs a promise manager.
+ *
+ * @param {function(function)} nextTick Function for executing functions in the next turn.
+ * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
+ * debugging purposes.
+ * @returns {object} Promise manager.
+ */
+function qFactory(nextTick, exceptionHandler) {
+ var $qMinErr = minErr('$q', TypeError);
+ function callOnce(self, resolveFn, rejectFn) {
+ var called = false;
+ function wrap(fn) {
+ return function(value) {
+ if (called) return;
+ called = true;
+ fn.call(self, value);
+ };
+ }
+
+ return [wrap(resolveFn), wrap(rejectFn)];
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$q#defer
+ * @kind function
+ *
+ * @description
+ * Creates a `Deferred` object which represents a task which will finish in the future.
+ *
+ * @returns {Deferred} Returns a new instance of deferred.
+ */
+ var defer = function() {
+ return new Deferred();
+ };
+
+ function Promise() {
+ this.$$state = { status: 0 };
+ }
+
+ Promise.prototype = {
+ then: function(onFulfilled, onRejected, progressBack) {
+ var result = new Deferred();
+
+ this.$$state.pending = this.$$state.pending || [];
+ this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
+ if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
+
+ return result.promise;
+ },
+
+ "catch": function(callback) {
+ return this.then(null, callback);
+ },
+
+ "finally": function(callback, progressBack) {
+ return this.then(function(value) {
+ return handleCallback(value, true, callback);
+ }, function(error) {
+ return handleCallback(error, false, callback);
+ }, progressBack);
+ }
+ };
+
+ //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
+ function simpleBind(context, fn) {
+ return function(value) {
+ fn.call(context, value);
+ };
+ }
+
+ function processQueue(state) {
+ var fn, promise, pending;
+
+ pending = state.pending;
+ state.processScheduled = false;
+ state.pending = undefined;
+ for (var i = 0, ii = pending.length; i < ii; ++i) {
+ promise = pending[i][0];
+ fn = pending[i][state.status];
+ try {
+ if (isFunction(fn)) {
+ promise.resolve(fn(state.value));
+ } else if (state.status === 1) {
+ promise.resolve(state.value);
+ } else {
+ promise.reject(state.value);
+ }
+ } catch (e) {
+ promise.reject(e);
+ exceptionHandler(e);
+ }
+ }
+ }
+
+ function scheduleProcessQueue(state) {
+ if (state.processScheduled || !state.pending) return;
+ state.processScheduled = true;
+ nextTick(function() { processQueue(state); });
+ }
+
+ function Deferred() {
+ this.promise = new Promise();
+ //Necessary to support unbound execution :/
+ this.resolve = simpleBind(this, this.resolve);
+ this.reject = simpleBind(this, this.reject);
+ this.notify = simpleBind(this, this.notify);
+ }
+
+ Deferred.prototype = {
+ resolve: function(val) {
+ if (this.promise.$$state.status) return;
+ if (val === this.promise) {
+ this.$$reject($qMinErr(
+ 'qcycle',
+ "Expected promise to be resolved with value other than itself '{0}'",
+ val));
+ } else {
+ this.$$resolve(val);
+ }
+
+ },
+
+ $$resolve: function(val) {
+ var then, fns;
+
+ fns = callOnce(this, this.$$resolve, this.$$reject);
+ try {
+ if ((isObject(val) || isFunction(val))) then = val && val.then;
+ if (isFunction(then)) {
+ this.promise.$$state.status = -1;
+ then.call(val, fns[0], fns[1], this.notify);
+ } else {
+ this.promise.$$state.value = val;
+ this.promise.$$state.status = 1;
+ scheduleProcessQueue(this.promise.$$state);
+ }
+ } catch (e) {
+ fns[1](e);
+ exceptionHandler(e);
+ }
+ },
+
+ reject: function(reason) {
+ if (this.promise.$$state.status) return;
+ this.$$reject(reason);
+ },
+
+ $$reject: function(reason) {
+ this.promise.$$state.value = reason;
+ this.promise.$$state.status = 2;
+ scheduleProcessQueue(this.promise.$$state);
+ },
+
+ notify: function(progress) {
+ var callbacks = this.promise.$$state.pending;
+
+ if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
+ nextTick(function() {
+ var callback, result;
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
+ result = callbacks[i][0];
+ callback = callbacks[i][3];
+ try {
+ result.notify(isFunction(callback) ? callback(progress) : progress);
+ } catch (e) {
+ exceptionHandler(e);
+ }
+ }
+ });
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#reject
+ * @kind function
+ *
+ * @description
+ * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
+ * used to forward rejection in a chain of promises. If you are dealing with the last promise in
+ * a promise chain, you don't need to worry about it.
+ *
+ * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
+ * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
+ * a promise error callback and you want to forward the error to the promise derived from the
+ * current promise, you have to "rethrow" the error by returning a rejection constructed via
+ * `reject`.
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * // success: do something and resolve promiseB
+ * // with the old or a new result
+ * return result;
+ * }, function(reason) {
+ * // error: handle the error if possible and
+ * // resolve promiseB with newPromiseOrValue,
+ * // otherwise forward the rejection to promiseB
+ * if (canHandle(reason)) {
+ * // handle the error and recover
+ * return newPromiseOrValue;
+ * }
+ * return $q.reject(reason);
+ * });
+ * ```
+ *
+ * @param {*} reason Constant, message, exception or an object representing the rejection reason.
+ * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
+ */
+ var reject = function(reason) {
+ var result = new Deferred();
+ result.reject(reason);
+ return result.promise;
+ };
+
+ var makePromise = function makePromise(value, resolved) {
+ var result = new Deferred();
+ if (resolved) {
+ result.resolve(value);
+ } else {
+ result.reject(value);
+ }
+ return result.promise;
+ };
+
+ var handleCallback = function handleCallback(value, isResolved, callback) {
+ var callbackOutput = null;
+ try {
+ if (isFunction(callback)) callbackOutput = callback();
+ } catch (e) {
+ return makePromise(e, false);
+ }
+ if (isPromiseLike(callbackOutput)) {
+ return callbackOutput.then(function() {
+ return makePromise(value, isResolved);
+ }, function(error) {
+ return makePromise(error, false);
+ });
+ } else {
+ return makePromise(value, isResolved);
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#when
+ * @kind function
+ *
+ * @description
+ * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
+ * the promise comes from a source that can't be trusted.
+ *
+ * @param {*} value Value or a promise
+ * @returns {Promise} Returns a promise of the passed value or promise
+ */
+
+
+ var when = function(value, callback, errback, progressBack) {
+ var result = new Deferred();
+ result.resolve(value);
+ return result.promise.then(callback, errback, progressBack);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#all
+ * @kind function
+ *
+ * @description
+ * Combines multiple promises into a single promise that is resolved when all of the input
+ * promises are resolved.
+ *
+ * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
+ * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
+ * each value corresponding to the promise at the same index/key in the `promises` array/hash.
+ * If any of the promises is resolved with a rejection, this resulting promise will be rejected
+ * with the same rejection value.
+ */
+
+ function all(promises) {
+ var deferred = new Deferred(),
+ counter = 0,
+ results = isArray(promises) ? [] : {};
+
+ forEach(promises, function(promise, key) {
+ counter++;
+ when(promise).then(function(value) {
+ if (results.hasOwnProperty(key)) return;
+ results[key] = value;
+ if (!(--counter)) deferred.resolve(results);
+ }, function(reason) {
+ if (results.hasOwnProperty(key)) return;
+ deferred.reject(reason);
+ });
+ });
+
+ if (counter === 0) {
+ deferred.resolve(results);
+ }
+
+ return deferred.promise;
+ }
+
+ var $Q = function Q(resolver) {
+ if (!isFunction(resolver)) {
+ throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
+ }
+
+ if (!(this instanceof Q)) {
+ // More useful when $Q is the Promise itself.
+ return new Q(resolver);
+ }
+
+ var deferred = new Deferred();
+
+ function resolveFn(value) {
+ deferred.resolve(value);
+ }
+
+ function rejectFn(reason) {
+ deferred.reject(reason);
+ }
+
+ resolver(resolveFn, rejectFn);
+
+ return deferred.promise;
+ };
+
+ $Q.defer = defer;
+ $Q.reject = reject;
+ $Q.when = when;
+ $Q.all = all;
+
+ return $Q;
+}
+
+function $$RAFProvider() { //rAF
+ this.$get = ['$window', '$timeout', function($window, $timeout) {
+ var requestAnimationFrame = $window.requestAnimationFrame ||
+ $window.webkitRequestAnimationFrame;
+
+ var cancelAnimationFrame = $window.cancelAnimationFrame ||
+ $window.webkitCancelAnimationFrame ||
+ $window.webkitCancelRequestAnimationFrame;
+
+ var rafSupported = !!requestAnimationFrame;
+ var rafFn = rafSupported
+ ? function(fn) {
+ var id = requestAnimationFrame(fn);
+ return function() {
+ cancelAnimationFrame(id);
+ };
+ }
+ : function(fn) {
+ var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
+ return function() {
+ $timeout.cancel(timer);
+ };
+ };
+
+ queueFn.supported = rafSupported;
+
+ var cancelLastRAF;
+ var taskCount = 0;
+ var taskQueue = [];
+ return queueFn;
+
+ function flush() {
+ for (var i = 0; i < taskQueue.length; i++) {
+ var task = taskQueue[i];
+ if (task) {
+ taskQueue[i] = null;
+ task();
+ }
+ }
+ taskCount = taskQueue.length = 0;
+ }
+
+ function queueFn(asyncFn) {
+ var index = taskQueue.length;
+
+ taskCount++;
+ taskQueue.push(asyncFn);
+
+ if (index === 0) {
+ cancelLastRAF = rafFn(flush);
+ }
+
+ return function cancelQueueFn() {
+ if (index >= 0) {
+ taskQueue[index] = null;
+ index = null;
+
+ if (--taskCount === 0 && cancelLastRAF) {
+ cancelLastRAF();
+ cancelLastRAF = null;
+ taskQueue.length = 0;
+ }
+ }
+ };
+ }
+ }];
+}
+
+/**
+ * DESIGN NOTES
+ *
+ * The design decisions behind the scope are heavily favored for speed and memory consumption.
+ *
+ * The typical use of scope is to watch the expressions, which most of the time return the same
+ * value as last time so we optimize the operation.
+ *
+ * Closures construction is expensive in terms of speed as well as memory:
+ * - No closures, instead use prototypical inheritance for API
+ * - Internal state needs to be stored on scope directly, which means that private state is
+ * exposed as $$____ properties
+ *
+ * Loop operations are optimized by using while(count--) { ... }
+ * - this means that in order to keep the same order of execution as addition we have to add
+ * items to the array at the beginning (unshift) instead of at the end (push)
+ *
+ * Child scopes are created and removed often
+ * - Using an array would be slow since inserts in middle are expensive so we use linked list
+ *
+ * There are few watches then a lot of observers. This is why you don't want the observer to be
+ * implemented in the same way as watch. Watch requires return of initialization function which
+ * are expensive to construct.
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $rootScopeProvider
+ * @description
+ *
+ * Provider for the $rootScope service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $rootScopeProvider#digestTtl
+ * @description
+ *
+ * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
+ * assuming that the model is unstable.
+ *
+ * The current default is 10 iterations.
+ *
+ * In complex applications it's possible that the dependencies between `$watch`s will result in
+ * several digest iterations. However if an application needs more than the default 10 digest
+ * iterations for its model to stabilize then you should investigate what is causing the model to
+ * continuously change during the digest.
+ *
+ * Increasing the TTL could have performance implications, so you should not change it without
+ * proper justification.
+ *
+ * @param {number} limit The number of digest iterations.
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $rootScope
+ * @description
+ *
+ * Every application has a single root {@link ng.$rootScope.Scope scope}.
+ * All other scopes are descendant scopes of the root scope. Scopes provide separation
+ * between the model and the view, via a mechanism for watching the model for changes.
+ * They also provide an event emission/broadcast and subscription facility. See the
+ * {@link guide/scope developer guide on scopes}.
+ */
+function $RootScopeProvider() {
+ var TTL = 10;
+ var $rootScopeMinErr = minErr('$rootScope');
+ var lastDirtyWatch = null;
+ var applyAsyncId = null;
+
+ this.digestTtl = function(value) {
+ if (arguments.length) {
+ TTL = value;
+ }
+ return TTL;
+ };
+
+ function createChildScopeClass(parent) {
+ function ChildScope() {
+ this.$$watchers = this.$$nextSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$id = nextUid();
+ this.$$ChildScope = null;
+ }
+ ChildScope.prototype = parent;
+ return ChildScope;
+ }
+
+ this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
+ function($injector, $exceptionHandler, $parse, $browser) {
+
+ function destroyChildScope($event) {
+ $event.currentScope.$$destroyed = true;
+ }
+
+ /**
+ * @ngdoc type
+ * @name $rootScope.Scope
+ *
+ * @description
+ * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
+ * {@link auto.$injector $injector}. Child scopes are created using the
+ * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
+ * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
+ * an in-depth introduction and usage examples.
+ *
+ *
+ * # Inheritance
+ * A scope can inherit from a parent scope, as in this example:
+ * ```js
+ var parent = $rootScope;
+ var child = parent.$new();
+
+ parent.salutation = "Hello";
+ expect(child.salutation).toEqual('Hello');
+
+ child.salutation = "Welcome";
+ expect(child.salutation).toEqual('Welcome');
+ expect(parent.salutation).toEqual('Hello');
+ * ```
+ *
+ * When interacting with `Scope` in tests, additional helper methods are available on the
+ * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
+ * details.
+ *
+ *
+ * @param {Object.<string, function()>=} providers Map of service factory which need to be
+ * provided for the current scope. Defaults to {@link ng}.
+ * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
+ * append/override services provided by `providers`. This is handy
+ * when unit-testing and having the need to override a default
+ * service.
+ * @returns {Object} Newly created scope.
+ *
+ */
+ function Scope() {
+ this.$id = nextUid();
+ this.$$phase = this.$parent = this.$$watchers =
+ this.$$nextSibling = this.$$prevSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$root = this;
+ this.$$destroyed = false;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$$isolateBindings = null;
+ }
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$id
+ *
+ * @description
+ * Unique scope ID (monotonically increasing) useful for debugging.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$parent
+ *
+ * @description
+ * Reference to the parent scope.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$root
+ *
+ * @description
+ * Reference to the root scope.
+ */
+
+ Scope.prototype = {
+ constructor: Scope,
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$new
+ * @kind function
+ *
+ * @description
+ * Creates a new child {@link ng.$rootScope.Scope scope}.
+ *
+ * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
+ * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
+ *
+ * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
+ * desired for the scope and its child scopes to be permanently detached from the parent and
+ * thus stop participating in model change detection and listener notification by invoking.
+ *
+ * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
+ * parent scope. The scope is isolated, as it can not see parent scope properties.
+ * When creating widgets, it is useful for the widget to not accidentally read parent
+ * state.
+ *
+ * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
+ * of the newly created scope. Defaults to `this` scope if not provided.
+ * This is used when creating a transclude scope to correctly place it
+ * in the scope hierarchy while maintaining the correct prototypical
+ * inheritance.
+ *
+ * @returns {Object} The newly created child scope.
+ *
+ */
+ $new: function(isolate, parent) {
+ var child;
+
+ parent = parent || this;
+
+ if (isolate) {
+ child = new Scope();
+ child.$root = this.$root;
+ } else {
+ // Only create a child scope class if somebody asks for one,
+ // but cache it to allow the VM to optimize lookups.
+ if (!this.$$ChildScope) {
+ this.$$ChildScope = createChildScopeClass(this);
+ }
+ child = new this.$$ChildScope();
+ }
+ child.$parent = parent;
+ child.$$prevSibling = parent.$$childTail;
+ if (parent.$$childHead) {
+ parent.$$childTail.$$nextSibling = child;
+ parent.$$childTail = child;
+ } else {
+ parent.$$childHead = parent.$$childTail = child;
+ }
+
+ // When the new scope is not isolated or we inherit from `this`, and
+ // the parent scope is destroyed, the property `$$destroyed` is inherited
+ // prototypically. In all other cases, this property needs to be set
+ // when the parent scope is destroyed.
+ // The listener needs to be added after the parent is set
+ if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
+
+ return child;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watch
+ * @kind function
+ *
+ * @description
+ * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
+ *
+ * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
+ * $digest()} and should return the value that will be watched. (Since
+ * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
+ * `watchExpression` can execute multiple times per
+ * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
+ * - The `listener` is called only when the value from the current `watchExpression` and the
+ * previous call to `watchExpression` are not equal (with the exception of the initial run,
+ * see below). Inequality is determined according to reference inequality,
+ * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
+ * via the `!==` Javascript operator, unless `objectEquality == true`
+ * (see next point)
+ * - When `objectEquality == true`, inequality of the `watchExpression` is determined
+ * according to the {@link angular.equals} function. To save the value of the object for
+ * later comparison, the {@link angular.copy} function is used. This therefore means that
+ * watching complex objects will have adverse memory and performance implications.
+ * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
+ * This is achieved by rerunning the watchers until no changes are detected. The rerun
+ * iteration limit is 10 to prevent an infinite loop deadlock.
+ *
+ *
+ * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
+ * you can register a `watchExpression` function with no `listener`. (Be prepared for
+ * multiple calls to your `watchExpression` because it will execute multiple times in a
+ * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
+ *
+ * After a watcher is registered with the scope, the `listener` fn is called asynchronously
+ * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
+ * watcher. In rare cases, this is undesirable because the listener is called when the result
+ * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
+ * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
+ * listener was called due to initialization.
+ *
+ *
+ *
+ * # Example
+ * ```js
+ // let's assume that scope was dependency injected as the $rootScope
+ var scope = $rootScope;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+
+
+
+ // Using a function as a watchExpression
+ var food;
+ scope.foodCounter = 0;
+ expect(scope.foodCounter).toEqual(0);
+ scope.$watch(
+ // This function returns the value being watched. It is called for each turn of the $digest loop
+ function() { return food; },
+ // This is the change listener, called when the value returned from the above function changes
+ function(newValue, oldValue) {
+ if ( newValue !== oldValue ) {
+ // Only increment the counter if the value changed
+ scope.foodCounter = scope.foodCounter + 1;
+ }
+ }
+ );
+ // No digest has been run so the counter will be zero
+ expect(scope.foodCounter).toEqual(0);
+
+ // Run the digest but since food has not changed count will still be zero
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(0);
+
+ // Update food and run digest. Now the counter will increment
+ food = 'cheeseburger';
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(1);
+
+ * ```
+ *
+ *
+ *
+ * @param {(function()|string)} watchExpression Expression that is evaluated on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
+ * a call to the `listener`.
+ *
+ * - `string`: Evaluated as {@link guide/expression expression}
+ * - `function(scope)`: called with current `scope` as a parameter.
+ * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
+ * of `watchExpression` changes.
+ *
+ * - `newVal` contains the current value of the `watchExpression`
+ * - `oldVal` contains the previous value of the `watchExpression`
+ * - `scope` refers to the current scope
+ * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
+ * comparing for reference equality.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $watch: function(watchExp, listener, objectEquality) {
+ var get = $parse(watchExp);
+
+ if (get.$$watchDelegate) {
+ return get.$$watchDelegate(this, listener, objectEquality, get);
+ }
+ var scope = this,
+ array = scope.$$watchers,
+ watcher = {
+ fn: listener,
+ last: initWatchVal,
+ get: get,
+ exp: watchExp,
+ eq: !!objectEquality
+ };
+
+ lastDirtyWatch = null;
+
+ if (!isFunction(listener)) {
+ watcher.fn = noop;
+ }
+
+ if (!array) {
+ array = scope.$$watchers = [];
+ }
+ // we use unshift since we use a while loop in $digest for speed.
+ // the while loop reads in reverse order.
+ array.unshift(watcher);
+
+ return function deregisterWatch() {
+ arrayRemove(array, watcher);
+ lastDirtyWatch = null;
+ };
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchGroup
+ * @kind function
+ *
+ * @description
+ * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
+ * If any one expression in the collection changes the `listener` is executed.
+ *
+ * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
+ * call to $digest() to see if any items changes.
+ * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
+ *
+ * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
+ * watched using {@link ng.$rootScope.Scope#$watch $watch()}
+ *
+ * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
+ * expression in `watchExpressions` changes
+ * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * The `scope` refers to the current scope.
+ * @returns {function()} Returns a de-registration function for all listeners.
+ */
+ $watchGroup: function(watchExpressions, listener) {
+ var oldValues = new Array(watchExpressions.length);
+ var newValues = new Array(watchExpressions.length);
+ var deregisterFns = [];
+ var self = this;
+ var changeReactionScheduled = false;
+ var firstRun = true;
+
+ if (!watchExpressions.length) {
+ // No expressions means we call the listener ASAP
+ var shouldCall = true;
+ self.$evalAsync(function() {
+ if (shouldCall) listener(newValues, newValues, self);
+ });
+ return function deregisterWatchGroup() {
+ shouldCall = false;
+ };
+ }
+
+ if (watchExpressions.length === 1) {
+ // Special case size of one
+ return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
+ newValues[0] = value;
+ oldValues[0] = oldValue;
+ listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
+ });
+ }
+
+ forEach(watchExpressions, function(expr, i) {
+ var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
+ newValues[i] = value;
+ oldValues[i] = oldValue;
+ if (!changeReactionScheduled) {
+ changeReactionScheduled = true;
+ self.$evalAsync(watchGroupAction);
+ }
+ });
+ deregisterFns.push(unwatchFn);
+ });
+
+ function watchGroupAction() {
+ changeReactionScheduled = false;
+
+ if (firstRun) {
+ firstRun = false;
+ listener(newValues, newValues, self);
+ } else {
+ listener(newValues, oldValues, self);
+ }
+ }
+
+ return function deregisterWatchGroup() {
+ while (deregisterFns.length) {
+ deregisterFns.shift()();
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchCollection
+ * @kind function
+ *
+ * @description
+ * Shallow watches the properties of an object and fires whenever any of the properties change
+ * (for arrays, this implies watching the array items; for object maps, this implies watching
+ * the properties). If a change is detected, the `listener` callback is fired.
+ *
+ * - The `obj` collection is observed via standard $watch operation and is examined on every
+ * call to $digest() to see if any items have been added, removed, or moved.
+ * - The `listener` is called whenever anything within the `obj` has changed. Examples include
+ * adding, removing, and moving items belonging to an object or array.
+ *
+ *
+ * # Example
+ * ```js
+ $scope.names = ['igor', 'matias', 'misko', 'james'];
+ $scope.dataCount = 4;
+
+ $scope.$watchCollection('names', function(newNames, oldNames) {
+ $scope.dataCount = newNames.length;
+ });
+
+ expect($scope.dataCount).toEqual(4);
+ $scope.$digest();
+
+ //still at 4 ... no changes
+ expect($scope.dataCount).toEqual(4);
+
+ $scope.names.pop();
+ $scope.$digest();
+
+ //now there's been a change
+ expect($scope.dataCount).toEqual(3);
+ * ```
+ *
+ *
+ * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
+ * expression value should evaluate to an object or an array which is observed on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
+ * collection will trigger a call to the `listener`.
+ *
+ * @param {function(newCollection, oldCollection, scope)} listener a callback function called
+ * when a change is detected.
+ * - The `newCollection` object is the newly modified data obtained from the `obj` expression
+ * - The `oldCollection` object is a copy of the former collection data.
+ * Due to performance considerations, the`oldCollection` value is computed only if the
+ * `listener` function declares two or more arguments.
+ * - The `scope` argument refers to the current scope.
+ *
+ * @returns {function()} Returns a de-registration function for this listener. When the
+ * de-registration function is executed, the internal watch operation is terminated.
+ */
+ $watchCollection: function(obj, listener) {
+ $watchCollectionInterceptor.$stateful = true;
+
+ var self = this;
+ // the current value, updated on each dirty-check run
+ var newValue;
+ // a shallow copy of the newValue from the last dirty-check run,
+ // updated to match newValue during dirty-check run
+ var oldValue;
+ // a shallow copy of the newValue from when the last change happened
+ var veryOldValue;
+ // only track veryOldValue if the listener is asking for it
+ var trackVeryOldValue = (listener.length > 1);
+ var changeDetected = 0;
+ var changeDetector = $parse(obj, $watchCollectionInterceptor);
+ var internalArray = [];
+ var internalObject = {};
+ var initRun = true;
+ var oldLength = 0;
+
+ function $watchCollectionInterceptor(_value) {
+ newValue = _value;
+ var newLength, key, bothNaN, newItem, oldItem;
+
+ // If the new value is undefined, then return undefined as the watch may be a one-time watch
+ if (isUndefined(newValue)) return;
+
+ if (!isObject(newValue)) { // if primitive
+ if (oldValue !== newValue) {
+ oldValue = newValue;
+ changeDetected++;
+ }
+ } else if (isArrayLike(newValue)) {
+ if (oldValue !== internalArray) {
+ // we are transitioning from something which was not an array into array.
+ oldValue = internalArray;
+ oldLength = oldValue.length = 0;
+ changeDetected++;
+ }
+
+ newLength = newValue.length;
+
+ if (oldLength !== newLength) {
+ // if lengths do not match we need to trigger change notification
+ changeDetected++;
+ oldValue.length = oldLength = newLength;
+ }
+ // copy the items to oldValue and look for changes.
+ for (var i = 0; i < newLength; i++) {
+ oldItem = oldValue[i];
+ newItem = newValue[i];
+
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[i] = newItem;
+ }
+ }
+ } else {
+ if (oldValue !== internalObject) {
+ // we are transitioning from something which was not an object into object.
+ oldValue = internalObject = {};
+ oldLength = 0;
+ changeDetected++;
+ }
+ // copy the items to oldValue and look for changes.
+ newLength = 0;
+ for (key in newValue) {
+ if (newValue.hasOwnProperty(key)) {
+ newLength++;
+ newItem = newValue[key];
+ oldItem = oldValue[key];
+
+ if (key in oldValue) {
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[key] = newItem;
+ }
+ } else {
+ oldLength++;
+ oldValue[key] = newItem;
+ changeDetected++;
+ }
+ }
+ }
+ if (oldLength > newLength) {
+ // we used to have more keys, need to find them and destroy them.
+ changeDetected++;
+ for (key in oldValue) {
+ if (!newValue.hasOwnProperty(key)) {
+ oldLength--;
+ delete oldValue[key];
+ }
+ }
+ }
+ }
+ return changeDetected;
+ }
+
+ function $watchCollectionAction() {
+ if (initRun) {
+ initRun = false;
+ listener(newValue, newValue, self);
+ } else {
+ listener(newValue, veryOldValue, self);
+ }
+
+ // make a copy for the next time a collection is changed
+ if (trackVeryOldValue) {
+ if (!isObject(newValue)) {
+ //primitive
+ veryOldValue = newValue;
+ } else if (isArrayLike(newValue)) {
+ veryOldValue = new Array(newValue.length);
+ for (var i = 0; i < newValue.length; i++) {
+ veryOldValue[i] = newValue[i];
+ }
+ } else { // if object
+ veryOldValue = {};
+ for (var key in newValue) {
+ if (hasOwnProperty.call(newValue, key)) {
+ veryOldValue[key] = newValue[key];
+ }
+ }
+ }
+ }
+ }
+
+ return this.$watch(changeDetector, $watchCollectionAction);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$digest
+ * @kind function
+ *
+ * @description
+ * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
+ * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
+ * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
+ * until no more listeners are firing. This means that it is possible to get into an infinite
+ * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
+ * iterations exceeds 10.
+ *
+ * Usually, you don't call `$digest()` directly in
+ * {@link ng.directive:ngController controllers} or in
+ * {@link ng.$compileProvider#directive directives}.
+ * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
+ * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
+ *
+ * If you want to be notified whenever `$digest()` is called,
+ * you can register a `watchExpression` function with
+ * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
+ *
+ * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
+ *
+ * # Example
+ * ```js
+ var scope = ...;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+ * ```
+ *
+ */
+ $digest: function() {
+ var watch, value, last,
+ watchers,
+ length,
+ dirty, ttl = TTL,
+ next, current, target = this,
+ watchLog = [],
+ logIdx, logMsg, asyncTask;
+
+ beginPhase('$digest');
+ // Check for changes to browser url that happened in sync before the call to $digest
+ $browser.$$checkUrlChange();
+
+ if (this === $rootScope && applyAsyncId !== null) {
+ // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
+ // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
+ $browser.defer.cancel(applyAsyncId);
+ flushApplyAsync();
+ }
+
+ lastDirtyWatch = null;
+
+ do { // "while dirty" loop
+ dirty = false;
+ current = target;
+
+ while (asyncQueue.length) {
+ try {
+ asyncTask = asyncQueue.shift();
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ lastDirtyWatch = null;
+ }
+
+ traverseScopesLoop:
+ do { // "traverse the scopes" loop
+ if ((watchers = current.$$watchers)) {
+ // process our watches
+ length = watchers.length;
+ while (length--) {
+ try {
+ watch = watchers[length];
+ // Most common watches are on primitives, in which case we can short
+ // circuit it with === operator, only when === fails do we use .equals
+ if (watch) {
+ if ((value = watch.get(current)) !== (last = watch.last) &&
+ !(watch.eq
+ ? equals(value, last)
+ : (typeof value === 'number' && typeof last === 'number'
+ && isNaN(value) && isNaN(last)))) {
+ dirty = true;
+ lastDirtyWatch = watch;
+ watch.last = watch.eq ? copy(value, null) : value;
+ watch.fn(value, ((last === initWatchVal) ? value : last), current);
+ if (ttl < 5) {
+ logIdx = 4 - ttl;
+ if (!watchLog[logIdx]) watchLog[logIdx] = [];
+ watchLog[logIdx].push({
+ msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
+ newVal: value,
+ oldVal: last
+ });
+ }
+ } else if (watch === lastDirtyWatch) {
+ // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
+ // have already been tested.
+ dirty = false;
+ break traverseScopesLoop;
+ }
+ }
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $broadcast
+ if (!(next = (current.$$childHead ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ } while ((current = next));
+
+ // `break traverseScopesLoop;` takes us to here
+
+ if ((dirty || asyncQueue.length) && !(ttl--)) {
+ clearPhase();
+ throw $rootScopeMinErr('infdig',
+ '{0} $digest() iterations reached. Aborting!\n' +
+ 'Watchers fired in the last 5 iterations: {1}',
+ TTL, watchLog);
+ }
+
+ } while (dirty || asyncQueue.length);
+
+ clearPhase();
+
+ while (postDigestQueue.length) {
+ try {
+ postDigestQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc event
+ * @name $rootScope.Scope#$destroy
+ * @eventType broadcast on scope being destroyed
+ *
+ * @description
+ * Broadcasted when a scope and its children are being destroyed.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$destroy
+ * @kind function
+ *
+ * @description
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
+ * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
+ * propagate to the current scope and its children. Removal also implies that the current
+ * scope is eligible for garbage collection.
+ *
+ * The `$destroy()` is usually used by directives such as
+ * {@link ng.directive:ngRepeat ngRepeat} for managing the
+ * unrolling of the loop.
+ *
+ * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
+ * Application code can register a `$destroy` event handler that will give it a chance to
+ * perform any necessary cleanup.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+ $destroy: function() {
+ // we can't destroy the root scope or a scope that has been already destroyed
+ if (this.$$destroyed) return;
+ var parent = this.$parent;
+
+ this.$broadcast('$destroy');
+ this.$$destroyed = true;
+ if (this === $rootScope) return;
+
+ for (var eventName in this.$$listenerCount) {
+ decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
+ }
+
+ // sever all the references to parent scopes (after this cleanup, the current scope should
+ // not be retained by any of our references and should be eligible for garbage collection)
+ if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
+ if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
+ if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
+ if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
+
+ // Disable listeners, watchers and apply/digest methods
+ this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
+ this.$on = this.$watch = this.$watchGroup = function() { return noop; };
+ this.$$listeners = {};
+
+ // All of the code below is bogus code that works around V8's memory leak via optimized code
+ // and inline caches.
+ //
+ // see:
+ // - https://code.google.com/p/v8/issues/detail?id=2073#c26
+ // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
+ // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
+
+ this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
+ this.$$childTail = this.$root = this.$$watchers = null;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$eval
+ * @kind function
+ *
+ * @description
+ * Executes the `expression` on the current scope and returns the result. Any exceptions in
+ * the expression are propagated (uncaught). This is useful when evaluating Angular
+ * expressions.
+ *
+ * # Example
+ * ```js
+ var scope = ng.$rootScope.Scope();
+ scope.a = 1;
+ scope.b = 2;
+
+ expect(scope.$eval('a+b')).toEqual(3);
+ expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
+ * ```
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ * @returns {*} The result of evaluating the expression.
+ */
+ $eval: function(expr, locals) {
+ return $parse(expr)(this, locals);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$evalAsync
+ * @kind function
+ *
+ * @description
+ * Executes the expression on the current scope at a later point in time.
+ *
+ * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
+ * that:
+ *
+ * - it will execute after the function that scheduled the evaluation (preferably before DOM
+ * rendering).
+ * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
+ * `expression` execution.
+ *
+ * Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
+ * will be scheduled. However, it is encouraged to always call code that changes the model
+ * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ */
+ $evalAsync: function(expr, locals) {
+ // if we are outside of an $digest loop and this is the first time we are scheduling async
+ // task also schedule async auto-flush
+ if (!$rootScope.$$phase && !asyncQueue.length) {
+ $browser.defer(function() {
+ if (asyncQueue.length) {
+ $rootScope.$digest();
+ }
+ });
+ }
+
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
+ },
+
+ $$postDigest: function(fn) {
+ postDigestQueue.push(fn);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$apply
+ * @kind function
+ *
+ * @description
+ * `$apply()` is used to execute an expression in angular from outside of the angular
+ * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
+ * Because we are calling into the angular framework we need to perform proper scope life
+ * cycle of {@link ng.$exceptionHandler exception handling},
+ * {@link ng.$rootScope.Scope#$digest executing watches}.
+ *
+ * ## Life cycle
+ *
+ * # Pseudo-Code of `$apply()`
+ * ```js
+ function $apply(expr) {
+ try {
+ return $eval(expr);
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ $root.$digest();
+ }
+ }
+ * ```
+ *
+ *
+ * Scope's `$apply()` method transitions through the following stages:
+ *
+ * 1. The {@link guide/expression expression} is executed using the
+ * {@link ng.$rootScope.Scope#$eval $eval()} method.
+ * 2. Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
+ * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
+ *
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ *
+ * @returns {*} The result of evaluating the expression.
+ */
+ $apply: function(expr) {
+ try {
+ beginPhase('$apply');
+ return this.$eval(expr);
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ clearPhase();
+ try {
+ $rootScope.$digest();
+ } catch (e) {
+ $exceptionHandler(e);
+ throw e;
+ }
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$applyAsync
+ * @kind function
+ *
+ * @description
+ * Schedule the invocation of $apply to occur at a later time. The actual time difference
+ * varies across browsers, but is typically around ~10 milliseconds.
+ *
+ * This can be used to queue up multiple expressions which need to be evaluated in the same
+ * digest.
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ */
+ $applyAsync: function(expr) {
+ var scope = this;
+ expr && applyAsyncQueue.push($applyAsyncExpression);
+ scheduleApplyAsync();
+
+ function $applyAsyncExpression() {
+ scope.$eval(expr);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$on
+ * @kind function
+ *
+ * @description
+ * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
+ * discussion of event life cycle.
+ *
+ * The event listener function format is: `function(event, args...)`. The `event` object
+ * passed into the listener has the following attributes:
+ *
+ * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
+ * `$broadcast`-ed.
+ * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
+ * event propagates through the scope hierarchy, this property is set to null.
+ * - `name` - `{string}`: name of the event.
+ * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
+ * further event propagation (available only for events that were `$emit`-ed).
+ * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
+ * to true.
+ * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
+ *
+ * @param {string} name Event name to listen on.
+ * @param {function(event, ...args)} listener Function to call when the event is emitted.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $on: function(name, listener) {
+ var namedListeners = this.$$listeners[name];
+ if (!namedListeners) {
+ this.$$listeners[name] = namedListeners = [];
+ }
+ namedListeners.push(listener);
+
+ var current = this;
+ do {
+ if (!current.$$listenerCount[name]) {
+ current.$$listenerCount[name] = 0;
+ }
+ current.$$listenerCount[name]++;
+ } while ((current = current.$parent));
+
+ var self = this;
+ return function() {
+ var indexOfListener = namedListeners.indexOf(listener);
+ if (indexOfListener !== -1) {
+ namedListeners[indexOfListener] = null;
+ decrementListenerCount(self, 1, name);
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$emit
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` upwards through the scope hierarchy notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$emit` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event traverses upwards toward the root scope and calls all
+ * registered listeners along the way. The event will stop propagating if one of the listeners
+ * cancels it.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to emit.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
+ */
+ $emit: function(name, args) {
+ var empty = [],
+ namedListeners,
+ scope = this,
+ stopPropagation = false,
+ event = {
+ name: name,
+ targetScope: scope,
+ stopPropagation: function() {stopPropagation = true;},
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ },
+ listenerArgs = concat([event], arguments, 1),
+ i, length;
+
+ do {
+ namedListeners = scope.$$listeners[name] || empty;
+ event.currentScope = scope;
+ for (i = 0, length = namedListeners.length; i < length; i++) {
+
+ // if listeners were deregistered, defragment the array
+ if (!namedListeners[i]) {
+ namedListeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+ try {
+ //allow all listeners attached to the current scope to run
+ namedListeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ //if any listener on the current scope stops propagation, prevent bubbling
+ if (stopPropagation) {
+ event.currentScope = null;
+ return event;
+ }
+ //traverse upwards
+ scope = scope.$parent;
+ } while (scope);
+
+ event.currentScope = null;
+
+ return event;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$broadcast
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$broadcast` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
+ * scope and calls all registered listeners along the way. The event cannot be canceled.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to broadcast.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
+ */
+ $broadcast: function(name, args) {
+ var target = this,
+ current = target,
+ next = target,
+ event = {
+ name: name,
+ targetScope: target,
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ };
+
+ if (!target.$$listenerCount[name]) return event;
+
+ var listenerArgs = concat([event], arguments, 1),
+ listeners, i, length;
+
+ //down while you can, then up and next sibling or up and next sibling until back at root
+ while ((current = next)) {
+ event.currentScope = current;
+ listeners = current.$$listeners[name] || [];
+ for (i = 0, length = listeners.length; i < length; i++) {
+ // if listeners were deregistered, defragment the array
+ if (!listeners[i]) {
+ listeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+
+ try {
+ listeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $digest
+ // (though it differs due to having the extra check for $$listenerCount)
+ if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ }
+
+ event.currentScope = null;
+ return event;
+ }
+ };
+
+ var $rootScope = new Scope();
+
+ //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
+ var asyncQueue = $rootScope.$$asyncQueue = [];
+ var postDigestQueue = $rootScope.$$postDigestQueue = [];
+ var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
+
+ return $rootScope;
+
+
+ function beginPhase(phase) {
+ if ($rootScope.$$phase) {
+ throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
+ }
+
+ $rootScope.$$phase = phase;
+ }
+
+ function clearPhase() {
+ $rootScope.$$phase = null;
+ }
+
+
+ function decrementListenerCount(current, count, name) {
+ do {
+ current.$$listenerCount[name] -= count;
+
+ if (current.$$listenerCount[name] === 0) {
+ delete current.$$listenerCount[name];
+ }
+ } while ((current = current.$parent));
+ }
+
+ /**
+ * function used as an initial value for watchers.
+ * because it's unique we can easily tell it apart from other values
+ */
+ function initWatchVal() {}
+
+ function flushApplyAsync() {
+ while (applyAsyncQueue.length) {
+ try {
+ applyAsyncQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ applyAsyncId = null;
+ }
+
+ function scheduleApplyAsync() {
+ if (applyAsyncId === null) {
+ applyAsyncId = $browser.defer(function() {
+ $rootScope.$apply(flushApplyAsync);
+ });
+ }
+ }
+ }];
+}
+
+/**
+ * @description
+ * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
+ */
+function $$SanitizeUriProvider() {
+ var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
+ imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
+
+ /**
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.aHrefSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ aHrefSanitizationWhitelist = regexp;
+ return this;
+ }
+ return aHrefSanitizationWhitelist;
+ };
+
+
+ /**
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during img[src] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.imgSrcSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ imgSrcSanitizationWhitelist = regexp;
+ return this;
+ }
+ return imgSrcSanitizationWhitelist;
+ };
+
+ this.$get = function() {
+ return function sanitizeUri(uri, isImage) {
+ var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
+ var normalizedVal;
+ normalizedVal = urlResolve(uri).href;
+ if (normalizedVal !== '' && !normalizedVal.match(regex)) {
+ return 'unsafe:' + normalizedVal;
+ }
+ return uri;
+ };
+ };
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $sceMinErr = minErr('$sce');
+
+var SCE_CONTEXTS = {
+ HTML: 'html',
+ CSS: 'css',
+ URL: 'url',
+ // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
+ // url. (e.g. ng-include, script src, templateUrl)
+ RESOURCE_URL: 'resourceUrl',
+ JS: 'js'
+};
+
+// Helper functions follow.
+
+function adjustMatcher(matcher) {
+ if (matcher === 'self') {
+ return matcher;
+ } else if (isString(matcher)) {
+ // Strings match exactly except for 2 wildcards - '*' and '**'.
+ // '*' matches any character except those from the set ':/.?&'.
+ // '**' matches any character (like .* in a RegExp).
+ // More than 2 *'s raises an error as it's ill defined.
+ if (matcher.indexOf('***') > -1) {
+ throw $sceMinErr('iwcard',
+ 'Illegal sequence *** in string matcher. String: {0}', matcher);
+ }
+ matcher = escapeForRegexp(matcher).
+ replace('\\*\\*', '.*').
+ replace('\\*', '[^:/.?&;]*');
+ return new RegExp('^' + matcher + '$');
+ } else if (isRegExp(matcher)) {
+ // The only other type of matcher allowed is a Regexp.
+ // Match entire URL / disallow partial matches.
+ // Flags are reset (i.e. no global, ignoreCase or multiline)
+ return new RegExp('^' + matcher.source + '$');
+ } else {
+ throw $sceMinErr('imatcher',
+ 'Matchers may only be "self", string patterns or RegExp objects');
+ }
+}
+
+
+function adjustMatchers(matchers) {
+ var adjustedMatchers = [];
+ if (isDefined(matchers)) {
+ forEach(matchers, function(matcher) {
+ adjustedMatchers.push(adjustMatcher(matcher));
+ });
+ }
+ return adjustedMatchers;
+}
+
+
+/**
+ * @ngdoc service
+ * @name $sceDelegate
+ * @kind function
+ *
+ * @description
+ *
+ * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
+ * Contextual Escaping (SCE)} services to AngularJS.
+ *
+ * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
+ * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
+ * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
+ * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
+ * work because `$sce` delegates to `$sceDelegate` for these operations.
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
+ *
+ * The default instance of `$sceDelegate` should work out of the box with little pain. While you
+ * can override it completely to change the behavior of `$sce`, the common case would
+ * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
+ * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
+ * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
+ * $sceDelegateProvider.resourceUrlWhitelist} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $sceDelegateProvider
+ * @description
+ *
+ * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
+ * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
+ * that the URLs used for sourcing Angular templates are safe. Refer {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
+ * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ *
+ * For the general details about this service in Angular, read the main page for {@link ng.$sce
+ * Strict Contextual Escaping (SCE)}.
+ *
+ * **Example**: Consider the following case. <a name="example"></a>
+ *
+ * - your app is hosted at url `http://myapp.example.com/`
+ * - but some of your templates are hosted on other domains you control such as
+ * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
+ * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
+ *
+ * Here is what a secure configuration for this scenario might look like:
+ *
+ * ```
+ * angular.module('myApp', []).config(function($sceDelegateProvider) {
+ * $sceDelegateProvider.resourceUrlWhitelist([
+ * // Allow same origin resource loads.
+ * 'self',
+ * // Allow loading from our assets domain. Notice the difference between * and **.
+ * 'http://srv*.assets.example.com/**'
+ * ]);
+ *
+ * // The blacklist overrides the whitelist so the open redirect here is blocked.
+ * $sceDelegateProvider.resourceUrlBlacklist([
+ * 'http://myapp.example.com/clickThru**'
+ * ]);
+ * });
+ * ```
+ */
+
+function $SceDelegateProvider() {
+ this.SCE_CONTEXTS = SCE_CONTEXTS;
+
+ // Resource URLs can also be trusted by policy.
+ var resourceUrlWhitelist = ['self'],
+ resourceUrlBlacklist = [];
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlWhitelist
+ * @kind function
+ *
+ * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * Note: **an empty whitelist array will block all URLs**!
+ *
+ * @return {Array} the currently set whitelist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
+ * same origin resource requests.
+ *
+ * @description
+ * Sets/Gets the whitelist of trusted resource URLs.
+ */
+ this.resourceUrlWhitelist = function(value) {
+ if (arguments.length) {
+ resourceUrlWhitelist = adjustMatchers(value);
+ }
+ return resourceUrlWhitelist;
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlBlacklist
+ * @kind function
+ *
+ * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * The typical usage for the blacklist is to **block
+ * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
+ * these would otherwise be trusted but actually return content from the redirected domain.
+ *
+ * Finally, **the blacklist overrides the whitelist** and has the final say.
+ *
+ * @return {Array} the currently set blacklist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
+ * is no blacklist.)
+ *
+ * @description
+ * Sets/Gets the blacklist of trusted resource URLs.
+ */
+
+ this.resourceUrlBlacklist = function(value) {
+ if (arguments.length) {
+ resourceUrlBlacklist = adjustMatchers(value);
+ }
+ return resourceUrlBlacklist;
+ };
+
+ this.$get = ['$injector', function($injector) {
+
+ var htmlSanitizer = function htmlSanitizer(html) {
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ };
+
+ if ($injector.has('$sanitize')) {
+ htmlSanitizer = $injector.get('$sanitize');
+ }
+
+
+ function matchUrl(matcher, parsedUrl) {
+ if (matcher === 'self') {
+ return urlIsSameOrigin(parsedUrl);
+ } else {
+ // definitely a regex. See adjustMatchers()
+ return !!matcher.exec(parsedUrl.href);
+ }
+ }
+
+ function isResourceUrlAllowedByPolicy(url) {
+ var parsedUrl = urlResolve(url.toString());
+ var i, n, allowed = false;
+ // Ensure that at least one item from the whitelist allows this url.
+ for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
+ if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
+ allowed = true;
+ break;
+ }
+ }
+ if (allowed) {
+ // Ensure that no item from the blacklist blocked this url.
+ for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
+ if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
+ allowed = false;
+ break;
+ }
+ }
+ }
+ return allowed;
+ }
+
+ function generateHolderType(Base) {
+ var holderType = function TrustedValueHolderType(trustedValue) {
+ this.$$unwrapTrustedValue = function() {
+ return trustedValue;
+ };
+ };
+ if (Base) {
+ holderType.prototype = new Base();
+ }
+ holderType.prototype.valueOf = function sceValueOf() {
+ return this.$$unwrapTrustedValue();
+ };
+ holderType.prototype.toString = function sceToString() {
+ return this.$$unwrapTrustedValue().toString();
+ };
+ return holderType;
+ }
+
+ var trustedValueHolderBase = generateHolderType(),
+ byType = {};
+
+ byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#trustAs
+ *
+ * @description
+ * Returns an object that is trusted by angular for use in specified strict
+ * contextual escaping contexts (such as ng-bind-html, ng-include, any src
+ * attribute interpolation, any dom event binding attribute interpolation
+ * such as for onclick, etc.) that uses the provided value.
+ * See {@link ng.$sce $sce} for enabling strict contextual escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resourceUrl, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+ function trustAs(type, trustedValue) {
+ var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (!Constructor) {
+ throw $sceMinErr('icontext',
+ 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
+ type, trustedValue);
+ }
+ if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
+ return trustedValue;
+ }
+ // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
+ // mutable objects, we ensure here that the value passed in is actually a string.
+ if (typeof trustedValue !== 'string') {
+ throw $sceMinErr('itype',
+ 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
+ type);
+ }
+ return new Constructor(trustedValue);
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#valueOf
+ *
+ * @description
+ * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
+ *
+ * If the passed parameter is not a value that had been returned by {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
+ *
+ * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
+ * call or anything else.
+ * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
+ * `value` unchanged.
+ */
+ function valueOf(maybeTrusted) {
+ if (maybeTrusted instanceof trustedValueHolderBase) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ } else {
+ return maybeTrusted;
+ }
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#getTrusted
+ *
+ * @description
+ * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
+ * returns the originally supplied value if the queried context type is a supertype of the
+ * created type. If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} call.
+ * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
+ */
+ function getTrusted(type, maybeTrusted) {
+ if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
+ return maybeTrusted;
+ }
+ var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (constructor && maybeTrusted instanceof constructor) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ }
+ // If we get here, then we may only take one of two actions.
+ // 1. sanitize the value for the requested type, or
+ // 2. throw an exception.
+ if (type === SCE_CONTEXTS.RESOURCE_URL) {
+ if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
+ return maybeTrusted;
+ } else {
+ throw $sceMinErr('insecurl',
+ 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
+ maybeTrusted.toString());
+ }
+ } else if (type === SCE_CONTEXTS.HTML) {
+ return htmlSanitizer(maybeTrusted);
+ }
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ }
+
+ return { trustAs: trustAs,
+ getTrusted: getTrusted,
+ valueOf: valueOf };
+ }];
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $sceProvider
+ * @description
+ *
+ * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
+ * - enable/disable Strict Contextual Escaping (SCE) in a module
+ * - override the default implementation with a custom delegate
+ *
+ * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
+ */
+
+/* jshint maxlen: false*/
+
+/**
+ * @ngdoc service
+ * @name $sce
+ * @kind function
+ *
+ * @description
+ *
+ * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
+ *
+ * # Strict Contextual Escaping
+ *
+ * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
+ * contexts to result in a value that is marked as safe to use for that context. One example of
+ * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
+ * to these contexts as privileged or SCE contexts.
+ *
+ * As of version 1.2, Angular ships with SCE enabled by default.
+ *
+ * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
+ * one to execute arbitrary javascript by the use of the expression() syntax. Refer
+ * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
+ * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
+ * to the top of your HTML document.
+ *
+ * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
+ * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
+ *
+ * Here's an example of a binding in a privileged context:
+ *
+ * ```
+ * <input ng-model="userHtml">
+ * <div ng-bind-html="userHtml"></div>
+ * ```
+ *
+ * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
+ * disabled, this application allows the user to render arbitrary HTML into the DIV.
+ * In a more realistic example, one may be rendering user comments, blog articles, etc. via
+ * bindings. (HTML is just one example of a context where rendering user controlled input creates
+ * security vulnerabilities.)
+ *
+ * For the case of HTML, you might use a library, either on the client side, or on the server side,
+ * to sanitize unsafe HTML before binding to the value and rendering it in the document.
+ *
+ * How would you ensure that every place that used these types of bindings was bound to a value that
+ * was sanitized by your library (or returned as safe for rendering by your server?) How can you
+ * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
+ * properties/fields and forgot to update the binding to the sanitized value?
+ *
+ * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
+ * determine that something explicitly says it's safe to use a value for binding in that
+ * context. You can then audit your code (a simple grep would do) to ensure that this is only done
+ * for those values that you can easily tell are safe - because they were received from your server,
+ * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
+ * allowing only the files in a specific directory to do this. Ensuring that the internal API
+ * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
+ *
+ * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
+ * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
+ * obtain values that will be accepted by SCE / privileged contexts.
+ *
+ *
+ * ## How does it work?
+ *
+ * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
+ * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
+ * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
+ * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
+ *
+ * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
+ * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
+ * simplified):
+ *
+ * ```
+ * var ngBindHtmlDirective = ['$sce', function($sce) {
+ * return function(scope, element, attr) {
+ * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
+ * element.html(value || '');
+ * });
+ * };
+ * }];
+ * ```
+ *
+ * ## Impact on loading templates
+ *
+ * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
+ * `templateUrl`'s specified by {@link guide/directive directives}.
+ *
+ * By default, Angular only loads templates from the same domain and protocol as the application
+ * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
+ * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
+ * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
+ *
+ * *Please note*:
+ * The browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy apply in addition to this and may further restrict whether the template is successfully
+ * loaded. This means that without the right CORS policy, loading templates from a different domain
+ * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
+ * browsers.
+ *
+ * ## This feels like too much overhead
+ *
+ * It's important to remember that SCE only applies to interpolation expressions.
+ *
+ * If your expressions are constant literals, they're automatically trusted and you don't need to
+ * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
+ * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
+ *
+ * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
+ * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
+ *
+ * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
+ * templates in `ng-include` from your application's domain without having to even know about SCE.
+ * It blocks loading templates from other domains or loading templates over http from an https
+ * served document. You can change these by setting your own custom {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
+ *
+ * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
+ * application that's secure and can be audited to verify that with much more ease than bolting
+ * security onto an application later.
+ *
+ * <a name="contexts"></a>
+ * ## What trusted context types are supported?
+ *
+ * | Context | Notes |
+ * |---------------------|----------------|
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
+ * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
+ * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
+ * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
+ * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
+ *
+ * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
+ *
+ * Each element in these arrays must be one of the following:
+ *
+ * - **'self'**
+ * - The special **string**, `'self'`, can be used to match against all URLs of the **same
+ * domain** as the application document using the **same protocol**.
+ * - **String** (except the special value `'self'`)
+ * - The string is matched against the full *normalized / absolute URL* of the resource
+ * being tested (substring matches are not good enough.)
+ * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
+ * match themselves.
+ * - `*`: matches zero or more occurrences of any character other than one of the following 6
+ * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
+ * in a whitelist.
+ * - `**`: matches zero or more occurrences of *any* character. As such, it's not
+ * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
+ * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
+ * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
+ * http://foo.example.com/templates/**).
+ * - **RegExp** (*see caveat below*)
+ * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
+ * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
+ * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
+ * have good test coverage). For instance, the use of `.` in the regex is correct only in a
+ * small number of cases. A `.` character in the regex used when matching the scheme or a
+ * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
+ * is highly recommended to use the string patterns and only fall back to regular expressions
+ * as a last resort.
+ * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
+ * matched against the **entire** *normalized / absolute URL* of the resource being tested
+ * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
+ * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
+ * - If you are generating your JavaScript from some other templating engine (not
+ * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
+ * remember to escape your regular expression (and be aware that you might need more than
+ * one level of escaping depending on your templating engine and the way you interpolated
+ * the value.) Do make use of your platform's escaping mechanism as it might be good
+ * enough before coding your own. E.g. Ruby has
+ * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
+ * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
+ * Javascript lacks a similar built in function for escaping. Take a look at Google
+ * Closure library's [goog.string.regExpEscape(s)](
+ * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
+ *
+ * ## Show me an example using SCE.
+ *
+ * <example module="mySceApp" deps="angular-sanitize.js">
+ * <file name="index.html">
+ * <div ng-controller="AppController as myCtrl">
+ * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
+ * <b>User comments</b><br>
+ * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
+ * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
+ * exploit.
+ * <div class="well">
+ * <div ng-repeat="userComment in myCtrl.userComments">
+ * <b>{{userComment.name}}</b>:
+ * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
+ * <br>
+ * </div>
+ * </div>
+ * </div>
+ * </file>
+ *
+ * <file name="script.js">
+ * angular.module('mySceApp', ['ngSanitize'])
+ * .controller('AppController', ['$http', '$templateCache', '$sce',
+ * function($http, $templateCache, $sce) {
+ * var self = this;
+ * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
+ * self.userComments = userComments;
+ * });
+ * self.explicitlyTrustedHtml = $sce.trustAsHtml(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * }]);
+ * </file>
+ *
+ * <file name="test_data.json">
+ * [
+ * { "name": "Alice",
+ * "htmlComment":
+ * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
+ * },
+ * { "name": "Bob",
+ * "htmlComment": "<i>Yes!</i> Am I the only other one?"
+ * }
+ * ]
+ * </file>
+ *
+ * <file name="protractor.js" type="protractor">
+ * describe('SCE doc demo', function() {
+ * it('should sanitize untrusted values', function() {
+ * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
+ * .toBe('<span>Is <i>anyone</i> reading this?</span>');
+ * });
+ *
+ * it('should NOT sanitize explicitly trusted values', function() {
+ * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * });
+ * });
+ * </file>
+ * </example>
+ *
+ *
+ *
+ * ## Can I disable SCE completely?
+ *
+ * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
+ * for little coding overhead. It will be much harder to take an SCE disabled application and
+ * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
+ * for cases where you have a lot of existing code that was written before SCE was introduced and
+ * you're migrating them a module at a time.
+ *
+ * That said, here's how you can completely disable SCE:
+ *
+ * ```
+ * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ * // Completely disable SCE. For demonstration purposes only!
+ * // Do not use in new projects.
+ * $sceProvider.enabled(false);
+ * });
+ * ```
+ *
+ */
+/* jshint maxlen: 100 */
+
+function $SceProvider() {
+ var enabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $sceProvider#enabled
+ * @kind function
+ *
+ * @param {boolean=} value If provided, then enables/disables SCE.
+ * @return {boolean} true if SCE is enabled, false otherwise.
+ *
+ * @description
+ * Enables/disables SCE and returns the current value.
+ */
+ this.enabled = function(value) {
+ if (arguments.length) {
+ enabled = !!value;
+ }
+ return enabled;
+ };
+
+
+ /* Design notes on the default implementation for SCE.
+ *
+ * The API contract for the SCE delegate
+ * -------------------------------------
+ * The SCE delegate object must provide the following 3 methods:
+ *
+ * - trustAs(contextEnum, value)
+ * This method is used to tell the SCE service that the provided value is OK to use in the
+ * contexts specified by contextEnum. It must return an object that will be accepted by
+ * getTrusted() for a compatible contextEnum and return this value.
+ *
+ * - valueOf(value)
+ * For values that were not produced by trustAs(), return them as is. For values that were
+ * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
+ * trustAs is wrapping the given values into some type, this operation unwraps it when given
+ * such a value.
+ *
+ * - getTrusted(contextEnum, value)
+ * This function should return the a value that is safe to use in the context specified by
+ * contextEnum or throw and exception otherwise.
+ *
+ * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
+ * opaque or wrapped in some holder object. That happens to be an implementation detail. For
+ * instance, an implementation could maintain a registry of all trusted objects by context. In
+ * such a case, trustAs() would return the same object that was passed in. getTrusted() would
+ * return the same object passed in if it was found in the registry under a compatible context or
+ * throw an exception otherwise. An implementation might only wrap values some of the time based
+ * on some criteria. getTrusted() might return a value and not throw an exception for special
+ * constants or objects even if not wrapped. All such implementations fulfill this contract.
+ *
+ *
+ * A note on the inheritance model for SCE contexts
+ * ------------------------------------------------
+ * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
+ * is purely an implementation details.
+ *
+ * The contract is simply this:
+ *
+ * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
+ * will also succeed.
+ *
+ * Inheritance happens to capture this in a natural way. In some future, we
+ * may not use inheritance anymore. That is OK because no code outside of
+ * sce.js and sceSpecs.js would need to be aware of this detail.
+ */
+
+ this.$get = ['$parse', '$sceDelegate', function(
+ $parse, $sceDelegate) {
+ // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
+ // the "expression(javascript expression)" syntax which is insecure.
+ if (enabled && msie < 8) {
+ throw $sceMinErr('iequirks',
+ 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
+ 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
+ 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
+ }
+
+ var sce = shallowCopy(SCE_CONTEXTS);
+
+ /**
+ * @ngdoc method
+ * @name $sce#isEnabled
+ * @kind function
+ *
+ * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
+ * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
+ *
+ * @description
+ * Returns a boolean indicating if SCE is enabled.
+ */
+ sce.isEnabled = function() {
+ return enabled;
+ };
+ sce.trustAs = $sceDelegate.trustAs;
+ sce.getTrusted = $sceDelegate.getTrusted;
+ sce.valueOf = $sceDelegate.valueOf;
+
+ if (!enabled) {
+ sce.trustAs = sce.getTrusted = function(type, value) { return value; };
+ sce.valueOf = identity;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAs
+ *
+ * @description
+ * Converts Angular {@link guide/expression expression} into a function. This is like {@link
+ * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
+ * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
+ * *result*)}
+ *
+ * @param {string} type The kind of SCE context in which this result will be used.
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+ sce.parseAs = function sceParseAs(type, expr) {
+ var parsed = $parse(expr);
+ if (parsed.literal && parsed.constant) {
+ return parsed;
+ } else {
+ return $parse(expr, function(value) {
+ return sce.getTrusted(type, value);
+ });
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAs
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
+ * returns an object that is trusted by angular for use in specified strict contextual
+ * escaping contexts (such as ng-bind-html, ng-include, any src attribute
+ * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
+ * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
+ * escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resource_url, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsHtml(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
+ * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
+ * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsResourceUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the return
+ * value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsJs(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
+ * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrusted
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
+ * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
+ * originally supplied value if the queried context type is a supertype of the created type.
+ * If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
+ * call.
+ * @returns {*} The value the was originally provided to
+ * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
+ * Otherwise, throws an exception.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedHtml
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedHtml(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedCss
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedCss(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedJs
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedJs(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsHtml(expression string)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsCss
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsCss(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsResourceUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsJs(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ // Shorthand delegations.
+ var parse = sce.parseAs,
+ getTrusted = sce.getTrusted,
+ trustAs = sce.trustAs;
+
+ forEach(SCE_CONTEXTS, function(enumValue, name) {
+ var lName = lowercase(name);
+ sce[camelCase("parse_as_" + lName)] = function(expr) {
+ return parse(enumValue, expr);
+ };
+ sce[camelCase("get_trusted_" + lName)] = function(value) {
+ return getTrusted(enumValue, value);
+ };
+ sce[camelCase("trust_as_" + lName)] = function(value) {
+ return trustAs(enumValue, value);
+ };
+ });
+
+ return sce;
+ }];
+}
+
+/**
+ * !!! This is an undocumented "private" service !!!
+ *
+ * @name $sniffer
+ * @requires $window
+ * @requires $document
+ *
+ * @property {boolean} history Does the browser support html5 history api ?
+ * @property {boolean} transitions Does the browser support CSS transition events ?
+ * @property {boolean} animations Does the browser support CSS animation events ?
+ *
+ * @description
+ * This is very simple implementation of testing browser's features.
+ */
+function $SnifferProvider() {
+ this.$get = ['$window', '$document', function($window, $document) {
+ var eventSupport = {},
+ android =
+ int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
+ boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
+ document = $document[0] || {},
+ vendorPrefix,
+ vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
+ bodyStyle = document.body && document.body.style,
+ transitions = false,
+ animations = false,
+ match;
+
+ if (bodyStyle) {
+ for (var prop in bodyStyle) {
+ if (match = vendorRegex.exec(prop)) {
+ vendorPrefix = match[0];
+ vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
+ break;
+ }
+ }
+
+ if (!vendorPrefix) {
+ vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
+ }
+
+ transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
+ animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
+
+ if (android && (!transitions || !animations)) {
+ transitions = isString(document.body.style.webkitTransition);
+ animations = isString(document.body.style.webkitAnimation);
+ }
+ }
+
+
+ return {
+ // Android has history.pushState, but it does not update location correctly
+ // so let's not use the history API at all.
+ // http://code.google.com/p/android/issues/detail?id=17471
+ // https://github.com/angular/angular.js/issues/904
+
+ // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
+ // so let's not use the history API also
+ // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
+ // jshint -W018
+ history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
+ // jshint +W018
+ hasEvent: function(event) {
+ // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
+ // it. In particular the event is not fired when backspace or delete key are pressed or
+ // when cut operation is performed.
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
+ // e.g. when placeholder changes, or a form is focused.
+ if (event === 'input' && msie <= 11) return false;
+
+ if (isUndefined(eventSupport[event])) {
+ var divElm = document.createElement('div');
+ eventSupport[event] = 'on' + event in divElm;
+ }
+
+ return eventSupport[event];
+ },
+ csp: csp(),
+ vendorPrefix: vendorPrefix,
+ transitions: transitions,
+ animations: animations,
+ android: android
+ };
+ }];
+}
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc service
+ * @name $templateRequest
+ *
+ * @description
+ * The `$templateRequest` service runs security checks then downloads the provided template using
+ * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
+ * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
+ * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
+ * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
+ * when `tpl` is of type string and `$templateCache` has the matching entry.
+ *
+ * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
+ * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
+ *
+ * @return {Promise} the HTTP Promise for the given.
+ *
+ * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
+ */
+function $TemplateRequestProvider() {
+ this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
+ function handleRequestFn(tpl, ignoreRequestError) {
+ handleRequestFn.totalPendingRequests++;
+
+ // We consider the template cache holds only trusted templates, so
+ // there's no need to go through whitelisting again for keys that already
+ // are included in there. This also makes Angular accept any script
+ // directive, no matter its name. However, we still need to unwrap trusted
+ // types.
+ if (!isString(tpl) || !$templateCache.get(tpl)) {
+ tpl = $sce.getTrustedResourceUrl(tpl);
+ }
+
+ var transformResponse = $http.defaults && $http.defaults.transformResponse;
+
+ if (isArray(transformResponse)) {
+ transformResponse = transformResponse.filter(function(transformer) {
+ return transformer !== defaultHttpResponseTransform;
+ });
+ } else if (transformResponse === defaultHttpResponseTransform) {
+ transformResponse = null;
+ }
+
+ var httpOptions = {
+ cache: $templateCache,
+ transformResponse: transformResponse
+ };
+
+ return $http.get(tpl, httpOptions)
+ ['finally'](function() {
+ handleRequestFn.totalPendingRequests--;
+ })
+ .then(function(response) {
+ return response.data;
+ }, handleError);
+
+ function handleError(resp) {
+ if (!ignoreRequestError) {
+ throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
+ }
+ return $q.reject(resp);
+ }
+ }
+
+ handleRequestFn.totalPendingRequests = 0;
+
+ return handleRequestFn;
+ }];
+}
+
+function $$TestabilityProvider() {
+ this.$get = ['$rootScope', '$browser', '$location',
+ function($rootScope, $browser, $location) {
+
+ /**
+ * @name $testability
+ *
+ * @description
+ * The private $$testability service provides a collection of methods for use when debugging
+ * or by automated test and debugging tools.
+ */
+ var testability = {};
+
+ /**
+ * @name $$testability#findBindings
+ *
+ * @description
+ * Returns an array of elements that are bound (via ng-bind or {{}})
+ * to expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The binding expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression. Filters and whitespace are ignored.
+ */
+ testability.findBindings = function(element, expression, opt_exactMatch) {
+ var bindings = element.getElementsByClassName('ng-binding');
+ var matches = [];
+ forEach(bindings, function(binding) {
+ var dataBinding = angular.element(binding).data('$binding');
+ if (dataBinding) {
+ forEach(dataBinding, function(bindingName) {
+ if (opt_exactMatch) {
+ var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
+ if (matcher.test(bindingName)) {
+ matches.push(binding);
+ }
+ } else {
+ if (bindingName.indexOf(expression) != -1) {
+ matches.push(binding);
+ }
+ }
+ });
+ }
+ });
+ return matches;
+ };
+
+ /**
+ * @name $$testability#findModels
+ *
+ * @description
+ * Returns an array of elements that are two-way found via ng-model to
+ * expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The model expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression.
+ */
+ testability.findModels = function(element, expression, opt_exactMatch) {
+ var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
+ for (var p = 0; p < prefixes.length; ++p) {
+ var attributeEquals = opt_exactMatch ? '=' : '*=';
+ var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
+ var elements = element.querySelectorAll(selector);
+ if (elements.length) {
+ return elements;
+ }
+ }
+ };
+
+ /**
+ * @name $$testability#getLocation
+ *
+ * @description
+ * Shortcut for getting the location in a browser agnostic way. Returns
+ * the path, search, and hash. (e.g. /path?a=b#hash)
+ */
+ testability.getLocation = function() {
+ return $location.url();
+ };
+
+ /**
+ * @name $$testability#setLocation
+ *
+ * @description
+ * Shortcut for navigating to a location without doing a full page reload.
+ *
+ * @param {string} url The location url (path, search and hash,
+ * e.g. /path?a=b#hash) to go to.
+ */
+ testability.setLocation = function(url) {
+ if (url !== $location.url()) {
+ $location.url(url);
+ $rootScope.$digest();
+ }
+ };
+
+ /**
+ * @name $$testability#whenStable
+ *
+ * @description
+ * Calls the callback when $timeout and $http requests are completed.
+ *
+ * @param {function} callback
+ */
+ testability.whenStable = function(callback) {
+ $browser.notifyWhenNoOutstandingRequests(callback);
+ };
+
+ return testability;
+ }];
+}
+
+function $TimeoutProvider() {
+ this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
+ function($rootScope, $browser, $q, $$q, $exceptionHandler) {
+ var deferreds = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $timeout
+ *
+ * @description
+ * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
+ * block and delegates any exceptions to
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * The return value of registering a timeout function is a promise, which will be resolved when
+ * the timeout is reached and the timeout function is executed.
+ *
+ * To cancel a timeout request, call `$timeout.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
+ * synchronously flush the queue of deferred functions.
+ *
+ * @param {function()} fn A function, whose execution should be delayed.
+ * @param {number=} [delay=0] Delay in milliseconds.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
+ * promise will be resolved with is the return value of the `fn` function.
+ *
+ */
+ function timeout(fn, delay, invokeApply) {
+ var skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise,
+ timeoutId;
+
+ timeoutId = $browser.defer(function() {
+ try {
+ deferred.resolve(fn());
+ } catch (e) {
+ deferred.reject(e);
+ $exceptionHandler(e);
+ }
+ finally {
+ delete deferreds[promise.$$timeoutId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+ }, delay);
+
+ promise.$$timeoutId = timeoutId;
+ deferreds[timeoutId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $timeout#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`. As a result of this, the promise will be
+ * resolved with a rejection.
+ *
+ * @param {Promise=} promise Promise returned by the `$timeout` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ timeout.cancel = function(promise) {
+ if (promise && promise.$$timeoutId in deferreds) {
+ deferreds[promise.$$timeoutId].reject('canceled');
+ delete deferreds[promise.$$timeoutId];
+ return $browser.defer.cancel(promise.$$timeoutId);
+ }
+ return false;
+ };
+
+ return timeout;
+ }];
+}
+
+// NOTE: The usage of window and document instead of $window and $document here is
+// deliberate. This service depends on the specific behavior of anchor nodes created by the
+// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
+// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
+// doesn't know about mocked locations and resolves URLs to the real document - which is
+// exactly the behavior needed here. There is little value is mocking these out for this
+// service.
+var urlParsingNode = document.createElement("a");
+var originUrl = urlResolve(window.location.href);
+
+
+/**
+ *
+ * Implementation Notes for non-IE browsers
+ * ----------------------------------------
+ * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
+ * results both in the normalizing and parsing of the URL. Normalizing means that a relative
+ * URL will be resolved into an absolute URL in the context of the application document.
+ * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
+ * properties are all populated to reflect the normalized URL. This approach has wide
+ * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ *
+ * Implementation Notes for IE
+ * ---------------------------
+ * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
+ * browsers. However, the parsed components will not be set if the URL assigned did not specify
+ * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
+ * work around that by performing the parsing in a 2nd step by taking a previously normalized
+ * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
+ * properties such as protocol, hostname, port, etc.
+ *
+ * References:
+ * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ * http://url.spec.whatwg.org/#urlutils
+ * https://github.com/angular/angular.js/pull/2902
+ * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
+ *
+ * @kind function
+ * @param {string} url The URL to be parsed.
+ * @description Normalizes and parses a URL.
+ * @returns {object} Returns the normalized URL as a dictionary.
+ *
+ * | member name | Description |
+ * |---------------|----------------|
+ * | href | A normalized version of the provided URL if it was not an absolute URL |
+ * | protocol | The protocol including the trailing colon |
+ * | host | The host and port (if the port is non-default) of the normalizedUrl |
+ * | search | The search params, minus the question mark |
+ * | hash | The hash string, minus the hash symbol
+ * | hostname | The hostname
+ * | port | The port, without ":"
+ * | pathname | The pathname, beginning with "/"
+ *
+ */
+function urlResolve(url) {
+ var href = url;
+
+ if (msie) {
+ // Normalize before parse. Refer Implementation Notes on why this is
+ // done in two steps on IE.
+ urlParsingNode.setAttribute("href", href);
+ href = urlParsingNode.href;
+ }
+
+ urlParsingNode.setAttribute('href', href);
+
+ // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
+ return {
+ href: urlParsingNode.href,
+ protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
+ host: urlParsingNode.host,
+ search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
+ hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
+ hostname: urlParsingNode.hostname,
+ port: urlParsingNode.port,
+ pathname: (urlParsingNode.pathname.charAt(0) === '/')
+ ? urlParsingNode.pathname
+ : '/' + urlParsingNode.pathname
+ };
+}
+
+/**
+ * Parse a request URL and determine whether this is a same-origin request as the application document.
+ *
+ * @param {string|object} requestUrl The url of the request as a string that will be resolved
+ * or a parsed URL object.
+ * @returns {boolean} Whether the request is for the same origin as the application document.
+ */
+function urlIsSameOrigin(requestUrl) {
+ var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
+ return (parsed.protocol === originUrl.protocol &&
+ parsed.host === originUrl.host);
+}
+
+/**
+ * @ngdoc service
+ * @name $window
+ *
+ * @description
+ * A reference to the browser's `window` object. While `window`
+ * is globally available in JavaScript, it causes testability problems, because
+ * it is a global variable. In angular we always refer to it through the
+ * `$window` service, so it may be overridden, removed or mocked for testing.
+ *
+ * Expressions, like the one defined for the `ngClick` directive in the example
+ * below, are evaluated with respect to the current scope. Therefore, there is
+ * no risk of inadvertently coding in a dependency on a global value in such an
+ * expression.
+ *
+ * @example
+ <example module="windowExample">
+ <file name="index.html">
+ <script>
+ angular.module('windowExample', [])
+ .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
+ $scope.greeting = 'Hello, World!';
+ $scope.doGreeting = function(greeting) {
+ $window.alert(greeting);
+ };
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="text" ng-model="greeting" />
+ <button ng-click="doGreeting(greeting)">ALERT</button>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should display the greeting in the input box', function() {
+ element(by.model('greeting')).sendKeys('Hello, E2E Tests');
+ // If we click the button it will block the test runner
+ // element(':button').click();
+ });
+ </file>
+ </example>
+ */
+function $WindowProvider() {
+ this.$get = valueFn(window);
+}
+
+/* global currencyFilter: true,
+ dateFilter: true,
+ filterFilter: true,
+ jsonFilter: true,
+ limitToFilter: true,
+ lowercaseFilter: true,
+ numberFilter: true,
+ orderByFilter: true,
+ uppercaseFilter: true,
+ */
+
+/**
+ * @ngdoc provider
+ * @name $filterProvider
+ * @description
+ *
+ * Filters are just functions which transform input to an output. However filters need to be
+ * Dependency Injected. To achieve this a filter definition consists of a factory function which is
+ * annotated with dependencies and is responsible for creating a filter function.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ *
+ * ```js
+ * // Filter registration
+ * function MyModule($provide, $filterProvider) {
+ * // create a service to demonstrate injection (not always needed)
+ * $provide.value('greet', function(name){
+ * return 'Hello ' + name + '!';
+ * });
+ *
+ * // register a filter factory which uses the
+ * // greet service to demonstrate DI.
+ * $filterProvider.register('greet', function(greet){
+ * // return the filter function which uses the greet service
+ * // to generate salutation
+ * return function(text) {
+ * // filters need to be forgiving so check input validity
+ * return text && greet(text) || text;
+ * };
+ * });
+ * }
+ * ```
+ *
+ * The filter function is registered with the `$injector` under the filter name suffix with
+ * `Filter`.
+ *
+ * ```js
+ * it('should be the same instance', inject(
+ * function($filterProvider) {
+ * $filterProvider.register('reverse', function(){
+ * return ...;
+ * });
+ * },
+ * function($filter, reverseFilter) {
+ * expect($filter('reverse')).toBe(reverseFilter);
+ * });
+ * ```
+ *
+ *
+ * For more information about how angular filters work, and how to create your own filters, see
+ * {@link guide/filter Filters} in the Angular Developer Guide.
+ */
+
+/**
+ * @ngdoc service
+ * @name $filter
+ * @kind function
+ * @description
+ * Filters are used for formatting data displayed to the user.
+ *
+ * The general syntax in templates is as follows:
+ *
+ * {{ expression [| filter_name[:parameter_value] ... ] }}
+ *
+ * @param {String} name Name of the filter function to retrieve
+ * @return {Function} the filter function
+ * @example
+ <example name="$filter" module="filterExample">
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <h3>{{ originalText }}</h3>
+ <h3>{{ filteredText }}</h3>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('filterExample', [])
+ .controller('MainCtrl', function($scope, $filter) {
+ $scope.originalText = 'hello';
+ $scope.filteredText = $filter('uppercase')($scope.originalText);
+ });
+ </file>
+ </example>
+ */
+$FilterProvider.$inject = ['$provide'];
+function $FilterProvider($provide) {
+ var suffix = 'Filter';
+
+ /**
+ * @ngdoc method
+ * @name $filterProvider#register
+ * @param {string|Object} name Name of the filter function, or an object map of filters where
+ * the keys are the filter names and the values are the filter factories.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
+ * of the registered filter instances.
+ */
+ function register(name, factory) {
+ if (isObject(name)) {
+ var filters = {};
+ forEach(name, function(filter, key) {
+ filters[key] = register(key, filter);
+ });
+ return filters;
+ } else {
+ return $provide.factory(name + suffix, factory);
+ }
+ }
+ this.register = register;
+
+ this.$get = ['$injector', function($injector) {
+ return function(name) {
+ return $injector.get(name + suffix);
+ };
+ }];
+
+ ////////////////////////////////////////
+
+ /* global
+ currencyFilter: false,
+ dateFilter: false,
+ filterFilter: false,
+ jsonFilter: false,
+ limitToFilter: false,
+ lowercaseFilter: false,
+ numberFilter: false,
+ orderByFilter: false,
+ uppercaseFilter: false,
+ */
+
+ register('currency', currencyFilter);
+ register('date', dateFilter);
+ register('filter', filterFilter);
+ register('json', jsonFilter);
+ register('limitTo', limitToFilter);
+ register('lowercase', lowercaseFilter);
+ register('number', numberFilter);
+ register('orderBy', orderByFilter);
+ register('uppercase', uppercaseFilter);
+}
+
+/**
+ * @ngdoc filter
+ * @name filter
+ * @kind function
+ *
+ * @description
+ * Selects a subset of items from `array` and returns it as a new array.
+ *
+ * @param {Array} array The source array.
+ * @param {string|Object|function()} expression The predicate to be used for selecting items from
+ * `array`.
+ *
+ * Can be one of:
+ *
+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
+ * objects with string properties in `array` that match this string will be returned. This also
+ * applies to nested object properties.
+ * The predicate can be negated by prefixing the string with `!`.
+ *
+ * - `Object`: A pattern object can be used to filter specific properties on objects contained
+ * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
+ * which have property `name` containing "M" and property `phone` containing "1". A special
+ * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
+ * property of the object or its nested object properties. That's equivalent to the simple
+ * substring match with a `string` as described above. The predicate can be negated by prefixing
+ * the string with `!`.
+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
+ * not containing "M".
+ *
+ * Note that a named property will match properties on the same level only, while the special
+ * `$` property will match properties on the same level or deeper. E.g. an array item like
+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
+ * **will** be matched by `{$: 'John'}`.
+ *
+ * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
+ * function is called for each element of `array`. The final result is an array of those
+ * elements that the predicate returned true for.
+ *
+ * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
+ * determining if the expected value (from the filter expression) and actual value (from
+ * the object in the array) should be considered a match.
+ *
+ * Can be one of:
+ *
+ * - `function(actual, expected)`:
+ * The function will be given the object value and the predicate value to compare and
+ * should return true if both values should be considered equal.
+ *
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
+ * This is essentially strict comparison of expected and actual.
+ *
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
+ * insensitive way.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div ng-init="friends = [{name:'John', phone:'555-1276'},
+ {name:'Mary', phone:'800-BIG-MARY'},
+ {name:'Mike', phone:'555-4321'},
+ {name:'Adam', phone:'555-5678'},
+ {name:'Julie', phone:'555-8765'},
+ {name:'Juliette', phone:'555-5678'}]"></div>
+
+ Search: <input ng-model="searchText">
+ <table id="searchTextResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friend in friends | filter:searchText">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ </tr>
+ </table>
+ <hr>
+ Any: <input ng-model="search.$"> <br>
+ Name only <input ng-model="search.name"><br>
+ Phone only <input ng-model="search.phone"><br>
+ Equality <input type="checkbox" ng-model="strict"><br>
+ <table id="searchObjResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friendObj in friends | filter:search:strict">
+ <td>{{friendObj.name}}</td>
+ <td>{{friendObj.phone}}</td>
+ </tr>
+ </table>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var expectFriendNames = function(expectedNames, key) {
+ element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
+ arr.forEach(function(wd, i) {
+ expect(wd.getText()).toMatch(expectedNames[i]);
+ });
+ });
+ };
+
+ it('should search across all fields when filtering with a string', function() {
+ var searchText = element(by.model('searchText'));
+ searchText.clear();
+ searchText.sendKeys('m');
+ expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
+
+ searchText.clear();
+ searchText.sendKeys('76');
+ expectFriendNames(['John', 'Julie'], 'friend');
+ });
+
+ it('should search in specific fields when filtering with a predicate object', function() {
+ var searchAny = element(by.model('search.$'));
+ searchAny.clear();
+ searchAny.sendKeys('i');
+ expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
+ });
+ it('should use a equal comparison when comparator is true', function() {
+ var searchName = element(by.model('search.name'));
+ var strict = element(by.model('strict'));
+ searchName.clear();
+ searchName.sendKeys('Julie');
+ strict.click();
+ expectFriendNames(['Julie'], 'friendObj');
+ });
+ </file>
+ </example>
+ */
+function filterFilter() {
+ return function(array, expression, comparator) {
+ if (!isArray(array)) return array;
+
+ var expressionType = (expression !== null) ? typeof expression : 'null';
+ var predicateFn;
+ var matchAgainstAnyProp;
+
+ switch (expressionType) {
+ case 'function':
+ predicateFn = expression;
+ break;
+ case 'boolean':
+ case 'null':
+ case 'number':
+ case 'string':
+ matchAgainstAnyProp = true;
+ //jshint -W086
+ case 'object':
+ //jshint +W086
+ predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
+ break;
+ default:
+ return array;
+ }
+
+ return array.filter(predicateFn);
+ };
+}
+
+// Helper functions for `filterFilter`
+function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
+ var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
+ var predicateFn;
+
+ if (comparator === true) {
+ comparator = equals;
+ } else if (!isFunction(comparator)) {
+ comparator = function(actual, expected) {
+ if (isUndefined(actual)) {
+ // No substring matching against `undefined`
+ return false;
+ }
+ if ((actual === null) || (expected === null)) {
+ // No substring matching against `null`; only match against `null`
+ return actual === expected;
+ }
+ if (isObject(actual) || isObject(expected)) {
+ // Prevent an object to be considered equal to a string like `'[object'`
+ return false;
+ }
+
+ actual = lowercase('' + actual);
+ expected = lowercase('' + expected);
+ return actual.indexOf(expected) !== -1;
+ };
+ }
+
+ predicateFn = function(item) {
+ if (shouldMatchPrimitives && !isObject(item)) {
+ return deepCompare(item, expression.$, comparator, false);
+ }
+ return deepCompare(item, expression, comparator, matchAgainstAnyProp);
+ };
+
+ return predicateFn;
+}
+
+function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
+ var actualType = (actual !== null) ? typeof actual : 'null';
+ var expectedType = (expected !== null) ? typeof expected : 'null';
+
+ if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
+ return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
+ } else if (isArray(actual)) {
+ // In case `actual` is an array, consider it a match
+ // if ANY of it's items matches `expected`
+ return actual.some(function(item) {
+ return deepCompare(item, expected, comparator, matchAgainstAnyProp);
+ });
+ }
+
+ switch (actualType) {
+ case 'object':
+ var key;
+ if (matchAgainstAnyProp) {
+ for (key in actual) {
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
+ return true;
+ }
+ }
+ return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
+ } else if (expectedType === 'object') {
+ for (key in expected) {
+ var expectedVal = expected[key];
+ if (isFunction(expectedVal) || isUndefined(expectedVal)) {
+ continue;
+ }
+
+ var matchAnyProperty = key === '$';
+ var actualVal = matchAnyProperty ? actual : actual[key];
+ if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return comparator(actual, expected);
+ }
+ break;
+ case 'function':
+ return false;
+ default:
+ return comparator(actual, expected);
+ }
+}
+
+/**
+ * @ngdoc filter
+ * @name currency
+ * @kind function
+ *
+ * @description
+ * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
+ * symbol for current locale is used.
+ *
+ * @param {number} amount Input to filter.
+ * @param {string=} symbol Currency symbol or identifier to be displayed.
+ * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
+ * @returns {string} Formatted number.
+ *
+ *
+ * @example
+ <example module="currencyExample">
+ <file name="index.html">
+ <script>
+ angular.module('currencyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.amount = 1234.56;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="number" ng-model="amount"> <br>
+ default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
+ custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
+ no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should init with 1234.56', function() {
+ expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
+ expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
+ });
+ it('should update', function() {
+ if (browser.params.browser == 'safari') {
+ // Safari does not understand the minus key. See
+ // https://github.com/angular/protractor/issues/481
+ return;
+ }
+ element(by.model('amount')).clear();
+ element(by.model('amount')).sendKeys('-1234');
+ expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
+ expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');
+ });
+ </file>
+ </example>
+ */
+currencyFilter.$inject = ['$locale'];
+function currencyFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(amount, currencySymbol, fractionSize) {
+ if (isUndefined(currencySymbol)) {
+ currencySymbol = formats.CURRENCY_SYM;
+ }
+
+ if (isUndefined(fractionSize)) {
+ fractionSize = formats.PATTERNS[1].maxFrac;
+ }
+
+ // if null or undefined pass it through
+ return (amount == null)
+ ? amount
+ : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
+ replace(/\u00A4/g, currencySymbol);
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name number
+ * @kind function
+ *
+ * @description
+ * Formats a number as text.
+ *
+ * If the input is null or undefined, it will just be returned.
+ * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
+ * If the input is not a number an empty string is returned.
+ *
+ * @param {number|string} number Number to format.
+ * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
+ * If this is not provided then the fraction size is computed from the current locale's number
+ * formatting pattern. In the case of the default locale, it will be 3.
+ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
+ *
+ * @example
+ <example module="numberFilterExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberFilterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = 1234.56789;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Enter number: <input ng-model='val'><br>
+ Default formatting: <span id='number-default'>{{val | number}}</span><br>
+ No fractions: <span>{{val | number:0}}</span><br>
+ Negative number: <span>{{-val | number:4}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format numbers', function() {
+ expect(element(by.id('number-default')).getText()).toBe('1,234.568');
+ expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
+ });
+
+ it('should update', function() {
+ element(by.model('val')).clear();
+ element(by.model('val')).sendKeys('3374.333');
+ expect(element(by.id('number-default')).getText()).toBe('3,374.333');
+ expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
+ });
+ </file>
+ </example>
+ */
+
+
+numberFilter.$inject = ['$locale'];
+function numberFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(number, fractionSize) {
+
+ // if null or undefined pass it through
+ return (number == null)
+ ? number
+ : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
+ fractionSize);
+ };
+}
+
+var DECIMAL_SEP = '.';
+function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
+ if (!isFinite(number) || isObject(number)) return '';
+
+ var isNegative = number < 0;
+ number = Math.abs(number);
+ var numStr = number + '',
+ formatedText = '',
+ parts = [];
+
+ var hasExponent = false;
+ if (numStr.indexOf('e') !== -1) {
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
+ number = 0;
+ } else {
+ formatedText = numStr;
+ hasExponent = true;
+ }
+ }
+
+ if (!hasExponent) {
+ var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
+
+ // determine fractionSize if it is not specified
+ if (isUndefined(fractionSize)) {
+ fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
+ }
+
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
+ // inspired by:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
+
+ var fraction = ('' + number).split(DECIMAL_SEP);
+ var whole = fraction[0];
+ fraction = fraction[1] || '';
+
+ var i, pos = 0,
+ lgroup = pattern.lgSize,
+ group = pattern.gSize;
+
+ if (whole.length >= (lgroup + group)) {
+ pos = whole.length - lgroup;
+ for (i = 0; i < pos; i++) {
+ if ((pos - i) % group === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+ }
+
+ for (i = pos; i < whole.length; i++) {
+ if ((whole.length - i) % lgroup === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+
+ // format fraction part.
+ while (fraction.length < fractionSize) {
+ fraction += '0';
+ }
+
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
+ } else {
+ if (fractionSize > 0 && number < 1) {
+ formatedText = number.toFixed(fractionSize);
+ number = parseFloat(formatedText);
+ }
+ }
+
+ if (number === 0) {
+ isNegative = false;
+ }
+
+ parts.push(isNegative ? pattern.negPre : pattern.posPre,
+ formatedText,
+ isNegative ? pattern.negSuf : pattern.posSuf);
+ return parts.join('');
+}
+
+function padNumber(num, digits, trim) {
+ var neg = '';
+ if (num < 0) {
+ neg = '-';
+ num = -num;
+ }
+ num = '' + num;
+ while (num.length < digits) num = '0' + num;
+ if (trim)
+ num = num.substr(num.length - digits);
+ return neg + num;
+}
+
+
+function dateGetter(name, size, offset, trim) {
+ offset = offset || 0;
+ return function(date) {
+ var value = date['get' + name]();
+ if (offset > 0 || value > -offset)
+ value += offset;
+ if (value === 0 && offset == -12) value = 12;
+ return padNumber(value, size, trim);
+ };
+}
+
+function dateStrGetter(name, shortForm) {
+ return function(date, formats) {
+ var value = date['get' + name]();
+ var get = uppercase(shortForm ? ('SHORT' + name) : name);
+
+ return formats[get][value];
+ };
+}
+
+function timeZoneGetter(date) {
+ var zone = -1 * date.getTimezoneOffset();
+ var paddedZone = (zone >= 0) ? "+" : "";
+
+ paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
+ padNumber(Math.abs(zone % 60), 2);
+
+ return paddedZone;
+}
+
+function getFirstThursdayOfYear(year) {
+ // 0 = index of January
+ var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
+ // 4 = index of Thursday (+1 to account for 1st = 5)
+ // 11 = index of *next* Thursday (+1 account for 1st = 12)
+ return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
+}
+
+function getThursdayThisWeek(datetime) {
+ return new Date(datetime.getFullYear(), datetime.getMonth(),
+ // 4 = index of Thursday
+ datetime.getDate() + (4 - datetime.getDay()));
+}
+
+function weekGetter(size) {
+ return function(date) {
+ var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
+ thisThurs = getThursdayThisWeek(date);
+
+ var diff = +thisThurs - +firstThurs,
+ result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
+
+ return padNumber(result, size);
+ };
+}
+
+function ampmGetter(date, formats) {
+ return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
+}
+
+function eraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
+}
+
+function longEraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
+}
+
+var DATE_FORMATS = {
+ yyyy: dateGetter('FullYear', 4),
+ yy: dateGetter('FullYear', 2, 0, true),
+ y: dateGetter('FullYear', 1),
+ MMMM: dateStrGetter('Month'),
+ MMM: dateStrGetter('Month', true),
+ MM: dateGetter('Month', 2, 1),
+ M: dateGetter('Month', 1, 1),
+ dd: dateGetter('Date', 2),
+ d: dateGetter('Date', 1),
+ HH: dateGetter('Hours', 2),
+ H: dateGetter('Hours', 1),
+ hh: dateGetter('Hours', 2, -12),
+ h: dateGetter('Hours', 1, -12),
+ mm: dateGetter('Minutes', 2),
+ m: dateGetter('Minutes', 1),
+ ss: dateGetter('Seconds', 2),
+ s: dateGetter('Seconds', 1),
+ // while ISO 8601 requires fractions to be prefixed with `.` or `,`
+ // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
+ sss: dateGetter('Milliseconds', 3),
+ EEEE: dateStrGetter('Day'),
+ EEE: dateStrGetter('Day', true),
+ a: ampmGetter,
+ Z: timeZoneGetter,
+ ww: weekGetter(2),
+ w: weekGetter(1),
+ G: eraGetter,
+ GG: eraGetter,
+ GGG: eraGetter,
+ GGGG: longEraGetter
+};
+
+var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
+ NUMBER_STRING = /^\-?\d+$/;
+
+/**
+ * @ngdoc filter
+ * @name date
+ * @kind function
+ *
+ * @description
+ * Formats `date` to a string based on the requested `format`.
+ *
+ * `format` string can be composed of the following elements:
+ *
+ * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
+ * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
+ * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
+ * * `'MMMM'`: Month in year (January-December)
+ * * `'MMM'`: Month in year (Jan-Dec)
+ * * `'MM'`: Month in year, padded (01-12)
+ * * `'M'`: Month in year (1-12)
+ * * `'dd'`: Day in month, padded (01-31)
+ * * `'d'`: Day in month (1-31)
+ * * `'EEEE'`: Day in Week,(Sunday-Saturday)
+ * * `'EEE'`: Day in Week, (Sun-Sat)
+ * * `'HH'`: Hour in day, padded (00-23)
+ * * `'H'`: Hour in day (0-23)
+ * * `'hh'`: Hour in AM/PM, padded (01-12)
+ * * `'h'`: Hour in AM/PM, (1-12)
+ * * `'mm'`: Minute in hour, padded (00-59)
+ * * `'m'`: Minute in hour (0-59)
+ * * `'ss'`: Second in minute, padded (00-59)
+ * * `'s'`: Second in minute (0-59)
+ * * `'sss'`: Millisecond in second, padded (000-999)
+ * * `'a'`: AM/PM marker
+ * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
+ * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
+ * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
+ * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
+ * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
+ *
+ * `format` string can also be one of the following predefined
+ * {@link guide/i18n localizable formats}:
+ *
+ * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
+ * (e.g. Sep 3, 2010 12:05:08 PM)
+ * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)
+ * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
+ * (e.g. Friday, September 3, 2010)
+ * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
+ * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
+ * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
+ * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
+ * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
+ *
+ * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
+ * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
+ * (e.g. `"h 'o''clock'"`).
+ *
+ * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
+ * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
+ * specified in the string input, the time is considered to be in the local timezone.
+ * @param {string=} format Formatting rules (see Description). If not specified,
+ * `mediumDate` is used.
+ * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.
+ * If not specified, the timezone of the browser will be used.
+ * @returns {string} Formatted string or the input if input is not recognized as date/millis.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
+ <span>{{1288323623006 | date:'medium'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
+ <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
+ <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
+ <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format date', function() {
+ expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
+ toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
+ expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
+ expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
+ toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
+ expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
+ toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
+ });
+ </file>
+ </example>
+ */
+dateFilter.$inject = ['$locale'];
+function dateFilter($locale) {
+
+
+ var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
+ // 1 2 3 4 5 6 7 8 9 10 11
+ function jsonStringToDate(string) {
+ var match;
+ if (match = string.match(R_ISO8601_STR)) {
+ var date = new Date(0),
+ tzHour = 0,
+ tzMin = 0,
+ dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
+ timeSetter = match[8] ? date.setUTCHours : date.setHours;
+
+ if (match[9]) {
+ tzHour = int(match[9] + match[10]);
+ tzMin = int(match[9] + match[11]);
+ }
+ dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
+ var h = int(match[4] || 0) - tzHour;
+ var m = int(match[5] || 0) - tzMin;
+ var s = int(match[6] || 0);
+ var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
+ timeSetter.call(date, h, m, s, ms);
+ return date;
+ }
+ return string;
+ }
+
+
+ return function(date, format, timezone) {
+ var text = '',
+ parts = [],
+ fn, match;
+
+ format = format || 'mediumDate';
+ format = $locale.DATETIME_FORMATS[format] || format;
+ if (isString(date)) {
+ date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
+ }
+
+ if (isNumber(date)) {
+ date = new Date(date);
+ }
+
+ if (!isDate(date)) {
+ return date;
+ }
+
+ while (format) {
+ match = DATE_FORMATS_SPLIT.exec(format);
+ if (match) {
+ parts = concat(parts, match, 1);
+ format = parts.pop();
+ } else {
+ parts.push(format);
+ format = null;
+ }
+ }
+
+ if (timezone && timezone === 'UTC') {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
+ }
+ forEach(parts, function(value) {
+ fn = DATE_FORMATS[value];
+ text += fn ? fn(date, $locale.DATETIME_FORMATS)
+ : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
+ });
+
+ return text;
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name json
+ * @kind function
+ *
+ * @description
+ * Allows you to convert a JavaScript object into JSON string.
+ *
+ * This filter is mostly useful for debugging. When using the double curly {{value}} notation
+ * the binding is automatically converted to JSON.
+ *
+ * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
+ * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
+ * @returns {string} JSON string.
+ *
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
+ <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should jsonify filtered objects', function() {
+ expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ });
+ </file>
+ </example>
+ *
+ */
+function jsonFilter() {
+ return function(object, spacing) {
+ if (isUndefined(spacing)) {
+ spacing = 2;
+ }
+ return toJson(object, spacing);
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name lowercase
+ * @kind function
+ * @description
+ * Converts string to lowercase.
+ * @see angular.lowercase
+ */
+var lowercaseFilter = valueFn(lowercase);
+
+
+/**
+ * @ngdoc filter
+ * @name uppercase
+ * @kind function
+ * @description
+ * Converts string to uppercase.
+ * @see angular.uppercase
+ */
+var uppercaseFilter = valueFn(uppercase);
+
+/**
+ * @ngdoc filter
+ * @name limitTo
+ * @kind function
+ *
+ * @description
+ * Creates a new array or string containing only a specified number of elements. The elements
+ * are taken from either the beginning or the end of the source array, string or number, as specified by
+ * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
+ * converted to a string.
+ *
+ * @param {Array|string|number} input Source array, string or number to be limited.
+ * @param {string|number} limit The length of the returned array or string. If the `limit` number
+ * is positive, `limit` number of items from the beginning of the source array/string are copied.
+ * If the number is negative, `limit` number of items from the end of the source array/string
+ * are copied. The `limit` will be trimmed if it exceeds `array.length`
+ * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
+ * had less than `limit` elements.
+ *
+ * @example
+ <example module="limitToExample">
+ <file name="index.html">
+ <script>
+ angular.module('limitToExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.numbers = [1,2,3,4,5,6,7,8,9];
+ $scope.letters = "abcdefghi";
+ $scope.longNumber = 2345432342;
+ $scope.numLimit = 3;
+ $scope.letterLimit = 3;
+ $scope.longNumberLimit = 3;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit">
+ <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
+ Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit">
+ <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
+ Limit {{longNumber}} to: <input type="number" step="1" ng-model="longNumberLimit">
+ <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var numLimitInput = element(by.model('numLimit'));
+ var letterLimitInput = element(by.model('letterLimit'));
+ var longNumberLimitInput = element(by.model('longNumberLimit'));
+ var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
+ var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
+ var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
+
+ it('should limit the number array to first three items', function() {
+ expect(numLimitInput.getAttribute('value')).toBe('3');
+ expect(letterLimitInput.getAttribute('value')).toBe('3');
+ expect(longNumberLimitInput.getAttribute('value')).toBe('3');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abc');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
+ });
+
+ // There is a bug in safari and protractor that doesn't like the minus key
+ // it('should update the output when -3 is entered', function() {
+ // numLimitInput.clear();
+ // numLimitInput.sendKeys('-3');
+ // letterLimitInput.clear();
+ // letterLimitInput.sendKeys('-3');
+ // longNumberLimitInput.clear();
+ // longNumberLimitInput.sendKeys('-3');
+ // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
+ // expect(limitedLetters.getText()).toEqual('Output letters: ghi');
+ // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
+ // });
+
+ it('should not exceed the maximum size of input array', function() {
+ numLimitInput.clear();
+ numLimitInput.sendKeys('100');
+ letterLimitInput.clear();
+ letterLimitInput.sendKeys('100');
+ longNumberLimitInput.clear();
+ longNumberLimitInput.sendKeys('100');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
+ });
+ </file>
+ </example>
+*/
+function limitToFilter() {
+ return function(input, limit) {
+ if (isNumber(input)) input = input.toString();
+ if (!isArray(input) && !isString(input)) return input;
+
+ if (Math.abs(Number(limit)) === Infinity) {
+ limit = Number(limit);
+ } else {
+ limit = int(limit);
+ }
+
+ //NaN check on limit
+ if (limit) {
+ return limit > 0 ? input.slice(0, limit) : input.slice(limit);
+ } else {
+ return isString(input) ? "" : [];
+ }
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name orderBy
+ * @kind function
+ *
+ * @description
+ * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
+ * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
+ * correctly, make sure they are actually being saved as numbers and not strings.
+ *
+ * @param {Array} array The array to sort.
+ * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
+ * used by the comparator to determine the order of elements.
+ *
+ * Can be one of:
+ *
+ * - `function`: Getter function. The result of this function will be sorted using the
+ * `<`, `===`, `>` operator.
+ * - `string`: An Angular expression. The result of this expression is used to compare elements
+ * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
+ * 3 first characters of a property called `name`). The result of a constant expression
+ * is interpreted as a property name to be used in comparisons (for example `"special name"`
+ * to sort object by the value of their `special name` property). An expression can be
+ * optionally prefixed with `+` or `-` to control ascending or descending sort order
+ * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
+ * element itself is used to compare where sorting.
+ * - `Array`: An array of function or string predicates. The first predicate in the array
+ * is used for sorting, but when two items are equivalent, the next predicate is used.
+ *
+ * If the predicate is missing or empty then it defaults to `'+'`.
+ *
+ * @param {boolean=} reverse Reverse the order of the array.
+ * @returns {Array} Sorted copy of the source array.
+ *
+ *
+ * @example
+ * The example below demonstrates a simple ngRepeat, where the data is sorted
+ * by age in descending order (predicate is set to `'-age'`).
+ * `reverse` is not set, which means it defaults to `false`.
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th>Name</th>
+ <th>Phone Number</th>
+ <th>Age</th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:'-age'">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * The predicate and reverse parameters can be controlled dynamically through scope properties,
+ * as shown in the next example.
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ $scope.predicate = '-age';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
+ <hr/>
+ [ <a href="" ng-click="predicate=''">unsorted</a> ]
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
+ (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
+ <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
+ <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
+ * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
+ * desired parameters.
+ *
+ * Example:
+ *
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
+ var orderBy = $filter('orderBy');
+ $scope.friends = [
+ { name: 'John', phone: '555-1212', age: 10 },
+ { name: 'Mary', phone: '555-9876', age: 19 },
+ { name: 'Mike', phone: '555-4321', age: 21 },
+ { name: 'Adam', phone: '555-5678', age: 35 },
+ { name: 'Julie', phone: '555-8765', age: 29 }
+ ];
+ $scope.order = function(predicate, reverse) {
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
+ };
+ $scope.order('-age',false);
+ }]);
+ </file>
+</example>
+ */
+orderByFilter.$inject = ['$parse'];
+function orderByFilter($parse) {
+ return function(array, sortPredicate, reverseOrder) {
+ if (!(isArrayLike(array))) return array;
+ sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
+ if (sortPredicate.length === 0) { sortPredicate = ['+']; }
+ sortPredicate = sortPredicate.map(function(predicate) {
+ var descending = false, get = predicate || identity;
+ if (isString(predicate)) {
+ if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
+ descending = predicate.charAt(0) == '-';
+ predicate = predicate.substring(1);
+ }
+ if (predicate === '') {
+ // Effectively no predicate was passed so we compare identity
+ return reverseComparator(compare, descending);
+ }
+ get = $parse(predicate);
+ if (get.constant) {
+ var key = get();
+ return reverseComparator(function(a, b) {
+ return compare(a[key], b[key]);
+ }, descending);
+ }
+ }
+ return reverseComparator(function(a, b) {
+ return compare(get(a),get(b));
+ }, descending);
+ });
+ return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
+
+ function comparator(o1, o2) {
+ for (var i = 0; i < sortPredicate.length; i++) {
+ var comp = sortPredicate[i](o1, o2);
+ if (comp !== 0) return comp;
+ }
+ return 0;
+ }
+ function reverseComparator(comp, descending) {
+ return descending
+ ? function(a, b) {return comp(b,a);}
+ : comp;
+ }
+
+ function isPrimitive(value) {
+ switch (typeof value) {
+ case 'number': /* falls through */
+ case 'boolean': /* falls through */
+ case 'string':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function objectToString(value) {
+ if (value === null) return 'null';
+ if (typeof value.valueOf === 'function') {
+ value = value.valueOf();
+ if (isPrimitive(value)) return value;
+ }
+ if (typeof value.toString === 'function') {
+ value = value.toString();
+ if (isPrimitive(value)) return value;
+ }
+ return '';
+ }
+
+ function compare(v1, v2) {
+ var t1 = typeof v1;
+ var t2 = typeof v2;
+ if (t1 === t2 && t1 === "object") {
+ v1 = objectToString(v1);
+ v2 = objectToString(v2);
+ }
+ if (t1 === t2) {
+ if (t1 === "string") {
+ v1 = v1.toLowerCase();
+ v2 = v2.toLowerCase();
+ }
+ if (v1 === v2) return 0;
+ return v1 < v2 ? -1 : 1;
+ } else {
+ return t1 < t2 ? -1 : 1;
+ }
+ }
+ };
+}
+
+function ngDirective(directive) {
+ if (isFunction(directive)) {
+ directive = {
+ link: directive
+ };
+ }
+ directive.restrict = directive.restrict || 'AC';
+ return valueFn(directive);
+}
+
+/**
+ * @ngdoc directive
+ * @name a
+ * @restrict E
+ *
+ * @description
+ * Modifies the default behavior of the html A tag so that the default action is prevented when
+ * the href attribute is empty.
+ *
+ * This change permits the easy creation of action links with the `ngClick` directive
+ * without changing the location or causing page reloads, e.g.:
+ * `<a href="" ng-click="list.addItem()">Add Item</a>`
+ */
+var htmlAnchorDirective = valueFn({
+ restrict: 'E',
+ compile: function(element, attr) {
+ if (!attr.href && !attr.xlinkHref && !attr.name) {
+ return function(scope, element) {
+ // If the linked element is not an anchor tag anymore, do nothing
+ if (element[0].nodeName.toLowerCase() !== 'a') return;
+
+ // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
+ var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
+ 'xlink:href' : 'href';
+ element.on('click', function(event) {
+ // if we have no href url, then don't navigate anywhere.
+ if (!element.attr(href)) {
+ event.preventDefault();
+ }
+ });
+ };
+ }
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngHref
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in an href attribute will
+ * make the link go to the wrong URL if the user clicks it before
+ * Angular has a chance to replace the `{{hash}}` markup with its
+ * value. Until Angular replaces the markup the link will be broken
+ * and will most likely return a 404 error. The `ngHref` directive
+ * solves this problem.
+ *
+ * The wrong way to write it:
+ * ```html
+ * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * @element A
+ * @param {template} ngHref any string which can contain `{{}}` markup.
+ *
+ * @example
+ * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
+ * in links and their different behaviors:
+ <example>
+ <file name="index.html">
+ <input ng-model="value" /><br />
+ <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
+ <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
+ <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
+ <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
+ <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
+ <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should execute ng-click but not reload when href without value', function() {
+ element(by.id('link-1')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('1');
+ expect(element(by.id('link-1')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when href empty string', function() {
+ element(by.id('link-2')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('2');
+ expect(element(by.id('link-2')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click and change url when ng-href specified', function() {
+ expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
+
+ element(by.id('link-3')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/123$/);
+ });
+ }, 5000, 'page should navigate to /123');
+ });
+
+ xit('should execute ng-click but not reload when href empty string and name specified', function() {
+ element(by.id('link-4')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('4');
+ expect(element(by.id('link-4')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when no href but name specified', function() {
+ element(by.id('link-5')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('5');
+ expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
+ });
+
+ it('should only change url when only ng-href', function() {
+ element(by.model('value')).clear();
+ element(by.model('value')).sendKeys('6');
+ expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
+
+ element(by.id('link-6')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/6$/);
+ });
+ }, 5000, 'page should navigate to /6');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrc
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrc` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img src="http://www.gravatar.com/avatar/{{hash}}"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrc any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrcset
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrcset` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrcset any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngDisabled
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ *
+ * This directive sets the `disabled` attribute on the element if the
+ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
+ *
+ * A special directive is necessary because we cannot use interpolation inside the `disabled`
+ * attribute. The following example would make the button enabled on Chrome/Firefox
+ * but not on older IEs:
+ *
+ * ```html
+ * <!-- See below for an example of ng-disabled being used correctly -->
+ * <div ng-init="isDisabled = false">
+ * <button disabled="{{isDisabled}}">Disabled</button>
+ * </div>
+ * ```
+ *
+ * This is because the HTML specification does not require browsers to preserve the values of
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
+ <button ng-model="button" ng-disabled="checked">Button</button>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle button', function() {
+ expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
+ * then the `disabled` attribute will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngChecked
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as checked. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngChecked` directive solves this problem for the `checked` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to check both: <input type="checkbox" ng-model="master"><br/>
+ <input id="checkSlave" type="checkbox" ng-checked="master">
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check both checkBoxes', function() {
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
+ element(by.model('master')).click();
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
+ * then special attribute "checked" will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngReadonly
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as readonly. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngReadonly` directive solves this problem for the `readonly` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
+ <input type="text" ng-readonly="checked" value="I'm Angular"/>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle readonly attr', function() {
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
+ * then special attribute "readonly" will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSelected
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as selected. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngSelected` directive solves this problem for the `selected` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to select: <input type="checkbox" ng-model="selected"><br/>
+ <select>
+ <option>Hello!</option>
+ <option id="greet" ng-selected="selected">Greetings!</option>
+ </select>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should select Greetings!', function() {
+ expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
+ element(by.model('selected')).click();
+ expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element OPTION
+ * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
+ * then special attribute "selected" will be set on the element
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngOpen
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as open. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngOpen` directive solves this problem for the `open` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me check multiple: <input type="checkbox" ng-model="open"><br/>
+ <details id="details" ng-open="open">
+ <summary>Show/Hide me</summary>
+ </details>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle open', function() {
+ expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
+ element(by.model('open')).click();
+ expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element DETAILS
+ * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
+ * then special attribute "open" will be set on the element
+ */
+
+var ngAttributeAliasDirectives = {};
+
+
+// boolean attrs are evaluated
+forEach(BOOLEAN_ATTR, function(propName, attrName) {
+ // binding to multiple is not supported
+ if (propName == "multiple") return;
+
+ var normalized = directiveNormalize('ng-' + attrName);
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ link: function(scope, element, attr) {
+ scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
+ attr.$set(attrName, !!value);
+ });
+ }
+ };
+ };
+});
+
+// aliased input attrs are evaluated
+forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
+ ngAttributeAliasDirectives[ngAttr] = function() {
+ return {
+ priority: 100,
+ link: function(scope, element, attr) {
+ //special case ngPattern when a literal regular expression value
+ //is used as the expression (this way we don't have to watch anything).
+ if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
+ var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
+ if (match) {
+ attr.$set("ngPattern", new RegExp(match[1], match[2]));
+ return;
+ }
+ }
+
+ scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
+ attr.$set(ngAttr, value);
+ });
+ }
+ };
+ };
+});
+
+// ng-src, ng-srcset, ng-href are interpolated
+forEach(['src', 'srcset', 'href'], function(attrName) {
+ var normalized = directiveNormalize('ng-' + attrName);
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ priority: 99, // it needs to run after the attributes are interpolated
+ link: function(scope, element, attr) {
+ var propName = attrName,
+ name = attrName;
+
+ if (attrName === 'href' &&
+ toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
+ name = 'xlinkHref';
+ attr.$attr[name] = 'xlink:href';
+ propName = null;
+ }
+
+ attr.$observe(normalized, function(value) {
+ if (!value) {
+ if (attrName === 'href') {
+ attr.$set(name, null);
+ }
+ return;
+ }
+
+ attr.$set(name, value);
+
+ // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
+ // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
+ // to set the property as well to achieve the desired effect.
+ // we use attr[attrName] value since $set can sanitize the url.
+ if (msie && propName) element.prop(propName, attr[name]);
+ });
+ }
+ };
+ };
+});
+
+/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
+ */
+var nullFormCtrl = {
+ $addControl: noop,
+ $$renameControl: nullFormRenameControl,
+ $removeControl: noop,
+ $setValidity: noop,
+ $setDirty: noop,
+ $setPristine: noop,
+ $setSubmitted: noop
+},
+SUBMITTED_CLASS = 'ng-submitted';
+
+function nullFormRenameControl(control, name) {
+ control.$name = name;
+}
+
+/**
+ * @ngdoc type
+ * @name form.FormController
+ *
+ * @property {boolean} $pristine True if user has not interacted with the form yet.
+ * @property {boolean} $dirty True if user has already interacted with the form.
+ * @property {boolean} $valid True if all of the containing forms and controls are valid.
+ * @property {boolean} $invalid True if at least one containing control or form is invalid.
+ * @property {boolean} $submitted True if user has submitted the form even if its invalid.
+ *
+ * @property {Object} $error Is an object hash, containing references to controls or
+ * forms with failing validators, where:
+ *
+ * - keys are validation tokens (error names),
+ * - values are arrays of controls or forms that have a failing validator for given error name.
+ *
+ * Built-in validation tokens:
+ *
+ * - `email`
+ * - `max`
+ * - `maxlength`
+ * - `min`
+ * - `minlength`
+ * - `number`
+ * - `pattern`
+ * - `required`
+ * - `url`
+ * - `date`
+ * - `datetimelocal`
+ * - `time`
+ * - `week`
+ * - `month`
+ *
+ * @description
+ * `FormController` keeps track of all its controls and nested forms as well as the state of them,
+ * such as being valid/invalid or dirty/pristine.
+ *
+ * Each {@link ng.directive:form form} directive creates an instance
+ * of `FormController`.
+ *
+ */
+//asks for $scope to fool the BC controller module
+FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
+function FormController(element, attrs, $scope, $animate, $interpolate) {
+ var form = this,
+ controls = [];
+
+ var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
+
+ // init state
+ form.$error = {};
+ form.$$success = {};
+ form.$pending = undefined;
+ form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$valid = true;
+ form.$invalid = false;
+ form.$submitted = false;
+
+ parentForm.$addControl(form);
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$rollbackViewValue
+ *
+ * @description
+ * Rollback all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is typically needed by the reset button of
+ * a form that uses `ng-model-options` to pend updates.
+ */
+ form.$rollbackViewValue = function() {
+ forEach(controls, function(control) {
+ control.$rollbackViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$commitViewValue
+ *
+ * @description
+ * Commit all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ form.$commitViewValue = function() {
+ forEach(controls, function(control) {
+ control.$commitViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$addControl
+ *
+ * @description
+ * Register a control with the form.
+ *
+ * Input elements using ngModelController do this automatically when they are linked.
+ */
+ form.$addControl = function(control) {
+ // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
+ // and not added to the scope. Now we throw an error.
+ assertNotHasOwnProperty(control.$name, 'input');
+ controls.push(control);
+
+ if (control.$name) {
+ form[control.$name] = control;
+ }
+ };
+
+ // Private API: rename a form control
+ form.$$renameControl = function(control, newName) {
+ var oldName = control.$name;
+
+ if (form[oldName] === control) {
+ delete form[oldName];
+ }
+ form[newName] = control;
+ control.$name = newName;
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$removeControl
+ *
+ * @description
+ * Deregister a control from the form.
+ *
+ * Input elements using ngModelController do this automatically when they are destroyed.
+ */
+ form.$removeControl = function(control) {
+ if (control.$name && form[control.$name] === control) {
+ delete form[control.$name];
+ }
+ forEach(form.$pending, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$error, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$$success, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+
+ arrayRemove(controls, control);
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setValidity
+ *
+ * @description
+ * Sets the validity of a form control.
+ *
+ * This method will also propagate to parent forms.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: element,
+ set: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ object[property] = [controller];
+ } else {
+ var index = list.indexOf(controller);
+ if (index === -1) {
+ list.push(controller);
+ }
+ }
+ },
+ unset: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ return;
+ }
+ arrayRemove(list, controller);
+ if (list.length === 0) {
+ delete object[property];
+ }
+ },
+ parentForm: parentForm,
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setDirty
+ *
+ * @description
+ * Sets the form to a dirty state.
+ *
+ * This method can be called to add the 'ng-dirty' class and set the form to a dirty
+ * state (ng-dirty class). This method will also propagate to parent forms.
+ */
+ form.$setDirty = function() {
+ $animate.removeClass(element, PRISTINE_CLASS);
+ $animate.addClass(element, DIRTY_CLASS);
+ form.$dirty = true;
+ form.$pristine = false;
+ parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setPristine
+ *
+ * @description
+ * Sets the form to its pristine state.
+ *
+ * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
+ * state (ng-pristine class). This method will also propagate to all the controls contained
+ * in this form.
+ *
+ * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
+ * saving or resetting it.
+ */
+ form.$setPristine = function() {
+ $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$submitted = false;
+ forEach(controls, function(control) {
+ control.$setPristine();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setUntouched
+ *
+ * @description
+ * Sets the form to its untouched state.
+ *
+ * This method can be called to remove the 'ng-touched' class and set the form controls to their
+ * untouched state (ng-untouched class).
+ *
+ * Setting a form controls back to their untouched state is often useful when setting the form
+ * back to its pristine state.
+ */
+ form.$setUntouched = function() {
+ forEach(controls, function(control) {
+ control.$setUntouched();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setSubmitted
+ *
+ * @description
+ * Sets the form to its submitted state.
+ */
+ form.$setSubmitted = function() {
+ $animate.addClass(element, SUBMITTED_CLASS);
+ form.$submitted = true;
+ parentForm.$setSubmitted();
+ };
+}
+
+/**
+ * @ngdoc directive
+ * @name ngForm
+ * @restrict EAC
+ *
+ * @description
+ * Nestable alias of {@link ng.directive:form `form`} directive. HTML
+ * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
+ * sub-group of controls needs to be determined.
+ *
+ * Note: the purpose of `ngForm` is to group controls,
+ * but not to be a replacement for the `<form>` tag with all of its capabilities
+ * (e.g. posting to the server, ...).
+ *
+ * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ *
+ */
+
+ /**
+ * @ngdoc directive
+ * @name form
+ * @restrict E
+ *
+ * @description
+ * Directive that instantiates
+ * {@link form.FormController FormController}.
+ *
+ * If the `name` attribute is specified, the form controller is published onto the current scope under
+ * this name.
+ *
+ * # Alias: {@link ng.directive:ngForm `ngForm`}
+ *
+ * In Angular, forms can be nested. This means that the outer form is valid when all of the child
+ * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
+ * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
+ * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
+ * using Angular validation directives in forms that are dynamically generated using the
+ * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
+ * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
+ * `ngForm` directive and nest these in an outer `form` element.
+ *
+ *
+ * # CSS classes
+ * - `ng-valid` is set if the form is valid.
+ * - `ng-invalid` is set if the form is invalid.
+ * - `ng-pristine` is set if the form is pristine.
+ * - `ng-dirty` is set if the form is dirty.
+ * - `ng-submitted` is set if the form was submitted.
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ *
+ * # Submitting a form and preventing the default action
+ *
+ * Since the role of forms in client-side Angular applications is different than in classical
+ * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
+ * page reload that sends the data to the server. Instead some javascript logic should be triggered
+ * to handle the form submission in an application-specific way.
+ *
+ * For this reason, Angular prevents the default action (form submission to the server) unless the
+ * `<form>` element has an `action` attribute specified.
+ *
+ * You can use one of the following two ways to specify what javascript method should be called when
+ * a form is submitted:
+ *
+ * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
+ * - {@link ng.directive:ngClick ngClick} directive on the first
+ * button or input field of type submit (input[type=submit])
+ *
+ * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
+ * or {@link ng.directive:ngClick ngClick} directives.
+ * This is because of the following form submission rules in the HTML specification:
+ *
+ * - If a form has only one input field then hitting enter in this field triggers form submit
+ * (`ngSubmit`)
+ * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
+ * doesn't trigger submit
+ * - if a form has one or more input fields and one or more buttons or input[type=submit] then
+ * hitting enter in any of the input fields will trigger the click handler on the *first* button or
+ * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
+ *
+ * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
+ * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * ## Animation Hooks
+ *
+ * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
+ * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
+ * other validations that are performed within the form. Animations in ngForm are similar to how
+ * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
+ * as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style a form element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-form {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-form.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
+ <file name="index.html">
+ <script>
+ angular.module('formExample', [])
+ .controller('FormController', ['$scope', function($scope) {
+ $scope.userType = 'guest';
+ }]);
+ </script>
+ <style>
+ .my-form {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-form.ng-invalid {
+ background: red;
+ }
+ </style>
+ <form name="myForm" ng-controller="FormController" class="my-form">
+ userType: <input name="input" ng-model="userType" required>
+ <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
+ <code>userType = {{userType}}</code><br>
+ <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
+ <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
+ <code>myForm.$valid = {{myForm.$valid}}</code><br>
+ <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should initialize to model', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+
+ expect(userType.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var userInput = element(by.model('userType'));
+
+ userInput.clear();
+ userInput.sendKeys('');
+
+ expect(userType.getText()).toEqual('userType =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ *
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ */
+var formDirectiveFactory = function(isNgForm) {
+ return ['$timeout', function($timeout) {
+ var formDirective = {
+ name: 'form',
+ restrict: isNgForm ? 'EAC' : 'E',
+ controller: FormController,
+ compile: function ngFormCompile(formElement, attr) {
+ // Setup initial state of the control
+ formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
+
+ var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
+
+ return {
+ pre: function ngFormPreLink(scope, formElement, attr, controller) {
+ // if `action` attr is not present on the form, prevent the default action (submission)
+ if (!('action' in attr)) {
+ // we can't use jq events because if a form is destroyed during submission the default
+ // action is not prevented. see #1238
+ //
+ // IE 9 is not affected because it doesn't fire a submit event and try to do a full
+ // page reload if the form was destroyed by submission of the form via a click handler
+ // on a button in the form. Looks like an IE9 specific bug.
+ var handleFormSubmission = function(event) {
+ scope.$apply(function() {
+ controller.$commitViewValue();
+ controller.$setSubmitted();
+ });
+
+ event.preventDefault();
+ };
+
+ addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+
+ // unregister the preventDefault listener so that we don't not leak memory but in a
+ // way that will achieve the prevention of the default action.
+ formElement.on('$destroy', function() {
+ $timeout(function() {
+ removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+ }, 0, false);
+ });
+ }
+
+ var parentFormCtrl = controller.$$parentForm;
+
+ if (nameAttr) {
+ setter(scope, null, controller.$name, controller, controller.$name);
+ attr.$observe(nameAttr, function(newValue) {
+ if (controller.$name === newValue) return;
+ setter(scope, null, controller.$name, undefined, controller.$name);
+ parentFormCtrl.$$renameControl(controller, newValue);
+ setter(scope, null, controller.$name, controller, controller.$name);
+ });
+ }
+ formElement.on('$destroy', function() {
+ parentFormCtrl.$removeControl(controller);
+ if (nameAttr) {
+ setter(scope, null, attr[nameAttr], undefined, controller.$name);
+ }
+ extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
+ });
+ }
+ };
+ }
+ };
+
+ return formDirective;
+ }];
+};
+
+var formDirective = formDirectiveFactory();
+var ngFormDirective = formDirectiveFactory(true);
+
+/* global VALID_CLASS: false,
+ INVALID_CLASS: false,
+ PRISTINE_CLASS: false,
+ DIRTY_CLASS: false,
+ UNTOUCHED_CLASS: false,
+ TOUCHED_CLASS: false,
+ ngModelMinErr: false,
+*/
+
+// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
+var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
+var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
+var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
+var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
+var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
+var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
+var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
+var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+
+var inputType = {
+
+ /**
+ * @ngdoc input
+ * @name input[text]
+ *
+ * @description
+ * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Adds `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="text-input-directive" module="textInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('textInputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ text: 'guest',
+ word: /^\s*\w*\s*$/
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Single word: <input type="text" name="input" ng-model="example.text"
+ ng-pattern="example.word" required ng-trim="false">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.pattern">
+ Single word only!</span>
+
+ <tt>text = {{example.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('example.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if multi word', function() {
+ input.clear();
+ input.sendKeys('hello world');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'text': textInputType,
+
+ /**
+ * @ngdoc input
+ * @name input[date]
+ *
+ * @description
+ * Input with date validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
+ * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
+ * modern browsers do not yet support this input type, it is important to provide cues to users on the
+ * expected input format via a placeholder or label.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO date string (yyyy-MM-dd).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO date string (yyyy-MM-dd).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="date-input-directive" module="dateInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateInputExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 22)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date in 2013:
+ <input type="date" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.date">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (see https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10-22');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'date': createDateInputType('date', DATE_REGEXP,
+ createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
+ 'yyyy-MM-dd'),
+
+ /**
+ * @ngdoc input
+ * @name input[datetime-local]
+ *
+ * @description
+ * Input with datetime validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="datetimelocal-input-directive" module="dateExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2010, 11, 28, 14, 57)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date between in 2013:
+ <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.datetimelocal">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2010-12-28T14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01T23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
+ createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
+ 'yyyy-MM-ddTHH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[time]
+ *
+ * @description
+ * Input with time validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
+ * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO time format (HH:mm:ss).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
+ * valid ISO time format (HH:mm:ss).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="time-input-directive" module="timeExample">
+ <file name="index.html">
+ <script>
+ angular.module('timeExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(1970, 0, 1, 14, 57, 0)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a between 8am and 5pm:
+ <input type="time" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.time">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "HH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'time': createDateInputType('time', TIME_REGEXP,
+ createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
+ 'HH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[week]
+ *
+ * @description
+ * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
+ * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * week format (yyyy-W##), for example: `2013-W02`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO week format (yyyy-W##).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO week format (yyyy-W##).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="week-input-directive" module="weekExample">
+ <file name="index.html">
+ <script>
+ angular.module('weekExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 0, 3)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date between in 2013:
+ <input id="exampleInput" type="week" name="input" ng-model="example.value"
+ placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.week">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-Www"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-W01');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-W01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
+
+ /**
+ * @ngdoc input
+ * @name input[month]
+ *
+ * @description
+ * Input with month validation and transformation. In browsers that do not yet support
+ * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * month format (yyyy-MM), for example: `2009-01`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ * If the model is not set to the first of the month, the next view to model update will set it
+ * to the first of the month.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
+ * a valid ISO month format (yyyy-MM).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
+ * be a valid ISO month format (yyyy-MM).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="month-input-directive" module="monthExample">
+ <file name="index.html">
+ <script>
+ angular.module('monthExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 1)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a month in 2013:
+ <input id="exampleInput" type="month" name="input" ng-model="example.value"
+ placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.month">
+ Not a valid month!</span>
+ <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'month': createDateInputType('month', MONTH_REGEXP,
+ createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
+ 'yyyy-MM'),
+
+ /**
+ * @ngdoc input
+ * @name input[number]
+ *
+ * @description
+ * Text input with number validation and transformation. Sets the `number` validation
+ * error if not a valid number.
+ *
+ * <div class="alert alert-warning">
+ * The model must always be of type `number` otherwise Angular will throw an error.
+ * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
+ * error docs for more information and an example of how to convert your model if necessary.
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="number-input-directive" module="numberExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ value: 12
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Number: <input type="number" name="input" ng-model="example.value"
+ min="0" max="99" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.number">
+ Not valid number!</span>
+ <tt>value = {{example.value}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('12');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if over max', function() {
+ input.clear();
+ input.sendKeys('123');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'number': numberInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[url]
+ *
+ * @description
+ * Text input with URL validation. Sets the `url` validation error key if the content is not a
+ * valid URL.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
+ * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
+ * the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="url-input-directive" module="urlExample">
+ <file name="index.html">
+ <script>
+ angular.module('urlExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.url = {
+ text: 'http://google.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ URL: <input type="url" name="input" ng-model="url.text" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.url">
+ Not valid url!</span>
+ <tt>text = {{url.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('url.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('url.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('http://google.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not url', function() {
+ input.clear();
+ input.sendKeys('box');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'url': urlInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[email]
+ *
+ * @description
+ * Text input with email validation. Sets the `email` validation error key if not a valid email
+ * address.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
+ * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
+ * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="email-input-directive" module="emailExample">
+ <file name="index.html">
+ <script>
+ angular.module('emailExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.email = {
+ text: 'me@example.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Email: <input type="email" name="input" ng-model="email.text" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.email">
+ Not valid email!</span>
+ <tt>text = {{email.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('email.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('email.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('me@example.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not email', function() {
+ input.clear();
+ input.sendKeys('xxx');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'email': emailInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[radio]
+ *
+ * @description
+ * HTML radio button.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string} value The value to which the expression should be set when selected.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {string} ngValue Angular expression which sets the value to which the expression should
+ * be set when selected.
+ *
+ * @example
+ <example name="radio-input-directive" module="radioExample">
+ <file name="index.html">
+ <script>
+ angular.module('radioExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.color = {
+ name: 'blue'
+ };
+ $scope.specialValue = {
+ "id": "12345",
+ "value": "green"
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <input type="radio" ng-model="color.name" value="red"> Red <br/>
+ <input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/>
+ <input type="radio" ng-model="color.name" value="blue"> Blue <br/>
+ <tt>color = {{color.name | json}}</tt><br/>
+ </form>
+ Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var color = element(by.binding('color.name'));
+
+ expect(color.getText()).toContain('blue');
+
+ element.all(by.model('color.name')).get(0).click();
+
+ expect(color.getText()).toContain('red');
+ });
+ </file>
+ </example>
+ */
+ 'radio': radioInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[checkbox]
+ *
+ * @description
+ * HTML checkbox.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
+ * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="checkbox-input-directive" module="checkboxExample">
+ <file name="index.html">
+ <script>
+ angular.module('checkboxExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.checkboxModel = {
+ value1 : true,
+ value2 : 'YES'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/>
+ Value2: <input type="checkbox" ng-model="checkboxModel.value2"
+ ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
+ <tt>value1 = {{checkboxModel.value1}}</tt><br/>
+ <tt>value2 = {{checkboxModel.value2}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var value1 = element(by.binding('checkboxModel.value1'));
+ var value2 = element(by.binding('checkboxModel.value2'));
+
+ expect(value1.getText()).toContain('true');
+ expect(value2.getText()).toContain('YES');
+
+ element(by.model('checkboxModel.value1')).click();
+ element(by.model('checkboxModel.value2')).click();
+
+ expect(value1.getText()).toContain('false');
+ expect(value2.getText()).toContain('NO');
+ });
+ </file>
+ </example>
+ */
+ 'checkbox': checkboxInputType,
+
+ 'hidden': noop,
+ 'button': noop,
+ 'submit': noop,
+ 'reset': noop,
+ 'file': noop
+};
+
+function stringBasedInputType(ctrl) {
+ ctrl.$formatters.push(function(value) {
+ return ctrl.$isEmpty(value) ? value : value.toString();
+ });
+}
+
+function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+}
+
+function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ var type = lowercase(element[0].type);
+
+ // In composition mode, users are still inputing intermediate text buffer,
+ // hold the listener until composition is done.
+ // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
+ if (!$sniffer.android) {
+ var composing = false;
+
+ element.on('compositionstart', function(data) {
+ composing = true;
+ });
+
+ element.on('compositionend', function() {
+ composing = false;
+ listener();
+ });
+ }
+
+ var listener = function(ev) {
+ if (timeout) {
+ $browser.defer.cancel(timeout);
+ timeout = null;
+ }
+ if (composing) return;
+ var value = element.val(),
+ event = ev && ev.type;
+
+ // By default we will trim the value
+ // If the attribute ng-trim exists we will avoid trimming
+ // If input type is 'password', the value is never trimmed
+ if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
+ value = trim(value);
+ }
+
+ // If a control is suffering from bad input (due to native validators), browsers discard its
+ // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
+ // control's value is the same empty value twice in a row.
+ if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
+ ctrl.$setViewValue(value, event);
+ }
+ };
+
+ // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
+ // input event on backspace, delete or cut
+ if ($sniffer.hasEvent('input')) {
+ element.on('input', listener);
+ } else {
+ var timeout;
+
+ var deferListener = function(ev, input, origValue) {
+ if (!timeout) {
+ timeout = $browser.defer(function() {
+ timeout = null;
+ if (!input || input.value !== origValue) {
+ listener(ev);
+ }
+ });
+ }
+ };
+
+ element.on('keydown', function(event) {
+ var key = event.keyCode;
+
+ // ignore
+ // command modifiers arrows
+ if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
+
+ deferListener(event, this, this.value);
+ });
+
+ // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
+ if ($sniffer.hasEvent('paste')) {
+ element.on('paste cut', deferListener);
+ }
+ }
+
+ // if user paste into input using mouse on older browser
+ // or form autocomplete on newer browser, we need "change" event to catch it
+ element.on('change', listener);
+
+ ctrl.$render = function() {
+ element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
+ };
+}
+
+function weekParser(isoWeek, existingDate) {
+ if (isDate(isoWeek)) {
+ return isoWeek;
+ }
+
+ if (isString(isoWeek)) {
+ WEEK_REGEXP.lastIndex = 0;
+ var parts = WEEK_REGEXP.exec(isoWeek);
+ if (parts) {
+ var year = +parts[1],
+ week = +parts[2],
+ hours = 0,
+ minutes = 0,
+ seconds = 0,
+ milliseconds = 0,
+ firstThurs = getFirstThursdayOfYear(year),
+ addDays = (week - 1) * 7;
+
+ if (existingDate) {
+ hours = existingDate.getHours();
+ minutes = existingDate.getMinutes();
+ seconds = existingDate.getSeconds();
+ milliseconds = existingDate.getMilliseconds();
+ }
+
+ return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
+ }
+ }
+
+ return NaN;
+}
+
+function createDateParser(regexp, mapping) {
+ return function(iso, date) {
+ var parts, map;
+
+ if (isDate(iso)) {
+ return iso;
+ }
+
+ if (isString(iso)) {
+ // When a date is JSON'ified to wraps itself inside of an extra
+ // set of double quotes. This makes the date parsing code unable
+ // to match the date string and parse it as a date.
+ if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
+ iso = iso.substring(1, iso.length - 1);
+ }
+ if (ISO_DATE_REGEXP.test(iso)) {
+ return new Date(iso);
+ }
+ regexp.lastIndex = 0;
+ parts = regexp.exec(iso);
+
+ if (parts) {
+ parts.shift();
+ if (date) {
+ map = {
+ yyyy: date.getFullYear(),
+ MM: date.getMonth() + 1,
+ dd: date.getDate(),
+ HH: date.getHours(),
+ mm: date.getMinutes(),
+ ss: date.getSeconds(),
+ sss: date.getMilliseconds() / 1000
+ };
+ } else {
+ map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
+ }
+
+ forEach(parts, function(part, index) {
+ if (index < mapping.length) {
+ map[mapping[index]] = +part;
+ }
+ });
+ return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
+ }
+ }
+
+ return NaN;
+ };
+}
+
+function createDateInputType(type, regexp, parseDate, format) {
+ return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
+ var previousDate;
+
+ ctrl.$$parserName = type;
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (regexp.test(value)) {
+ // Note: We cannot read ctrl.$modelValue, as there might be a different
+ // parser/formatter in the processing chain so that the model
+ // contains some different data format!
+ var parsedDate = parseDate(value, previousDate);
+ if (timezone === 'UTC') {
+ parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());
+ }
+ return parsedDate;
+ }
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (value && !isDate(value)) {
+ throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
+ }
+ if (isValidDate(value)) {
+ previousDate = value;
+ if (previousDate && timezone === 'UTC') {
+ var timezoneOffset = 60000 * previousDate.getTimezoneOffset();
+ previousDate = new Date(previousDate.getTime() + timezoneOffset);
+ }
+ return $filter('date')(value, format, timezone);
+ } else {
+ previousDate = null;
+ return '';
+ }
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
+ };
+ attr.$observe('min', function(val) {
+ minVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
+ };
+ attr.$observe('max', function(val) {
+ maxVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ function isValidDate(value) {
+ // Invalid Date: getTime() returns NaN
+ return value && !(value.getTime && value.getTime() !== value.getTime());
+ }
+
+ function parseObservedDateValue(val) {
+ return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
+ }
+ };
+}
+
+function badInputChecker(scope, element, attr, ctrl) {
+ var node = element[0];
+ var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
+ if (nativeValidation) {
+ ctrl.$parsers.push(function(value) {
+ var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
+ // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
+ // - also sets validity.badInput (should only be validity.typeMismatch).
+ // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
+ // - can ignore this case as we can still read out the erroneous email...
+ return validity.badInput && !validity.typeMismatch ? undefined : value;
+ });
+ }
+}
+
+function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+
+ ctrl.$$parserName = 'number';
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (NUMBER_REGEXP.test(value)) return parseFloat(value);
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (!ctrl.$isEmpty(value)) {
+ if (!isNumber(value)) {
+ throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
+ }
+ value = value.toString();
+ }
+ return value;
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
+ };
+
+ attr.$observe('min', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ minVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
+ };
+
+ attr.$observe('max', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+}
+
+function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'url';
+ ctrl.$validators.url = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
+ };
+}
+
+function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'email';
+ ctrl.$validators.email = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
+ };
+}
+
+function radioInputType(scope, element, attr, ctrl) {
+ // make the name unique, if not defined
+ if (isUndefined(attr.name)) {
+ element.attr('name', nextUid());
+ }
+
+ var listener = function(ev) {
+ if (element[0].checked) {
+ ctrl.$setViewValue(attr.value, ev && ev.type);
+ }
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ var value = attr.value;
+ element[0].checked = (value == ctrl.$viewValue);
+ };
+
+ attr.$observe('value', ctrl.$render);
+}
+
+function parseConstantExpr($parse, context, name, expression, fallback) {
+ var parseFn;
+ if (isDefined(expression)) {
+ parseFn = $parse(expression);
+ if (!parseFn.constant) {
+ throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
+ '`{1}`.', name, expression);
+ }
+ return parseFn(context);
+ }
+ return fallback;
+}
+
+function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
+ var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
+ var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
+
+ var listener = function(ev) {
+ ctrl.$setViewValue(element[0].checked, ev && ev.type);
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ element[0].checked = ctrl.$viewValue;
+ };
+
+ // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
+ // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
+ // it to a boolean.
+ ctrl.$isEmpty = function(value) {
+ return value === false;
+ };
+
+ ctrl.$formatters.push(function(value) {
+ return equals(value, trueValue);
+ });
+
+ ctrl.$parsers.push(function(value) {
+ return value ? trueValue : falseValue;
+ });
+}
+
+
+/**
+ * @ngdoc directive
+ * @name textarea
+ * @restrict E
+ *
+ * @description
+ * HTML textarea element control with angular data-binding. The data-binding and validation
+ * properties of this element are exactly the same as those of the
+ * {@link ng.directive:input input element}.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name input
+ * @restrict E
+ *
+ * @description
+ * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
+ * input state control, and validation.
+ * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Not every feature offered is available for all input types.
+ * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {boolean=} ngRequired Sets `required` attribute if set to true
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="input-directive" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = {name: 'guest', last: 'visitor'};
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <form name="myForm">
+ User name: <input type="text" name="userName" ng-model="user.name" required>
+ <span class="error" ng-show="myForm.userName.$error.required">
+ Required!</span><br>
+ Last name: <input type="text" name="lastName" ng-model="user.last"
+ ng-minlength="3" ng-maxlength="10">
+ <span class="error" ng-show="myForm.lastName.$error.minlength">
+ Too short!</span>
+ <span class="error" ng-show="myForm.lastName.$error.maxlength">
+ Too long!</span><br>
+ </form>
+ <hr>
+ <tt>user = {{user}}</tt><br/>
+ <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
+ <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
+ <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
+ <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
+ <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
+ <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var user = element(by.exactBinding('user'));
+ var userNameValid = element(by.binding('myForm.userName.$valid'));
+ var lastNameValid = element(by.binding('myForm.lastName.$valid'));
+ var lastNameError = element(by.binding('myForm.lastName.$error'));
+ var formValid = element(by.binding('myForm.$valid'));
+ var userNameInput = element(by.model('user.name'));
+ var userLastInput = element(by.model('user.last'));
+
+ it('should initialize to model', function() {
+ expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
+ expect(userNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty when required', function() {
+ userNameInput.clear();
+ userNameInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"last":"visitor"}');
+ expect(userNameValid.getText()).toContain('false');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be valid if empty when min length is set', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"name":"guest","last":""}');
+ expect(lastNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if less than required min length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('xx');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('minlength');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be invalid if longer than max length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('some ridiculously long name');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('maxlength');
+ expect(formValid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
+ function($browser, $sniffer, $filter, $parse) {
+ return {
+ restrict: 'E',
+ require: ['?ngModel'],
+ link: {
+ pre: function(scope, element, attr, ctrls) {
+ if (ctrls[0]) {
+ (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
+ $browser, $filter, $parse);
+ }
+ }
+ }
+ };
+}];
+
+
+
+var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
+/**
+ * @ngdoc directive
+ * @name ngValue
+ *
+ * @description
+ * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
+ * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
+ * the bound value.
+ *
+ * `ngValue` is useful when dynamically generating lists of radio buttons using
+ * {@link ngRepeat `ngRepeat`}, as shown below.
+ *
+ * Likewise, `ngValue` can be used to generate `<option>` elements for
+ * the {@link select `select`} element. In that case however, only strings are supported
+ * for the `value `attribute, so the resulting `ngModel` will always be a string.
+ * Support for `select` models with non-string values is available via `ngOptions`.
+ *
+ * @element input
+ * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
+ * of the `input` element
+ *
+ * @example
+ <example name="ngValue-directive" module="valueExample">
+ <file name="index.html">
+ <script>
+ angular.module('valueExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.names = ['pizza', 'unicorns', 'robots'];
+ $scope.my = { favorite: 'unicorns' };
+ }]);
+ </script>
+ <form ng-controller="ExampleController">
+ <h2>Which is your favorite?</h2>
+ <label ng-repeat="name in names" for="{{name}}">
+ {{name}}
+ <input type="radio"
+ ng-model="my.favorite"
+ ng-value="name"
+ id="{{name}}"
+ name="favorite">
+ </label>
+ <div>You chose {{my.favorite}}</div>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var favorite = element(by.binding('my.favorite'));
+
+ it('should initialize to model', function() {
+ expect(favorite.getText()).toContain('unicorns');
+ });
+ it('should bind the values to the inputs', function() {
+ element.all(by.model('my.favorite')).get(0).click();
+ expect(favorite.getText()).toContain('pizza');
+ });
+ </file>
+ </example>
+ */
+var ngValueDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ compile: function(tpl, tplAttr) {
+ if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
+ return function ngValueConstantLink(scope, elm, attr) {
+ attr.$set('value', scope.$eval(attr.ngValue));
+ };
+ } else {
+ return function ngValueLink(scope, elm, attr) {
+ scope.$watch(attr.ngValue, function valueWatchAction(value) {
+ attr.$set('value', value);
+ });
+ };
+ }
+ }
+ };
+};
+
+/**
+ * @ngdoc directive
+ * @name ngBind
+ * @restrict AC
+ *
+ * @description
+ * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
+ * with the value of a given expression, and to update the text content when the value of that
+ * expression changes.
+ *
+ * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
+ * `{{ expression }}` which is similar but less verbose.
+ *
+ * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
+ * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
+ * element attribute, it makes the bindings invisible to the user while the page is loading.
+ *
+ * An alternative solution to this problem would be using the
+ * {@link ng.directive:ngCloak ngCloak} directive.
+ *
+ *
+ * @element ANY
+ * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+ * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.name = 'Whirled';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Enter name: <input type="text" ng-model="name"><br>
+ Hello <span ng-bind="name"></span>!
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var nameInput = element(by.model('name'));
+
+ expect(element(by.binding('name')).getText()).toBe('Whirled');
+ nameInput.clear();
+ nameInput.sendKeys('world');
+ expect(element(by.binding('name')).getText()).toBe('world');
+ });
+ </file>
+ </example>
+ */
+var ngBindDirective = ['$compile', function($compile) {
+ return {
+ restrict: 'AC',
+ compile: function ngBindCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBind);
+ element = element[0];
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
+ element.textContent = value === undefined ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindTemplate
+ *
+ * @description
+ * The `ngBindTemplate` directive specifies that the element
+ * text content should be replaced with the interpolation of the template
+ * in the `ngBindTemplate` attribute.
+ * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
+ * expressions. This directive is needed since some HTML elements
+ * (such as TITLE and OPTION) cannot contain SPAN elements.
+ *
+ * @element ANY
+ * @param {string} ngBindTemplate template of form
+ * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
+ *
+ * @example
+ * Try it here: enter text in text box and watch the greeting change.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.salutation = 'Hello';
+ $scope.name = 'World';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Salutation: <input type="text" ng-model="salutation"><br>
+ Name: <input type="text" ng-model="name"><br>
+ <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var salutationElem = element(by.binding('salutation'));
+ var salutationInput = element(by.model('salutation'));
+ var nameInput = element(by.model('name'));
+
+ expect(salutationElem.getText()).toBe('Hello World!');
+
+ salutationInput.clear();
+ salutationInput.sendKeys('Greetings');
+ nameInput.clear();
+ nameInput.sendKeys('user');
+
+ expect(salutationElem.getText()).toBe('Greetings user!');
+ });
+ </file>
+ </example>
+ */
+var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
+ return {
+ compile: function ngBindTemplateCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindTemplateLink(scope, element, attr) {
+ var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
+ $compile.$$addBindingInfo(element, interpolateFn.expressions);
+ element = element[0];
+ attr.$observe('ngBindTemplate', function(value) {
+ element.textContent = value === undefined ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindHtml
+ *
+ * @description
+ * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
+ * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
+ * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
+ * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
+ * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
+ *
+ * You may also bypass sanitization for values you know are safe. To do so, bind to
+ * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
+ * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
+ *
+ * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
+ * will have an exception (instead of an exploit.)
+ *
+ * @element ANY
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+
+ <example module="bindHtmlExample" deps="angular-sanitize.js">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p ng-bind-html="myHTML"></p>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('bindHtmlExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.myHTML =
+ 'I am an <code>HTML</code>string with ' +
+ '<a href="#">links!</a> and other <em>stuff</em>';
+ }]);
+ </file>
+
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind-html', function() {
+ expect(element(by.binding('myHTML')).getText()).toBe(
+ 'I am an HTMLstring with links! and other stuff');
+ });
+ </file>
+ </example>
+ */
+var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
+ return {
+ restrict: 'A',
+ compile: function ngBindHtmlCompile(tElement, tAttrs) {
+ var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
+ var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
+ return (value || '').toString();
+ });
+ $compile.$$addBindingClass(tElement);
+
+ return function ngBindHtmlLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBindHtml);
+
+ scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
+ // we re-evaluate the expr because we want a TrustedValueHolderType
+ // for $sce, not a string
+ element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
+ });
+ };
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngChange
+ *
+ * @description
+ * Evaluate the given expression when the user changes the input.
+ * The expression is evaluated immediately, unlike the JavaScript onchange event
+ * which only triggers at the end of a change (usually, when the user leaves the
+ * form element or presses the return key).
+ *
+ * The `ngChange` expression is only evaluated when a change in the input value causes
+ * a new value to be committed to the model.
+ *
+ * It will not be evaluated:
+ * * if the value returned from the `$parsers` transformation pipeline has not changed
+ * * if the input has continued to be invalid since the model will stay `null`
+ * * if the model is changed programmatically and not by a change to the input value
+ *
+ *
+ * Note, this directive requires `ngModel` to be present.
+ *
+ * @element input
+ * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
+ * in input value.
+ *
+ * @example
+ * <example name="ngChange-directive" module="changeExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('changeExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.counter = 0;
+ * $scope.change = function() {
+ * $scope.counter++;
+ * };
+ * }]);
+ * </script>
+ * <div ng-controller="ExampleController">
+ * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
+ * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
+ * <label for="ng-change-example2">Confirmed</label><br />
+ * <tt>debug = {{confirmed}}</tt><br/>
+ * <tt>counter = {{counter}}</tt><br/>
+ * </div>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var counter = element(by.binding('counter'));
+ * var debug = element(by.binding('confirmed'));
+ *
+ * it('should evaluate the expression if changing from view', function() {
+ * expect(counter.getText()).toContain('0');
+ *
+ * element(by.id('ng-change-example1')).click();
+ *
+ * expect(counter.getText()).toContain('1');
+ * expect(debug.getText()).toContain('true');
+ * });
+ *
+ * it('should not evaluate the expression if changing from model', function() {
+ * element(by.id('ng-change-example2')).click();
+
+ * expect(counter.getText()).toContain('0');
+ * expect(debug.getText()).toContain('true');
+ * });
+ * </file>
+ * </example>
+ */
+var ngChangeDirective = valueFn({
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ ctrl.$viewChangeListeners.push(function() {
+ scope.$eval(attr.ngChange);
+ });
+ }
+});
+
+function classDirective(name, selector) {
+ name = 'ngClass' + name;
+ return ['$animate', function($animate) {
+ return {
+ restrict: 'AC',
+ link: function(scope, element, attr) {
+ var oldVal;
+
+ scope.$watch(attr[name], ngClassWatchAction, true);
+
+ attr.$observe('class', function(value) {
+ ngClassWatchAction(scope.$eval(attr[name]));
+ });
+
+
+ if (name !== 'ngClass') {
+ scope.$watch('$index', function($index, old$index) {
+ // jshint bitwise: false
+ var mod = $index & 1;
+ if (mod !== (old$index & 1)) {
+ var classes = arrayClasses(scope.$eval(attr[name]));
+ mod === selector ?
+ addClasses(classes) :
+ removeClasses(classes);
+ }
+ });
+ }
+
+ function addClasses(classes) {
+ var newClasses = digestClassCounts(classes, 1);
+ attr.$addClass(newClasses);
+ }
+
+ function removeClasses(classes) {
+ var newClasses = digestClassCounts(classes, -1);
+ attr.$removeClass(newClasses);
+ }
+
+ function digestClassCounts(classes, count) {
+ var classCounts = element.data('$classCounts') || {};
+ var classesToUpdate = [];
+ forEach(classes, function(className) {
+ if (count > 0 || classCounts[className]) {
+ classCounts[className] = (classCounts[className] || 0) + count;
+ if (classCounts[className] === +(count > 0)) {
+ classesToUpdate.push(className);
+ }
+ }
+ });
+ element.data('$classCounts', classCounts);
+ return classesToUpdate.join(' ');
+ }
+
+ function updateClasses(oldClasses, newClasses) {
+ var toAdd = arrayDifference(newClasses, oldClasses);
+ var toRemove = arrayDifference(oldClasses, newClasses);
+ toAdd = digestClassCounts(toAdd, 1);
+ toRemove = digestClassCounts(toRemove, -1);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(element, toAdd);
+ }
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(element, toRemove);
+ }
+ }
+
+ function ngClassWatchAction(newVal) {
+ if (selector === true || scope.$index % 2 === selector) {
+ var newClasses = arrayClasses(newVal || []);
+ if (!oldVal) {
+ addClasses(newClasses);
+ } else if (!equals(newVal,oldVal)) {
+ var oldClasses = arrayClasses(oldVal);
+ updateClasses(oldClasses, newClasses);
+ }
+ }
+ oldVal = shallowCopy(newVal);
+ }
+ }
+ };
+
+ function arrayDifference(tokens1, tokens2) {
+ var values = [];
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values.push(token);
+ }
+ return values;
+ }
+
+ function arrayClasses(classVal) {
+ if (isArray(classVal)) {
+ return classVal;
+ } else if (isString(classVal)) {
+ return classVal.split(' ');
+ } else if (isObject(classVal)) {
+ var classes = [];
+ forEach(classVal, function(v, k) {
+ if (v) {
+ classes = classes.concat(k.split(' '));
+ }
+ });
+ return classes;
+ }
+ return classVal;
+ }
+ }];
+}
+
+/**
+ * @ngdoc directive
+ * @name ngClass
+ * @restrict AC
+ *
+ * @description
+ * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
+ * an expression that represents all classes to be added.
+ *
+ * The directive operates in three different ways, depending on which of three types the expression
+ * evaluates to:
+ *
+ * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
+ * names.
+ *
+ * 2. If the expression evaluates to an array, each element of the array should be a string that is
+ * one or more space-delimited class names.
+ *
+ * 3. If the expression evaluates to an object, then for each key-value pair of the
+ * object with a truthy value the corresponding key is used as a class name.
+ *
+ * The directive won't add duplicate classes if a particular class was already set.
+ *
+ * When the expression changes, the previously added classes are removed and only then the
+ * new classes are added.
+ *
+ * @animations
+ * **add** - happens just before the class is applied to the elements
+ *
+ * **remove** - happens just before the class is removed from the element
+ *
+ * @element ANY
+ * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class
+ * names, an array, or a map of class names to boolean values. In the case of a map, the
+ * names of the properties whose values are truthy will be added as css classes to the
+ * element.
+ *
+ * @example Example that demonstrates basic bindings via ngClass directive.
+ <example>
+ <file name="index.html">
+ <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
+ <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
+ <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
+ <input type="checkbox" ng-model="error"> error (apply "red" class)
+ <hr>
+ <p ng-class="style">Using String Syntax</p>
+ <input type="text" ng-model="style" placeholder="Type: bold strike red">
+ <hr>
+ <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
+ <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
+ <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
+ <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
+ </file>
+ <file name="style.css">
+ .strike {
+ text-decoration: line-through;
+ }
+ .bold {
+ font-weight: bold;
+ }
+ .red {
+ color: red;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var ps = element.all(by.css('p'));
+
+ it('should let you toggle the class', function() {
+
+ expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
+ expect(ps.first().getAttribute('class')).not.toMatch(/red/);
+
+ element(by.model('important')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/bold/);
+
+ element(by.model('error')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/red/);
+ });
+
+ it('should let you toggle string example', function() {
+ expect(ps.get(1).getAttribute('class')).toBe('');
+ element(by.model('style')).clear();
+ element(by.model('style')).sendKeys('red');
+ expect(ps.get(1).getAttribute('class')).toBe('red');
+ });
+
+ it('array example should have 3 classes', function() {
+ expect(ps.last().getAttribute('class')).toBe('');
+ element(by.model('style1')).sendKeys('bold');
+ element(by.model('style2')).sendKeys('strike');
+ element(by.model('style3')).sendKeys('red');
+ expect(ps.last().getAttribute('class')).toBe('bold strike red');
+ });
+ </file>
+ </example>
+
+ ## Animations
+
+ The example below demonstrates how to perform animations using ngClass.
+
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
+ <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
+ <br>
+ <span class="base-class" ng-class="myVar">Sample Text</span>
+ </file>
+ <file name="style.css">
+ .base-class {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .base-class.my-class {
+ color: red;
+ font-size:3em;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class', function() {
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+
+ element(by.id('setbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).
+ toMatch(/my-class/);
+
+ element(by.id('clearbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+ });
+ </file>
+ </example>
+
+
+ ## ngClass and pre-existing CSS3 Transitions/Animations
+ The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
+ Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
+ any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
+ to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and
+ {@link ng.$animate#removeClass $animate.removeClass}.
+ */
+var ngClassDirective = classDirective('', true);
+
+/**
+ * @ngdoc directive
+ * @name ngClassOdd
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}}
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassOddDirective = classDirective('Odd', 0);
+
+/**
+ * @ngdoc directive
+ * @name ngClassEven
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
+ * result of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}} &nbsp; &nbsp; &nbsp;
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassEvenDirective = classDirective('Even', 1);
+
+/**
+ * @ngdoc directive
+ * @name ngCloak
+ * @restrict AC
+ *
+ * @description
+ * The `ngCloak` directive is used to prevent the Angular html template from being briefly
+ * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
+ * directive to avoid the undesirable flicker effect caused by the html template display.
+ *
+ * The directive can be applied to the `<body>` element, but the preferred usage is to apply
+ * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
+ * of the browser view.
+ *
+ * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
+ * `angular.min.js`.
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```css
+ * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
+ * display: none !important;
+ * }
+ * ```
+ *
+ * When this css rule is loaded by the browser, all html elements (including their children) that
+ * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
+ * during the compilation of the template it deletes the `ngCloak` element attribute, making
+ * the compiled element visible.
+ *
+ * For the best result, the `angular.js` script must be loaded in the head section of the html
+ * document; alternatively, the css rule above must be included in the external stylesheet of the
+ * application.
+ *
+ * @element ANY
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div id="template1" ng-cloak>{{ 'hello' }}</div>
+ <div id="template2" class="ng-cloak">{{ 'world' }}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should remove the template directive and css class', function() {
+ expect($('#template1').getAttribute('ng-cloak')).
+ toBeNull();
+ expect($('#template2').getAttribute('ng-cloak')).
+ toBeNull();
+ });
+ </file>
+ </example>
+ *
+ */
+var ngCloakDirective = ngDirective({
+ compile: function(element, attr) {
+ attr.$set('ngCloak', undefined);
+ element.removeClass('ng-cloak');
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngController
+ *
+ * @description
+ * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
+ * supports the principles behind the Model-View-Controller design pattern.
+ *
+ * MVC components in angular:
+ *
+ * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
+ * are accessed through bindings.
+ * * View — The template (HTML with data bindings) that is rendered into the View.
+ * * Controller — The `ngController` directive specifies a Controller class; the class contains business
+ * logic behind the application to decorate the scope with functions and values
+ *
+ * Note that you can also attach controllers to the DOM by declaring it in a route definition
+ * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
+ * again using `ng-controller` in the template itself. This will cause the controller to be attached
+ * and executed twice.
+ *
+ * @element ANY
+ * @scope
+ * @priority 500
+ * @param {expression} ngController Name of a constructor function registered with the current
+ * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
+ * that on the current scope evaluates to a constructor function.
+ *
+ * The controller instance can be published into a scope property by specifying
+ * `ng-controller="as propertyName"`.
+ *
+ * If the current `$controllerProvider` is configured to use globals (via
+ * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
+ * also be the name of a globally accessible constructor function (not recommended).
+ *
+ * @example
+ * Here is a simple form for editing user contact information. Adding, removing, clearing, and
+ * greeting are methods declared on the controller (see source tab). These methods can
+ * easily be called from the angular markup. Any changes to the data are automatically reflected
+ * in the View without the need for a manual update.
+ *
+ * Two different declaration styles are included below:
+ *
+ * * one binds methods and properties directly onto the controller using `this`:
+ * `ng-controller="SettingsController1 as settings"`
+ * * one injects `$scope` into the controller:
+ * `ng-controller="SettingsController2"`
+ *
+ * The second option is more common in the Angular community, and is generally used in boilerplates
+ * and in this guide. However, there are advantages to binding properties directly to the controller
+ * and avoiding scope.
+ *
+ * * Using `controller as` makes it obvious which controller you are accessing in the template when
+ * multiple controllers apply to an element.
+ * * If you are writing your controllers as classes you have easier access to the properties and
+ * methods, which will appear on the scope, from inside the controller code.
+ * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
+ * inheritance masking primitives.
+ *
+ * This example demonstrates the `controller as` syntax.
+ *
+ * <example name="ngControllerAs" module="controllerAsExample">
+ * <file name="index.html">
+ * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
+ * Name: <input type="text" ng-model="settings.name"/>
+ * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in settings.contacts">
+ * <select ng-model="contact.type">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value"/>
+ * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
+ * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
+ * </li>
+ * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerAsExample', [])
+ * .controller('SettingsController1', SettingsController1);
+ *
+ * function SettingsController1() {
+ * this.name = "John Smith";
+ * this.contacts = [
+ * {type: 'phone', value: '408 555 1212'},
+ * {type: 'email', value: 'john.smith@example.org'} ];
+ * }
+ *
+ * SettingsController1.prototype.greet = function() {
+ * alert(this.name);
+ * };
+ *
+ * SettingsController1.prototype.addContact = function() {
+ * this.contacts.push({type: 'email', value: 'yourname@example.org'});
+ * };
+ *
+ * SettingsController1.prototype.removeContact = function(contactToRemove) {
+ * var index = this.contacts.indexOf(contactToRemove);
+ * this.contacts.splice(index, 1);
+ * };
+ *
+ * SettingsController1.prototype.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller as', function() {
+ * var container = element(by.id('ctrl-as-exmpl'));
+ * expect(container.element(by.model('settings.name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ *
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.linkText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.linkText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in settings.contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ * </example>
+ *
+ * This example demonstrates the "attach to `$scope`" style of controller.
+ *
+ * <example name="ngController" module="controllerExample">
+ * <file name="index.html">
+ * <div id="ctrl-exmpl" ng-controller="SettingsController2">
+ * Name: <input type="text" ng-model="name"/>
+ * [ <a href="" ng-click="greet()">greet</a> ]<br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <select ng-model="contact.type">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value"/>
+ * [ <a href="" ng-click="clearContact(contact)">clear</a>
+ * | <a href="" ng-click="removeContact(contact)">X</a> ]
+ * </li>
+ * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerExample', [])
+ * .controller('SettingsController2', ['$scope', SettingsController2]);
+ *
+ * function SettingsController2($scope) {
+ * $scope.name = "John Smith";
+ * $scope.contacts = [
+ * {type:'phone', value:'408 555 1212'},
+ * {type:'email', value:'john.smith@example.org'} ];
+ *
+ * $scope.greet = function() {
+ * alert($scope.name);
+ * };
+ *
+ * $scope.addContact = function() {
+ * $scope.contacts.push({type:'email', value:'yourname@example.org'});
+ * };
+ *
+ * $scope.removeContact = function(contactToRemove) {
+ * var index = $scope.contacts.indexOf(contactToRemove);
+ * $scope.contacts.splice(index, 1);
+ * };
+ *
+ * $scope.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * }
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller', function() {
+ * var container = element(by.id('ctrl-exmpl'));
+ *
+ * expect(container.element(by.model('name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.linkText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.linkText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ *</example>
+
+ */
+var ngControllerDirective = [function() {
+ return {
+ restrict: 'A',
+ scope: true,
+ controller: '@',
+ priority: 500
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngCsp
+ *
+ * @element html
+ * @description
+ * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
+ *
+ * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
+ *
+ * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
+ * For Angular to be CSP compatible there are only two things that we need to do differently:
+ *
+ * - don't use `Function` constructor to generate optimized value getters
+ * - don't inject custom stylesheet into the document
+ *
+ * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
+ * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
+ * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
+ * be raised.
+ *
+ * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
+ * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
+ * To make those directives work in CSP mode, include the `angular-csp.css` manually.
+ *
+ * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
+ * autodetection however triggers a CSP error to be logged in the console:
+ *
+ * ```
+ * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
+ * script in the following Content Security Policy directive: "default-src 'self'". Note that
+ * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
+ * ```
+ *
+ * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
+ * directive on the root element of the application or on the `angular.js` script tag, whichever
+ * appears first in the html document.
+ *
+ * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
+ *
+ * @example
+ * This example shows how to apply the `ngCsp` directive to the `html` tag.
+ ```html
+ <!doctype html>
+ <html ng-app ng-csp>
+ ...
+ ...
+ </html>
+ ```
+ * @example
+ // Note: the suffix `.csp` in the example name triggers
+ // csp mode in our http server!
+ <example name="example.csp" module="cspExample" ng-csp="true">
+ <file name="index.html">
+ <div ng-controller="MainController as ctrl">
+ <div>
+ <button ng-click="ctrl.inc()" id="inc">Increment</button>
+ <span id="counter">
+ {{ctrl.counter}}
+ </span>
+ </div>
+
+ <div>
+ <button ng-click="ctrl.evil()" id="evil">Evil</button>
+ <span id="evilError">
+ {{ctrl.evilError}}
+ </span>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cspExample', [])
+ .controller('MainController', function() {
+ this.counter = 0;
+ this.inc = function() {
+ this.counter++;
+ };
+ this.evil = function() {
+ // jshint evil:true
+ try {
+ eval('1+2');
+ } catch (e) {
+ this.evilError = e.message;
+ }
+ };
+ });
+ </file>
+ <file name="protractor.js" type="protractor">
+ var util, webdriver;
+
+ var incBtn = element(by.id('inc'));
+ var counter = element(by.id('counter'));
+ var evilBtn = element(by.id('evil'));
+ var evilError = element(by.id('evilError'));
+
+ function getAndClearSevereErrors() {
+ return browser.manage().logs().get('browser').then(function(browserLog) {
+ return browserLog.filter(function(logEntry) {
+ return logEntry.level.value > webdriver.logging.Level.WARNING.value;
+ });
+ });
+ }
+
+ function clearErrors() {
+ getAndClearSevereErrors();
+ }
+
+ function expectNoErrors() {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ expect(filteredLog.length).toEqual(0);
+ if (filteredLog.length) {
+ console.log('browser console errors: ' + util.inspect(filteredLog));
+ }
+ });
+ }
+
+ function expectError(regex) {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ var found = false;
+ filteredLog.forEach(function(log) {
+ if (log.message.match(regex)) {
+ found = true;
+ }
+ });
+ if (!found) {
+ throw new Error('expected an error that matches ' + regex);
+ }
+ });
+ }
+
+ beforeEach(function() {
+ util = require('util');
+ webdriver = require('protractor/node_modules/selenium-webdriver');
+ });
+
+ // For now, we only test on Chrome,
+ // as Safari does not load the page with Protractor's injected scripts,
+ // and Firefox webdriver always disables content security policy (#6358)
+ if (browser.params.browser !== 'chrome') {
+ return;
+ }
+
+ it('should not report errors when the page is loaded', function() {
+ // clear errors so we are not dependent on previous tests
+ clearErrors();
+ // Need to reload the page as the page is already loaded when
+ // we come here
+ browser.driver.getCurrentUrl().then(function(url) {
+ browser.get(url);
+ });
+ expectNoErrors();
+ });
+
+ it('should evaluate expressions', function() {
+ expect(counter.getText()).toEqual('0');
+ incBtn.click();
+ expect(counter.getText()).toEqual('1');
+ expectNoErrors();
+ });
+
+ it('should throw and report an error when using "eval"', function() {
+ evilBtn.click();
+ expect(evilError.getText()).toMatch(/Content Security Policy/);
+ expectError(/Content Security Policy/);
+ });
+ </file>
+ </example>
+ */
+
+// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
+// bootstrap the system (before $parse is instantiated), for this reason we just have
+// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
+
+/**
+ * @ngdoc directive
+ * @name ngClick
+ *
+ * @description
+ * The ngClick directive allows you to specify custom behavior when
+ * an element is clicked.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
+ * click. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-click="count = count + 1" ng-init="count=0">
+ Increment
+ </button>
+ <span>
+ count: {{count}}
+ </span>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-click', function() {
+ expect(element(by.binding('count')).getText()).toMatch('0');
+ element(by.css('button')).click();
+ expect(element(by.binding('count')).getText()).toMatch('1');
+ });
+ </file>
+ </example>
+ */
+/*
+ * A collection of directives that allows creation of custom event handlers that are defined as
+ * angular expressions and are compiled and executed within the current scope.
+ */
+var ngEventDirectives = {};
+
+// For events that might fire synchronously during DOM manipulation
+// we need to execute their event handlers asynchronously using $evalAsync,
+// so that they are not executed in an inconsistent state.
+var forceAsyncEvents = {
+ 'blur': true,
+ 'focus': true
+};
+forEach(
+ 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
+ function(eventName) {
+ var directiveName = directiveNormalize('ng-' + eventName);
+ ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
+ return {
+ restrict: 'A',
+ compile: function($element, attr) {
+ // We expose the powerful $event object on the scope that provides access to the Window,
+ // etc. that isn't protected by the fast paths in $parse. We explicitly request better
+ // checks at the cost of speed since event handler expressions are not executed as
+ // frequently as regular change detection.
+ var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
+ return function ngEventHandler(scope, element) {
+ element.on(eventName, function(event) {
+ var callback = function() {
+ fn(scope, {$event:event});
+ };
+ if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
+ scope.$evalAsync(callback);
+ } else {
+ scope.$apply(callback);
+ }
+ });
+ };
+ }
+ };
+ }];
+ }
+);
+
+/**
+ * @ngdoc directive
+ * @name ngDblclick
+ *
+ * @description
+ * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
+ * a dblclick. (The Event object is available as `$event`)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-dblclick="count = count + 1" ng-init="count=0">
+ Increment (on double click)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousedown
+ *
+ * @description
+ * The ngMousedown directive allows you to specify custom behavior on mousedown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
+ * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousedown="count = count + 1" ng-init="count=0">
+ Increment (on mouse down)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseup
+ *
+ * @description
+ * Specify custom behavior on mouseup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
+ * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseup="count = count + 1" ng-init="count=0">
+ Increment (on mouse up)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngMouseover
+ *
+ * @description
+ * Specify custom behavior on mouseover event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
+ * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseover="count = count + 1" ng-init="count=0">
+ Increment (when mouse is over)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseenter
+ *
+ * @description
+ * Specify custom behavior on mouseenter event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
+ * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseenter="count = count + 1" ng-init="count=0">
+ Increment (when mouse enters)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseleave
+ *
+ * @description
+ * Specify custom behavior on mouseleave event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
+ * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseleave="count = count + 1" ng-init="count=0">
+ Increment (when mouse leaves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousemove
+ *
+ * @description
+ * Specify custom behavior on mousemove event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
+ * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousemove="count = count + 1" ng-init="count=0">
+ Increment (when mouse moves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeydown
+ *
+ * @description
+ * Specify custom behavior on keydown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
+ * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keydown="count = count + 1" ng-init="count=0">
+ key down count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeyup
+ *
+ * @description
+ * Specify custom behavior on keyup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
+ * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <p>Typing in the input box below updates the key count</p>
+ <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
+
+ <p>Typing in the input box below updates the keycode</p>
+ <input ng-keyup="event=$event">
+ <p>event keyCode: {{ event.keyCode }}</p>
+ <p>event altKey: {{ event.altKey }}</p>
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeypress
+ *
+ * @description
+ * Specify custom behavior on keypress event.
+ *
+ * @element ANY
+ * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
+ * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
+ * and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keypress="count = count + 1" ng-init="count=0">
+ key press count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSubmit
+ *
+ * @description
+ * Enables binding angular expressions to onsubmit events.
+ *
+ * Additionally it prevents the default action (which for form means sending the request to the
+ * server and reloading the current page), but only if the form does not contain `action`,
+ * `data-action`, or `x-action` attributes.
+ *
+ * <div class="alert alert-warning">
+ * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
+ * `ngSubmit` handlers together. See the
+ * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
+ * for a detailed discussion of when `ngSubmit` may be triggered.
+ * </div>
+ *
+ * @element form
+ * @priority 0
+ * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
+ * ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example module="submitExample">
+ <file name="index.html">
+ <script>
+ angular.module('submitExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [];
+ $scope.text = 'hello';
+ $scope.submit = function() {
+ if ($scope.text) {
+ $scope.list.push(this.text);
+ $scope.text = '';
+ }
+ };
+ }]);
+ </script>
+ <form ng-submit="submit()" ng-controller="ExampleController">
+ Enter text and hit enter:
+ <input type="text" ng-model="text" name="text" />
+ <input type="submit" id="submit" value="Submit" />
+ <pre>list={{list}}</pre>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-submit', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ expect(element(by.model('text')).getAttribute('value')).toBe('');
+ });
+ it('should ignore empty strings', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngFocus
+ *
+ * @description
+ * Specify custom behavior on focus event.
+ *
+ * Note: As the `focus` event is executed synchronously when calling `input.focus()`
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
+ * focus. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngBlur
+ *
+ * @description
+ * Specify custom behavior on blur event.
+ *
+ * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
+ * an element has lost focus.
+ *
+ * Note: As the `blur` event is executed synchronously also during DOM manipulations
+ * (e.g. removing a focussed input),
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
+ * blur. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCopy
+ *
+ * @description
+ * Specify custom behavior on copy event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
+ * copy. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
+ copied: {{copied}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCut
+ *
+ * @description
+ * Specify custom behavior on cut event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
+ * cut. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
+ cut: {{cut}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngPaste
+ *
+ * @description
+ * Specify custom behavior on paste event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
+ * paste. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
+ pasted: {{paste}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngIf
+ * @restrict A
+ *
+ * @description
+ * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
+ * {expression}. If the expression assigned to `ngIf` evaluates to a false
+ * value then the element is removed from the DOM, otherwise a clone of the
+ * element is reinserted into the DOM.
+ *
+ * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
+ * element in the DOM rather than changing its visibility via the `display` css property. A common
+ * case when this difference is significant is when using css selectors that rely on an element's
+ * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
+ *
+ * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
+ * is created when the element is restored. The scope created within `ngIf` inherits from
+ * its parent scope using
+ * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
+ * An important implication of this is if `ngModel` is used within `ngIf` to bind to
+ * a javascript primitive defined in the parent scope. In this case any modifications made to the
+ * variable within the child scope will override (hide) the value in the parent scope.
+ *
+ * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
+ * is if an element's class attribute is directly modified after it's compiled, using something like
+ * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
+ * the added class will be lost because the original compiled state is used to regenerate the element.
+ *
+ * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
+ * and `leave` effects.
+ *
+ * @animations
+ * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
+ * leave - happens just before the `ngIf` contents are removed from the DOM
+ *
+ * @element ANY
+ * @scope
+ * @priority 600
+ * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
+ * the element is removed from the DOM tree. If it is truthy a copy of the compiled
+ * element is added to the DOM tree.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
+ Show when checked:
+ <span ng-if="checked" class="animate-if">
+ This is removed when the checkbox is unchecked.
+ </span>
+ </file>
+ <file name="animations.css">
+ .animate-if {
+ background:white;
+ border:1px solid black;
+ padding:10px;
+ }
+
+ .animate-if.ng-enter, .animate-if.ng-leave {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .animate-if.ng-enter,
+ .animate-if.ng-leave.ng-leave-active {
+ opacity:0;
+ }
+
+ .animate-if.ng-leave,
+ .animate-if.ng-enter.ng-enter-active {
+ opacity:1;
+ }
+ </file>
+ </example>
+ */
+var ngIfDirective = ['$animate', function($animate) {
+ return {
+ multiElement: true,
+ transclude: 'element',
+ priority: 600,
+ terminal: true,
+ restrict: 'A',
+ $$tlb: true,
+ link: function($scope, $element, $attr, ctrl, $transclude) {
+ var block, childScope, previousElements;
+ $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
+
+ if (value) {
+ if (!childScope) {
+ $transclude(function(clone, newScope) {
+ childScope = newScope;
+ clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block = {
+ clone: clone
+ };
+ $animate.enter(clone, $element.parent(), $element);
+ });
+ }
+ } else {
+ if (previousElements) {
+ previousElements.remove();
+ previousElements = null;
+ }
+ if (childScope) {
+ childScope.$destroy();
+ childScope = null;
+ }
+ if (block) {
+ previousElements = getBlockNodes(block.clone);
+ $animate.leave(previousElements).then(function() {
+ previousElements = null;
+ });
+ block = null;
+ }
+ }
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngInclude
+ * @restrict ECA
+ *
+ * @description
+ * Fetches, compiles and includes an external HTML fragment.
+ *
+ * By default, the template URL is restricted to the same domain and protocol as the
+ * application document. This is done by calling {@link $sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
+ * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
+ * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
+ * ng.$sce Strict Contextual Escaping}.
+ *
+ * In addition, the browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy may further restrict whether the template is successfully loaded.
+ * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
+ * access on some browsers.
+ *
+ * @animations
+ * enter - animation is used to bring new content into the browser.
+ * leave - animation is used to animate existing content away.
+ *
+ * The enter and leave animation occur concurrently.
+ *
+ * @scope
+ * @priority 400
+ *
+ * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
+ * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
+ * @param {string=} onload Expression to evaluate when a new partial is loaded.
+ *
+ * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
+ * $anchorScroll} to scroll the viewport after the content is loaded.
+ *
+ * - If the attribute is not set, disable scrolling.
+ * - If the attribute is set without value, enable scrolling.
+ * - Otherwise enable scrolling only if the expression evaluates to truthy value.
+ *
+ * @example
+ <example module="includeExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="template" ng-options="t.name for t in templates">
+ <option value="">(blank)</option>
+ </select>
+ url of the template: <code>{{template.url}}</code>
+ <hr/>
+ <div class="slide-animate-container">
+ <div class="slide-animate" ng-include="template.url"></div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('includeExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.templates =
+ [ { name: 'template1.html', url: 'template1.html'},
+ { name: 'template2.html', url: 'template2.html'} ];
+ $scope.template = $scope.templates[0];
+ }]);
+ </file>
+ <file name="template1.html">
+ Content of template1.html
+ </file>
+ <file name="template2.html">
+ Content of template2.html
+ </file>
+ <file name="animations.css">
+ .slide-animate-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .slide-animate {
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter, .slide-animate.ng-leave {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ display:block;
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter {
+ top:-50px;
+ }
+ .slide-animate.ng-enter.ng-enter-active {
+ top:0;
+ }
+
+ .slide-animate.ng-leave {
+ top:0;
+ }
+ .slide-animate.ng-leave.ng-leave-active {
+ top:50px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var templateSelect = element(by.model('template'));
+ var includeElem = element(by.css('[ng-include]'));
+
+ it('should load template1.html', function() {
+ expect(includeElem.getText()).toMatch(/Content of template1.html/);
+ });
+
+ it('should load template2.html', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ // See https://github.com/angular/protractor/issues/480
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(2).click();
+ expect(includeElem.getText()).toMatch(/Content of template2.html/);
+ });
+
+ it('should change to blank', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(0).click();
+ expect(includeElem.isPresent()).toBe(false);
+ });
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentRequested
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted every time the ngInclude content is requested.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentLoaded
+ * @eventType emit on the current ngInclude scope
+ * @description
+ * Emitted every time the ngInclude content is reloaded.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentError
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
+ function($templateRequest, $anchorScroll, $animate) {
+ return {
+ restrict: 'ECA',
+ priority: 400,
+ terminal: true,
+ transclude: 'element',
+ controller: angular.noop,
+ compile: function(element, attr) {
+ var srcExp = attr.ngInclude || attr.src,
+ onloadExp = attr.onload || '',
+ autoScrollExp = attr.autoscroll;
+
+ return function(scope, $element, $attr, ctrl, $transclude) {
+ var changeCounter = 0,
+ currentScope,
+ previousElement,
+ currentElement;
+
+ var cleanupLastIncludeContent = function() {
+ if (previousElement) {
+ previousElement.remove();
+ previousElement = null;
+ }
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ if (currentElement) {
+ $animate.leave(currentElement).then(function() {
+ previousElement = null;
+ });
+ previousElement = currentElement;
+ currentElement = null;
+ }
+ };
+
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
+ var afterAnimation = function() {
+ if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
+ $anchorScroll();
+ }
+ };
+ var thisChangeId = ++changeCounter;
+
+ if (src) {
+ //set the 2nd param to true to ignore the template request error so that the inner
+ //contents and scope can be cleaned up.
+ $templateRequest(src, true).then(function(response) {
+ if (thisChangeId !== changeCounter) return;
+ var newScope = scope.$new();
+ ctrl.template = response;
+
+ // Note: This will also link all children of ng-include that were contained in the original
+ // html. If that content contains controllers, ... they could pollute/change the scope.
+ // However, using ng-include on an element with additional content does not make sense...
+ // Note: We can't remove them in the cloneAttchFn of $transclude as that
+ // function is called before linking the content, which would apply child
+ // directives to non existing elements.
+ var clone = $transclude(newScope, function(clone) {
+ cleanupLastIncludeContent();
+ $animate.enter(clone, null, $element).then(afterAnimation);
+ });
+
+ currentScope = newScope;
+ currentElement = clone;
+
+ currentScope.$emit('$includeContentLoaded', src);
+ scope.$eval(onloadExp);
+ }, function() {
+ if (thisChangeId === changeCounter) {
+ cleanupLastIncludeContent();
+ scope.$emit('$includeContentError', src);
+ }
+ });
+ scope.$emit('$includeContentRequested', src);
+ } else {
+ cleanupLastIncludeContent();
+ ctrl.template = null;
+ }
+ });
+ };
+ }
+ };
+}];
+
+// This directive is called during the $transclude call of the first `ngInclude` directive.
+// It will replace and compile the content of the element with the loaded template.
+// We need this directive so that the element content is already filled when
+// the link function of another directive on the same element as ngInclude
+// is called.
+var ngIncludeFillContentDirective = ['$compile',
+ function($compile) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ require: 'ngInclude',
+ link: function(scope, $element, $attr, ctrl) {
+ if (/SVG/.test($element[0].toString())) {
+ // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
+ // support innerHTML, so detect this here and try to generate the contents
+ // specially.
+ $element.empty();
+ $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
+ function namespaceAdaptedClone(clone) {
+ $element.append(clone);
+ }, {futureParentElement: $element});
+ return;
+ }
+
+ $element.html(ctrl.template);
+ $compile($element.contents())(scope);
+ }
+ };
+ }];
+
+/**
+ * @ngdoc directive
+ * @name ngInit
+ * @restrict AC
+ *
+ * @description
+ * The `ngInit` directive allows you to evaluate an expression in the
+ * current scope.
+ *
+ * <div class="alert alert-error">
+ * The only appropriate use of `ngInit` is for aliasing special properties of
+ * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
+ * should use {@link guide/controller controllers} rather than `ngInit`
+ * to initialize values on a scope.
+ * </div>
+ * <div class="alert alert-warning">
+ * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
+ * sure you have parenthesis for correct precedence:
+ * <pre class="prettyprint">
+ * `<div ng-init="test1 = (data | orderBy:'name')"></div>`
+ * </pre>
+ * </div>
+ *
+ * @priority 450
+ *
+ * @element ANY
+ * @param {expression} ngInit {@link guide/expression Expression} to eval.
+ *
+ * @example
+ <example module="initExample">
+ <file name="index.html">
+ <script>
+ angular.module('initExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [['a', 'b'], ['c', 'd']];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
+ <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
+ <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
+ </div>
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should alias index positions', function() {
+ var elements = element.all(by.css('.example-init'));
+ expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
+ expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
+ expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
+ expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
+ });
+ </file>
+ </example>
+ */
+var ngInitDirective = ngDirective({
+ priority: 450,
+ compile: function() {
+ return {
+ pre: function(scope, element, attrs) {
+ scope.$eval(attrs.ngInit);
+ }
+ };
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngList
+ *
+ * @description
+ * Text input that converts between a delimited string and an array of strings. The default
+ * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
+ * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
+ *
+ * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
+ * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
+ * list item is respected. This implies that the user of the directive is responsible for
+ * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
+ * tab or newline character.
+ * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
+ * when joining the list items back together) and whitespace around each list item is stripped
+ * before it is added to the model.
+ *
+ * ### Example with Validation
+ *
+ * <example name="ngList-directive" module="listExample">
+ * <file name="app.js">
+ * angular.module('listExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.names = ['morpheus', 'neo', 'trinity'];
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <form name="myForm" ng-controller="ExampleController">
+ * List: <input name="namesInput" ng-model="names" ng-list required>
+ * <span class="error" ng-show="myForm.namesInput.$error.required">
+ * Required!</span>
+ * <br>
+ * <tt>names = {{names}}</tt><br/>
+ * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
+ * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
+ * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ * </form>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var listInput = element(by.model('names'));
+ * var names = element(by.exactBinding('names'));
+ * var valid = element(by.binding('myForm.namesInput.$valid'));
+ * var error = element(by.css('span.error'));
+ *
+ * it('should initialize to model', function() {
+ * expect(names.getText()).toContain('["morpheus","neo","trinity"]');
+ * expect(valid.getText()).toContain('true');
+ * expect(error.getCssValue('display')).toBe('none');
+ * });
+ *
+ * it('should be invalid if empty', function() {
+ * listInput.clear();
+ * listInput.sendKeys('');
+ *
+ * expect(names.getText()).toContain('');
+ * expect(valid.getText()).toContain('false');
+ * expect(error.getCssValue('display')).not.toBe('none');
+ * });
+ * </file>
+ * </example>
+ *
+ * ### Example - splitting on whitespace
+ * <example name="ngList-directive-newlines">
+ * <file name="index.html">
+ * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
+ * <pre>{{ list | json }}</pre>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it("should split the text by newlines", function() {
+ * var listInput = element(by.model('list'));
+ * var output = element(by.binding('list | json'));
+ * listInput.sendKeys('abc\ndef\nghi');
+ * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]');
+ * });
+ * </file>
+ * </example>
+ *
+ * @element input
+ * @param {string=} ngList optional delimiter that should be used to split the value.
+ */
+var ngListDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ // We want to control whitespace trimming so we use this convoluted approach
+ // to access the ngList attribute, which doesn't pre-trim the attribute
+ var ngList = element.attr(attr.$attr.ngList) || ', ';
+ var trimValues = attr.ngTrim !== 'false';
+ var separator = trimValues ? trim(ngList) : ngList;
+
+ var parse = function(viewValue) {
+ // If the viewValue is invalid (say required but empty) it will be `undefined`
+ if (isUndefined(viewValue)) return;
+
+ var list = [];
+
+ if (viewValue) {
+ forEach(viewValue.split(separator), function(value) {
+ if (value) list.push(trimValues ? trim(value) : value);
+ });
+ }
+
+ return list;
+ };
+
+ ctrl.$parsers.push(parse);
+ ctrl.$formatters.push(function(value) {
+ if (isArray(value)) {
+ return value.join(ngList);
+ }
+
+ return undefined;
+ });
+
+ // Override the standard $isEmpty because an empty array means the input is empty.
+ ctrl.$isEmpty = function(value) {
+ return !value || !value.length;
+ };
+ }
+ };
+};
+
+/* global VALID_CLASS: true,
+ INVALID_CLASS: true,
+ PRISTINE_CLASS: true,
+ DIRTY_CLASS: true,
+ UNTOUCHED_CLASS: true,
+ TOUCHED_CLASS: true,
+*/
+
+var VALID_CLASS = 'ng-valid',
+ INVALID_CLASS = 'ng-invalid',
+ PRISTINE_CLASS = 'ng-pristine',
+ DIRTY_CLASS = 'ng-dirty',
+ UNTOUCHED_CLASS = 'ng-untouched',
+ TOUCHED_CLASS = 'ng-touched',
+ PENDING_CLASS = 'ng-pending';
+
+var ngModelMinErr = minErr('ngModel');
+
+/**
+ * @ngdoc type
+ * @name ngModel.NgModelController
+ *
+ * @property {string} $viewValue Actual string value in the view.
+ * @property {*} $modelValue The value in the model that the control is bound to.
+ * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
+ the control reads value from the DOM. The functions are called in array order, each passing
+ its return value through to the next. The last return value is forwarded to the
+ {@link ngModel.NgModelController#$validators `$validators`} collection.
+
+Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
+`$viewValue`}.
+
+Returning `undefined` from a parser means a parse error occurred. In that case,
+no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
+will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
+is set to `true`. The parse error is stored in `ngModel.$error.parse`.
+
+ *
+ * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
+ the model value changes. The functions are called in reverse array order, each passing the value through to the
+ next. The last return value is used as the actual DOM value.
+ Used to format / convert values for display in the control.
+ * ```js
+ * function formatter(value) {
+ * if (value) {
+ * return value.toUpperCase();
+ * }
+ * }
+ * ngModel.$formatters.push(formatter);
+ * ```
+ *
+ * @property {Object.<string, function>} $validators A collection of validators that are applied
+ * whenever the model value changes. The key value within the object refers to the name of the
+ * validator while the function refers to the validation operation. The validation operation is
+ * provided with the model value as an argument and must return a true or false value depending
+ * on the response of that validation.
+ *
+ * ```js
+ * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ * return /[0-9]+/.test(value) &&
+ * /[a-z]+/.test(value) &&
+ * /[A-Z]+/.test(value) &&
+ * /\W+/.test(value);
+ * };
+ * ```
+ *
+ * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
+ * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
+ * is expected to return a promise when it is run during the model validation process. Once the promise
+ * is delivered then the validation status will be set to true when fulfilled and false when rejected.
+ * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
+ * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
+ * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
+ * will only run once all synchronous validators have passed.
+ *
+ * Please note that if $http is used then it is important that the server returns a success HTTP response code
+ * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
+ *
+ * ```js
+ * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ *
+ * // Lookup user by username
+ * return $http.get('/api/users/' + value).
+ * then(function resolved() {
+ * //username exists, this means validation fails
+ * return $q.reject('exists');
+ * }, function rejected() {
+ * //username does not exist, therefore this validation passes
+ * return true;
+ * });
+ * };
+ * ```
+ *
+ * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
+ * view value has changed. It is called with no arguments, and its return value is ignored.
+ * This can be used in place of additional $watches against the model value.
+ *
+ * @property {Object} $error An object hash with all failing validator ids as keys.
+ * @property {Object} $pending An object hash with all pending validator ids as keys.
+ *
+ * @property {boolean} $untouched True if control has not lost focus yet.
+ * @property {boolean} $touched True if control has lost focus.
+ * @property {boolean} $pristine True if user has not interacted with the control yet.
+ * @property {boolean} $dirty True if user has already interacted with the control.
+ * @property {boolean} $valid True if there is no error.
+ * @property {boolean} $invalid True if at least one error on the control.
+ * @property {string} $name The name attribute of the control.
+ *
+ * @description
+ *
+ * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
+ * The controller contains services for data-binding, validation, CSS updates, and value formatting
+ * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
+ * listening to DOM events.
+ * Such DOM related logic should be provided by other directives which make use of
+ * `NgModelController` for data-binding to control elements.
+ * Angular provides this DOM logic for most {@link input `input`} elements.
+ * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
+ * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
+ *
+ * @example
+ * ### Custom Control Example
+ * This example shows how to use `NgModelController` with a custom control to achieve
+ * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
+ * collaborate together to achieve the desired result.
+ *
+ * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
+ * contents be edited in place by the user.
+ *
+ * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
+ * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
+ * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
+ * that content using the `$sce` service.
+ *
+ * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
+ <file name="style.css">
+ [contenteditable] {
+ border: 1px solid black;
+ background-color: white;
+ min-height: 20px;
+ }
+
+ .ng-invalid {
+ border: 1px solid red;
+ }
+
+ </file>
+ <file name="script.js">
+ angular.module('customControl', ['ngSanitize']).
+ directive('contenteditable', ['$sce', function($sce) {
+ return {
+ restrict: 'A', // only activate on element attribute
+ require: '?ngModel', // get a hold of NgModelController
+ link: function(scope, element, attrs, ngModel) {
+ if (!ngModel) return; // do nothing if no ng-model
+
+ // Specify how UI should be updated
+ ngModel.$render = function() {
+ element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
+ };
+
+ // Listen for change events to enable binding
+ element.on('blur keyup change', function() {
+ scope.$evalAsync(read);
+ });
+ read(); // initialize
+
+ // Write data to the model
+ function read() {
+ var html = element.html();
+ // When we clear the content editable the browser leaves a <br> behind
+ // If strip-br attribute is provided then we strip this out
+ if ( attrs.stripBr && html == '<br>' ) {
+ html = '';
+ }
+ ngModel.$setViewValue(html);
+ }
+ }
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <form name="myForm">
+ <div contenteditable
+ name="myWidget" ng-model="userContent"
+ strip-br="true"
+ required>Change me!</div>
+ <span ng-show="myForm.myWidget.$error.required">Required!</span>
+ <hr>
+ <textarea ng-model="userContent"></textarea>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should data-bind and become invalid', function() {
+ if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
+ // SafariDriver can't handle contenteditable
+ // and Firefox driver can't clear contenteditables very well
+ return;
+ }
+ var contentEditable = element(by.css('[contenteditable]'));
+ var content = 'Change me!';
+
+ expect(contentEditable.getText()).toEqual(content);
+
+ contentEditable.clear();
+ contentEditable.sendKeys(protractor.Key.BACK_SPACE);
+ expect(contentEditable.getText()).toEqual('');
+ expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
+ });
+ </file>
+ * </example>
+ *
+ *
+ */
+var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
+ function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
+ this.$viewValue = Number.NaN;
+ this.$modelValue = Number.NaN;
+ this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
+ this.$validators = {};
+ this.$asyncValidators = {};
+ this.$parsers = [];
+ this.$formatters = [];
+ this.$viewChangeListeners = [];
+ this.$untouched = true;
+ this.$touched = false;
+ this.$pristine = true;
+ this.$dirty = false;
+ this.$valid = true;
+ this.$invalid = false;
+ this.$error = {}; // keep invalid keys here
+ this.$$success = {}; // keep valid keys here
+ this.$pending = undefined; // keep pending keys here
+ this.$name = $interpolate($attr.name || '', false)($scope);
+
+
+ var parsedNgModel = $parse($attr.ngModel),
+ parsedNgModelAssign = parsedNgModel.assign,
+ ngModelGet = parsedNgModel,
+ ngModelSet = parsedNgModelAssign,
+ pendingDebounce = null,
+ parserValid,
+ ctrl = this;
+
+ this.$$setOptions = function(options) {
+ ctrl.$options = options;
+ if (options && options.getterSetter) {
+ var invokeModelGetter = $parse($attr.ngModel + '()'),
+ invokeModelSetter = $parse($attr.ngModel + '($$$p)');
+
+ ngModelGet = function($scope) {
+ var modelValue = parsedNgModel($scope);
+ if (isFunction(modelValue)) {
+ modelValue = invokeModelGetter($scope);
+ }
+ return modelValue;
+ };
+ ngModelSet = function($scope, newValue) {
+ if (isFunction(parsedNgModel($scope))) {
+ invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
+ } else {
+ parsedNgModelAssign($scope, ctrl.$modelValue);
+ }
+ };
+ } else if (!parsedNgModel.assign) {
+ throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
+ $attr.ngModel, startingTag($element));
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$render
+ *
+ * @description
+ * Called when the view needs to be updated. It is expected that the user of the ng-model
+ * directive will implement this method.
+ *
+ * The `$render()` method is invoked in the following situations:
+ *
+ * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
+ * committed value then `$render()` is called to update the input control.
+ * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
+ * the `$viewValue` are different to last time.
+ *
+ * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
+ * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`
+ * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
+ * invoked if you only change a property on the objects.
+ */
+ this.$render = noop;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$isEmpty
+ *
+ * @description
+ * This is called when we need to determine if the value of an input is empty.
+ *
+ * For instance, the required directive does this to work out if the input has data or not.
+ *
+ * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
+ *
+ * You can override this for input directives whose concept of being empty is different to the
+ * default. The `checkboxInputType` directive does this because in its case a value of `false`
+ * implies empty.
+ *
+ * @param {*} value The value of the input to check for emptiness.
+ * @returns {boolean} True if `value` is "empty".
+ */
+ this.$isEmpty = function(value) {
+ return isUndefined(value) || value === '' || value === null || value !== value;
+ };
+
+ var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
+ currentValidationRunId = 0;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setValidity
+ *
+ * @description
+ * Change the validity state, and notify the form.
+ *
+ * This method can be called within $parsers/$formatters or a custom validation implementation.
+ * However, in most cases it should be sufficient to use the `ngModel.$validators` and
+ * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
+ *
+ * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
+ * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
+ * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
+ * The `validationErrorKey` should be in camelCase and will get converted into dash-case
+ * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
+ * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
+ * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
+ * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
+ * Skipped is used by Angular when validators do not run because of parse errors and
+ * when `$asyncValidators` do not run because any of the `$validators` failed.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: $element,
+ set: function(object, property) {
+ object[property] = true;
+ },
+ unset: function(object, property) {
+ delete object[property];
+ },
+ parentForm: parentForm,
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setPristine
+ *
+ * @description
+ * Sets the control to its pristine state.
+ *
+ * This method can be called to remove the `ng-dirty` class and set the control to its pristine
+ * state (`ng-pristine` class). A model is considered to be pristine when the control
+ * has not been changed from when first compiled.
+ */
+ this.$setPristine = function() {
+ ctrl.$dirty = false;
+ ctrl.$pristine = true;
+ $animate.removeClass($element, DIRTY_CLASS);
+ $animate.addClass($element, PRISTINE_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setDirty
+ *
+ * @description
+ * Sets the control to its dirty state.
+ *
+ * This method can be called to remove the `ng-pristine` class and set the control to its dirty
+ * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
+ * from when first compiled.
+ */
+ this.$setDirty = function() {
+ ctrl.$dirty = true;
+ ctrl.$pristine = false;
+ $animate.removeClass($element, PRISTINE_CLASS);
+ $animate.addClass($element, DIRTY_CLASS);
+ parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setUntouched
+ *
+ * @description
+ * Sets the control to its untouched state.
+ *
+ * This method can be called to remove the `ng-touched` class and set the control to its
+ * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
+ * by default, however this function can be used to restore that state if the model has
+ * already been touched by the user.
+ */
+ this.$setUntouched = function() {
+ ctrl.$touched = false;
+ ctrl.$untouched = true;
+ $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setTouched
+ *
+ * @description
+ * Sets the control to its touched state.
+ *
+ * This method can be called to remove the `ng-untouched` class and set the control to its
+ * touched state (`ng-touched` class). A model is considered to be touched when the user has
+ * first focused the control element and then shifted focus away from the control (blur event).
+ */
+ this.$setTouched = function() {
+ ctrl.$touched = true;
+ ctrl.$untouched = false;
+ $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$rollbackViewValue
+ *
+ * @description
+ * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
+ * which may be caused by a pending debounced event or because the input is waiting for a some
+ * future event.
+ *
+ * If you have an input that uses `ng-model-options` to set up debounced events or events such
+ * as blur you can have a situation where there is a period when the `$viewValue`
+ * is out of synch with the ngModel's `$modelValue`.
+ *
+ * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
+ * programmatically before these debounced/future events have resolved/occurred, because Angular's
+ * dirty checking mechanism is not able to tell whether the model has actually changed or not.
+ *
+ * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
+ * input which may have such events pending. This is important in order to make sure that the
+ * input field will be updated with the new model value and any pending operations are cancelled.
+ *
+ * <example name="ng-model-cancel-update" module="cancel-update-example">
+ * <file name="app.js">
+ * angular.module('cancel-update-example', [])
+ *
+ * .controller('CancelUpdateController', ['$scope', function($scope) {
+ * $scope.resetWithCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myForm.myInput1.$rollbackViewValue();
+ * $scope.myValue = '';
+ * }
+ * };
+ * $scope.resetWithoutCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myValue = '';
+ * }
+ * };
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <div ng-controller="CancelUpdateController">
+ * <p>Try typing something in each input. See that the model only updates when you
+ * blur off the input.
+ * </p>
+ * <p>Now see what happens if you start typing then press the Escape key</p>
+ *
+ * <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
+ * <p>With $rollbackViewValue()</p>
+ * <input name="myInput1" ng-model="myValue" ng-keydown="resetWithCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ *
+ * <p>Without $rollbackViewValue()</p>
+ * <input name="myInput2" ng-model="myValue" ng-keydown="resetWithoutCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ * </form>
+ * </div>
+ * </file>
+ * </example>
+ */
+ this.$rollbackViewValue = function() {
+ $timeout.cancel(pendingDebounce);
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
+ ctrl.$render();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$validate
+ *
+ * @description
+ * Runs each of the registered validators (first synchronous validators and then
+ * asynchronous validators).
+ * If the validity changes to invalid, the model will be set to `undefined`,
+ * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
+ * If the validity changes to valid, it will set the model to the last available valid
+ * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
+ */
+ this.$validate = function() {
+ // ignore $validate before model is initialized
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ return;
+ }
+
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ // Note: we use the $$rawModelValue as $modelValue might have been
+ // set to undefined during a view -> model update that found validation
+ // errors. We can't parse the view here, since that could change
+ // the model although neither viewValue nor the model on the scope changed
+ var modelValue = ctrl.$$rawModelValue;
+
+ var prevValid = ctrl.$valid;
+ var prevModelValue = ctrl.$modelValue;
+
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+
+ ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
+ // If there was no change in validity, don't update the model
+ // This prevents changing an invalid modelValue to undefined
+ if (!allowInvalid && prevValid !== allValid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ });
+
+ };
+
+ this.$$runValidators = function(modelValue, viewValue, doneCallback) {
+ currentValidationRunId++;
+ var localValidationRunId = currentValidationRunId;
+
+ // check parser error
+ if (!processParseErrors()) {
+ validationDone(false);
+ return;
+ }
+ if (!processSyncValidators()) {
+ validationDone(false);
+ return;
+ }
+ processAsyncValidators();
+
+ function processParseErrors() {
+ var errorKey = ctrl.$$parserName || 'parse';
+ if (parserValid === undefined) {
+ setValidity(errorKey, null);
+ } else {
+ if (!parserValid) {
+ forEach(ctrl.$validators, function(v, name) {
+ setValidity(name, null);
+ });
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ }
+ // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
+ setValidity(errorKey, parserValid);
+ return parserValid;
+ }
+ return true;
+ }
+
+ function processSyncValidators() {
+ var syncValidatorsValid = true;
+ forEach(ctrl.$validators, function(validator, name) {
+ var result = validator(modelValue, viewValue);
+ syncValidatorsValid = syncValidatorsValid && result;
+ setValidity(name, result);
+ });
+ if (!syncValidatorsValid) {
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ return false;
+ }
+ return true;
+ }
+
+ function processAsyncValidators() {
+ var validatorPromises = [];
+ var allValid = true;
+ forEach(ctrl.$asyncValidators, function(validator, name) {
+ var promise = validator(modelValue, viewValue);
+ if (!isPromiseLike(promise)) {
+ throw ngModelMinErr("$asyncValidators",
+ "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
+ }
+ setValidity(name, undefined);
+ validatorPromises.push(promise.then(function() {
+ setValidity(name, true);
+ }, function(error) {
+ allValid = false;
+ setValidity(name, false);
+ }));
+ });
+ if (!validatorPromises.length) {
+ validationDone(true);
+ } else {
+ $q.all(validatorPromises).then(function() {
+ validationDone(allValid);
+ }, noop);
+ }
+ }
+
+ function setValidity(name, isValid) {
+ if (localValidationRunId === currentValidationRunId) {
+ ctrl.$setValidity(name, isValid);
+ }
+ }
+
+ function validationDone(allValid) {
+ if (localValidationRunId === currentValidationRunId) {
+
+ doneCallback(allValid);
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$commitViewValue
+ *
+ * @description
+ * Commit a pending update to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ this.$commitViewValue = function() {
+ var viewValue = ctrl.$viewValue;
+
+ $timeout.cancel(pendingDebounce);
+
+ // If the view value has not changed then we should just exit, except in the case where there is
+ // a native validator on the element. In this case the validation state may have changed even though
+ // the viewValue has stayed empty.
+ if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
+ return;
+ }
+ ctrl.$$lastCommittedViewValue = viewValue;
+
+ // change to dirty
+ if (ctrl.$pristine) {
+ this.$setDirty();
+ }
+ this.$$parseAndValidate();
+ };
+
+ this.$$parseAndValidate = function() {
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ var modelValue = viewValue;
+ parserValid = isUndefined(modelValue) ? undefined : true;
+
+ if (parserValid) {
+ for (var i = 0; i < ctrl.$parsers.length; i++) {
+ modelValue = ctrl.$parsers[i](modelValue);
+ if (isUndefined(modelValue)) {
+ parserValid = false;
+ break;
+ }
+ }
+ }
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ // ctrl.$modelValue has not been touched yet...
+ ctrl.$modelValue = ngModelGet($scope);
+ }
+ var prevModelValue = ctrl.$modelValue;
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+ ctrl.$$rawModelValue = modelValue;
+
+ if (allowInvalid) {
+ ctrl.$modelValue = modelValue;
+ writeToModelIfNeeded();
+ }
+
+ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
+ // This can happen if e.g. $setViewValue is called from inside a parser
+ ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
+ if (!allowInvalid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+ writeToModelIfNeeded();
+ }
+ });
+
+ function writeToModelIfNeeded() {
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ };
+
+ this.$$writeModelToScope = function() {
+ ngModelSet($scope, ctrl.$modelValue);
+ forEach(ctrl.$viewChangeListeners, function(listener) {
+ try {
+ listener();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setViewValue
+ *
+ * @description
+ * Update the view value.
+ *
+ * This method should be called when an input directive want to change the view value; typically,
+ * this is done from within a DOM event handler.
+ *
+ * For example {@link ng.directive:input input} calls it when the value of the input changes and
+ * {@link ng.directive:select select} calls it when an option is selected.
+ *
+ * If the new `value` is an object (rather than a string or a number), we should make a copy of the
+ * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
+ * watch of objects, it only looks for a change of identity. If you only change the property of
+ * the object then ngModel will not realise that the object has changed and will not invoke the
+ * `$parsers` and `$validators` pipelines.
+ *
+ * For this reason, you should not change properties of the copy once it has been passed to
+ * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
+ *
+ * When this method is called, the new `value` will be staged for committing through the `$parsers`
+ * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
+ * value sent directly for processing, finally to be applied to `$modelValue` and then the
+ * **expression** specified in the `ng-model` attribute.
+ *
+ * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
+ *
+ * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
+ * and the `default` trigger is not listed, all those actions will remain pending until one of the
+ * `updateOn` events is triggered on the DOM element.
+ * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
+ * directive is used with a custom debounce for this particular event.
+ *
+ * Note that calling this function does not trigger a `$digest`.
+ *
+ * @param {string} value Value from the view.
+ * @param {string} trigger Event that triggered the update.
+ */
+ this.$setViewValue = function(value, trigger) {
+ ctrl.$viewValue = value;
+ if (!ctrl.$options || ctrl.$options.updateOnDefault) {
+ ctrl.$$debounceViewValueCommit(trigger);
+ }
+ };
+
+ this.$$debounceViewValueCommit = function(trigger) {
+ var debounceDelay = 0,
+ options = ctrl.$options,
+ debounce;
+
+ if (options && isDefined(options.debounce)) {
+ debounce = options.debounce;
+ if (isNumber(debounce)) {
+ debounceDelay = debounce;
+ } else if (isNumber(debounce[trigger])) {
+ debounceDelay = debounce[trigger];
+ } else if (isNumber(debounce['default'])) {
+ debounceDelay = debounce['default'];
+ }
+ }
+
+ $timeout.cancel(pendingDebounce);
+ if (debounceDelay) {
+ pendingDebounce = $timeout(function() {
+ ctrl.$commitViewValue();
+ }, debounceDelay);
+ } else if ($rootScope.$$phase) {
+ ctrl.$commitViewValue();
+ } else {
+ $scope.$apply(function() {
+ ctrl.$commitViewValue();
+ });
+ }
+ };
+
+ // model -> value
+ // Note: we cannot use a normal scope.$watch as we want to detect the following:
+ // 1. scope value is 'a'
+ // 2. user enters 'b'
+ // 3. ng-change kicks in and reverts scope value to 'a'
+ // -> scope value did not change since the last digest as
+ // ng-change executes in apply phase
+ // 4. view should be changed back to 'a'
+ $scope.$watch(function ngModelWatch() {
+ var modelValue = ngModelGet($scope);
+
+ // if scope model value and ngModel value are out of sync
+ // TODO(perf): why not move this to the action fn?
+ if (modelValue !== ctrl.$modelValue &&
+ // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
+ (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
+ ) {
+ ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
+ parserValid = undefined;
+
+ var formatters = ctrl.$formatters,
+ idx = formatters.length;
+
+ var viewValue = modelValue;
+ while (idx--) {
+ viewValue = formatters[idx](viewValue);
+ }
+ if (ctrl.$viewValue !== viewValue) {
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
+ ctrl.$render();
+
+ ctrl.$$runValidators(modelValue, viewValue, noop);
+ }
+ }
+
+ return modelValue;
+ });
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngModel
+ *
+ * @element input
+ * @priority 1
+ *
+ * @description
+ * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
+ * property on the scope using {@link ngModel.NgModelController NgModelController},
+ * which is created and exposed by this directive.
+ *
+ * `ngModel` is responsible for:
+ *
+ * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
+ * require.
+ * - Providing validation behavior (i.e. required, number, email, url).
+ * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
+ * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
+ * - Registering the control with its parent {@link ng.directive:form form}.
+ *
+ * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
+ * current scope. If the property doesn't already exist on this scope, it will be created
+ * implicitly and added to the scope.
+ *
+ * For best practices on using `ngModel`, see:
+ *
+ * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
+ *
+ * For basic examples, how to use `ngModel`, see:
+ *
+ * - {@link ng.directive:input input}
+ * - {@link input[text] text}
+ * - {@link input[checkbox] checkbox}
+ * - {@link input[radio] radio}
+ * - {@link input[number] number}
+ * - {@link input[email] email}
+ * - {@link input[url] url}
+ * - {@link input[date] date}
+ * - {@link input[datetime-local] datetime-local}
+ * - {@link input[time] time}
+ * - {@link input[month] month}
+ * - {@link input[week] week}
+ * - {@link ng.directive:select select}
+ * - {@link ng.directive:textarea textarea}
+ *
+ * # CSS classes
+ * The following CSS classes are added and removed on the associated input/select/textarea element
+ * depending on the validity of the model.
+ *
+ * - `ng-valid`: the model is valid
+ * - `ng-invalid`: the model is invalid
+ * - `ng-valid-[key]`: for each valid key added by `$setValidity`
+ * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
+ * - `ng-pristine`: the control hasn't been interacted with yet
+ * - `ng-dirty`: the control has been interacted with
+ * - `ng-touched`: the control has been blurred
+ * - `ng-untouched`: the control hasn't been blurred
+ * - `ng-pending`: any `$asyncValidators` are unfulfilled
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ * ## Animation Hooks
+ *
+ * Animations within models are triggered when any of the associated CSS classes are added and removed
+ * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
+ * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
+ * The animations that are triggered within ngModel are similar to how they work in ngClass and
+ * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style an input element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-input {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-input.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = '1';
+ }]);
+ </script>
+ <style>
+ .my-input {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-input.ng-invalid {
+ color:white;
+ background: red;
+ }
+ </style>
+ Update input to see transitions when valid/invalid.
+ Integer is a valid value.
+ <form name="testForm" ng-controller="ExampleController">
+ <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
+ </form>
+ </file>
+ * </example>
+ *
+ * ## Binding to a getter/setter
+ *
+ * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
+ * function that returns a representation of the model when called with zero arguments, and sets
+ * the internal state of a model when called with an argument. It's sometimes useful to use this
+ * for models that have an internal representation that's different than what the model exposes
+ * to the view.
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
+ * frequently than other parts of your code.
+ * </div>
+ *
+ * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
+ * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
+ * a `<form>`, which will enable this behavior for all `<input>`s within it. See
+ * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
+ *
+ * The following example shows how to use `ngModel` with a getter/setter:
+ *
+ * @example
+ * <example name="ngModel-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ * </example>
+ */
+var ngModelDirective = ['$rootScope', function($rootScope) {
+ return {
+ restrict: 'A',
+ require: ['ngModel', '^?form', '^?ngModelOptions'],
+ controller: NgModelController,
+ // Prelink needs to run before any input directive
+ // so that we can set the NgModelOptions in NgModelController
+ // before anyone else uses it.
+ priority: 1,
+ compile: function ngModelCompile(element) {
+ // Setup initial state of the control
+ element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
+
+ return {
+ pre: function ngModelPreLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0],
+ formCtrl = ctrls[1] || nullFormCtrl;
+
+ modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
+
+ // notify others, especially parent forms
+ formCtrl.$addControl(modelCtrl);
+
+ attr.$observe('name', function(newValue) {
+ if (modelCtrl.$name !== newValue) {
+ formCtrl.$$renameControl(modelCtrl, newValue);
+ }
+ });
+
+ scope.$on('$destroy', function() {
+ formCtrl.$removeControl(modelCtrl);
+ });
+ },
+ post: function ngModelPostLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0];
+ if (modelCtrl.$options && modelCtrl.$options.updateOn) {
+ element.on(modelCtrl.$options.updateOn, function(ev) {
+ modelCtrl.$$debounceViewValueCommit(ev && ev.type);
+ });
+ }
+
+ element.on('blur', function(ev) {
+ if (modelCtrl.$touched) return;
+
+ if ($rootScope.$$phase) {
+ scope.$evalAsync(modelCtrl.$setTouched);
+ } else {
+ scope.$apply(modelCtrl.$setTouched);
+ }
+ });
+ }
+ };
+ }
+ };
+}];
+
+var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
+
+/**
+ * @ngdoc directive
+ * @name ngModelOptions
+ *
+ * @description
+ * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
+ * events that will trigger a model update and/or a debouncing delay so that the actual update only
+ * takes place when a timer expires; this timer will be reset after another change takes place.
+ *
+ * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
+ * be different than the value in the actual model. This means that if you update the model you
+ * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
+ * order to make sure it is synchronized with the model and that any debounced action is canceled.
+ *
+ * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
+ * method is by making sure the input is placed inside a form that has a `name` attribute. This is
+ * important because `form` controllers are published to the related scope under the name in their
+ * `name` attribute.
+ *
+ * Any pending changes will take place immediately when an enclosing form is submitted via the
+ * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * `ngModelOptions` has an effect on the element it's declared on and its descendants.
+ *
+ * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
+ * - `updateOn`: string specifying which event should the input be bound to. You can set several
+ * events using an space delimited list. There is a special event called `default` that
+ * matches the default events belonging of the control.
+ * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
+ * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
+ * custom value for each event. For example:
+ * `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
+ * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
+ * not validate correctly instead of the default behavior of setting the model to undefined.
+ * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
+ `ngModel` as getters/setters.
+ * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
+ * `<input type="date">`, `<input type="time">`, ... . Right now, the only supported value is `'UTC'`,
+ * otherwise the default timezone of the browser will be used.
+ *
+ * @example
+
+ The following example shows how to override immediate updates. Changes on the inputs within the
+ form will update the model only when the control loses focus (blur event). If `escape` key is
+ pressed while the input field is focused, the value is reset to the value in the current model.
+
+ <example name="ngModelOptions-directive-blur" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ updateOn: 'blur' }"
+ ng-keyup="cancel($event)" /><br />
+
+ Other data:
+ <input type="text" ng-model="user.data" /><br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say', data: '' };
+
+ $scope.cancel = function(e) {
+ if (e.keyCode == 27) {
+ $scope.userForm.userName.$rollbackViewValue();
+ }
+ };
+ }]);
+ </file>
+ <file name="protractor.js" type="protractor">
+ var model = element(by.binding('user.name'));
+ var input = element(by.model('user.name'));
+ var other = element(by.model('user.data'));
+
+ it('should allow custom events', function() {
+ input.sendKeys(' hello');
+ input.click();
+ expect(model.getText()).toEqual('say');
+ other.click();
+ expect(model.getText()).toEqual('say hello');
+ });
+
+ it('should $rollbackViewValue when model changes', function() {
+ input.sendKeys(' hello');
+ expect(input.getAttribute('value')).toEqual('say hello');
+ input.sendKeys(protractor.Key.ESCAPE);
+ expect(input.getAttribute('value')).toEqual('say');
+ other.click();
+ expect(model.getText()).toEqual('say');
+ });
+ </file>
+ </example>
+
+ This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
+ If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
+
+ <example name="ngModelOptions-directive-debounce" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ debounce: 1000 }" />
+ <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say' };
+ }]);
+ </file>
+ </example>
+
+ This one shows how to bind to getter/setters:
+
+ <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ </example>
+ */
+var ngModelOptionsDirective = function() {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$attrs', function($scope, $attrs) {
+ var that = this;
+ this.$options = $scope.$eval($attrs.ngModelOptions);
+ // Allow adding/overriding bound events
+ if (this.$options.updateOn !== undefined) {
+ this.$options.updateOnDefault = false;
+ // extract "default" pseudo-event from list of events that can trigger a model update
+ this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
+ that.$options.updateOnDefault = true;
+ return ' ';
+ }));
+ } else {
+ this.$options.updateOnDefault = true;
+ }
+ }]
+ };
+};
+
+
+
+// helper methods
+function addSetValidityMethod(context) {
+ var ctrl = context.ctrl,
+ $element = context.$element,
+ classCache = {},
+ set = context.set,
+ unset = context.unset,
+ parentForm = context.parentForm,
+ $animate = context.$animate;
+
+ classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
+
+ ctrl.$setValidity = setValidity;
+
+ function setValidity(validationErrorKey, state, controller) {
+ if (state === undefined) {
+ createAndSet('$pending', validationErrorKey, controller);
+ } else {
+ unsetAndCleanup('$pending', validationErrorKey, controller);
+ }
+ if (!isBoolean(state)) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ if (state) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ set(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ set(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ }
+ }
+ if (ctrl.$pending) {
+ cachedToggleClass(PENDING_CLASS, true);
+ ctrl.$valid = ctrl.$invalid = undefined;
+ toggleValidationCss('', null);
+ } else {
+ cachedToggleClass(PENDING_CLASS, false);
+ ctrl.$valid = isObjectEmpty(ctrl.$error);
+ ctrl.$invalid = !ctrl.$valid;
+ toggleValidationCss('', ctrl.$valid);
+ }
+
+ // re-read the state as the set/unset methods could have
+ // combined state in ctrl.$error[validationError] (used for forms),
+ // where setting/unsetting only increments/decrements the value,
+ // and does not replace it.
+ var combinedState;
+ if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
+ combinedState = undefined;
+ } else if (ctrl.$error[validationErrorKey]) {
+ combinedState = false;
+ } else if (ctrl.$$success[validationErrorKey]) {
+ combinedState = true;
+ } else {
+ combinedState = null;
+ }
+
+ toggleValidationCss(validationErrorKey, combinedState);
+ parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
+ }
+
+ function createAndSet(name, value, controller) {
+ if (!ctrl[name]) {
+ ctrl[name] = {};
+ }
+ set(ctrl[name], value, controller);
+ }
+
+ function unsetAndCleanup(name, value, controller) {
+ if (ctrl[name]) {
+ unset(ctrl[name], value, controller);
+ }
+ if (isObjectEmpty(ctrl[name])) {
+ ctrl[name] = undefined;
+ }
+ }
+
+ function cachedToggleClass(className, switchValue) {
+ if (switchValue && !classCache[className]) {
+ $animate.addClass($element, className);
+ classCache[className] = true;
+ } else if (!switchValue && classCache[className]) {
+ $animate.removeClass($element, className);
+ classCache[className] = false;
+ }
+ }
+
+ function toggleValidationCss(validationErrorKey, isValid) {
+ validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
+
+ cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
+ cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
+ }
+}
+
+function isObjectEmpty(obj) {
+ if (obj) {
+ for (var prop in obj) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngNonBindable
+ * @restrict AC
+ * @priority 1000
+ *
+ * @description
+ * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
+ * DOM element. This is useful if the element contains what appears to be Angular directives and
+ * bindings but which should be ignored by Angular. This could be the case if you have a site that
+ * displays snippets of code, for instance.
+ *
+ * @element ANY
+ *
+ * @example
+ * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
+ * but the one wrapped in `ngNonBindable` is left alone.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div>Normal: {{1 + 2}}</div>
+ <div ng-non-bindable>Ignored: {{1 + 2}}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-non-bindable', function() {
+ expect(element(by.binding('1 + 2')).getText()).toContain('3');
+ expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
+ });
+ </file>
+ </example>
+ */
+var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
+
+/**
+ * @ngdoc directive
+ * @name ngPluralize
+ * @restrict EA
+ *
+ * @description
+ * `ngPluralize` is a directive that displays messages according to en-US localization rules.
+ * These rules are bundled with angular.js, but can be overridden
+ * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
+ * by specifying the mappings between
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * and the strings to be displayed.
+ *
+ * # Plural categories and explicit number rules
+ * There are two
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * in Angular's default en-US locale: "one" and "other".
+ *
+ * While a plural category may match many numbers (for example, in en-US locale, "other" can match
+ * any number that is not 1), an explicit number rule can only match one number. For example, the
+ * explicit number rule for "3" matches the number 3. There are examples of plural categories
+ * and explicit number rules throughout the rest of this documentation.
+ *
+ * # Configuring ngPluralize
+ * You configure ngPluralize by providing 2 attributes: `count` and `when`.
+ * You can also provide an optional attribute, `offset`.
+ *
+ * The value of the `count` attribute can be either a string or an {@link guide/expression
+ * Angular expression}; these are evaluated on the current scope for its bound value.
+ *
+ * The `when` attribute specifies the mappings between plural categories and the actual
+ * string to be displayed. The value of the attribute should be a JSON object.
+ *
+ * The following example shows how to configure ngPluralize:
+ *
+ * ```html
+ * <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ * 'one': '1 person is viewing.',
+ * 'other': '{} people are viewing.'}">
+ * </ng-pluralize>
+ *```
+ *
+ * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
+ * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
+ * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
+ * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
+ * show "a dozen people are viewing".
+ *
+ * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
+ * into pluralized strings. In the previous example, Angular will replace `{}` with
+ * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
+ * for <span ng-non-bindable>{{numberExpression}}</span>.
+ *
+ * # Configuring ngPluralize with offset
+ * The `offset` attribute allows further customization of pluralized text, which can result in
+ * a better user experience. For example, instead of the message "4 people are viewing this document",
+ * you might display "John, Kate and 2 others are viewing this document".
+ * The offset attribute allows you to offset a number by any desired value.
+ * Let's take a look at an example:
+ *
+ * ```html
+ * <ng-pluralize count="personCount" offset=2
+ * when="{'0': 'Nobody is viewing.',
+ * '1': '{{person1}} is viewing.',
+ * '2': '{{person1}} and {{person2}} are viewing.',
+ * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ * </ng-pluralize>
+ * ```
+ *
+ * Notice that we are still using two plural categories(one, other), but we added
+ * three explicit number rules 0, 1 and 2.
+ * When one person, perhaps John, views the document, "John is viewing" will be shown.
+ * When three people view the document, no explicit number rule is found, so
+ * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
+ * is shown.
+ *
+ * Note that when you specify offsets, you must provide explicit number rules for
+ * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
+ * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
+ * plural categories "one" and "other".
+ *
+ * @param {string|expression} count The variable to be bound to.
+ * @param {string} when The mapping between plural category to its corresponding strings.
+ * @param {number=} offset Offset to deduct from the total number.
+ *
+ * @example
+ <example module="pluralizeExample">
+ <file name="index.html">
+ <script>
+ angular.module('pluralizeExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.person1 = 'Igor';
+ $scope.person2 = 'Misko';
+ $scope.personCount = 1;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
+ Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
+ Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
+
+ <!--- Example with simple pluralization rules for en locale --->
+ Without Offset:
+ <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ 'one': '1 person is viewing.',
+ 'other': '{} people are viewing.'}">
+ </ng-pluralize><br>
+
+ <!--- Example with offset --->
+ With Offset(2):
+ <ng-pluralize count="personCount" offset=2
+ when="{'0': 'Nobody is viewing.',
+ '1': '{{person1}} is viewing.',
+ '2': '{{person1}} and {{person2}} are viewing.',
+ 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ </ng-pluralize>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should show correct pluralized string', function() {
+ var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var countInput = element(by.model('personCount'));
+
+ expect(withoutOffset.getText()).toEqual('1 person is viewing.');
+ expect(withOffset.getText()).toEqual('Igor is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('0');
+
+ expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
+ expect(withOffset.getText()).toEqual('Nobody is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('2');
+
+ expect(withoutOffset.getText()).toEqual('2 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('3');
+
+ expect(withoutOffset.getText()).toEqual('3 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('4');
+
+ expect(withoutOffset.getText()).toEqual('4 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
+ });
+ it('should show data-bound names', function() {
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var personCount = element(by.model('personCount'));
+ var person1 = element(by.model('person1'));
+ var person2 = element(by.model('person2'));
+ personCount.clear();
+ personCount.sendKeys('4');
+ person1.clear();
+ person1.sendKeys('Di');
+ person2.clear();
+ person2.sendKeys('Vojta');
+ expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
+ });
+ </file>
+ </example>
+ */
+var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
+ var BRACE = /{}/g,
+ IS_WHEN = /^when(Minus)?(.+)$/;
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element, attr) {
+ var numberExp = attr.count,
+ whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
+ offset = attr.offset || 0,
+ whens = scope.$eval(whenExp) || {},
+ whensExpFns = {},
+ startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
+ watchRemover = angular.noop,
+ lastCount;
+
+ forEach(attr, function(expression, attributeName) {
+ var tmpMatch = IS_WHEN.exec(attributeName);
+ if (tmpMatch) {
+ var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
+ whens[whenKey] = element.attr(attr.$attr[attributeName]);
+ }
+ });
+ forEach(whens, function(expression, key) {
+ whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
+
+ });
+
+ scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
+ var count = parseFloat(newVal);
+ var countIsNaN = isNaN(count);
+
+ if (!countIsNaN && !(count in whens)) {
+ // If an explicit number rule such as 1, 2, 3... is defined, just use it.
+ // Otherwise, check it against pluralization rules in $locale service.
+ count = $locale.pluralCat(count - offset);
+ }
+
+ // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
+ // In JS `NaN !== NaN`, so we have to exlicitly check.
+ if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {
+ watchRemover();
+ watchRemover = scope.$watch(whensExpFns[count], updateElementText);
+ lastCount = count;
+ }
+ });
+
+ function updateElementText(newText) {
+ element.text(newText || '');
+ }
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngRepeat
+ *
+ * @description
+ * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
+ * instance gets its own scope, where the given loop variable is set to the current collection item,
+ * and `$index` is set to the item index or key.
+ *
+ * Special properties are exposed on the local scope of each template instance, including:
+ *
+ * | Variable | Type | Details |
+ * |-----------|-----------------|-----------------------------------------------------------------------------|
+ * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
+ * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
+ * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
+ * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
+ * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
+ * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
+ *
+ * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
+ * This may be useful when, for instance, nesting ngRepeats.
+ *
+ * # Iterating over object properties
+ *
+ * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
+ * syntax:
+ *
+ * ```js
+ * <div ng-repeat="(key, value) in myObj"> ... </div>
+ * ```
+ *
+ * You need to be aware that the JavaScript specification does not define what order
+ * it will return the keys for an object. In order to have a guaranteed deterministic order
+ * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.
+ *
+ * If this is not desired, the recommended workaround is to convert your object into an array
+ * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
+ * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
+ * or implement a `$watch` on the object yourself.
+ *
+ * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the
+ * strategy of providing keys in the order in which they were defined, although there are exceptions
+ * when keys are deleted and reinstated.
+ *
+ *
+ * # Tracking and Duplicates
+ *
+ * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
+ *
+ * * When an item is added, a new instance of the template is added to the DOM.
+ * * When an item is removed, its template instance is removed from the DOM.
+ * * When items are reordered, their respective templates are reordered in the DOM.
+ *
+ * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
+ * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
+ * items and DOM elements.
+ *
+ * If you do need to repeat duplicate items, you can substitute the default tracking behavior
+ * with your own using the `track by` expression.
+ *
+ * For example, you may track items by the index of each item in the collection, using the
+ * special scope property `$index`:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * You may use arbitrary expressions in `track by`, including references to custom functions
+ * on the scope:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * If you are working with objects that have an identifier property, you can track
+ * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
+ * will not have to rebuild the DOM elements for items it has already rendered, even if the
+ * JavaScript objects in the collection have been substituted for new ones:
+ * ```html
+ * <div ng-repeat="model in collection track by model.id">
+ * {{model.name}}
+ * </div>
+ * ```
+ *
+ * When no `track by` expression is provided, it is equivalent to tracking by the built-in
+ * `$id` function, which tracks items by their identity:
+ * ```html
+ * <div ng-repeat="obj in collection track by $id(obj)">
+ * {{obj.prop}}
+ * </div>
+ * ```
+ *
+ * # Special repeat start and end points
+ * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
+ * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
+ * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
+ * up to and including the ending HTML tag where **ng-repeat-end** is placed.
+ *
+ * The example below makes use of this feature:
+ * ```html
+ * <header ng-repeat-start="item in items">
+ * Header {{ item }}
+ * </header>
+ * <div class="body">
+ * Body {{ item }}
+ * </div>
+ * <footer ng-repeat-end>
+ * Footer {{ item }}
+ * </footer>
+ * ```
+ *
+ * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
+ * ```html
+ * <header>
+ * Header A
+ * </header>
+ * <div class="body">
+ * Body A
+ * </div>
+ * <footer>
+ * Footer A
+ * </footer>
+ * <header>
+ * Header B
+ * </header>
+ * <div class="body">
+ * Body B
+ * </div>
+ * <footer>
+ * Footer B
+ * </footer>
+ * ```
+ *
+ * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
+ * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
+ *
+ * @animations
+ * **.enter** - when a new item is added to the list or when an item is revealed after a filter
+ *
+ * **.leave** - when an item is removed from the list or when an item is filtered out
+ *
+ * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
+ *
+ * @element ANY
+ * @scope
+ * @priority 1000
+ * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
+ * formats are currently supported:
+ *
+ * * `variable in expression` – where variable is the user defined loop variable and `expression`
+ * is a scope expression giving the collection to enumerate.
+ *
+ * For example: `album in artist.albums`.
+ *
+ * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
+ * and `expression` is the scope expression giving the collection to enumerate.
+ *
+ * For example: `(name, age) in {'adam':10, 'amalie':12}`.
+ *
+ * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
+ * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
+ * is specified, ng-repeat associates elements by identity. It is an error to have
+ * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
+ * mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
+ * applied before the tracking expression.
+ *
+ * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
+ * will be associated by item identity in the array.
+ *
+ * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
+ * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
+ * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
+ * element in the same way in the DOM.
+ *
+ * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
+ * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
+ * property is same.
+ *
+ * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
+ * to items in conjunction with a tracking expression.
+ *
+ * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
+ * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
+ * when a filter is active on the repeater, but the filtered result set is empty.
+ *
+ * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
+ * the items have been processed through the filter.
+ *
+ * @example
+ * This example initializes the scope to a list of names and
+ * then uses `ngRepeat` to display every person:
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-init="friends = [
+ {name:'John', age:25, gender:'boy'},
+ {name:'Jessie', age:30, gender:'girl'},
+ {name:'Johanna', age:28, gender:'girl'},
+ {name:'Joy', age:15, gender:'girl'},
+ {name:'Mary', age:28, gender:'girl'},
+ {name:'Peter', age:95, gender:'boy'},
+ {name:'Sebastian', age:50, gender:'boy'},
+ {name:'Erika', age:27, gender:'girl'},
+ {name:'Patrick', age:40, gender:'boy'},
+ {name:'Samantha', age:60, gender:'girl'}
+ ]">
+ I have {{friends.length}} friends. They are:
+ <input type="search" ng-model="q" placeholder="filter friends..." />
+ <ul class="example-animate-container">
+ <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
+ [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
+ </li>
+ <li class="animate-repeat" ng-if="results.length == 0">
+ <strong>No results found...</strong>
+ </li>
+ </ul>
+ </div>
+ </file>
+ <file name="animations.css">
+ .example-animate-container {
+ background:white;
+ border:1px solid black;
+ list-style:none;
+ margin:0;
+ padding:0 10px;
+ }
+
+ .animate-repeat {
+ line-height:40px;
+ list-style:none;
+ box-sizing:border-box;
+ }
+
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter,
+ .animate-repeat.ng-leave {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ }
+
+ .animate-repeat.ng-leave.ng-leave-active,
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter {
+ opacity:0;
+ max-height:0;
+ }
+
+ .animate-repeat.ng-leave,
+ .animate-repeat.ng-move.ng-move-active,
+ .animate-repeat.ng-enter.ng-enter-active {
+ opacity:1;
+ max-height:40px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var friends = element.all(by.repeater('friend in friends'));
+
+ it('should render initial data set', function() {
+ expect(friends.count()).toBe(10);
+ expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
+ expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
+ expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
+ expect(element(by.binding('friends.length')).getText())
+ .toMatch("I have 10 friends. They are:");
+ });
+
+ it('should update repeater when filter predicate changes', function() {
+ expect(friends.count()).toBe(10);
+
+ element(by.model('q')).sendKeys('ma');
+
+ expect(friends.count()).toBe(2);
+ expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
+ expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
+ });
+ </file>
+ </example>
+ */
+var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
+ var NG_REMOVED = '$$NG_REMOVED';
+ var ngRepeatMinErr = minErr('ngRepeat');
+
+ var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
+ // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
+ scope[valueIdentifier] = value;
+ if (keyIdentifier) scope[keyIdentifier] = key;
+ scope.$index = index;
+ scope.$first = (index === 0);
+ scope.$last = (index === (arrayLength - 1));
+ scope.$middle = !(scope.$first || scope.$last);
+ // jshint bitwise: false
+ scope.$odd = !(scope.$even = (index&1) === 0);
+ // jshint bitwise: true
+ };
+
+ var getBlockStart = function(block) {
+ return block.clone[0];
+ };
+
+ var getBlockEnd = function(block) {
+ return block.clone[block.clone.length - 1];
+ };
+
+
+ return {
+ restrict: 'A',
+ multiElement: true,
+ transclude: 'element',
+ priority: 1000,
+ terminal: true,
+ $$tlb: true,
+ compile: function ngRepeatCompile($element, $attr) {
+ var expression = $attr.ngRepeat;
+ var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
+
+ var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
+ expression);
+ }
+
+ var lhs = match[1];
+ var rhs = match[2];
+ var aliasAs = match[3];
+ var trackByExp = match[4];
+
+ match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
+ lhs);
+ }
+ var valueIdentifier = match[3] || match[1];
+ var keyIdentifier = match[2];
+
+ if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
+ /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
+ throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
+ aliasAs);
+ }
+
+ var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
+ var hashFnLocals = {$id: hashKey};
+
+ if (trackByExp) {
+ trackByExpGetter = $parse(trackByExp);
+ } else {
+ trackByIdArrayFn = function(key, value) {
+ return hashKey(value);
+ };
+ trackByIdObjFn = function(key) {
+ return key;
+ };
+ }
+
+ return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
+
+ if (trackByExpGetter) {
+ trackByIdExpFn = function(key, value, index) {
+ // assign key, value, and $index to the locals so that they can be used in hash functions
+ if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
+ hashFnLocals[valueIdentifier] = value;
+ hashFnLocals.$index = index;
+ return trackByExpGetter($scope, hashFnLocals);
+ };
+ }
+
+ // Store a list of elements from previous run. This is a hash where key is the item from the
+ // iterator, and the value is objects with following properties.
+ // - scope: bound scope
+ // - element: previous element.
+ // - index: position
+ //
+ // We are using no-proto object so that we don't need to guard against inherited props via
+ // hasOwnProperty.
+ var lastBlockMap = createMap();
+
+ //watch props
+ $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
+ var index, length,
+ previousNode = $element[0], // node that cloned nodes should be inserted after
+ // initialized to the comment node anchor
+ nextNode,
+ // Same as lastBlockMap but it has the current state. It will become the
+ // lastBlockMap on the next iteration.
+ nextBlockMap = createMap(),
+ collectionLength,
+ key, value, // key/value of iteration
+ trackById,
+ trackByIdFn,
+ collectionKeys,
+ block, // last object information {scope, element, id}
+ nextBlockOrder,
+ elementsToRemove;
+
+ if (aliasAs) {
+ $scope[aliasAs] = collection;
+ }
+
+ if (isArrayLike(collection)) {
+ collectionKeys = collection;
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
+ } else {
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
+ // if object, extract keys, sort them and use to determine order of iteration over obj props
+ collectionKeys = [];
+ for (var itemKey in collection) {
+ if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {
+ collectionKeys.push(itemKey);
+ }
+ }
+ collectionKeys.sort();
+ }
+
+ collectionLength = collectionKeys.length;
+ nextBlockOrder = new Array(collectionLength);
+
+ // locate existing items
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ trackById = trackByIdFn(key, value, index);
+ if (lastBlockMap[trackById]) {
+ // found previously seen block
+ block = lastBlockMap[trackById];
+ delete lastBlockMap[trackById];
+ nextBlockMap[trackById] = block;
+ nextBlockOrder[index] = block;
+ } else if (nextBlockMap[trackById]) {
+ // if collision detected. restore lastBlockMap and throw an error
+ forEach(nextBlockOrder, function(block) {
+ if (block && block.scope) lastBlockMap[block.id] = block;
+ });
+ throw ngRepeatMinErr('dupes',
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
+ expression, trackById, value);
+ } else {
+ // new never before seen block
+ nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
+ nextBlockMap[trackById] = true;
+ }
+ }
+
+ // remove leftover items
+ for (var blockKey in lastBlockMap) {
+ block = lastBlockMap[blockKey];
+ elementsToRemove = getBlockNodes(block.clone);
+ $animate.leave(elementsToRemove);
+ if (elementsToRemove[0].parentNode) {
+ // if the element was not removed yet because of pending animation, mark it as deleted
+ // so that we can ignore it later
+ for (index = 0, length = elementsToRemove.length; index < length; index++) {
+ elementsToRemove[index][NG_REMOVED] = true;
+ }
+ }
+ block.scope.$destroy();
+ }
+
+ // we are not using forEach for perf reasons (trying to avoid #call)
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ block = nextBlockOrder[index];
+
+ if (block.scope) {
+ // if we have already seen this object, then we need to reuse the
+ // associated scope/element
+
+ nextNode = previousNode;
+
+ // skip nodes that are already pending removal via leave animation
+ do {
+ nextNode = nextNode.nextSibling;
+ } while (nextNode && nextNode[NG_REMOVED]);
+
+ if (getBlockStart(block) != nextNode) {
+ // existing item which got moved
+ $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
+ }
+ previousNode = getBlockEnd(block);
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ } else {
+ // new item which we don't know about
+ $transclude(function ngRepeatTransclude(clone, scope) {
+ block.scope = scope;
+ // http://jsperf.com/clone-vs-createcomment
+ var endNode = ngRepeatEndComment.cloneNode(false);
+ clone[clone.length++] = endNode;
+
+ // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
+ $animate.enter(clone, null, jqLite(previousNode));
+ previousNode = endNode;
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block.clone = clone;
+ nextBlockMap[block.id] = block;
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ });
+ }
+ }
+ lastBlockMap = nextBlockMap;
+ });
+ };
+ }
+ };
+}];
+
+var NG_HIDE_CLASS = 'ng-hide';
+var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
+/**
+ * @ngdoc directive
+ * @name ngShow
+ *
+ * @description
+ * The `ngShow` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
+ * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is visible) -->
+ * <div ng-show="myValue"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is hidden) -->
+ * <div ng-show="myValue" class="ng-hide"></div>
+ * ```
+ *
+ * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
+ * with extra animation classes that can be added.
+ *
+ * ```css
+ * .ng-hide:not(.ng-hide-animate) {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngShow`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass except that
+ * you must also include the !important flag to override the display property
+ * so that you can perform an animation when the element is hidden during the time of the animation.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * /&#42; this is required as of 1.3x to properly
+ * apply all styling in a show/hide animation &#42;/
+ * transition: 0s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add-active,
+ * .my-element.ng-hide-remove-active {
+ * /&#42; the transition is defined in the active class &#42;/
+ * transition: 1s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
+ * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
+ *
+ * @element ANY
+ * @param {expression} ngShow If the {@link guide/expression expression} is truthy
+ * then the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-show" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-show" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-show {
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-show.ng-hide-add.ng-hide-add-active,
+ .animate-show.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transition: all linear 0.5s;
+ transition: all linear 0.5s;
+ }
+
+ .animate-show.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngShowDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
+ // we're adding a temporary, animation-specific class for ng-hide since this way
+ // we can control when the element is actually displayed on screen without having
+ // to have a global/greedy CSS selector that breaks when other animations are run.
+ // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
+ $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngHide
+ *
+ * @description
+ * The `ngHide` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
+ * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is hidden) -->
+ * <div ng-hide="myValue" class="ng-hide"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is visible) -->
+ * <div ng-hide="myValue"></div>
+ * ```
+ *
+ * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class in CSS:
+ *
+ * ```css
+ * .ng-hide {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngHide`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
+ * CSS class is added and removed for you instead of your own CSS class.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * transition: 0.5s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
+ * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
+ *
+ * @element ANY
+ * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
+ * the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-hide" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-hide" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-hide {
+ -webkit-transition: all linear 0.5s;
+ transition: all linear 0.5s;
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-hide.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngHideDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
+ // The comment inside of the ngShowDirective explains why we add and
+ // remove a temporary class for the show/hide animation
+ $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngStyle
+ * @restrict AC
+ *
+ * @description
+ * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
+ *
+ * @element ANY
+ * @param {expression} ngStyle
+ *
+ * {@link guide/expression Expression} which evals to an
+ * object whose keys are CSS style names and values are corresponding values for those CSS
+ * keys.
+ *
+ * Since some CSS style names are not valid keys for an object, they must be quoted.
+ * See the 'background-color' style in the example below.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input type="button" value="set color" ng-click="myStyle={color:'red'}">
+ <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
+ <input type="button" value="clear" ng-click="myStyle={}">
+ <br/>
+ <span ng-style="myStyle">Sample Text</span>
+ <pre>myStyle={{myStyle}}</pre>
+ </file>
+ <file name="style.css">
+ span {
+ color: black;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var colorSpan = element(by.css('span'));
+
+ it('should check ng-style', function() {
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ element(by.css('input[value=\'set color\']')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
+ element(by.css('input[value=clear]')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ });
+ </file>
+ </example>
+ */
+var ngStyleDirective = ngDirective(function(scope, element, attr) {
+ scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
+ if (oldStyles && (newStyles !== oldStyles)) {
+ forEach(oldStyles, function(val, style) { element.css(style, '');});
+ }
+ if (newStyles) element.css(newStyles);
+ }, true);
+});
+
+/**
+ * @ngdoc directive
+ * @name ngSwitch
+ * @restrict EA
+ *
+ * @description
+ * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
+ * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
+ * as specified in the template.
+ *
+ * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
+ * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
+ * matches the value obtained from the evaluated expression. In other words, you define a container element
+ * (where you place the directive), place an expression on the **`on="..."` attribute**
+ * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
+ * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
+ * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
+ * attribute is displayed.
+ *
+ * <div class="alert alert-info">
+ * Be aware that the attribute values to match against cannot be expressions. They are interpreted
+ * as literal string values to match against.
+ * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
+ * value of the expression `$scope.someVal`.
+ * </div>
+
+ * @animations
+ * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
+ * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
+ *
+ * @usage
+ *
+ * ```
+ * <ANY ng-switch="expression">
+ * <ANY ng-switch-when="matchValue1">...</ANY>
+ * <ANY ng-switch-when="matchValue2">...</ANY>
+ * <ANY ng-switch-default>...</ANY>
+ * </ANY>
+ * ```
+ *
+ *
+ * @scope
+ * @priority 1200
+ * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
+ * On child elements add:
+ *
+ * * `ngSwitchWhen`: the case statement to match against. If match then this
+ * case will be displayed. If the same match appears multiple times, all the
+ * elements will be displayed.
+ * * `ngSwitchDefault`: the default case when no other case match. If there
+ * are multiple default cases, all of them will be displayed when no other
+ * case match.
+ *
+ *
+ * @example
+ <example module="switchExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="selection" ng-options="item for item in items">
+ </select>
+ <code>selection={{selection}}</code>
+ <hr/>
+ <div class="animate-switch-container"
+ ng-switch on="selection">
+ <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
+ <div class="animate-switch" ng-switch-when="home">Home Span</div>
+ <div class="animate-switch" ng-switch-default>default</div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('switchExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.items = ['settings', 'home', 'other'];
+ $scope.selection = $scope.items[0];
+ }]);
+ </file>
+ <file name="animations.css">
+ .animate-switch-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .animate-switch {
+ padding:10px;
+ }
+
+ .animate-switch.ng-animate {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ }
+
+ .animate-switch.ng-leave.ng-leave-active,
+ .animate-switch.ng-enter {
+ top:-50px;
+ }
+ .animate-switch.ng-leave,
+ .animate-switch.ng-enter.ng-enter-active {
+ top:0;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var switchElem = element(by.css('[ng-switch]'));
+ var select = element(by.model('selection'));
+
+ it('should start in settings', function() {
+ expect(switchElem.getText()).toMatch(/Settings Div/);
+ });
+ it('should change to home', function() {
+ select.all(by.css('option')).get(1).click();
+ expect(switchElem.getText()).toMatch(/Home Span/);
+ });
+ it('should select default', function() {
+ select.all(by.css('option')).get(2).click();
+ expect(switchElem.getText()).toMatch(/default/);
+ });
+ </file>
+ </example>
+ */
+var ngSwitchDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'EA',
+ require: 'ngSwitch',
+
+ // asks for $scope to fool the BC controller module
+ controller: ['$scope', function ngSwitchController() {
+ this.cases = {};
+ }],
+ link: function(scope, element, attr, ngSwitchController) {
+ var watchExpr = attr.ngSwitch || attr.on,
+ selectedTranscludes = [],
+ selectedElements = [],
+ previousLeaveAnimations = [],
+ selectedScopes = [];
+
+ var spliceFactory = function(array, index) {
+ return function() { array.splice(index, 1); };
+ };
+
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
+ var i, ii;
+ for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
+ $animate.cancel(previousLeaveAnimations[i]);
+ }
+ previousLeaveAnimations.length = 0;
+
+ for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
+ var selected = getBlockNodes(selectedElements[i].clone);
+ selectedScopes[i].$destroy();
+ var promise = previousLeaveAnimations[i] = $animate.leave(selected);
+ promise.then(spliceFactory(previousLeaveAnimations, i));
+ }
+
+ selectedElements.length = 0;
+ selectedScopes.length = 0;
+
+ if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
+ forEach(selectedTranscludes, function(selectedTransclude) {
+ selectedTransclude.transclude(function(caseElement, selectedScope) {
+ selectedScopes.push(selectedScope);
+ var anchor = selectedTransclude.element;
+ caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
+ var block = { clone: caseElement };
+
+ selectedElements.push(block);
+ $animate.enter(caseElement, anchor.parent(), anchor);
+ });
+ });
+ }
+ });
+ }
+ };
+}];
+
+var ngSwitchWhenDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attrs, ctrl, $transclude) {
+ ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
+ ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
+ }
+});
+
+var ngSwitchDefaultDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attr, ctrl, $transclude) {
+ ctrl.cases['?'] = (ctrl.cases['?'] || []);
+ ctrl.cases['?'].push({ transclude: $transclude, element: element });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngTransclude
+ * @restrict EAC
+ *
+ * @description
+ * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
+ *
+ * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
+ *
+ * @element ANY
+ *
+ * @example
+ <example module="transcludeExample">
+ <file name="index.html">
+ <script>
+ angular.module('transcludeExample', [])
+ .directive('pane', function(){
+ return {
+ restrict: 'E',
+ transclude: true,
+ scope: { title:'@' },
+ template: '<div style="border: 1px solid black;">' +
+ '<div style="background-color: gray">{{title}}</div>' +
+ '<ng-transclude></ng-transclude>' +
+ '</div>'
+ };
+ })
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.title = 'Lorem Ipsum';
+ $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input ng-model="title"> <br/>
+ <textarea ng-model="text"></textarea> <br/>
+ <pane title="{{title}}">{{text}}</pane>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should have transcluded', function() {
+ var titleElement = element(by.model('title'));
+ titleElement.clear();
+ titleElement.sendKeys('TITLE');
+ var textElement = element(by.model('text'));
+ textElement.clear();
+ textElement.sendKeys('TEXT');
+ expect(element(by.binding('title')).getText()).toEqual('TITLE');
+ expect(element(by.binding('text')).getText()).toEqual('TEXT');
+ });
+ </file>
+ </example>
+ *
+ */
+var ngTranscludeDirective = ngDirective({
+ restrict: 'EAC',
+ link: function($scope, $element, $attrs, controller, $transclude) {
+ if (!$transclude) {
+ throw minErr('ngTransclude')('orphan',
+ 'Illegal use of ngTransclude directive in the template! ' +
+ 'No parent directive that requires a transclusion found. ' +
+ 'Element: {0}',
+ startingTag($element));
+ }
+
+ $transclude(function(clone) {
+ $element.empty();
+ $element.append(clone);
+ });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name script
+ * @restrict E
+ *
+ * @description
+ * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
+ * template can be used by {@link ng.directive:ngInclude `ngInclude`},
+ * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
+ * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
+ * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
+ *
+ * @param {string} type Must be set to `'text/ng-template'`.
+ * @param {string} id Cache name of the template.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <script type="text/ng-template" id="/tpl.html">
+ Content of the template.
+ </script>
+
+ <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
+ <div id="tpl-content" ng-include src="currentTpl"></div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should load template defined inside script tag', function() {
+ element(by.css('#tpl-link')).click();
+ expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
+ });
+ </file>
+ </example>
+ */
+var scriptDirective = ['$templateCache', function($templateCache) {
+ return {
+ restrict: 'E',
+ terminal: true,
+ compile: function(element, attr) {
+ if (attr.type == 'text/ng-template') {
+ var templateUrl = attr.id,
+ text = element[0].text;
+
+ $templateCache.put(templateUrl, text);
+ }
+ }
+ };
+}];
+
+var ngOptionsMinErr = minErr('ngOptions');
+/**
+ * @ngdoc directive
+ * @name select
+ * @restrict E
+ *
+ * @description
+ * HTML `SELECT` element with angular data-binding.
+ *
+ * # `ngOptions`
+ *
+ * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
+ * elements for the `<select>` element using the array or object obtained by evaluating the
+ * `ngOptions` comprehension expression.
+ *
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
+ * similar result. However, `ngOptions` provides some benefits such as reducing memory and
+ * increasing speed by not creating a new scope for each repeated instance, as well as providing
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
+ * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
+ * to a non-string value. This is because an option element can only be bound to string values at
+ * present.
+ *
+ * When an item in the `<select>` menu is selected, the array element or object property
+ * represented by the selected option will be bound to the model identified by the `ngModel`
+ * directive.
+ *
+ * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
+ * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
+ * option. See example below for demonstration.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
+ * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
+ * </div>
+ *
+ * ## `select` **`as`**
+ *
+ * Using `select` **`as`** will bind the result of the `select` expression to the model, but
+ * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
+ * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
+ * is used, the result of that expression will be set as the value of the `option` and `select` elements.
+ *
+ *
+ * ### `select` **`as`** and **`track by`**
+ *
+ * <div class="alert alert-warning">
+ * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
+ * </div>
+ *
+ * Consider the following example:
+ *
+ * ```html
+ * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
+ * ```
+ *
+ * ```js
+ * $scope.values = [{
+ * id: 1,
+ * label: 'aLabel',
+ * subItem: { name: 'aSubItem' }
+ * }, {
+ * id: 2,
+ * label: 'bLabel',
+ * subItem: { name: 'bSubItem' }
+ * }];
+ *
+ * $scope.selected = { name: 'aSubItem' };
+ * ```
+ *
+ * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
+ * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
+ * following:
+ *
+ * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
+ * 2. Apply **`track by`** to the already selected value in `ngModel`.
+ * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
+ * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
+ * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
+ * selected" option.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required The control is considered valid only if value is entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {comprehension_expression=} ngOptions in one of the following forms:
+ *
+ * * for array data sources:
+ * * `label` **`for`** `value` **`in`** `array`
+ * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
+ * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
+ * (for including a filter with `track by`)
+ * * for object data sources:
+ * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`group by`** `group`
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
+ *
+ * Where:
+ *
+ * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
+ * * `value`: local variable which will refer to each item in the `array` or each property value
+ * of `object` during iteration.
+ * * `key`: local variable which will refer to a property name in `object` during iteration.
+ * * `label`: The result of this expression will be the label for `<option>` element. The
+ * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
+ * * `select`: The result of this expression will be bound to the model of the parent `<select>`
+ * element. If not specified, `select` expression will default to `value`.
+ * * `group`: The result of this expression will be used to group options using the `<optgroup>`
+ * DOM element.
+ * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
+ * used to identify the objects in the array. The `trackexpr` will most likely refer to the
+ * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
+ * even when the options are recreated (e.g. reloaded from the server).
+ *
+ * @example
+ <example module="selectExample">
+ <file name="index.html">
+ <script>
+ angular.module('selectExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.colors = [
+ {name:'black', shade:'dark'},
+ {name:'white', shade:'light'},
+ {name:'red', shade:'dark'},
+ {name:'blue', shade:'dark'},
+ {name:'yellow', shade:'light'}
+ ];
+ $scope.myColor = $scope.colors[2]; // red
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <ul>
+ <li ng-repeat="color in colors">
+ Name: <input ng-model="color.name">
+ [<a href ng-click="colors.splice($index, 1)">X</a>]
+ </li>
+ <li>
+ [<a href ng-click="colors.push({})">add</a>]
+ </li>
+ </ul>
+ <hr/>
+ Color (null not allowed):
+ <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>
+
+ Color (null allowed):
+ <span class="nullable">
+ <select ng-model="myColor" ng-options="color.name for color in colors">
+ <option value="">-- choose color --</option>
+ </select>
+ </span><br/>
+
+ Color grouped by shade:
+ <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
+ </select><br/>
+
+
+ Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
+ <hr/>
+ Currently selected: {{ {selected_color:myColor} }}
+ <div style="border:solid 1px black; height:20px"
+ ng-style="{'background-color':myColor.name}">
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-options', function() {
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
+ element.all(by.model('myColor')).first().click();
+ element.all(by.css('select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
+ element(by.css('.nullable select[ng-model="myColor"]')).click();
+ element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
+ });
+ </file>
+ </example>
+ */
+
+var ngOptionsDirective = valueFn({
+ restrict: 'A',
+ terminal: true
+});
+
+// jshint maxlen: false
+var selectDirective = ['$compile', '$parse', function($compile, $parse) {
+ //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
+ var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
+ nullModelCtrl = {$setViewValue: noop};
+// jshint maxlen: 100
+
+ return {
+ restrict: 'E',
+ require: ['select', '?ngModel'],
+ controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
+ var self = this,
+ optionsMap = {},
+ ngModelCtrl = nullModelCtrl,
+ nullOption,
+ unknownOption;
+
+
+ self.databound = $attrs.ngModel;
+
+
+ self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
+ ngModelCtrl = ngModelCtrl_;
+ nullOption = nullOption_;
+ unknownOption = unknownOption_;
+ };
+
+
+ self.addOption = function(value, element) {
+ assertNotHasOwnProperty(value, '"option value"');
+ optionsMap[value] = true;
+
+ if (ngModelCtrl.$viewValue == value) {
+ $element.val(value);
+ if (unknownOption.parent()) unknownOption.remove();
+ }
+ // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
+ // Adding an <option selected="selected"> element to a <select required="required"> should
+ // automatically select the new element
+ if (element && element[0].hasAttribute('selected')) {
+ element[0].selected = true;
+ }
+ };
+
+
+ self.removeOption = function(value) {
+ if (this.hasOption(value)) {
+ delete optionsMap[value];
+ if (ngModelCtrl.$viewValue === value) {
+ this.renderUnknownOption(value);
+ }
+ }
+ };
+
+
+ self.renderUnknownOption = function(val) {
+ var unknownVal = '? ' + hashKey(val) + ' ?';
+ unknownOption.val(unknownVal);
+ $element.prepend(unknownOption);
+ $element.val(unknownVal);
+ unknownOption.prop('selected', true); // needed for IE
+ };
+
+
+ self.hasOption = function(value) {
+ return optionsMap.hasOwnProperty(value);
+ };
+
+ $scope.$on('$destroy', function() {
+ // disable unknown option so that we don't do work when the whole select is being destroyed
+ self.renderUnknownOption = noop;
+ });
+ }],
+
+ link: function(scope, element, attr, ctrls) {
+ // if ngModel is not defined, we don't need to do anything
+ if (!ctrls[1]) return;
+
+ var selectCtrl = ctrls[0],
+ ngModelCtrl = ctrls[1],
+ multiple = attr.multiple,
+ optionsExp = attr.ngOptions,
+ nullOption = false, // if false, user will not be able to select it (used by ngOptions)
+ emptyOption,
+ renderScheduled = false,
+ // we can't just jqLite('<option>') since jqLite is not smart enough
+ // to create it in <select> and IE barfs otherwise.
+ optionTemplate = jqLite(document.createElement('option')),
+ optGroupTemplate =jqLite(document.createElement('optgroup')),
+ unknownOption = optionTemplate.clone();
+
+ // find "null" option
+ for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
+ if (children[i].value === '') {
+ emptyOption = nullOption = children.eq(i);
+ break;
+ }
+ }
+
+ selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
+
+ // required validator
+ if (multiple) {
+ ngModelCtrl.$isEmpty = function(value) {
+ return !value || value.length === 0;
+ };
+ }
+
+ if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
+ else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
+ else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
+
+
+ ////////////////////////////
+
+
+
+ function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
+ ngModelCtrl.$render = function() {
+ var viewValue = ngModelCtrl.$viewValue;
+
+ if (selectCtrl.hasOption(viewValue)) {
+ if (unknownOption.parent()) unknownOption.remove();
+ selectElement.val(viewValue);
+ if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
+ } else {
+ if (viewValue == null && emptyOption) {
+ selectElement.val('');
+ } else {
+ selectCtrl.renderUnknownOption(viewValue);
+ }
+ }
+ };
+
+ selectElement.on('change', function() {
+ scope.$apply(function() {
+ if (unknownOption.parent()) unknownOption.remove();
+ ngModelCtrl.$setViewValue(selectElement.val());
+ });
+ });
+ }
+
+ function setupAsMultiple(scope, selectElement, ctrl) {
+ var lastView;
+ ctrl.$render = function() {
+ var items = new HashMap(ctrl.$viewValue);
+ forEach(selectElement.find('option'), function(option) {
+ option.selected = isDefined(items.get(option.value));
+ });
+ };
+
+ // we have to do it on each watch since ngModel watches reference, but
+ // we need to work of an array, so we need to see if anything was inserted/removed
+ scope.$watch(function selectMultipleWatch() {
+ if (!equals(lastView, ctrl.$viewValue)) {
+ lastView = shallowCopy(ctrl.$viewValue);
+ ctrl.$render();
+ }
+ });
+
+ selectElement.on('change', function() {
+ scope.$apply(function() {
+ var array = [];
+ forEach(selectElement.find('option'), function(option) {
+ if (option.selected) {
+ array.push(option.value);
+ }
+ });
+ ctrl.$setViewValue(array);
+ });
+ });
+ }
+
+ function setupAsOptions(scope, selectElement, ctrl) {
+ var match;
+
+ if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {
+ throw ngOptionsMinErr('iexp',
+ "Expected expression in form of " +
+ "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
+ " but got '{0}'. Element: {1}",
+ optionsExp, startingTag(selectElement));
+ }
+
+ var displayFn = $parse(match[2] || match[1]),
+ valueName = match[4] || match[6],
+ selectAs = / as /.test(match[0]) && match[1],
+ selectAsFn = selectAs ? $parse(selectAs) : null,
+ keyName = match[5],
+ groupByFn = $parse(match[3] || ''),
+ valueFn = $parse(match[2] ? match[1] : valueName),
+ valuesFn = $parse(match[7]),
+ track = match[8],
+ trackFn = track ? $parse(match[8]) : null,
+ trackKeysCache = {},
+ // This is an array of array of existing option groups in DOM.
+ // We try to reuse these if possible
+ // - optionGroupsCache[0] is the options with no option group
+ // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
+ optionGroupsCache = [[{element: selectElement, label:''}]],
+ //re-usable object to represent option's locals
+ locals = {};
+
+ if (nullOption) {
+ // compile the element since there might be bindings in it
+ $compile(nullOption)(scope);
+
+ // remove the class, which is added automatically because we recompile the element and it
+ // becomes the compilation root
+ nullOption.removeClass('ng-scope');
+
+ // we need to remove it before calling selectElement.empty() because otherwise IE will
+ // remove the label from the element. wtf?
+ nullOption.remove();
+ }
+
+ // clear contents, we'll add what's needed based on the model
+ selectElement.empty();
+
+ selectElement.on('change', selectionChanged);
+
+ ctrl.$render = render;
+
+ scope.$watchCollection(valuesFn, scheduleRendering);
+ scope.$watchCollection(getLabels, scheduleRendering);
+
+ if (multiple) {
+ scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);
+ }
+
+ // ------------------------------------------------------------------ //
+
+ function callExpression(exprFn, key, value) {
+ locals[valueName] = value;
+ if (keyName) locals[keyName] = key;
+ return exprFn(scope, locals);
+ }
+
+ function selectionChanged() {
+ scope.$apply(function() {
+ var collection = valuesFn(scope) || [];
+ var viewValue;
+ if (multiple) {
+ viewValue = [];
+ forEach(selectElement.val(), function(selectedKey) {
+ selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;
+ viewValue.push(getViewValue(selectedKey, collection[selectedKey]));
+ });
+ } else {
+ var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();
+ viewValue = getViewValue(selectedKey, collection[selectedKey]);
+ }
+ ctrl.$setViewValue(viewValue);
+ render();
+ });
+ }
+
+ function getViewValue(key, value) {
+ if (key === '?') {
+ return undefined;
+ } else if (key === '') {
+ return null;
+ } else {
+ var viewValueFn = selectAsFn ? selectAsFn : valueFn;
+ return callExpression(viewValueFn, key, value);
+ }
+ }
+
+ function getLabels() {
+ var values = valuesFn(scope);
+ var toDisplay;
+ if (values && isArray(values)) {
+ toDisplay = new Array(values.length);
+ for (var i = 0, ii = values.length; i < ii; i++) {
+ toDisplay[i] = callExpression(displayFn, i, values[i]);
+ }
+ return toDisplay;
+ } else if (values) {
+ // TODO: Add a test for this case
+ toDisplay = {};
+ for (var prop in values) {
+ if (values.hasOwnProperty(prop)) {
+ toDisplay[prop] = callExpression(displayFn, prop, values[prop]);
+ }
+ }
+ }
+ return toDisplay;
+ }
+
+ function createIsSelectedFn(viewValue) {
+ var selectedSet;
+ if (multiple) {
+ if (trackFn && isArray(viewValue)) {
+
+ selectedSet = new HashMap([]);
+ for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {
+ // tracking by key
+ selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);
+ }
+ } else {
+ selectedSet = new HashMap(viewValue);
+ }
+ } else if (trackFn) {
+ viewValue = callExpression(trackFn, null, viewValue);
+ }
+
+ return function isSelected(key, value) {
+ var compareValueFn;
+ if (trackFn) {
+ compareValueFn = trackFn;
+ } else if (selectAsFn) {
+ compareValueFn = selectAsFn;
+ } else {
+ compareValueFn = valueFn;
+ }
+
+ if (multiple) {
+ return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));
+ } else {
+ return viewValue === callExpression(compareValueFn, key, value);
+ }
+ };
+ }
+
+ function scheduleRendering() {
+ if (!renderScheduled) {
+ scope.$$postDigest(render);
+ renderScheduled = true;
+ }
+ }
+
+ /**
+ * A new labelMap is created with each render.
+ * This function is called for each existing option with added=false,
+ * and each new option with added=true.
+ * - Labels that are passed to this method twice,
+ * (once with added=true and once with added=false) will end up with a value of 0, and
+ * will cause no change to happen to the corresponding option.
+ * - Labels that are passed to this method only once with added=false will end up with a
+ * value of -1 and will eventually be passed to selectCtrl.removeOption()
+ * - Labels that are passed to this method only once with added=true will end up with a
+ * value of 1 and will eventually be passed to selectCtrl.addOption()
+ */
+ function updateLabelMap(labelMap, label, added) {
+ labelMap[label] = labelMap[label] || 0;
+ labelMap[label] += (added ? 1 : -1);
+ }
+
+ function render() {
+ renderScheduled = false;
+
+ // Temporary location for the option groups before we render them
+ var optionGroups = {'':[]},
+ optionGroupNames = [''],
+ optionGroupName,
+ optionGroup,
+ option,
+ existingParent, existingOptions, existingOption,
+ viewValue = ctrl.$viewValue,
+ values = valuesFn(scope) || [],
+ keys = keyName ? sortedKeys(values) : values,
+ key,
+ value,
+ groupLength, length,
+ groupIndex, index,
+ labelMap = {},
+ selected,
+ isSelected = createIsSelectedFn(viewValue),
+ anySelected = false,
+ lastElement,
+ element,
+ label,
+ optionId;
+
+ trackKeysCache = {};
+
+ // We now build up the list of options we need (we merge later)
+ for (index = 0; length = keys.length, index < length; index++) {
+ key = index;
+ if (keyName) {
+ key = keys[index];
+ if (key.charAt(0) === '$') continue;
+ }
+ value = values[key];
+
+ optionGroupName = callExpression(groupByFn, key, value) || '';
+ if (!(optionGroup = optionGroups[optionGroupName])) {
+ optionGroup = optionGroups[optionGroupName] = [];
+ optionGroupNames.push(optionGroupName);
+ }
+
+ selected = isSelected(key, value);
+ anySelected = anySelected || selected;
+
+ label = callExpression(displayFn, key, value); // what will be seen by the user
+
+ // doing displayFn(scope, locals) || '' overwrites zero values
+ label = isDefined(label) ? label : '';
+ optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);
+ if (trackFn) {
+ trackKeysCache[optionId] = key;
+ }
+
+ optionGroup.push({
+ // either the index into array or key from object
+ id: optionId,
+ label: label,
+ selected: selected // determine if we should be selected
+ });
+ }
+ if (!multiple) {
+ if (nullOption || viewValue === null) {
+ // insert null option if we have a placeholder, or the model is null
+ optionGroups[''].unshift({id:'', label:'', selected:!anySelected});
+ } else if (!anySelected) {
+ // option could not be found, we have to insert the undefined item
+ optionGroups[''].unshift({id:'?', label:'', selected:true});
+ }
+ }
+
+ // Now we need to update the list of DOM nodes to match the optionGroups we computed above
+ for (groupIndex = 0, groupLength = optionGroupNames.length;
+ groupIndex < groupLength;
+ groupIndex++) {
+ // current option group name or '' if no group
+ optionGroupName = optionGroupNames[groupIndex];
+
+ // list of options for that group. (first item has the parent)
+ optionGroup = optionGroups[optionGroupName];
+
+ if (optionGroupsCache.length <= groupIndex) {
+ // we need to grow the optionGroups
+ existingParent = {
+ element: optGroupTemplate.clone().attr('label', optionGroupName),
+ label: optionGroup.label
+ };
+ existingOptions = [existingParent];
+ optionGroupsCache.push(existingOptions);
+ selectElement.append(existingParent.element);
+ } else {
+ existingOptions = optionGroupsCache[groupIndex];
+ existingParent = existingOptions[0]; // either SELECT (no group) or OPTGROUP element
+
+ // update the OPTGROUP label if not the same.
+ if (existingParent.label != optionGroupName) {
+ existingParent.element.attr('label', existingParent.label = optionGroupName);
+ }
+ }
+
+ lastElement = null; // start at the beginning
+ for (index = 0, length = optionGroup.length; index < length; index++) {
+ option = optionGroup[index];
+ if ((existingOption = existingOptions[index + 1])) {
+ // reuse elements
+ lastElement = existingOption.element;
+ if (existingOption.label !== option.label) {
+ updateLabelMap(labelMap, existingOption.label, false);
+ updateLabelMap(labelMap, option.label, true);
+ lastElement.text(existingOption.label = option.label);
+ lastElement.prop('label', existingOption.label);
+ }
+ if (existingOption.id !== option.id) {
+ lastElement.val(existingOption.id = option.id);
+ }
+ // lastElement.prop('selected') provided by jQuery has side-effects
+ if (lastElement[0].selected !== option.selected) {
+ lastElement.prop('selected', (existingOption.selected = option.selected));
+ if (msie) {
+ // See #7692
+ // The selected item wouldn't visually update on IE without this.
+ // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well
+ lastElement.prop('selected', existingOption.selected);
+ }
+ }
+ } else {
+ // grow elements
+
+ // if it's a null option
+ if (option.id === '' && nullOption) {
+ // put back the pre-compiled element
+ element = nullOption;
+ } else {
+ // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but
+ // in this version of jQuery on some browser the .text() returns a string
+ // rather then the element.
+ (element = optionTemplate.clone())
+ .val(option.id)
+ .prop('selected', option.selected)
+ .attr('selected', option.selected)
+ .prop('label', option.label)
+ .text(option.label);
+ }
+
+ existingOptions.push(existingOption = {
+ element: element,
+ label: option.label,
+ id: option.id,
+ selected: option.selected
+ });
+ updateLabelMap(labelMap, option.label, true);
+ if (lastElement) {
+ lastElement.after(element);
+ } else {
+ existingParent.element.append(element);
+ }
+ lastElement = element;
+ }
+ }
+ // remove any excessive OPTIONs in a group
+ index++; // increment since the existingOptions[0] is parent element not OPTION
+ while (existingOptions.length > index) {
+ option = existingOptions.pop();
+ updateLabelMap(labelMap, option.label, false);
+ option.element.remove();
+ }
+ }
+ // remove any excessive OPTGROUPs from select
+ while (optionGroupsCache.length > groupIndex) {
+ // remove all the labels in the option group
+ optionGroup = optionGroupsCache.pop();
+ for (index = 1; index < optionGroup.length; ++index) {
+ updateLabelMap(labelMap, optionGroup[index].label, false);
+ }
+ optionGroup[0].element.remove();
+ }
+ forEach(labelMap, function(count, label) {
+ if (count > 0) {
+ selectCtrl.addOption(label);
+ } else if (count < 0) {
+ selectCtrl.removeOption(label);
+ }
+ });
+ }
+ }
+ }
+ };
+}];
+
+var optionDirective = ['$interpolate', function($interpolate) {
+ var nullSelectCtrl = {
+ addOption: noop,
+ removeOption: noop
+ };
+
+ return {
+ restrict: 'E',
+ priority: 100,
+ compile: function(element, attr) {
+ if (isUndefined(attr.value)) {
+ var interpolateFn = $interpolate(element.text(), true);
+ if (!interpolateFn) {
+ attr.$set('value', element.text());
+ }
+ }
+
+ return function(scope, element, attr) {
+ var selectCtrlName = '$selectController',
+ parent = element.parent(),
+ selectCtrl = parent.data(selectCtrlName) ||
+ parent.parent().data(selectCtrlName); // in case we are in optgroup
+
+ if (!selectCtrl || !selectCtrl.databound) {
+ selectCtrl = nullSelectCtrl;
+ }
+
+ if (interpolateFn) {
+ scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
+ attr.$set('value', newVal);
+ if (oldVal !== newVal) {
+ selectCtrl.removeOption(oldVal);
+ }
+ selectCtrl.addOption(newVal, element);
+ });
+ } else {
+ selectCtrl.addOption(attr.value, element);
+ }
+
+ element.on('$destroy', function() {
+ selectCtrl.removeOption(attr.value);
+ });
+ };
+ }
+ };
+}];
+
+var styleDirective = valueFn({
+ restrict: 'E',
+ terminal: false
+});
+
+var requiredDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+ attr.required = true; // force truthy in case we are on non input element
+
+ ctrl.$validators.required = function(modelValue, viewValue) {
+ return !attr.required || !ctrl.$isEmpty(viewValue);
+ };
+
+ attr.$observe('required', function() {
+ ctrl.$validate();
+ });
+ }
+ };
+};
+
+
+var patternDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var regexp, patternExp = attr.ngPattern || attr.pattern;
+ attr.$observe('pattern', function(regex) {
+ if (isString(regex) && regex.length > 0) {
+ regex = new RegExp('^' + regex + '$');
+ }
+
+ if (regex && !regex.test) {
+ throw minErr('ngPattern')('noregexp',
+ 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
+ regex, startingTag(elm));
+ }
+
+ regexp = regex || undefined;
+ ctrl.$validate();
+ });
+
+ ctrl.$validators.pattern = function(modelValue, viewValue) {
+ // HTML5 pattern constraint validates the input value, so we validate the viewValue
+ return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
+ };
+ }
+ };
+};
+
+
+var maxlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var maxlength = -1;
+ attr.$observe('maxlength', function(value) {
+ var intVal = int(value);
+ maxlength = isNaN(intVal) ? -1 : intVal;
+ ctrl.$validate();
+ });
+ ctrl.$validators.maxlength = function(modelValue, viewValue) {
+ return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
+ };
+ }
+ };
+};
+
+var minlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var minlength = 0;
+ attr.$observe('minlength', function(value) {
+ minlength = int(value) || 0;
+ ctrl.$validate();
+ });
+ ctrl.$validators.minlength = function(modelValue, viewValue) {
+ return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
+ };
+ }
+ };
+};
+
+ if (window.angular.bootstrap) {
+ //AngularJS is already loaded, so we can return here...
+ console.log('WARNING: Tried to load angular more than once.');
+ return;
+ }
+
+ //try to bind to jquery now so that one can write jqLite(document).ready()
+ //but we will rebind on bootstrap again.
+ bindJQuery();
+
+ publishExternalAPI(angular);
+
+ jqLite(document).ready(function() {
+ angularInit(document, bootstrap);
+ });
+
+})(window, document);
+
+!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); \ No newline at end of file
diff --git a/afb-client/bower_components/angular/angular.min.js b/afb-client/bower_components/angular/angular.min.js
new file mode 100644
index 0000000..8dcf6e0
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js
@@ -0,0 +1,253 @@
+/*
+ AngularJS v1.3.20
+ (c) 2010-2014 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(R,W,u){'use strict';function S(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.20/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ta(b){if(null==b||Ua(b))return!1;var a="length"in Object(b)&&b.length;
+return b.nodeType===qa&&a?!0:x(b)||H(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function r(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(H(b)||Ta(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==r)b.forEach(a,c,b);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d,b);return b}function Ed(b,a,c){for(var d=Object.keys(b).sort(),
+e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function lc(b){return function(a,c){b(c,a)}}function Fd(){return++rb}function mc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function w(b){for(var a=b.$$hashKey,c=1,d=arguments.length;c<d;c++){var e=arguments[c];if(e)for(var f=Object.keys(e),g=0,h=f.length;g<h;g++){var l=f[g];b[l]=e[l]}}mc(b,a);return b}function aa(b){return parseInt(b,10)}function Ob(b,a){return w(Object.create(b),a)}function A(){}function ra(b){return b}function ea(b){return function(){return b}}
+function D(b){return"undefined"===typeof b}function y(b){return"undefined"!==typeof b}function L(b){return null!==b&&"object"===typeof b}function x(b){return"string"===typeof b}function Y(b){return"number"===typeof b}function ha(b){return"[object Date]"===Ca.call(b)}function z(b){return"function"===typeof b}function Va(b){return"[object RegExp]"===Ca.call(b)}function Ua(b){return b&&b.window===b}function Wa(b){return b&&b.$evalAsync&&b.$watch}function Xa(b){return"boolean"===typeof b}function nc(b){return!(!b||
+!(b.nodeName||b.prop&&b.attr&&b.find))}function Gd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function wa(b){return K(b.nodeName||b[0]&&b[0].nodeName)}function Ya(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return a}function Da(b,a,c,d){if(Ua(b)||Wa(b))throw Ja("cpws");if(a){if(b===a)throw Ja("cpi");c=c||[];d=d||[];if(L(b)){var e=c.indexOf(b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(H(b))for(var f=a.length=0;f<b.length;f++)e=Da(b[f],null,c,d),L(b[f])&&(c.push(b[f]),
+d.push(e)),a.push(e);else{var g=a.$$hashKey;H(a)?a.length=0:r(a,function(b,c){delete a[c]});for(f in b)b.hasOwnProperty(f)&&(e=Da(b[f],null,c,d),L(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e);mc(a,g)}}else if(a=b)H(b)?a=Da(b,[],c,d):ha(b)?a=new Date(b.getTime()):Va(b)?(a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex):L(b)&&(e=Object.create(Object.getPrototypeOf(b)),a=Da(b,e,c,d));return a}function sa(b,a){if(H(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(L(b))for(c in a=
+a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ia(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(H(b)){if(!H(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ia(b[d],a[d]))return!1;return!0}}else{if(ha(b))return ha(a)?ia(b.getTime(),a.getTime()):!1;if(Va(b))return Va(a)?b.toString()==a.toString():!1;if(Wa(b)||Wa(a)||Ua(b)||Ua(a)||H(a)||ha(a)||Va(a))return!1;c={};for(d in b)if("$"!==
+d.charAt(0)&&!z(b[d])){if(!ia(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&"$"!==d.charAt(0)&&a[d]!==u&&!z(a[d]))return!1;return!0}return!1}function Za(b,a,c){return b.concat($a.call(a,c))}function oc(b,a){var c=2<arguments.length?$a.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?a.apply(b,Za(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Hd(b,a){var c=a;"string"===typeof b&&
+"$"===b.charAt(0)&&"$"===b.charAt(1)?c=u:Ua(a)?c="$WINDOW":a&&W===a?c="$DOCUMENT":Wa(a)&&(c="$SCOPE");return c}function ab(b,a){if("undefined"===typeof b)return u;Y(a)||(a=a?2:null);return JSON.stringify(b,Hd,a)}function pc(b){return x(b)?JSON.parse(b):b}function xa(b){b=B(b).clone();try{b.empty()}catch(a){}var c=B("<div>").append(b).html();try{return b[0].nodeType===bb?K(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+K(b)})}catch(d){return K(c)}}function qc(b){try{return decodeURIComponent(b)}catch(a){}}
+function rc(b){var a={},c,d;r((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=qc(c[0]),y(d)&&(b=y(c[1])?qc(c[1]):!0,sc.call(a,d)?H(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Pb(b){var a=[];r(b,function(b,d){H(b)?r(b,function(b){a.push(Ea(d,!0)+(!0===b?"":"="+Ea(b,!0)))}):a.push(Ea(d,!0)+(!0===b?"":"="+Ea(b,!0)))});return a.length?a.join("&"):""}function sb(b){return Ea(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Ea(b,a){return encodeURIComponent(b).replace(/%40/gi,
+"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Id(b,a){var c,d,e=tb.length;b=B(b);for(d=0;d<e;++d)if(c=tb[d]+a,x(c=b.attr(c)))return c;return null}function Jd(b,a){var c,d,e={};r(tb,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});r(tb,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Id(c,"strict-di"),
+a(c,d?[d]:[],e))}function tc(b,a,c){L(c)||(c={});c=w({strictDi:!1},c);var d=function(){b=B(b);if(b.injector()){var d=b[0]===W?"document":xa(b);throw Ja("btstrpd",d.replace(/</,"&lt;").replace(/>/,"&gt;"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=cb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",
+d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;R&&e.test(R.name)&&(c.debugInfoEnabled=!0,R.name=R.name.replace(e,""));if(R&&!f.test(R.name))return d();R.name=R.name.replace(f,"");ca.resumeBootstrap=function(b){r(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function Kd(){R.name="NG_ENABLE_DEBUG_INFO!"+R.name;R.location.reload()}function Ld(b){b=ca.element(b).injector();if(!b)throw Ja("test");return b.get("$$testability")}
+function uc(b,a){a=a||"_";return b.replace(Md,function(b,d){return(d?a:"")+b.toLowerCase()})}function Nd(){var b;vc||((ta=R.jQuery)&&ta.fn.on?(B=ta,w(ta.fn,{scope:Ka.scope,isolateScope:Ka.isolateScope,controller:Ka.controller,injector:Ka.injector,inheritedData:Ka.inheritedData}),b=ta.cleanData,ta.cleanData=function(a){var c;if(Qb)Qb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=ta._data(e,"events"))&&c.$destroy&&ta(e).triggerHandler("$destroy");b(a)}):B=T,ca.element=B,vc=!0)}function Rb(b,a,c){if(!b)throw Ja("areq",
+a||"?",c||"required");return b}function La(b,a,c){c&&H(b)&&(b=b[b.length-1]);Rb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ma(b,a){if("hasOwnProperty"===b)throw Ja("badname",a);}function wc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?oc(e,b):b}function ub(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==b);return B(c)}function ja(){return Object.create(null)}
+function Od(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=S("$injector"),d=S("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||S;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(c,d,e,f){f||(f=b);return function(){f[e||"push"]([c,d,arguments]);return t}}if(!g)throw c("nomod",f);var b=[],d=[],e=[],q=a("$injector","invoke","push",d),t={_invokeQueue:b,_configBlocks:d,
+_runBlocks:e,requires:g,name:f,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:q,run:function(a){e.push(a);return this}};h&&q(h);return t})}})}function Pd(b){w(b,{bootstrap:tc,copy:Da,extend:w,equals:ia,
+element:B,forEach:r,injector:cb,noop:A,bind:oc,toJson:ab,fromJson:pc,identity:ra,isUndefined:D,isDefined:y,isString:x,isFunction:z,isObject:L,isNumber:Y,isElement:nc,isArray:H,version:Qd,isDate:ha,lowercase:K,uppercase:vb,callbacks:{counter:0},getTestability:Ld,$$minErr:S,$$csp:db,reloadWithDebugInfo:Kd});eb=Od(R);try{eb("ngLocale")}catch(a){eb("ngLocale",[]).provider("$locale",Rd)}eb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Sd});a.provider("$compile",xc).directive({a:Td,
+input:yc,textarea:yc,form:Ud,script:Vd,select:Wd,style:Xd,option:Yd,ngBind:Zd,ngBindHtml:$d,ngBindTemplate:ae,ngClass:be,ngClassEven:ce,ngClassOdd:de,ngCloak:ee,ngController:fe,ngForm:ge,ngHide:he,ngIf:ie,ngInclude:je,ngInit:ke,ngNonBindable:le,ngPluralize:me,ngRepeat:ne,ngShow:oe,ngStyle:pe,ngSwitch:qe,ngSwitchWhen:re,ngSwitchDefault:se,ngOptions:te,ngTransclude:ue,ngModel:ve,ngList:we,ngChange:xe,pattern:zc,ngPattern:zc,required:Ac,ngRequired:Ac,minlength:Bc,ngMinlength:Bc,maxlength:Cc,ngMaxlength:Cc,
+ngValue:ye,ngModelOptions:ze}).directive({ngInclude:Ae}).directive(wb).directive(Dc);a.provider({$anchorScroll:Be,$animate:Ce,$browser:De,$cacheFactory:Ee,$controller:Fe,$document:Ge,$exceptionHandler:He,$filter:Ec,$interpolate:Ie,$interval:Je,$http:Ke,$httpBackend:Le,$location:Me,$log:Ne,$parse:Oe,$rootScope:Pe,$q:Qe,$$q:Re,$sce:Se,$sceDelegate:Te,$sniffer:Ue,$templateCache:Ve,$templateRequest:We,$$testability:Xe,$timeout:Ye,$window:Ze,$$rAF:$e,$$asyncCallback:af,$$jqLite:bf})}])}function fb(b){return b.replace(cf,
+function(a,b,d,e){return e?d.toUpperCase():d}).replace(df,"Moz$1")}function Fc(b){b=b.nodeType;return b===qa||!b||9===b}function Gc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Sb.test(b)){c=c||e.appendChild(a.createElement("div"));d=(ef.exec(b)||["",""])[1].toLowerCase();d=ka[d]||ka._default;c.innerHTML=d[1]+b.replace(ff,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Za(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";r(f,function(a){e.appendChild(a)});
+return e}function T(b){if(b instanceof T)return b;var a;x(b)&&(b=N(b),a=!0);if(!(this instanceof T)){if(a&&"<"!=b.charAt(0))throw Tb("nosel");return new T(b)}if(a){a=W;var c;b=(c=gf.exec(b))?[a.createElement(c[1])]:(c=Gc(b,a))?c.childNodes:[]}Hc(this,b)}function Ub(b){return b.cloneNode(!0)}function xb(b,a){a||yb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)yb(c[d])}function Ic(b,a,c,d){if(y(d))throw Tb("offargs");var e=(d=zb(b))&&d.events,f=d&&d.handle;if(f)if(a)r(a.split(" "),
+function(a){if(y(c)){var d=e[a];Ya(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,f,!1),delete e[a]}function yb(b,a){var c=b.ng339,d=c&&Ab[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Ic(b)),delete Ab[c],b.ng339=u))}function zb(b,a){var c=b.ng339,c=c&&Ab[c];a&&!c&&(b.ng339=c=++hf,c=Ab[c]={events:{},data:{},handle:u});return c}function Vb(b,a,c){if(Fc(b)){var d=y(c),e=!d&&a&&!L(a),
+f=!a;b=(b=zb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];w(b,a)}}}function Bb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function Cb(b,a){a&&b.setAttribute&&r(a.split(" "),function(a){b.setAttribute("class",N((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+N(a)+" "," ")))})}function Db(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");
+r(a.split(" "),function(a){a=N(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",N(c))}}function Hc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Jc(b,a){return Eb(b,"$"+(a||"ngController")+"Controller")}function Eb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=H(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=B.data(b,a[d]))!==u)return c;b=b.parentNode||
+11===b.nodeType&&b.host}}function Kc(b){for(xb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Lc(b,a){a||xb(b);var c=b.parentNode;c&&c.removeChild(b)}function jf(b,a){a=a||R;if("complete"===a.document.readyState)a.setTimeout(b);else B(a).on("load",b)}function Mc(b,a){var c=Fb[a.toLowerCase()];return c&&Nc[wa(b)]&&c}function kf(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Oc[a]}function lf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=
+a[e||c.type],g=f?f.length:0;if(g){if(D(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=sa(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function bf(){this.$get=function(){return w(T,{hasClass:function(b,a){b.attr&&(b=b[0]);
+return Bb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return Db(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return Cb(b,a)}})}}function Na(b,a){var c=b&&b.$$hashKey;if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Fd)():c+":"+b}function gb(b,a){if(a){var c=0;this.nextUid=function(){return++c}}r(b,this.put,this)}function mf(b){return(b=b.toString().replace(Pc,"").match(Qc))?"function("+(b[1]||"").replace(/[\s\r\n]+/,
+" ")+")":"fn"}function cb(b,a){function c(a){return function(b,c){if(L(b))r(b,lc(a));else return a(b,c)}}function d(a,b){Ma(a,"service");if(z(b)||H(b))b=q.instantiate(b);if(!b.$get)throw Fa("pget",a);return p[a+"Provider"]=b}function e(a,b){return function(){var c=s.invoke(b,this);if(D(c))throw Fa("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;r(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=q.get(e[0]);f[e[1]].apply(f,
+e[2])}}if(!n.get(a)){n.put(a,!0);try{x(a)?(c=eb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(q.invoke(a)):H(a)?b.push(q.invoke(a)):La(a,"module")}catch(e){throw H(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Fa("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Fa("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),
+b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var k=[],l=cb.$$annotate(b,a,g),h,q,p;q=0;for(h=l.length;q<h;q++){p=l[q];if("string"!==typeof p)throw Fa("itkn",p);k.push(f&&f.hasOwnProperty(p)?f[p]:d(p,g))}H(b)&&(b=b[h]);return b.apply(c,k)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((H(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return L(a)||z(a)?a:d},get:d,annotate:cb.$$annotate,has:function(a){return p.hasOwnProperty(a+
+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new gb([],!0),p={$provide:{provider:c(d),factory:c(f),service:c(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ea(b),!1)}),constant:c(function(a,b){Ma(a,"constant");p[a]=b;t[a]=b}),decorator:function(a,b){var c=q.get(a+"Provider"),d=c.$get;c.$get=function(){var a=s.invoke(d,c);return s.invoke(b,null,{$delegate:a})}}}},q=p.$injector=h(p,function(a,b){ca.isString(b)&&k.push(b);
+throw Fa("unpr",k.join(" <- "));}),t={},s=t.$injector=h(t,function(a,b){var c=q.get(a+"Provider",b);return s.invoke(c.$get,c,u,a)});r(g(b),function(a){s.invoke(a||A)});return s}function Be(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===wa(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():nc(c)?(c=c[0],c="fixed"!==
+a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):Y(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,0)}function g(){var a=c.hash(),b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||jf(function(){d.$evalAsync(g)})});return g}]}function af(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}:
+function(b){return a(b,0,!1)}}]}function nf(b,a,c,d){function e(a){try{a.apply(null,$a.call(arguments,1))}finally{if(m--,0===m)for(;C.length;)try{C.pop()()}catch(b){c.error(b)}}}function f(a,b){(function da(){r($,function(a){a()});I=b(da,a)})()}function g(){h();l()}function h(){a:{try{M=t.state;break a}catch(a){}M=void 0}M=D(M)?null:M;ia(M,P)&&(M=P);P=M}function l(){if(G!==n.url()||E!==M)G=n.url(),E=M,r(X,function(a){a(n.url(),M)})}function k(a){try{return decodeURIComponent(a)}catch(b){return a}}
+var n=this,p=a[0],q=b.location,t=b.history,s=b.setTimeout,F=b.clearTimeout,v={};n.isMock=!1;var m=0,C=[];n.$$completeOutstandingRequest=e;n.$$incOutstandingRequestCount=function(){m++};n.notifyWhenNoOutstandingRequests=function(a){r($,function(a){a()});0===m?a():C.push(a)};var $=[],I;n.addPollFn=function(a){D(I)&&f(100,s);$.push(a);return a};var M,E,G=q.href,O=a.find("base"),Q=null;h();E=M;n.url=function(a,c,e){D(e)&&(e=null);q!==b.location&&(q=b.location);t!==b.history&&(t=b.history);if(a){var f=
+E===e;if(G===a&&(!d.history||f))return n;var g=G&&Ga(G)===Ga(a);G=a;E=e;if(!d.history||g&&f){if(!g||Q)Q=a;c?q.replace(a):g?(c=q,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):q.href=a}else t[c?"replaceState":"pushState"](e,"",a),h(),E=M;return n}return Q||q.href.replace(/%27/g,"'")};n.state=function(){return M};var X=[],ba=!1,P=null;n.onUrlChange=function(a){if(!ba){if(d.history)B(b).on("popstate",g);B(b).on("hashchange",g);ba=!0}X.push(a);return a};n.$$checkUrlChange=l;n.baseHref=function(){var a=
+O.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};var fa={},y="",la=n.baseHref();n.cookies=function(a,b){var d,e,f,g;if(a)b===u?p.cookie=encodeURIComponent(a)+"=;path="+la+";expires=Thu, 01 Jan 1970 00:00:00 GMT":x(b)&&(d=(p.cookie=encodeURIComponent(a)+"="+encodeURIComponent(b)+";path="+la).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(p.cookie!==y)for(y=p.cookie,d=y.split("; "),fa={},f=0;f<d.length;f++)e=
+d[f],g=e.indexOf("="),0<g&&(a=k(e.substring(0,g)),fa[a]===u&&(fa[a]=k(e.substring(g+1))));return fa}};n.defer=function(a,b){var c;m++;c=s(function(){delete v[c];e(a)},b||0);v[c]=!0;return c};n.defer.cancel=function(a){return v[a]?(delete v[a],F(a),e(A),!0):!1}}function De(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new nf(b,d,a,c)}]}function Ee(){this.$get=function(){function b(b,d){function e(a){a!=p&&(q?q==a&&(q=a.n):q=a,f(a.n,a.p),f(a,p),p=a,p.n=null)}function f(a,
+b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw S("$cacheFactory")("iid",b);var g=0,h=w({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},p=null,q=null;return a[b]={put:function(a,b){if(k<Number.MAX_VALUE){var c=n[a]||(n[a]={key:a});e(c)}if(!D(b))return a in l||g++,l[a]=b,g>k&&this.remove(q.key),b},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==p&&(p=b.p);b==q&&(q=b.n);f(b.n,b.p);delete n[a]}delete l[a];
+g--},removeAll:function(){l={};g=0;n={};p=q=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return w({},h,{size:g})}}}var a={};b.info=function(){var b={};r(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Ve(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function xc(b,a){function c(a,b){var c=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,d={};r(a,function(a,e){var f=a.match(c);if(!f)throw ma("iscp",b,e,a);d[e]={mode:f[1][0],collection:"*"===
+f[2],optional:"?"===f[3],attrName:f[4]||e}});return d}var d={},e=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,f=/(([\w\-]+)(?:\:([^;]+))?;?)/,g=Gd("ngSrc,ngSrcset,src,srcset"),h=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function p(a,e){Ma(a,"directive");x(a)?(Rb(e,"directiveFactory"),d.hasOwnProperty(a)||(d[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,e){var f=[];r(d[a],function(d,g){try{var h=b.invoke(d);z(h)?h={compile:ea(h)}:!h.compile&&h.link&&
+(h.compile=ea(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";L(h.scope)&&(h.$$isolateBindings=c(h.scope,h.name));f.push(h)}catch(l){e(l)}});return f}])),d[a].push(e)):r(a,lc(p));return this};this.aHrefSanitizationWhitelist=function(b){return y(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};
+var k=!0;this.debugInfoEnabled=function(a){return y(a)?(k=a,this):k};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,s,F,v,m,C,$,I,M){function E(a,b){try{a.addClass(b)}catch(c){}}function G(a,b,c,d,e){a instanceof B||(a=B(a));r(a,function(b,c){b.nodeType==bb&&b.nodeValue.match(/\S+/)&&(a[c]=B(b).wrap("<span></span>").parent()[0])});var f=O(a,b,a,c,d,e);G.$$addScopeClass(a);
+var g=null;return function(b,c,d){Rb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==wa(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Xb(g,B("<div>").append(a).html())):c?Ka.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);G.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function O(a,b,c,d,e,f){function g(a,
+c,d,e){var f,l,k,q,p,s,t;if(m)for(t=Array(c.length),q=0;q<h.length;q+=3)f=h[q],t[f]=c[f];else t=c;q=0;for(p=h.length;q<p;)l=t[h[q++]],c=h[q++],f=h[q++],c?(c.scope?(k=a.$new(),G.$$addScopeInfo(B(l),k)):k=a,s=c.transcludeOnThisElement?Q(a,c.transclude,e,c.elementTranscludeOnThisElement):!c.templateOnThisElement&&e?e:!e&&b?Q(a,b):null,c(f,k,l,d,s)):f&&f(a,l.childNodes,u,e)}for(var h=[],l,k,q,p,m,s=0;s<a.length;s++){l=new Yb;k=X(a[s],[],l,0===s?d:u,e);(f=k.length?fa(k,a[s],l,b,c,null,[],[],f):null)&&
+f.scope&&G.$$addScopeClass(l.$$element);l=f&&f.terminal||!(q=a[s].childNodes)||!q.length?null:O(q,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||l)h.push(s,f,l),p=!0,m=m||f;f=null}return p?g:null}function Q(a,b,c,d){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function X(a,b,c,d,g){var h=c.$attr,l;switch(a.nodeType){case qa:la(b,ya(wa(a)),"E",d,g);for(var k,
+q,p,m=a.attributes,s=0,t=m&&m.length;s<t;s++){var M=!1,I=!1;k=m[s];l=k.name;q=N(k.value);k=ya(l);if(p=U.test(k))l=l.replace(Rc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=k.replace(/(Start|End)$/,"");D(F)&&k===F+"Start"&&(M=l,I=l.substr(0,l.length-5)+"end",l=l.substr(0,l.length-6));k=ya(l.toLowerCase());h[k]=l;if(p||!c.hasOwnProperty(k))c[k]=q,Mc(a,k)&&(c[k]=!0);Pa(a,b,q,k,p);la(b,k,"A",d,g,M,I)}a=a.className;L(a)&&(a=a.animVal);if(x(a)&&""!==a)for(;l=f.exec(a);)k=ya(l[2]),
+la(b,k,"C",d,g)&&(c[k]=N(l[3])),a=a.substr(l.index+l[0].length);break;case bb:za(b,a.nodeValue);break;case 8:try{if(l=e.exec(a.nodeValue))k=ya(l[1]),la(b,k,"M",d,g)&&(c[k]=N(l[2]))}catch(v){}}b.sort(da);return b}function ba(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ma("uterdir",b,c);a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return B(d)}function P(a,b,c){return function(d,e,f,g,h){e=ba(e[0],
+b,c);return a(d,e,f,g,h)}}function fa(a,d,e,f,g,l,k,p,m){function s(a,b,c,d){if(a){c&&(a=P(a,c,d));a.require=J.require;a.directiveName=da;if(Q===J||J.$$isolateScope)a=Y(a,{isolateScope:!0});k.push(a)}if(b){c&&(b=P(b,c,d));b.require=J.require;b.directiveName=da;if(Q===J||J.$$isolateScope)b=Y(b,{isolateScope:!0});p.push(b)}}function M(a,b,c,d){var e,f="data",g=!1,l=c,k;if(x(b)){k=b.match(h);b=b.substring(k[0].length);k[3]&&(k[1]?k[3]=null:k[1]=k[3]);"^"===k[1]?f="inheritedData":"^^"===k[1]&&(f="inheritedData",
+l=c.parent());"?"===k[2]&&(g=!0);e=null;d&&"data"===f&&(e=d[b])&&(e=e.instance);e=e||l[f]("$"+b+"Controller");if(!e&&!g)throw ma("ctreq",b,a);return e||null}H(b)&&(e=[],r(b,function(b){e.push(M(a,b,c,d))}));return e}function I(a,c,f,g,l){function h(a,b,c){var d;Wa(a)||(c=b,b=a,a=u);A&&(d=C);c||(c=A?X.parent():X);return l(a,b,d,c,Wb)}var m,s,t,E,C,ib,X,P;d===f?(P=e,X=e.$$element):(X=B(f),P=new Yb(X,e));Q&&(E=c.$new(!0));l&&(ib=h,ib.$$boundTransclude=l);O&&($={},C={},r(O,function(a){var b={$scope:a===
+Q||a.$$isolateScope?E:c,$element:X,$attrs:P,$transclude:ib};t=a.controller;"@"==t&&(t=P[a.name]);b=v(t,b,!0,a.controllerAs);C[a.name]=b;A||X.data("$"+a.name+"Controller",b.instance);$[a.name]=b}));if(Q){G.$$addScopeInfo(X,E,!0,!(na&&(na===Q||na===Q.$$originalDirective)));G.$$addScopeClass(X,!0);g=$&&$[Q.name];var ba=E;g&&g.identifier&&!0===Q.bindToController&&(ba=g.instance);r(E.$$isolateBindings=Q.$$isolateBindings,function(a,d){var e=a.attrName,f=a.optional,g,l,h,k;switch(a.mode){case "@":P.$observe(e,
+function(a){ba[d]=a});P.$$observers[e].$$scope=c;P[e]&&(ba[d]=b(P[e])(c));break;case "=":if(f&&!P[e])break;l=F(P[e]);k=l.literal?ia:function(a,b){return a===b||a!==a&&b!==b};h=l.assign||function(){g=ba[d]=l(c);throw ma("nonassign",P[e],Q.name);};g=ba[d]=l(c);f=function(a){k(a,ba[d])||(k(a,g)?h(c,a=ba[d]):ba[d]=a);return g=a};f.$stateful=!0;f=a.collection?c.$watchCollection(P[e],f):c.$watch(F(P[e],f),null,l.literal);E.$on("$destroy",f);break;case "&":l=F(P[e]),ba[d]=function(a){return l(c,a)}}})}$&&
+(r($,function(a){a()}),$=null);g=0;for(m=k.length;g<m;g++)s=k[g],Z(s,s.isolateScope?E:c,X,P,s.require&&M(s.directiveName,s.require,X,C),ib);var Wb=c;Q&&(Q.template||null===Q.templateUrl)&&(Wb=E);a&&a(Wb,f.childNodes,u,l);for(g=p.length-1;0<=g;g--)s=p[g],Z(s,s.isolateScope?E:c,X,P,s.require&&M(s.directiveName,s.require,X,C),ib)}m=m||{};for(var E=-Number.MAX_VALUE,C,O=m.controllerDirectives,$,Q=m.newIsolateScopeDirective,na=m.templateDirective,fa=m.nonTlbTranscludeDirective,la=!1,D=!1,A=m.hasElementTranscludeDirective,
+w=e.$$element=B(d),J,da,V,hb=f,za,K=0,R=a.length;K<R;K++){J=a[K];var Pa=J.$$start,U=J.$$end;Pa&&(w=ba(d,Pa,U));V=u;if(E>J.priority)break;if(V=J.scope)J.templateUrl||(L(V)?(Oa("new/isolated scope",Q||C,J,w),Q=J):Oa("new/isolated scope",Q,J,w)),C=C||J;da=J.name;!J.templateUrl&&J.controller&&(V=J.controller,O=O||{},Oa("'"+da+"' controller",O[da],J,w),O[da]=J);if(V=J.transclude)la=!0,J.$$tlb||(Oa("transclusion",fa,J,w),fa=J),"element"==V?(A=!0,E=J.priority,V=w,w=e.$$element=B(W.createComment(" "+da+": "+
+e[da]+" ")),d=w[0],T(g,$a.call(V,0),d),hb=G(V,f,E,l&&l.name,{nonTlbTranscludeDirective:fa})):(V=B(Ub(d)).contents(),w.empty(),hb=G(V,f));if(J.template)if(D=!0,Oa("template",na,J,w),na=J,V=z(J.template)?J.template(w,e):J.template,V=Sc(V),J.replace){l=J;V=Sb.test(V)?Tc(Xb(J.templateNamespace,N(V))):[];d=V[0];if(1!=V.length||d.nodeType!==qa)throw ma("tplrt",da,"");T(g,w,d);R={$attr:{}};V=X(d,[],R);var aa=a.splice(K+1,a.length-(K+1));Q&&y(V);a=a.concat(V).concat(aa);S(e,R);R=a.length}else w.html(V);if(J.templateUrl)D=
+!0,Oa("template",na,J,w),na=J,J.replace&&(l=J),I=of(a.splice(K,a.length-K),w,e,g,la&&hb,k,p,{controllerDirectives:O,newIsolateScopeDirective:Q,templateDirective:na,nonTlbTranscludeDirective:fa}),R=a.length;else if(J.compile)try{za=J.compile(w,e,hb),z(za)?s(null,za,Pa,U):za&&s(za.pre,za.post,Pa,U)}catch(pf){c(pf,xa(w))}J.terminal&&(I.terminal=!0,E=Math.max(E,J.priority))}I.scope=C&&!0===C.scope;I.transcludeOnThisElement=la;I.elementTranscludeOnThisElement=A;I.templateOnThisElement=D;I.transclude=hb;
+m.hasElementTranscludeDirective=A;return I}function y(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function la(b,e,f,g,l,h,k){if(e===l)return null;l=null;if(d.hasOwnProperty(e)){var q;e=a.get(e+"Directive");for(var m=0,s=e.length;m<s;m++)try{q=e[m],(g===u||g>q.priority)&&-1!=q.restrict.indexOf(f)&&(h&&(q=Ob(q,{$$start:h,$$end:k})),b.push(q),l=q)}catch(I){c(I)}}return l}function D(b){if(d.hasOwnProperty(b))for(var c=a.get(b+"Directive"),e=0,f=c.length;e<f;e++)if(b=c[e],b.multiElement)return!0;
+return!1}function S(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;r(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});r(b,function(b,f){"class"==f?(E(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function of(a,b,c,d,e,f,g,l){var h=[],k,q,p=b[0],m=a.shift(),t=Ob(m,{templateUrl:null,transclude:null,
+replace:null,$$originalDirective:m}),I=z(m.templateUrl)?m.templateUrl(b,c):m.templateUrl,M=m.templateNamespace;b.empty();s(I).then(function(s){var F,v;s=Sc(s);if(m.replace){s=Sb.test(s)?Tc(Xb(M,N(s))):[];F=s[0];if(1!=s.length||F.nodeType!==qa)throw ma("tplrt",m.name,I);s={$attr:{}};T(d,b,F);var C=X(F,[],s);L(m.scope)&&y(C);a=C.concat(a);S(c,s)}else F=p,b.html(s);a.unshift(t);k=fa(a,F,c,e,b,m,f,g,l);r(d,function(a,c){a==F&&(d[c]=b[0])});for(q=O(b[0].childNodes,e);h.length;){s=h.shift();v=h.shift();
+var G=h.shift(),P=h.shift(),C=b[0];if(!s.$$destroyed){if(v!==p){var $=v.className;l.hasElementTranscludeDirective&&m.replace||(C=Ub(F));T(G,B(v),C);E(B(C),$)}v=k.transcludeOnThisElement?Q(s,k.transclude,P):P;k(q,s,C,d,v)}}h=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(h?h.push(b,c,d,a):(k.transcludeOnThisElement&&(a=Q(b,k.transclude,e)),k(q,b,c,d,a)))}}function da(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Oa(a,b,c,d){if(b)throw ma("multidir",
+b.name,c.name,a,xa(d));}function za(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&G.$$addBindingClass(a);return function(a,c){var e=c.parent();b||G.$$addBindingClass(e);G.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Xb(a,b){a=K(a||"html");switch(a){case "svg":case "math":var c=W.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==
+b)return $.HTML;var c=wa(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return $.RESOURCE_URL}function Pa(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var k=b(d,!0,h,f);if(k){if("multiple"===e&&"select"===wa(a))throw ma("selmulti",xa(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers={});if(l.test(e))throw ma("nodomevents");var p=g[e];p!==d&&(k=p&&b(p,!0,h,f),d=p);k&&(g[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||
+a).$watch(k,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,l;if(a)for(g=0,l=a.length;g<l;g++)if(a[g]==d){a[g++]=c;l=g+e-1;for(var h=a.length;g<h;g++,l++)l<h?a[g]=a[l]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=W.createDocumentFragment();a.appendChild(d);B(c).data(B(d).data());ta?(Qb=!0,ta.cleanData([d])):delete B.cache[d[B.expando]];d=1;for(e=b.length;d<e;d++)f=b[d],B(f).remove(),
+a.appendChild(f),delete b[d];b[0]=c;b.length=1}function Y(a,b){return w(function(){return a.apply(null,arguments)},a,b)}function Z(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(l){c(l,xa(d))}}var Yb=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};Yb.prototype={$normalize:ya,$addClass:function(a){a&&0<a.length&&I.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&I.removeClass(this.$$element,a)},$updateClass:function(a,
+b){var c=Uc(a,b);c&&c.length&&I.addClass(this.$$element,c);(c=Uc(b,a))&&c.length&&I.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Mc(f,a),l=kf(f,a),f=a;g?(this.$$element.prop(a,b),e=g):l&&(this[l]=b,f=l);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=uc(a,"-"));g=wa(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=M(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",l=N(b),h=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,h=/\s/.test(l)?
+h:/(,)/,l=l.split(h),h=Math.floor(l.length/2),k=0;k<h;k++)var q=2*k,g=g+M(N(l[q]),!0),g=g+(" "+N(l[q+1]));l=N(l[2*k]).split(/\s/);g+=M(N(l[0]),!0);2===l.length&&(g+=" "+N(l[1]));this[a]=b=g}!1!==d&&(null===b||b===u?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&r(a[f],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ja()),e=d[a]||(d[a]=[]);e.push(b);m.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});
+return function(){Ya(e,b)}}};var V=b.startSymbol(),na=b.endSymbol(),Sc="{{"==V||"}}"==na?ra:function(a){return a.replace(/\{\{/g,V).replace(/}}/g,na)},U=/^ngAttr[A-Z]/;G.$$addBindingInfo=k?function(a,b){var c=a.data("$binding")||[];H(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:A;G.$$addBindingClass=k?function(a){E(a,"ng-binding")}:A;G.$$addScopeInfo=k?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:A;G.$$addScopeClass=k?function(a,b){E(a,b?"ng-isolate-scope":
+"ng-scope")}:A;return G}]}function ya(b){return fb(b.replace(Rc,""))}function Uc(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function Tc(b){b=B(b);var a=b.length;if(1>=a)return b;for(;a--;)8===b[a].nodeType&&qf.call(b,a,1);return b}function Fe(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){Ma(a,"controller");L(a)?w(b,a):b[a]=c};this.allowGlobals=function(){a=
+!0};this.$get=["$injector","$window",function(d,e){function f(a,b,c,d){if(!a||!L(a.$scope))throw S("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,l,k){var n,p,q;l=!0===l;k&&x(k)&&(q=k);if(x(g)){k=g.match(c);if(!k)throw rf("ctrlfmt",g);p=k[1];q=q||k[3];g=b.hasOwnProperty(p)?b[p]:wc(h.$scope,p,!0)||(a?wc(e,p,!0):u);La(g,p,!0)}if(l)return l=(H(g)?g[g.length-1]:g).prototype,n=Object.create(l||null),q&&f(h,q,n,p||g.name),w(function(){d.invoke(g,n,h,p);return n},{instance:n,identifier:q});
+n=d.instantiate(g,h,p);q&&f(h,q,n,p||g.name);return n}}]}function Ge(){this.$get=["$window",function(b){return B(b.document)}]}function He(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b,a){if(x(b)){var c=b.replace(sf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(Vc))||(d=(d=c.match(tf))&&uf[d[0]].test(c));d&&(b=pc(c))}}return b}function Wc(b){var a=ja(),c,d,e;if(!b)return a;r(b.split("\n"),function(b){e=b.indexOf(":");c=K(N(b.substr(0,
+e)));d=N(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Xc(b){var a=L(b)?b:u;return function(c){a||(a=Wc(b));return c?(c=a[K(c)],void 0===c&&(c=null),c):a}}function Yc(b,a,c,d){if(z(d))return d(b,a,c);r(d,function(d){b=d(b,a,c)});return b}function Ke(){var b=this.defaults={transformResponse:[Zb],transformRequest:[function(a){return L(a)&&"[object File]"!==Ca.call(a)&&"[object Blob]"!==Ca.call(a)&&"[object FormData]"!==Ca.call(a)?ab(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},
+post:sa($b),put:sa($b),patch:sa($b)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=w({},a);b.data=a.data?Yc(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a){var b,c={};r(a,function(a,d){z(a)?(b=
+a(),null!=b&&(c[d]=b)):c[d]=a});return c}if(!ca.isObject(a))throw S("$http")("badreq",a);var e=w({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},a);e.headers=function(a){var c=b.headers,e=w({},a.headers),f,g,c=w({},c.common,c[K(a.method)]);a:for(f in c){a=K(f);for(g in e)if(K(g)===a)continue a;e[f]=c[f]}return d(e)}(a);e.method=vb(e.method);var f=[function(a){var d=a.headers,e=Yc(a.data,Xc(d),u,a.transformRequest);D(e)&&r(d,function(a,b){"content-type"===K(b)&&
+delete d[b]});D(a.withCredentials)&&!D(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},u],g=h.when(e);for(r(t,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var l=f.shift(),g=g.then(a,l)}g.success=function(a){La(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){La(a,"fn");g.then(null,function(b){a(b.data,
+b.status,b.headers,e)});return g};return g}function n(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}E&&(200<=b&&300>b?E.put(Q,[b,c,Wc(d),e]):E.remove(Q));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:Xc(d),config:c,statusText:e})}function n(a){m(a.data,a.status,sa(a.headers()),a.statusText)}function t(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),M=I.promise,
+E,G,O=c.headers,Q=p(c.url,c.params);k.pendingRequests.push(c);M.then(t,t);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(E=L(c.cache)?c.cache:L(b.cache)?b.cache:q);E&&(G=E.get(Q),y(G)?G&&z(G.then)?G.then(n,n):H(G)?m(G[1],G[0],sa(G[2]),G[3]):m(G,200,{},"OK"):E.put(Q,M));D(G)&&((G=Zc(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:u)&&(O[c.xsrfHeaderName||b.xsrfHeaderName]=G),d(c.method,Q,f,l,O,c.timeout,c.withCredentials,c.responseType));return M}function p(a,b){if(!b)return a;
+var c=[];Ed(b,function(a,b){null===a||D(a)||(H(a)||(a=[a]),r(a,function(a){L(a)&&(a=ha(a)?a.toISOString():ab(a));c.push(Ea(b)+"="+Ea(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var q=f("$http"),t=[];r(c,function(a){t.unshift(x(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){r(arguments,function(a){k[a]=function(b,c){return k(w(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){r(arguments,function(a){k[a]=function(b,c,d){return k(w(d||
+{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function vf(){return new R.XMLHttpRequest}function Le(){this.$get=["$browser","$window","$document",function(b,a,c){return wf(b,vf,b.defer,a.angular.callbacks,c[0])}]}function wf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,t="unknown";
+a&&("load"!==a.type||d[b].called||(a={type:"error"}),t=a.type,g="error"===a.type?404:200);c&&c(g,t)};f.addEventListener("load",n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,p,q,t){function s(){m&&m();C&&C.abort()}function F(a,d,e,f,g){I!==u&&c.cancel(I);m=C=null;a(d,e,f,g);b.$$completeOutstandingRequest(A)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==K(e)){var v="_"+(d.counter++).toString(36);d[v]=function(a){d[v].data=a;d[v].called=!0};
+var m=f(h.replace("JSON_CALLBACK","angular.callbacks."+v),v,function(a,b){F(k,a,d[v].data,"",b);d[v]=A})}else{var C=a();C.open(e,h,!0);r(n,function(a,b){y(a)&&C.setRequestHeader(b,a)});C.onload=function(){var a=C.statusText||"",b="response"in C?C.response:C.responseText,c=1223===C.status?204:C.status;0===c&&(c=b?200:"file"==Aa(h).protocol?404:0);F(k,c,b,C.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};C.onerror=e;C.onabort=e;q&&(C.withCredentials=!0);if(t)try{C.responseType=t}catch($){if("json"!==
+t)throw $;}C.send(l||null)}if(0<p)var I=c(s,p);else p&&z(p.then)&&p.then(s)}}function Ie(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(f,g,t,s){function F(c){return c.replace(k,b).replace(n,a)}function v(a){try{var b=a;a=t?e.getTrusted(t,b):e.valueOf(b);var c;if(s&&!y(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;
+case "number":a=""+a;break;default:a=ab(a)}c=a}return c}catch(g){c=ac("interr",f,g.toString()),d(c)}}s=!!s;for(var m,C,r=0,I=[],M=[],E=f.length,G=[],O=[];r<E;)if(-1!=(m=f.indexOf(b,r))&&-1!=(C=f.indexOf(a,m+h)))r!==m&&G.push(F(f.substring(r,m))),r=f.substring(m+h,C),I.push(r),M.push(c(r,v)),r=C+l,O.push(G.length),G.push("");else{r!==E&&G.push(F(f.substring(r)));break}if(t&&1<G.length)throw ac("noconcat",f);if(!g||I.length){var Q=function(a){for(var b=0,c=I.length;b<c;b++){if(s&&D(a[b]))return;G[O[b]]=
+a[b]}return G.join("")};return w(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=M[b](a);return Q(e)}catch(g){a=ac("interr",f,g.toString()),d(a)}},{exp:f,expressions:I,$$watchDelegate:function(a,b,c){var d;return a.$watchGroup(M,function(c,e){var f=Q(c);z(b)&&b.call(this,f,c!==e?d:f,a);d=f},c)}})}}var h=b.length,l=a.length,k=new RegExp(b.replace(/./g,f),"g"),n=new RegExp(a.replace(/./g,f),"g");g.startSymbol=function(){return b};g.endSymbol=function(){return a};return g}]}function Je(){this.$get=
+["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=a.setInterval,p=a.clearInterval,q=0,t=y(k)&&!k,s=(t?d:c).defer(),F=s.promise;l=y(l)?l:0;F.then(null,null,e);F.$$intervalId=n(function(){s.notify(q++);0<l&&q>=l&&(s.resolve(q),p(F.$$intervalId),delete f[F.$$intervalId]);t||b.$apply()},h);f[F.$$intervalId]=s;return F}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):
+!1};return e}]}function Rd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),
+DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=sb(b[a]);
+return b.join("/")}function $c(b,a){var c=Aa(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=aa(c.port)||xf[c.protocol]||null}function ad(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=rc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ua(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ga(b){var a=b.indexOf("#");
+return-1==a?b:b.substr(0,a)}function Gb(b){return b.replace(/(#.+)|#$/,"$1")}function cc(b,a,c){this.$$html5=!0;c=c||"";$c(b,this);this.$$parse=function(b){var c=ua(a,b);if(!x(c))throw Hb("ipthprfx",b,a);ad(c,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var b=Pb(this.$$search),c=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=a+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),
+!0;var f,g;(f=ua(b,d))!==u?(g=f,g=(f=ua(c,f))!==u?a+(ua("/",f)||f):b+g):(f=ua(a,d))!==u?g=a+f:a==d+"/"&&(g=a);g&&this.$$parse(g);return!!g}}function dc(b,a,c){$c(b,this);this.$$parse=function(d){var e=ua(b,d)||ua(a,d),f;D(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",D(e)&&(b=d,this.replace())):(f=ua(c,e),D(f)&&(f=e));ad(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var a=
+Pb(this.$$search),e=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+(this.$$url?c+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ga(b)==Ga(a)?(this.$$parse(a),!0):!1}}function bd(b,a,c){this.$$html5=!0;dc.apply(this,arguments);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ga(d)?f=d:(g=ua(a,d))?f=b+c+g:a===d+"/"&&(f=a);f&&this.$$parse(f);return!!f};this.$$compose=function(){var a=Pb(this.$$search),
+e=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+c+this.$$url}}function Ib(b){return function(){return this[b]}}function cd(b,a){return function(c){if(D(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Me(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Xa(b)?(a.enabled=b,this):L(b)?(Xa(b.enabled)&&(a.enabled=b.enabled),Xa(b.requireBase)&&
+(a.requireBase=b.requireBase),Xa(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var p=d.url(),q;if(a.enabled){if(!n&&a.requireBase)throw Hb("nobase");q=p.substring(0,p.indexOf("/",
+p.indexOf("//")+2))+(n||"/");n=e.history?cc:bd}else q=Ga(p),n=dc;var t=q.substr(0,Ga(q).lastIndexOf("/")+1);k=new n(q,t,"#"+b);k.$$parseLinkUrl(p,p);k.$$state=d.state();var s=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=B(b.target);"a"!==wa(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var l=e.prop("href"),h=e.attr("href")||e.attr("xlink:href");L(l)&&"[object SVGAnimatedString]"===l.toString()&&(l=
+Aa(l.animVal).href);s.test(l)||!l||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(l,h)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Gb(k.absUrl())!=Gb(p)&&d.url(k.absUrl(),!0);var F=!0;d.onUrlChange(function(a,b){D(ua(t,a))?g.location.href=a:(c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,
+!1,e)):(F=!1,l(d,e)))}),c.$$phase||c.$digest())});c.$watch(function(){var a=Gb(d.url()),b=Gb(k.absUrl()),f=d.state(),g=k.$$replace,q=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(F||q)F=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(q&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function Ne(){var b=!0,a=this;this.debugEnabled=function(a){return y(a)?(b=
+a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||A;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];r(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),
+debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function va(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw ga("isecfld",a);return b}function dd(b,a){b+="";if(!x(b))throw ga("iseccst",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw ga("isecfn",a);if(b.window===b)throw ga("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw ga("isecdom",a);if(b===Object)throw ga("isecobj",
+a);}return b}function ec(b){return b.constant}function jb(b,a,c,d,e){oa(b,e);oa(a,e);c=c.split(".");for(var f,g=0;1<c.length;g++){f=va(c.shift(),e);var h=0===g&&a&&a[f]||b[f];h||(h={},b[f]=h);b=oa(h,e)}f=va(c.shift(),e);oa(b[f],e);return b[f]=d}function Qa(b){return"constructor"==b}function ed(b,a,c,d,e,f,g){va(b,f);va(a,f);va(c,f);va(d,f);va(e,f);var h=function(a){return oa(a,f)},l=g||Qa(b)?h:ra,k=g||Qa(a)?h:ra,n=g||Qa(c)?h:ra,p=g||Qa(d)?h:ra,q=g||Qa(e)?h:ra;return function(f,g){var h=g&&g.hasOwnProperty(b)?
+g:f;if(null==h)return h;h=l(h[b]);if(!a)return h;if(null==h)return u;h=k(h[a]);if(!c)return h;if(null==h)return u;h=n(h[c]);if(!d)return h;if(null==h)return u;h=p(h[d]);return e?null==h?u:h=q(h[e]):h}}function yf(b,a){return function(c,d){return b(c,d,oa,a)}}function zf(b,a,c){var d=a.expensiveChecks,e=d?Af:Bf,f=e[b];if(f)return f;var g=b.split("."),h=g.length;if(a.csp)f=6>h?ed(g[0],g[1],g[2],g[3],g[4],c,d):function(a,b){var e=0,f;do f=ed(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=u,a=f;while(e<
+h);return f};else{var l="";d&&(l+="s = eso(s, fe);\nl = eso(l, fe);\n");var k=d;r(g,function(a,b){va(a,c);var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"."+a;if(d||Qa(a))e="eso("+e+", fe)",k=!0;l+="if(s == null) return undefined;\ns="+e+";\n"});l+="return s;";a=new Function("s","l","eso","fe",l);a.toString=ea(l);k&&(a=yf(a,c));f=a}f.sharedGetter=!0;f.assign=function(a,c,d){return jb(a,d,b,c,b)};return e[b]=f}function fc(b){return z(b.valueOf)?b.valueOf():Cf.call(b)}function Oe(){var b=ja(),
+a=ja();this.$get=["$filter","$sniffer",function(c,d){function e(a){var b=a;a.sharedGetter&&(b=function(b,c){return a(b,c)},b.literal=a.literal,b.constant=a.constant,b.assign=a.assign);return b}function f(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];e.constant||(e.inputs?f(e.inputs,b):-1===b.indexOf(e)&&b.push(e))}return b}function g(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function h(a,b,c,d){var e=d.$$inputs||(d.$$inputs=f(d.inputs,
+[])),l;if(1===e.length){var h=g,e=e[0];return a.$watch(function(a){var b=e(a);g(b,h)||(l=d(a),h=b&&fc(b));return l},b,c)}for(var k=[],q=0,p=e.length;q<p;q++)k[q]=g;return a.$watch(function(a){for(var b=!1,c=0,f=e.length;c<f;c++){var h=e[c](a);if(b||(b=!g(h,k[c])))k[c]=h&&fc(h)}b&&(l=d(a));return l},b,c)}function l(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function k(a,b,c,d){function e(a){var b=
+!0;r(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function n(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function p(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==k&&c!==l?function(c,d){var e=a(c,d);return b(e,c,d)}:function(c,d){var e=a(c,d),f=b(e,c,d);return y(e)?f:e};a.$$watchDelegate&&a.$$watchDelegate!==
+h?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=h,c.inputs=[a]);return c}var q={csp:d.csp,expensiveChecks:!1},t={csp:d.csp,expensiveChecks:!0};return function(d,f,g){var m,r,u;switch(typeof d){case "string":u=d=d.trim();var I=g?a:b;m=I[u];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(r=!0,d=d.substring(2)),g=g?t:q,m=new gc(g),m=(new kb(m,c,g)).parse(d),m.constant?m.$$watchDelegate=n:r?(m=e(m),m.$$watchDelegate=m.literal?k:l):m.inputs&&(m.$$watchDelegate=h),I[u]=m);return p(m,f);
+case "function":return p(d,f);default:return p(A,f)}}}]}function Qe(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return fd(function(a){b.$evalAsync(a)},a)}]}function Re(){this.$get=["$browser","$exceptionHandler",function(b,a){return fd(function(a){b.defer(a)},a)}]}function fd(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&
+c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=u;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(l){d.reject(l),a(l)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=S("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||
+[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(L(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status=
+-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)?
+b(c):c)}catch(l){a(l)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},p=function t(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof t))return new t(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
+p.defer=function(){return new g};p.reject=function(a){var b=new g;b.reject(a);return b.promise};p.when=n;p.all=function(a){var b=new g,c=0,d=H(a)?[]:{};r(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return p}function $e(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b=
+n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function Pe(){function b(a){function b(){this.$$watchers=this.$$nextSibling=
+this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$id=++rb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=S("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++rb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=
+null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$isolateBindings=null}function p(a){if(v.$$phase)throw c("inprog",v.$$phase);v.$$phase=a}function q(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function t(){}function s(){for(;u.length;)try{u.shift()()}catch(a){g(a)}e=null}function F(){null===e&&(e=l.defer(function(){v.$apply(s)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?
+(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c){var e=h(a);if(e.$$watchDelegate)return e.$$watchDelegate(this,b,c,e);var f=this.$$watchers,g={fn:b,last:t,get:e,exp:a,eq:!!c};d=null;z(b)||(g.fn=A);f||(f=this.$$watchers=[]);f.unshift(g);return function(){Ya(f,
+g);d=null}},$watchGroup:function(a,b){function c(){l=!1;h?(h=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,l=!1,h=!0;if(!a.length){var k=!0;g.$evalAsync(function(){k&&b(e,e,g)});return function(){k=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});r(a,function(a,b){var h=g.$watch(a,function(a,f){e[b]=a;d[b]=f;l||(l=!0,g.$evalAsync(c))});f.push(h)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=
+a;var b,d,g,l;if(!D(e)){if(L(e))if(Ta(e))for(f!==p&&(f=p,t=f.length=0,k++),a=e.length,t!==a&&(k++,f.length=t=a),b=0;b<a;b++)l=f[b],g=e[b],d=l!==l&&g!==g,d||l===g||(k++,f[b]=g);else{f!==n&&(f=n={},t=0,k++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],l=f[b],b in f?(d=l!==l&&g!==g,d||l===g||(k++,f[b]=g)):(t++,f[b]=g,k++));if(t>a)for(b in k++,f)e.hasOwnProperty(b)||(t--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,g,l=1<b.length,k=0,q=h(a,c),p=[],n={},m=!0,t=0;return this.$watch(q,
+function(){m?(m=!1,b(e,e,d)):b(e,g,d);if(l)if(L(e))if(Ta(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)sc.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,q,n,r=a,F,P=[],u,y;p("$digest");l.$$checkUrlChange();this===v&&null!==e&&(l.defer.cancel(e),s());d=null;do{n=!1;for(F=this;m.length;){try{y=m.shift(),y.scope.$eval(y.expression,y.locals)}catch(w){g(w)}d=null}a:do{if(k=F.$$watchers)for(q=k.length;q--;)try{if(b=k[q])if((f=b.get(F))!==(h=b.last)&&
+!(b.eq?ia(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))n=!0,d=b,b.last=b.eq?Da(f,null):f,b.fn(f,h===t?f:h,F),5>r&&(u=4-r,P[u]||(P[u]=[]),P[u].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){n=!1;break a}}catch(D){g(D)}if(!(k=F.$$childHead||F!==this&&F.$$nextSibling))for(;F!==this&&!(k=F.$$nextSibling);)F=F.$parent}while(F=k);if((n||m.length)&&!r--)throw v.$$phase=null,c("infdig",a,P);}while(n||m.length);for(v.$$phase=null;C.length;)try{C.shift()()}catch(B){g(B)}},
+$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==v){for(var b in this.$$listenerCount)q(this,this.$$listenerCount[b],b);a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=
+this.$applyAsync=A;this.$on=this.$watch=this.$watchGroup=function(){return A};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}}},$eval:function(a,b){return h(a)(this,b)},$evalAsync:function(a,b){v.$$phase||m.length||l.defer(function(){m.length&&v.$digest()});m.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){C.push(a)},$apply:function(a){try{return p("$apply"),this.$eval(a)}catch(b){g(b)}finally{v.$$phase=
+null;try{v.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&u.push(b);F()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,q(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,l={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){l.defaultPrevented=
+!0},defaultPrevented:!1},h=Za([l],arguments,1),k,q;do{d=e.$$listeners[a]||c;l.currentScope=e;k=0;for(q=d.length;k<q;k++)if(d[k])try{d[k].apply(null,h)}catch(p){g(p)}else d.splice(k,1),k--,q--;if(f)return l.currentScope=null,l;e=e.$parent}while(e);l.currentScope=null;return l},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=Za([e],arguments,1),l,h;c=d;){e.currentScope=
+c;d=c.$$listeners[a]||[];l=0;for(h=d.length;l<h;l++)if(d[l])try{d[l].apply(null,f)}catch(k){g(k)}else d.splice(l,1),l--,h--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var v=new n,m=v.$$asyncQueue=[],C=v.$$postDigestQueue=[],u=v.$$applyAsyncQueue=[];return v}]}function Sd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=
+function(a){return y(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Aa(c).href;return""===f||f.match(e)?c:"unsafe:"+f}}}function Df(b){if("self"===b)return b;if(x(b)){if(-1<b.indexOf("***"))throw Ba("iwcard",b);b=gd(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Va(b))return new RegExp("^"+b.source+"$");throw Ba("imatcher");}function hd(b){var a=[];y(b)&&r(b,function(b){a.push(Df(b))});
+return a}function Te(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=hd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&(a=hd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?Zc(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};
+return b}var f=function(a){throw Ba("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]=e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ba("icontext",a,b);if(null===b||b===u||""===b)return b;if("string"!==typeof b)throw Ba("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===u||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof
+g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Aa(e.toString()),p,q,t=!1;p=0;for(q=b.length;p<q;p++)if(d(b[p],g)){t=!0;break}if(t)for(p=0,q=a.length;p<q;p++)if(d(a[p],g)){t=!1;break}if(t)return e;throw Ba("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Ba("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function Se(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&
+8>Ra)throw Ba("iequirks");var d=sa(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=ra);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;r(pa,function(a,b){var c=K(b);d[fb("parse_as_"+c)]=function(b){return e(a,b)};d[fb("get_trusted_"+c)]=function(b){return f(a,b)};d[fb("trust_as_"+
+c)]=function(b){return g(a,b)}});return d}]}function Ue(){this.$get=["$window","$document",function(b,a){var c={},d=aa((/android (\d+)/.exec(K((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var p in l)if(k=h.exec(p)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in
+l);!d||k&&n||(k=x(f.body.style.webkitTransition),n=x(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ra)return!1;if(D(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:db(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function We(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;x(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=
+a.defaults&&a.defaults.transformResponse;H(h)?h=h.filter(function(a){return a!==Zb}):h===Zb&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){return a.data},function(a){if(!g)throw ma("tpload",f);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function Xe(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];r(a,function(a){var d=
+ca.element(a).data("$binding");d&&r(d,function(d){c?(new RegExp("(^|\\s)"+gd(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function Ye(){this.$get=
+["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){var n=y(k)&&!k,p=(n?d:c).defer(),q=p.promise;l=a.defer(function(){try{p.resolve(f())}catch(a){p.reject(a),e(a)}finally{delete g[q.$$timeoutId]}n||b.$apply()},l);q.$$timeoutId=l;g[l]=p;return q}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Aa(b){Ra&&(Z.setAttribute("href",b),b=Z.href);
+Z.setAttribute("href",b);return{href:Z.href,protocol:Z.protocol?Z.protocol.replace(/:$/,""):"",host:Z.host,search:Z.search?Z.search.replace(/^\?/,""):"",hash:Z.hash?Z.hash.replace(/^#/,""):"",hostname:Z.hostname,port:Z.port,pathname:"/"===Z.pathname.charAt(0)?Z.pathname:"/"+Z.pathname}}function Zc(b){b=x(b)?Aa(b):b;return b.protocol===id.protocol&&b.host===id.host}function Ze(){this.$get=ea(R)}function Ec(b){function a(c,d){if(L(c)){var e={};r(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+
+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",jd);a("date",kd);a("filter",Ef);a("json",Ff);a("limitTo",Gf);a("lowercase",Hf);a("number",ld);a("orderBy",md);a("uppercase",If)}function Ef(){return function(b,a,c){if(!H(b))return b;var d;switch(null!==a?typeof a:"null"){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=Jf(a,c,d);break;default:return b}return b.filter(a)}}function Jf(b,
+a,c){var d=L(b)&&"$"in b;!0===a?a=ia:z(a)||(a=function(a,b){if(D(a))return!1;if(null===a||null===b)return a===b;if(L(a)||L(b))return!1;a=K(""+a);b=K(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!L(e)?Ha(e,b.$,a,!1):Ha(e,b,a,c)}}function Ha(b,a,c,d,e){var f=null!==b?typeof b:"null",g=null!==a?typeof a:"null";if("string"===g&&"!"===a.charAt(0))return!Ha(b,a.substring(1),c,d);if(H(b))return b.some(function(b){return Ha(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==
+h.charAt(0)&&Ha(b[h],a,c,!0))return!0;return e?!1:Ha(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!D(e)&&(f="$"===h,!Ha(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function jd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){D(d)&&(d=a.CURRENCY_SYM);D(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:nd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function ld(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==
+b?b:nd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function nd(b,a,c,d,e){if(!isFinite(b)||L(b))return"";var f=0>b;b=Math.abs(b);var g=b+"",h="",l=[],k=!1;if(-1!==g.indexOf("e")){var n=g.match(/([\d\.]+)e(-?)(\d+)/);n&&"-"==n[2]&&n[3]>e+1?b=0:(h=g,k=!0)}if(k)0<e&&1>b&&(h=b.toFixed(e),b=parseFloat(h));else{g=(g.split(od)[1]||"").length;D(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(od),k=g[0],g=g[1]||"",p=0,q=a.lgSize,
+t=a.gSize;if(k.length>=q+t)for(p=k.length-q,n=0;n<p;n++)0===(p-n)%t&&0!==n&&(h+=c),h+=k.charAt(n);for(n=p;n<k.length;n++)0===(k.length-n)%q&&0!==n&&(h+=c),h+=k.charAt(n);for(;g.length<e;)g+="0";e&&"0"!==e&&(h+=d+g.substr(0,e))}0===b&&(f=!1);l.push(f?a.negPre:a.posPre,h,f?a.negSuf:a.posSuf);return l.join("")}function Jb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function U(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=
+c;0===e&&-12==c&&(e=12);return Jb(e,a,d)}}function Kb(b,a){return function(c,d){var e=c["get"+b](),f=vb(a?"SHORT"+b:b);return d[f][e]}}function pd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function qd(b){return function(a){var c=pd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Jb(a,b)}}function hc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function kd(b){function a(a){var b;if(b=a.match(c)){a=
+new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=aa(b[9]+b[10]),g=aa(b[9]+b[11]));h.call(a,aa(b[1]),aa(b[2])-1,aa(b[3]));f=aa(b[4]||0)-f;g=aa(b[5]||0)-g;h=aa(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;x(c)&&(c=Kf.test(c)?
+aa(c):a(c));Y(c)&&(c=new Date(c));if(!ha(c))return c;for(;e;)(k=Lf.exec(e))?(h=Za(h,k,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=new Date(c.getTime()),c.setMinutes(c.getMinutes()+c.getTimezoneOffset()));r(h,function(a){l=Mf[a];g+=l?l(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ff(){return function(b,a){D(a)&&(a=2);return ab(b,a)}}function Gf(){return function(b,a){Y(b)&&(b=b.toString());return H(b)||x(b)?(a=Infinity===Math.abs(Number(a))?Number(a):
+aa(a))?0<a?b.slice(0,a):b.slice(a):x(b)?"":[]:b}}function md(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&&(a=g(a),b=g(b));return c===d?("string"===c&&(a=
+a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!Ta(a))return a;c=H(c)?c:[c];0===c.length&&(c=["+"]);c=c.map(function(a){var c=!1,d=a||ra;if(x(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),a=a.substring(1);if(""===a)return e(h,c);d=b(a);if(d.constant){var f=d();return e(function(a,b){return h(a[f],b[f])},c)}}return e(function(a,b){return h(d(a),d(b))},c)});return $a.call(a).sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},
+d))}}function Ia(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ea(b)}function rd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Lb;f.$error={};f.$$success={};f.$pending=u;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){r(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){r(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ma(a.$name,
+"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];r(f.$pending,function(b,c){f.$setValidity(c,null,a)});r(f.$error,function(b,c){f.$setValidity(c,null,a)});r(f.$$success,function(b,c){f.$setValidity(c,null,a)});Ya(g,a)};sd({ctrl:this,$element:b,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];
+d&&(Ya(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Sa);d.addClass(b,Mb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Sa,Mb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;r(g,function(a){a.$setPristine()})};f.$setUntouched=function(){r(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function ic(b){b.$formatters.push(function(a){return b.$isEmpty(a)?
+a:a.toString()})}function lb(b,a,c,d,e,f){var g=K(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=N(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};
+a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Nb(b,a){return function(c,d){var e,f;if(ha(c))return c;if(x(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(Nf.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,
+dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},r(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function mb(b,a,c,d){return function(e,f,g,h,l,k,n){function p(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function q(a){return y(a)?ha(a)?a:c(a):u}td(e,f,g,h);lb(e,f,g,h,l,k);var t=h&&h.$options&&h.$options.timezone,s;h.$$parserName=b;
+h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,s),"UTC"===t&&b.setMinutes(b.getMinutes()-b.getTimezoneOffset()),b):u});h.$formatters.push(function(a){if(a&&!ha(a))throw nb("datefmt",a);if(p(a)){if((s=a)&&"UTC"===t){var b=6E4*s.getTimezoneOffset();s=new Date(s.getTime()+b)}return n("date")(a,d,t)}s=null;return""});if(y(g.min)||g.ngMin){var r;h.$validators.min=function(a){return!p(a)||D(r)||c(a)>=r};g.$observe("min",function(a){r=q(a);h.$validate()})}if(y(g.max)||g.ngMax){var v;
+h.$validators.max=function(a){return!p(a)||D(v)||c(a)<=v};g.$observe("max",function(a){v=q(a);h.$validate()})}}}function td(b,a,c,d){(d.$$hasNativeValidators=L(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?u:b})}function ud(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw nb("constexpr",c,d);return b(a)}return e}function jc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],
+n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){if(!H(a)){if(x(a))return a.split(" ");if(L(a)){var b=[];r(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||{},d=[];r(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var t=l(k,1);h.$addClass(t)}else if(!ia(b,
+n)){var s=e(n),t=d(k,s),k=d(s,k),t=l(t,1),k=l(k,-1);t&&t.length&&c.addClass(g,t);k&&k.length&&c.removeClass(g,k)}}n=sa(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function sd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+uc(b,"-"):"";
+a(ob+b,!0===c);a(vd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[vd]=!(f[ob]=e.hasClass(ob));d.$setValidity=function(b,e,f){e===u?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),wd(d.$pending)&&(d.$pending=u));Xa(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(xd,!0),d.$valid=d.$invalid=u,c("",null)):(a(xd,!1),d.$valid=wd(d.$error),d.$invalid=
+!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?u:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function wd(b){if(b)for(var a in b)return!1;return!0}var Of=/^\/(.+)\/([a-z]*)$/,K=function(b){return x(b)?b.toLowerCase():b},sc=Object.prototype.hasOwnProperty,vb=function(b){return x(b)?b.toUpperCase():b},Ra,B,ta,$a=[].slice,qf=[].splice,Pf=[].push,Ca=Object.prototype.toString,Ja=S("ng"),ca=R.angular||(R.angular={}),eb,rb=0;Ra=W.documentMode;A.$inject=[];ra.$inject=[];var H=
+Array.isArray,N=function(b){return x(b)?b.trim():b},gd=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},db=function(){if(y(db.isActive_))return db.isActive_;var b=!(!W.querySelector("[ng-csp]")&&!W.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return db.isActive_=b},tb=["ng-","data-ng-","ng:","x-ng-"],Md=/[A-Z]/g,vc=!1,Qb,qa=1,bb=3,Qd={full:"1.3.20",major:1,minor:3,dot:20,codeName:"shallow-translucence"};T.expando="ng339";var Ab=
+T.cache={},hf=1;T._data=function(b){return this.cache[b[this.expando]]||{}};var cf=/([\:\-\_]+(.))/g,df=/^moz([A-Z])/,Qf={mouseleave:"mouseout",mouseenter:"mouseover"},Tb=S("jqLite"),gf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Sb=/<|&#?\w+;/,ef=/<([\w:]+)/,ff=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ka={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],
+td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option;ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead;ka.th=ka.td;var Ka=T.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===W.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),T(R).on("load",a))},toString:function(){var b=[];r(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?B(this[b]):B(this[this.length+b])},length:0,push:Pf,sort:[].sort,
+splice:[].splice},Fb={};r("multiple selected checked disabled readOnly required open".split(" "),function(b){Fb[K(b)]=b});var Nc={};r("input select option textarea button form details".split(" "),function(b){Nc[b]=!0});var Oc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};r({data:Vb,removeData:yb},function(b,a){T[a]=b});r({data:Vb,inheritedData:Eb,scope:function(b){return B.data(b,"$scope")||Eb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return B.data(b,
+"$isolateScope")||B.data(b,"$isolateScopeNoTemplate")},controller:Jc,injector:function(b){return Eb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Bb,css:function(b,a,c){a=fb(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==bb&&2!==d&&8!==d)if(d=K(a),Fb[d])if(y(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||A).specified?d:u;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=
+b.getAttribute(a,2),null===b?u:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(D(b)){var d=a.nodeType;return d===qa||d===bb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(D(a)){if(b.multiple&&"select"===wa(b)){var c=[];r(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(D(a))return b.innerHTML;xb(b,!0);b.innerHTML=a},empty:Kc},function(b,a){T.prototype[a]=
+function(a,d){var e,f,g=this.length;if(b!==Kc&&(2==b.length&&b!==Bb&&b!==Jc?a:d)===u){if(L(a)){for(e=0;e<g;e++)if(b===Vb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===u?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});r({removeData:yb,on:function a(c,d,e,f){if(y(f))throw Tb("onargs");if(Fc(c)){var g=zb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=lf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],
+l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===d?a(c,Qf[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Ic,one:function(a,c,d){a=B(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;xb(a);r(new T(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];r(a.childNodes,
+function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new T(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;r(new T(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=B(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Lc,detach:function(a){Lc(a,!0)},after:function(a,
+c){var d=a,e=a.parentNode;c=new T(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,d.nextSibling);d=h}},addClass:Db,removeClass:Cb,toggleClass:function(a,c,d){c&&r(c.split(" "),function(c){var f=d;D(f)&&(f=!Bb(a,c));(f?Db:Cb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Ub,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=
+zb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:A,type:g,target:a},c.type&&(e=w(e,c)),c=sa(h),f=d?[e].concat(d):[e],r(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){T.prototype[c]=function(c,
+e,f){for(var g,h=0,l=this.length;h<l;h++)D(g)?(g=a(this[h],c,e,f),y(g)&&(g=B(g))):Hc(g,a(this[h],c,e,f));return y(g)?g:this};T.prototype.bind=T.prototype.on;T.prototype.unbind=T.prototype.off});gb.prototype={put:function(a,c){this[Na(a,this.nextUid)]=c},get:function(a){return this[Na(a,this.nextUid)]},remove:function(a){var c=this[a=Na(a,this.nextUid)];delete this[a];return c}};var Qc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,Rf=/,/,Sf=/^\s*(_?)(\S+?)\1\s*$/,Pc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Fa=S("$injector");
+cb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=[];if(a.length){if(c)throw x(d)&&d||(d=a.name||mf(a)),Fa("strictdi",d);c=a.toString().replace(Pc,"");c=c.match(Qc);r(c[1].split(Rf),function(a){a.replace(Sf,function(a,c,d){e.push(d)})})}a.$inject=e}}else H(a)?(c=a.length-1,La(a[c],"fn"),e=a.slice(0,c)):La(a,"fn",!0);return e};var Tf=S("$animate"),Ce=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Tf("notcsel",
+c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};this.$get=["$$q","$$asyncCallback","$rootScope",function(a,d,e){function f(d){var f,g=a.defer();g.promise.$$cancelFn=function(){f&&f()};e.$$postDigest(function(){f=d(function(){g.resolve()})});return g.promise}function g(a,c){var d=[],e=[],f=ja();r((a.attr("class")||"").split(/\s+/),function(a){f[a]=!0});r(c,function(a,
+c){var g=f[c];!1===a&&g?e.push(c):!0!==a||g||d.push(c)});return 0<d.length+e.length&&[d.length?d:null,e.length?e:null]}function h(a,c,d){for(var e=0,f=c.length;e<f;++e)a[c[e]]=d}function l(){n||(n=a.defer(),d(function(){n.resolve();n=null}));return n.promise}function k(a,c){if(ca.isObject(c)){var d=w(c.from||{},c.to||{});a.css(d)}}var n;return{animate:function(a,c,d){k(a,{from:c,to:d});return l()},enter:function(a,c,d,e){k(a,e);d?d.after(a):c.prepend(a);return l()},leave:function(a,c){k(a,c);a.remove();
+return l()},move:function(a,c,d,e){return this.enter(a,c,d,e)},addClass:function(a,c,d){return this.setClass(a,c,[],d)},$$addClassImmediately:function(a,c,d){a=B(a);c=x(c)?c:H(c)?c.join(" "):"";r(a,function(a){Db(a,c)});k(a,d);return l()},removeClass:function(a,c,d){return this.setClass(a,[],c,d)},$$removeClassImmediately:function(a,c,d){a=B(a);c=x(c)?c:H(c)?c.join(" "):"";r(a,function(a){Cb(a,c)});k(a,d);return l()},setClass:function(a,c,d,e){var k=this,l=!1;a=B(a);var m=a.data("$$animateClasses");
+m?e&&m.options&&(m.options=ca.extend(m.options||{},e)):(m={classes:{},options:e},l=!0);e=m.classes;c=H(c)?c:c.split(" ");d=H(d)?d:d.split(" ");h(e,c,!0);h(e,d,!1);l&&(m.promise=f(function(c){var d=a.data("$$animateClasses");a.removeData("$$animateClasses");if(d){var e=g(a,d.classes);e&&k.$$setClassImmediately(a,e[0],e[1],d.options)}c()}),a.data("$$animateClasses",m));return m.promise},$$setClassImmediately:function(a,c,d,e){c&&this.$$addClassImmediately(a,c);d&&this.$$removeClassImmediately(a,d);
+k(a,e);return l()},enabled:A,cancel:A}}]}],ma=S("$compile");xc.$inject=["$provide","$$sanitizeUriProvider"];var Rc=/^((?:x|data)[\:\-_])/i,rf=S("$controller"),Vc="application/json",$b={"Content-Type":Vc+";charset=utf-8"},tf=/^\[|^\{(?!\{)/,uf={"[":/]$/,"{":/}$/},sf=/^\)\]\}',?\n/,ac=S("$interpolate"),Uf=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,xf={http:80,https:443,ftp:21},Hb=S("$location"),Vf={$$html5:!1,$$replace:!1,absUrl:Ib("$$absUrl"),url:function(a){if(D(a))return this.$$url;var c=Uf.exec(a);(c[1]||
+""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Ib("$$protocol"),host:Ib("$$host"),port:Ib("$$port"),path:cd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(x(a)||Y(a))a=a.toString(),this.$$search=rc(a);else if(L(a))a=Da(a,{}),r(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Hb("isrcharg");
+break;default:D(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:cd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};r([bd,dc,cc],function(a){a.prototype=Object.create(Vf);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==cc||!this.$$html5)throw Hb("nostate");this.$$state=D(c)?null:c;return this}});var ga=S("$parse"),Wf=Function.prototype.call,Xf=Function.prototype.apply,
+Yf=Function.prototype.bind,pb=ja();r({"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:function(){}},function(a,c){a.constant=a.literal=a.sharedGetter=!0;pb[c]=a});pb["this"]=function(a){return a};pb["this"].sharedGetter=!0;var qb=w(ja(),{"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return y(d)?y(e)?d+e:d:y(e)?e:u},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(y(d)?d:0)-(y(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,
+c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,
+c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Zf={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,
+text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var c=a+this.peek(),d=c+this.peek(2),e=qb[c],f=qb[d];qb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===
+typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ga("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=K(this.text.charAt(this.index));
+if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&
+!this.isNumber(c))break;this.index++}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=Zf[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===
+a){this.index++;this.tokens.push({index:c,text:e,constant:!0,value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var kb=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};kb.ZERO=w(function(){return 0},{sharedGetter:!0,constant:!0});kb.prototype={constructor:kb,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;
+return a},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.peek().identifier&&this.peek().text in pb?a=pb[this.consume().text]:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c,d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a,d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):
+"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,c){throw ga("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw ga("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,
+c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){if(0===this.tokens.length)throw ga("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=qb[a];return w(function(a,f){return d(a,f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a,c,d,e){var f=qb[c];return w(function(c,e){return f(c,e,a,d)},{constant:a.constant&&d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=
+this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return zf(a,this.options,this.text)},constant:function(){var a=this.consume().value;return w(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c,d){for(var e,f=0,g=a.length;f<g;f++)e=a[f](c,d);return e}},
+filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},filter:function(a){var c=this.$filter(this.consume().text),d,e;if(this.peek(":"))for(d=[],e=[];this.expect(":");)d.push(this.expression());var f=[a].concat(d||[]);return w(function(f,h){var l=a(f,h);if(e){e[0]=l;for(l=d.length;l--;)e[l+1]=d[l](f,h);return c.apply(u,e)}return c(l)},{constant:!c.$stateful&&f.every(ec),inputs:!c.$stateful&&f})},expression:function(){return this.assignment()},assignment:function(){var a=
+this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),w(function(d,f){return a.assign(d,c(d,f),f)},{inputs:[a,c]})):a},ternary:function(){var a=this.logicalOR(),c;if(this.expect("?")&&(c=this.assignment(),this.consume(":"))){var d=this.assignment();return w(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})}return a},logicalOR:function(){for(var a=
+this.logicalAND(),c;c=this.expect("||");)a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},logicalAND:function(){for(var a=this.equality(),c;c=this.expect("&&");)a=this.binaryFn(a,c.text,this.equality(),!0);return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a=this.binaryFn(a,c.text,this.relational());return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a=this.binaryFn(a,c.text,this.additive());return a},
+additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(kb.ZERO,a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c=this.identifier();
+return w(function(d,e,f){d=f||a(d,e);return null==d?u:c(d)},{assign:function(d,e,f){var g=a(d,f);g||a.assign(d,g={},f);return c.assign(g,e)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return w(function(e,f){var g=a(e,f),h=dd(d(e,f),c);va(h,c);return g?oa(g[h],c):u},{assign:function(e,f,g){var h=va(dd(d(e,g),c),c),l=oa(a(e,g),c);l||a.assign(e,l={},g);return l[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());
+while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var l=c?c(g,h):y(c)?u:g,k=a(g,h,l)||A;if(f)for(var n=d.length;n--;)f[n]=oa(d[n](g,h),e);oa(l,e);if(k){if(k.constructor===k)throw ga("isecfn",e);if(k===Wf||k===Xf||k===Yf)throw ga("isecff",e);}l=k.apply?k.apply(l,f):k(f[0],f[1],f[2],f[3],f[4]);f&&(f.length=0);return oa(l,e)}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))
+}this.consume("]");return w(function(c,d){for(var e=[],f=0,g=a.length;f<g;f++)e.push(a[f](c,d));return e},{literal:!0,constant:a.every(ec),inputs:a})},object:function(){var a=[],c=[];if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.consume();d.constant?a.push(d.value):d.identifier?a.push(d.text):this.throwError("invalid key",d);this.consume(":");c.push(this.expression())}while(this.expect(","))}this.consume("}");return w(function(d,f){for(var g={},h=0,l=c.length;h<l;h++)g[a[h]]=
+c[h](d,f);return g},{literal:!0,constant:c.every(ec),inputs:c})}};var Bf=ja(),Af=ja(),Cf=Object.prototype.valueOf,Ba=S("$sce"),pa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ma=S("$compile"),Z=W.createElement("a"),id=Aa(R.location.href);Ec.$inject=["$provide"];jd.$inject=["$locale"];ld.$inject=["$locale"];var od=".",Mf={yyyy:U("FullYear",4),yy:U("FullYear",2,0,!0),y:U("FullYear",1),MMMM:Kb("Month"),MMM:Kb("Month",!0),MM:U("Month",2,1),M:U("Month",1,1),dd:U("Date",2),d:U("Date",
+1),HH:U("Hours",2),H:U("Hours",1),hh:U("Hours",2,-12),h:U("Hours",1,-12),mm:U("Minutes",2),m:U("Minutes",1),ss:U("Seconds",2),s:U("Seconds",1),sss:U("Milliseconds",3),EEEE:Kb("Day"),EEE:Kb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Jb(Math[0<a?"floor":"ceil"](a/60),2)+Jb(Math.abs(a%60),2))},ww:qd(2),w:qd(1),G:hc,GG:hc,GGG:hc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},Lf=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
+Kf=/^\-?\d+$/;kd.$inject=["$locale"];var Hf=ea(K),If=ea(vb);md.$inject=["$parse"];var Td=ea({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===Ca.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),wb={};r(Fb,function(a,c){if("multiple"!=a){var d=ya("ng-"+c);wb[d]=function(){return{restrict:"A",priority:100,link:function(a,f,g){a.$watch(g[d],
+function(a){g.$set(c,!!a)})}}}}});r(Oc,function(a,c){wb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(Of))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});r(["src","srcset","href"],function(a){var c=ya("ng-"+a);wb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===Ca.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",
+g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ra&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Lb={$addControl:A,$$renameControl:function(a,c){a.$name=c},$removeControl:A,$setValidity:A,$setDirty:A,$setPristine:A,$setSubmitted:A};rd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var yd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:rd,compile:function(d,e){d.addClass(Sa).addClass(ob);var f=e.name?"name":a&&e.ngForm?"ngForm":
+!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var p=k.$$parentForm;f&&(jb(a,null,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(jb(a,null,k.$name,u,k.$name),p.$$renameControl(k,c),jb(a,null,k.$name,k,k.$name))}));d.on("$destroy",function(){p.$removeControl(k);
+f&&jb(a,null,e[f],u,k.$name);w(k,Lb)})}}}}}]},Ud=yd(),ge=yd(!0),Nf=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,$f=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,ag=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,bg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,zd=/^(\d{4})-(\d{2})-(\d{2})$/,Ad=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,kc=/^(\d{4})-W(\d\d)$/,Bd=/^(\d{4})-(\d\d)$/,
+Cd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Dd={text:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e)},date:mb("date",zd,Nb(zd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Ad,Nb(Ad,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Cd,Nb(Cd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:mb("week",kc,function(a,c){if(ha(a))return a;if(x(a)){kc.lastIndex=0;var d=kc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=pd(e),f=7*(f-1);c&&(d=c.getHours(),g=
+c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:mb("month",Bd,Nb(Bd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){td(a,c,d,e);lb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:bg.test(a)?parseFloat(a):u});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!Y(a))throw nb("numfmt",a);a=a.toString()}return a});if(y(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||
+D(h)||a>=h};d.$observe("min",function(a){y(a)&&!Y(a)&&(a=parseFloat(a,10));h=Y(a)&&!isNaN(a)?a:u;e.$validate()})}if(y(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||D(l)||a<=l};d.$observe("max",function(a){y(a)&&!Y(a)&&(a=parseFloat(a,10));l=Y(a)&&!isNaN(a)?a:u;e.$validate()})}},url:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||$f.test(d)}},email:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e);
+e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||ag.test(d)}},radio:function(a,c,d,e){D(d.name)&&c.attr("name",++rb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=ud(l,a,"ngTrueValue",d.ngTrueValue,!0),n=ud(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&
+a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ia(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:A,button:A,submit:A,reset:A,file:A},yc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Dd[K(h.type)]||Dd.text)(f,g,h,l[0],c,a,d,e)}}}}],cg=/^(true|false|\d+)$/,ye=function(){return{restrict:"A",priority:100,compile:function(a,
+c){return cg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},Zd=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===u?"":a})}}}}],ae=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));
+c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===u?"":a})}}}}],$d=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],xe=ea({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
+be=jc("",!0),de=jc("Odd",0),ce=jc("Even",1),ee=Ia({compile:function(a,c){c.$set("ngCloak",u);a.removeClass("ng-cloak")}}),fe=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Dc={},dg={blur:!0,focus:!0};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Dc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=
+d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};dg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ie=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=W.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=
+ub(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],je=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,p,q,r){var s=0,u,v,m,C=function(){v&&(v.remove(),v=null);u&&(u.$destroy(),u=null);m&&(d.leave(m).then(function(){v=null}),v=m,m=null)};e.$watch(g,function(g){var p=function(){!y(l)||l&&!e.$eval(l)||
+c()},M=++s;g?(a(g,!0).then(function(a){if(M===s){var c=e.$new();q.template=a;a=r(c,function(a){C();d.enter(a,null,f).then(p)});u=c;m=a;u.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){M===s&&(C(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(C(),q.template=null)})}}}}],Ae=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Gc(f.template,W).childNodes)(c,function(a){d.append(a)},
+{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ke=Ia({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),we=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?N(f):f;e.$parsers.push(function(a){if(!D(a)){var c=[];a&&r(a.split(h),function(a){a&&c.push(g?N(a):a)});return c}});e.$formatters.push(function(a){return H(a)?a.join(f):u});e.$isEmpty=function(a){return!a||
+!a.length}}}},ob="ng-valid",vd="ng-invalid",Sa="ng-pristine",Mb="ng-dirty",xd="ng-pending",nb=S("ngModel"),eg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=u;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;
+this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=u;this.$name=n(d.name||"",!1)(a);var p=f(d.ngModel),q=p.assign,t=p,s=q,F=null,v,m=this;this.$$setOptions=function(a){if((m.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");t=function(a){var d=p(a);z(d)&&(d=c(a));return d};s=function(a,c){z(p(a))?g(a,{$$$p:m.$modelValue}):q(a,m.$modelValue)}}else if(!p.assign)throw nb("nonassign",d.ngModel,xa(e));};this.$render=A;this.$isEmpty=function(a){return D(a)||
+""===a||null===a||a!==a};var C=e.inheritedData("$formController")||Lb,w=0;sd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:C,$animate:g});this.$setPristine=function(){m.$dirty=!1;m.$pristine=!0;g.removeClass(e,Mb);g.addClass(e,Sa)};this.$setDirty=function(){m.$dirty=!0;m.$pristine=!1;g.removeClass(e,Sa);g.addClass(e,Mb);C.$setDirty()};this.$setUntouched=function(){m.$touched=!1;m.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=
+function(){m.$touched=!0;m.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);m.$viewValue=m.$$lastCommittedViewValue;m.$render()};this.$validate=function(){if(!Y(m.$modelValue)||!isNaN(m.$modelValue)){var a=m.$$rawModelValue,c=m.$valid,d=m.$modelValue,e=m.$options&&m.$options.allowInvalid;m.$$runValidators(a,m.$$lastCommittedViewValue,function(f){e||c===f||(m.$modelValue=f?a:u,m.$modelValue!==d&&m.$$writeModelToScope())})}};this.$$runValidators=
+function(a,c,d){function e(){var d=!0;r(m.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(r(m.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;r(m.$asyncValidators,function(f,h){var l=f(a,c);if(!l||!z(l.then))throw nb("$asyncValidators",l);g(h,u);d.push(l.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},A):h(!0)}function g(a,c){l===w&&m.$setValidity(a,c)}function h(a){l===w&&d(a)}w++;var l=w;(function(){var a=
+m.$$parserName||"parse";if(v===u)g(a,null);else return v||(r(m.$validators,function(a,c){g(c,null)}),r(m.$asyncValidators,function(a,c){g(c,null)})),g(a,v),v;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=m.$viewValue;h.cancel(F);if(m.$$lastCommittedViewValue!==a||""===a&&m.$$hasNativeValidators)m.$$lastCommittedViewValue=a,m.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=m.$$lastCommittedViewValue;if(v=D(c)?u:!0)for(var d=
+0;d<m.$parsers.length;d++)if(c=m.$parsers[d](c),D(c)){v=!1;break}Y(m.$modelValue)&&isNaN(m.$modelValue)&&(m.$modelValue=t(a));var e=m.$modelValue,f=m.$options&&m.$options.allowInvalid;m.$$rawModelValue=c;f&&(m.$modelValue=c,m.$modelValue!==e&&m.$$writeModelToScope());m.$$runValidators(c,m.$$lastCommittedViewValue,function(a){f||(m.$modelValue=a?c:u,m.$modelValue!==e&&m.$$writeModelToScope())})};this.$$writeModelToScope=function(){s(a,m.$modelValue);r(m.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};
+this.$setViewValue=function(a,c){m.$viewValue=a;m.$options&&!m.$options.updateOnDefault||m.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=m.$options;e&&y(e.debounce)&&(e=e.debounce,Y(e)?d=e:Y(e[c])?d=e[c]:Y(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){m.$commitViewValue()},d):l.$$phase?m.$commitViewValue():a.$apply(function(){m.$commitViewValue()})};a.$watch(function(){var c=t(a);if(c!==m.$modelValue&&(m.$modelValue===m.$modelValue||c===c)){m.$modelValue=
+m.$$rawModelValue=c;v=u;for(var d=m.$formatters,e=d.length,f=c;e--;)f=d[e](f);m.$viewValue!==f&&(m.$viewValue=m.$$lastCommittedViewValue=f,m.$render(),m.$$runValidators(c,f,A))}return c})}],ve=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:eg,priority:1,compile:function(c){c.addClass(Sa).addClass("ng-untouched").addClass(ob);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Lb;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",
+function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],fg=/(\s+|^)default(\s+|$)/,ze=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);
+this.$options.updateOn!==u?(this.$options.updateOnDefault=!1,this.$options.updateOn=N(this.$options.updateOn.replace(fg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},le=Ia({terminal:!0,priority:1E3}),me=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function l(a){g.text(a||"")}var k=h.count,n=h.$attr.when&&g.attr(h.$attr.when),p=h.offset||0,q=f.$eval(n)||{},t={},n=c.startSymbol(),s=
+c.endSymbol(),u=n+k+"-"+p+s,v=ca.noop,m;r(h,function(a,c){var d=e.exec(c);d&&(d=(d[1]?"-":"")+K(d[2]),q[d]=g.attr(h.$attr[c]))});r(q,function(a,e){t[e]=c(a.replace(d,u))});f.$watch(k,function(c){c=parseFloat(c);var d=isNaN(c);d||c in q||(c=a.pluralCat(c-p));c===m||d&&isNaN(m)||(v(),v=f.$watch(t[c],l),m=c)})}}}],ne=["$parse","$animate",function(a,c){var d=S("ngRepeat"),e=function(a,c,d,e,k,n,p){a[d]=e;k&&(a[k]=n);a.$index=c;a.$first=0===c;a.$last=c===p-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=
+0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=W.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],p=k[2],q=k[3],t=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",n);var s=k[3]||k[1],F=k[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||
+/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(q)))throw d("badident",q);var v,m,C,y,w={$id:Na};t?v=a(t):(C=function(a,c){return Na(c)},y=function(a){return a});return function(a,f,g,k,n){v&&(m=function(c,d,e){F&&(w[F]=c);w[s]=d;w.$index=e;return v(a,w)});var t=ja();a.$watchCollection(p,function(g){var k,p,v=f[0],G,w=ja(),D,I,A,z,H,O,x;q&&(a[q]=g);if(Ta(g))H=g,p=m||C;else{p=m||y;H=[];for(x in g)g.hasOwnProperty(x)&&"$"!=x.charAt(0)&&H.push(x);H.sort()}D=
+H.length;x=Array(D);for(k=0;k<D;k++)if(I=g===H?k:H[k],A=g[I],z=p(I,A,k),t[z])O=t[z],delete t[z],w[z]=O,x[k]=O;else{if(w[z])throw r(x,function(a){a&&a.scope&&(t[a.id]=a)}),d("dupes",h,z,A);x[k]={id:z,scope:u,clone:u};w[z]=!0}for(G in t){O=t[G];z=ub(O.clone);c.leave(z);if(z[0].parentNode)for(k=0,p=z.length;k<p;k++)z[k].$$NG_REMOVED=!0;O.scope.$destroy()}for(k=0;k<D;k++)if(I=g===H?k:H[k],A=g[I],O=x[k],O.scope){G=v;do G=G.nextSibling;while(G&&G.$$NG_REMOVED);O.clone[0]!=G&&c.move(ub(O.clone),null,B(v));
+v=O.clone[O.clone.length-1];e(O.scope,k,s,A,F,I,D)}else n(function(a,d){O.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,B(v));v=f;O.clone=a;w[O.id]=O;e(O.scope,k,s,A,F,I,D)});t=w})}}}}],oe=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],he=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?
+"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],pe=Ia(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&r(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),qe=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=
+0;for(e=k.length;d<e;++d){var s=ub(h[d].clone);k[d].$destroy();(l[d]=a.leave(s)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&r(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=W.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],re=Ia({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,
+element:c})}}),se=Ia({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),ue=Ia({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw S("ngTransclude")("orphan",xa(c));f(function(a){c.empty();c.append(a)})}}),Vd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],gg=S("ngOptions"),te=ea({restrict:"A",
+terminal:!0}),Wd=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,e={$setViewValue:A};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var l=this,k={},n=e,p;l.databound=d.ngModel;l.init=function(a,c,d){n=a;p=d};l.addOption=function(c,d){Ma(c,'"option value"');
+k[c]=!0;n.$viewValue==c&&(a.val(c),p.parent()&&p.remove());d&&d[0].hasAttribute("selected")&&(d[0].selected=!0)};l.removeOption=function(a){this.hasOption(a)&&(delete k[a],n.$viewValue===a&&this.renderUnknownOption(a))};l.renderUnknownOption=function(c){c="? "+Na(c)+" ?";p.val(c);a.prepend(p);a.val(c);p.prop("selected",!0)};l.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",function(){l.renderUnknownOption=A})}],link:function(e,g,h,l){function k(a,c,d,e){d.$render=function(){var a=
+d.$viewValue;e.hasOption(a)?(z.parent()&&z.remove(),c.val(a),""===a&&v.prop("selected",!0)):null==a&&v?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){z.parent()&&z.remove();d.$setViewValue(c.val())})})}function n(a,c,d){var e;d.$render=function(){var a=new gb(d.$viewValue);r(c.find("option"),function(c){c.selected=y(a.get(c.value))})};a.$watch(function(){ia(e,d.$viewValue)||(e=sa(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];r(c.find("option"),
+function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function p(e,f,g){function h(a,c,d){T[A]=d;I&&(T[I]=c);return a(e,T)}function l(a){var c;if(t)if(K&&H(a)){c=new gb([]);for(var d=0;d<a.length;d++)c.put(h(K,null,a[d]),!0)}else c=new gb(a);else K&&(a=h(K,null,a));return function(d,e){var f;f=K?K:x?x:E;return t?y(c.remove(h(f,d,e))):a===h(f,d,e)}}function k(){m||(e.$$postDigest(p),m=!0)}function n(a,c,d){a[c]=a[c]||0;a[c]+=d?1:-1}function p(){m=!1;var a={"":[]},c=[""],d,k,s,u,v;s=g.$viewValue;
+u=L(e)||[];var A=I?Object.keys(u).sort():u,x,B,H,E,P={};v=l(s);var N=!1,U,W;R={};for(E=0;H=A.length,E<H;E++){x=E;if(I&&(x=A[E],"$"===x.charAt(0)))continue;B=u[x];d=h(M,x,B)||"";(k=a[d])||(k=a[d]=[],c.push(d));d=v(x,B);N=N||d;B=h(z,x,B);B=y(B)?B:"";W=K?K(e,T):I?A[E]:E;K&&(R[W]=x);k.push({id:W,label:B,selected:d})}t||(w||null===s?a[""].unshift({id:"",label:"",selected:!N}):N||a[""].unshift({id:"?",label:"",selected:!0}));x=0;for(A=c.length;x<A;x++){d=c[x];k=a[d];S.length<=x?(s={element:D.clone().attr("label",
+d),label:k.label},u=[s],S.push(u),f.append(s.element)):(u=S[x],s=u[0],s.label!=d&&s.element.attr("label",s.label=d));N=null;E=0;for(H=k.length;E<H;E++)d=k[E],(v=u[E+1])?(N=v.element,v.label!==d.label&&(n(P,v.label,!1),n(P,d.label,!0),N.text(v.label=d.label),N.prop("label",v.label)),v.id!==d.id&&N.val(v.id=d.id),N[0].selected!==d.selected&&(N.prop("selected",v.selected=d.selected),Ra&&N.prop("selected",v.selected))):(""===d.id&&w?U=w:(U=C.clone()).val(d.id).prop("selected",d.selected).attr("selected",
+d.selected).prop("label",d.label).text(d.label),u.push(v={element:U,label:d.label,id:d.id,selected:d.selected}),n(P,d.label,!0),N?N.after(U):s.element.append(U),N=U);for(E++;u.length>E;)d=u.pop(),n(P,d.label,!1),d.element.remove()}for(;S.length>x;){k=S.pop();for(E=1;E<k.length;++E)n(P,k[E].label,!1);k[0].element.remove()}r(P,function(a,c){0<a?q.addOption(c):0>a&&q.removeOption(c)})}var v;if(!(v=s.match(d)))throw gg("iexp",s,xa(f));var z=c(v[2]||v[1]),A=v[4]||v[6],B=/ as /.test(v[0])&&v[1],x=B?c(B):
+null,I=v[5],M=c(v[3]||""),E=c(v[2]?v[1]:A),L=c(v[7]),K=v[8]?c(v[8]):null,R={},S=[[{element:f,label:""}]],T={};w&&(a(w)(e),w.removeClass("ng-scope"),w.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=L(e)||[],c;if(t)c=[],r(f.val(),function(d){d=K?R[d]:d;c.push("?"===d?u:""===d?null:h(x?x:E,d,a[d]))});else{var d=K?R[f.val()]:f.val();c="?"===d?u:""===d?null:h(x?x:E,d,a[d])}g.$setViewValue(c);p()})});g.$render=p;e.$watchCollection(L,k);e.$watchCollection(function(){var a=L(e),c;
+if(a&&H(a)){c=Array(a.length);for(var d=0,f=a.length;d<f;d++)c[d]=h(z,d,a[d])}else if(a)for(d in c={},a)a.hasOwnProperty(d)&&(c[d]=h(z,d,a[d]));return c},k);t&&e.$watchCollection(function(){return g.$modelValue},k)}if(l[1]){var q=l[0];l=l[1];var t=h.multiple,s=h.ngOptions,w=!1,v,m=!1,C=B(W.createElement("option")),D=B(W.createElement("optgroup")),z=C.clone();h=0;for(var A=g.children(),x=A.length;h<x;h++)if(""===A[h].value){v=w=A.eq(h);break}q.init(l,w,z);t&&(l.$isEmpty=function(a){return!a||0===a.length});
+s?p(e,g,l):t?n(e,g,l):k(e,g,l,q)}}}}],Yd=["$interpolate",function(a){var c={addOption:A,removeOption:A};return{restrict:"E",priority:100,compile:function(d,e){if(D(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),n=k.data("$selectController")||k.parent().data("$selectController");n&&n.databound||(n=c);f?a.$watch(f,function(a,c){e.$set("value",a);c!==a&&n.removeOption(c);n.addOption(a,d)}):n.addOption(e.value,d);d.on("$destroy",function(){n.removeOption(e.value)})}}}}],
+Xd=ea({restrict:"E",terminal:!1}),Ac=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}},zc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){x(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw S("ngPattern")("noregexp",g,a,xa(c));f=
+a||u;e.$validate()});e.$validators.pattern=function(a,c){return e.$isEmpty(c)||D(f)||f.test(c)}}}}},Cc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=aa(a);f=isNaN(a)?-1:a;e.$validate()});e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Bc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=aa(a)||0;e.$validate()});e.$validators.minlength=
+function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};R.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(Nd(),Pd(ca),B(W).ready(function(){Jd(W,tc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>');
+//# sourceMappingURL=angular.min.js.map
diff --git a/afb-client/bower_components/angular/angular.min.js.gzip b/afb-client/bower_components/angular/angular.min.js.gzip
new file mode 100644
index 0000000..ede8ca3
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js.gzip
Binary files differ
diff --git a/afb-client/bower_components/angular/angular.min.js.map b/afb-client/bower_components/angular/angular.min.js.map
new file mode 100644
index 0000000..3104bba
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular.min.js",
+"lineCount":252,
+"mappings":"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",
+"sources":["angular.js"],
+"names":["window","document","undefined","minErr","isArrayLike","obj","isWindow","length","Object","nodeType","NODE_TYPE_ELEMENT","isString","isArray","forEach","iterator","context","key","isFunction","hasOwnProperty","call","isPrimitive","forEachSorted","keys","sort","i","reverseParams","iteratorFn","value","nextUid","uid","setHashKey","h","$$hashKey","extend","dst","ii","arguments","j","jj","int","str","parseInt","inherit","parent","extra","create","noop","identity","$","valueFn","isUndefined","isDefined","isObject","isNumber","isDate","toString","isRegExp","isScope","$evalAsync","$watch","isBoolean","isElement","node","nodeName","prop","attr","find","makeMap","items","split","nodeName_","element","lowercase","arrayRemove","array","index","indexOf","splice","copy","source","destination","stackSource","stackDest","ngMinErr","push","result","Date","getTime","RegExp","match","lastIndex","emptyObject","getPrototypeOf","shallowCopy","src","charAt","equals","o1","o2","t1","t2","keySet","concat","array1","array2","slice","bind","self","fn","curryArgs","startIndex","apply","toJsonReplacer","val","toJson","pretty","JSON","stringify","fromJson","json","parse","startingTag","jqLite","clone","empty","e","elemHtml","append","html","NODE_TYPE_TEXT","replace","tryDecodeURIComponent","decodeURIComponent","parseKeyValue","keyValue","key_value","toKeyValue","parts","arrayValue","encodeUriQuery","join","encodeUriSegment","pctEncodeSpaces","encodeURIComponent","getNgAttribute","ngAttr","ngAttrPrefixes","angularInit","bootstrap","appElement","module","config","prefix","name","hasAttribute","getAttribute","candidate","querySelector","strictDi","modules","defaultConfig","doBootstrap","injector","tag","unshift","$provide","debugInfoEnabled","$compileProvider","createInjector","invoke","bootstrapApply","scope","compile","$apply","data","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","test","angular","resumeBootstrap","angular.resumeBootstrap","extraModules","resumeDeferredBootstrap","reloadWithDebugInfo","location","reload","getTestability","rootElement","get","snake_case","separator","SNAKE_CASE_REGEXP","letter","pos","toLowerCase","bindJQuery","originalCleanData","bindJQueryFired","jQuery","on","JQLitePrototype","isolateScope","controller","inheritedData","cleanData","jQuery.cleanData","elems","events","skipDestroyOnNextJQueryCleanData","elem","_data","$destroy","triggerHandler","JQLite","assertArg","arg","reason","assertArgFn","acceptArrayAnnotation","constructor","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","nextSibling","createMap","setupModuleLoader","ensure","factory","$injectorMinErr","$$minErr","requires","configFn","invokeLater","provider","method","insertMethod","queue","invokeQueue","moduleInstance","configBlocks","runBlocks","_invokeQueue","_configBlocks","_runBlocks","service","constant","animation","filter","directive","run","block","publishExternalAPI","version","uppercase","counter","csp","angularModule","$LocaleProvider","ngModule","$$sanitizeUri","$$SanitizeUriProvider","$CompileProvider","a","htmlAnchorDirective","input","inputDirective","textarea","form","formDirective","script","scriptDirective","select","selectDirective","style","styleDirective","option","optionDirective","ngBind","ngBindDirective","ngBindHtml","ngBindHtmlDirective","ngBindTemplate","ngBindTemplateDirective","ngClass","ngClassDirective","ngClassEven","ngClassEvenDirective","ngClassOdd","ngClassOddDirective","ngCloak","ngCloakDirective","ngController","ngControllerDirective","ngForm","ngFormDirective","ngHide","ngHideDirective","ngIf","ngIfDirective","ngInclude","ngIncludeDirective","ngInit","ngInitDirective","ngNonBindable","ngNonBindableDirective","ngPluralize","ngPluralizeDirective","ngRepeat","ngRepeatDirective","ngShow","ngShowDirective","ngStyle","ngStyleDirective","ngSwitch","ngSwitchDirective","ngSwitchWhen","ngSwitchWhenDirective","ngSwitchDefault","ngSwitchDefaultDirective","ngOptions","ngOptionsDirective","ngTransclude","ngTranscludeDirective","ngModel","ngModelDirective","ngList","ngListDirective","ngChange","ngChangeDirective","pattern","patternDirective","ngPattern","required","requiredDirective","ngRequired","minlength","minlengthDirective","ngMinlength","maxlength","maxlengthDirective","ngMaxlength","ngValue","ngValueDirective","ngModelOptions","ngModelOptionsDirective","ngIncludeFillContentDirective","ngAttributeAliasDirectives","ngEventDirectives","$anchorScroll","$AnchorScrollProvider","$animate","$AnimateProvider","$browser","$BrowserProvider","$cacheFactory","$CacheFactoryProvider","$controller","$ControllerProvider","$document","$DocumentProvider","$exceptionHandler","$ExceptionHandlerProvider","$filter","$FilterProvider","$interpolate","$InterpolateProvider","$interval","$IntervalProvider","$http","$HttpProvider","$httpBackend","$HttpBackendProvider","$location","$LocationProvider","$log","$LogProvider","$parse","$ParseProvider","$rootScope","$RootScopeProvider","$q","$QProvider","$$q","$$QProvider","$sce","$SceProvider","$sceDelegate","$SceDelegateProvider","$sniffer","$SnifferProvider","$templateCache","$TemplateCacheProvider","$templateRequest","$TemplateRequestProvider","$$testability","$$TestabilityProvider","$timeout","$TimeoutProvider","$window","$WindowProvider","$$rAF","$$RAFProvider","$$asyncCallback","$$AsyncCallbackProvider","$$jqLite","$$jqLiteProvider","camelCase","SPECIAL_CHARS_REGEXP","_","offset","toUpperCase","MOZ_HACK_REGEXP","jqLiteAcceptsData","NODE_TYPE_DOCUMENT","jqLiteBuildFragment","tmp","fragment","createDocumentFragment","HTML_REGEXP","appendChild","createElement","TAG_NAME_REGEXP","exec","wrap","wrapMap","_default","innerHTML","XHTML_TAG_REGEXP","lastChild","childNodes","firstChild","textContent","createTextNode","argIsString","trim","jqLiteMinErr","parsed","SINGLE_TAG_REGEXP","jqLiteAddNodes","jqLiteClone","cloneNode","jqLiteDealoc","onlyDescendants","jqLiteRemoveData","querySelectorAll","descendants","l","jqLiteOff","type","unsupported","expandoStore","jqLiteExpandoStore","handle","listenerFns","removeEventListener","expandoId","ng339","jqCache","createIfNecessary","jqId","jqLiteData","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","setAttribute","cssClass","jqLiteAddClass","existingClasses","root","elements","jqLiteController","jqLiteInheritedData","documentElement","names","parentNode","NODE_TYPE_DOCUMENT_FRAGMENT","host","jqLiteEmpty","removeChild","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","readyState","setTimeout","getBooleanAttrName","booleanAttr","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","getAliasedAttrName","ALIASED_ATTR","createEventHandler","eventHandler","event","isDefaultPrevented","event.isDefaultPrevented","defaultPrevented","eventFns","eventFnsLength","immediatePropagationStopped","originalStopImmediatePropagation","stopImmediatePropagation","event.stopImmediatePropagation","stopPropagation","isImmediatePropagationStopped","event.isImmediatePropagationStopped","$get","this.$get","hasClass","classes","addClass","removeClass","hashKey","nextUidFn","objType","HashMap","isolatedUid","this.nextUid","put","anonFn","args","fnText","STRIP_COMMENTS","FN_ARGS","modulesToLoad","supportObject","delegate","provider_","providerInjector","instantiate","providerCache","providerSuffix","enforceReturnValue","enforcedReturnValue","instanceInjector","factoryFn","enforce","loadModules","moduleFn","runInvokeQueue","invokeArgs","loadedModules","message","stack","createInternalInjector","cache","getService","serviceName","caller","INSTANTIATING","err","shift","locals","$inject","$$annotate","Type","instance","prototype","returnedValue","annotate","has","$injector","instanceCache","decorator","decorFn","origProvider","orig$get","origProvider.$get","origInstance","$delegate","autoScrollingEnabled","disableAutoScrolling","this.disableAutoScrolling","getFirstAnchor","list","Array","some","scrollTo","scrollIntoView","scroll","yOffset","getComputedStyle","position","getBoundingClientRect","bottom","elemTop","top","scrollBy","hash","elm","getElementById","getElementsByName","autoScrollWatch","autoScrollWatchAction","newVal","oldVal","supported","Browser","completeOutstandingRequest","outstandingRequestCount","outstandingRequestCallbacks","pop","error","startPoller","interval","check","pollFns","pollFn","pollTimeout","cacheStateAndFireUrlChange","cacheState","fireUrlChange","history","state","cachedState","lastCachedState","lastBrowserUrl","url","lastHistoryState","urlChangeListeners","listener","safeDecodeURIComponent","rawDocument","clearTimeout","pendingDeferIds","isMock","$$completeOutstandingRequest","$$incOutstandingRequestCount","self.$$incOutstandingRequestCount","notifyWhenNoOutstandingRequests","self.notifyWhenNoOutstandingRequests","callback","addPollFn","self.addPollFn","href","baseElement","reloadLocation","self.url","sameState","sameBase","stripHash","substr","self.state","urlChangeInit","onUrlChange","self.onUrlChange","$$checkUrlChange","baseHref","self.baseHref","lastCookies","lastCookieString","cookiePath","cookies","self.cookies","cookieLength","cookie","warn","cookieArray","substring","defer","self.defer","delay","timeoutId","cancel","self.defer.cancel","deferId","cacheFactory","cacheId","options","refresh","entry","freshEnd","staleEnd","n","link","p","nextEntry","prevEntry","caches","size","stats","id","capacity","Number","MAX_VALUE","lruHash","lruEntry","remove","removeAll","destroy","info","cacheFactory.info","cacheFactory.get","$$sanitizeUriProvider","parseIsolateBindings","directiveName","LOCAL_REGEXP","bindings","definition","scopeName","$compileMinErr","mode","collection","optional","attrName","hasDirectives","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","REQUIRE_PREFIX_REGEXP","EVENT_HANDLER_ATTR_REGEXP","this.directive","registerDirective","directiveFactory","Suffix","directives","priority","require","restrict","$$isolateBindings","aHrefSanitizationWhitelist","this.aHrefSanitizationWhitelist","regexp","imgSrcSanitizationWhitelist","this.imgSrcSanitizationWhitelist","this.debugInfoEnabled","enabled","safeAddClass","$element","className","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","nodeValue","compositeLinkFn","compileNodes","$$addScopeClass","namespace","publicLinkFn","cloneConnectFn","parentBoundTranscludeFn","transcludeControllers","futureParentElement","$$boundTransclude","$linkNode","wrapTemplate","controllerName","$$addScopeInfo","nodeList","$rootElement","childLinkFn","childScope","childBoundTranscludeFn","stableNodeList","nodeLinkFnFound","linkFns","idx","nodeLinkFn","$new","transcludeOnThisElement","createBoundTranscludeFn","transclude","elementTranscludeOnThisElement","templateOnThisElement","attrs","linkFnFound","Attributes","collectDirectives","applyDirectivesToNode","$$element","terminal","previousBoundTranscludeFn","elementTransclusion","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","$$transcluded","attrsMap","$attr","addDirective","directiveNormalize","isNgAttr","nAttrs","attributes","attrStartName","attrEndName","ngAttrName","NG_ATTR_BINDING","PREFIX_REGEXP","directiveNName","directiveIsMultiElement","nName","addAttrInterpolateDirective","animVal","addTextInterpolateDirective","NODE_TYPE_COMMENT","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","addLinkFns","pre","post","newIsolateScopeDirective","$$isolateScope","cloneAndAnnotateFn","getControllers","elementControllers","retrievalMethod","$searchElement","linkNode","controllersBoundTransclude","cloneAttachFn","hasElementTranscludeDirective","scopeToChild","controllerDirectives","$scope","$attrs","$transclude","controllerInstance","controllerAs","templateDirective","$$originalDirective","isolateScopeController","isolateBindingContext","identifier","bindToController","lastValue","parentGet","parentSet","compare","$observe","$$observers","$$scope","literal","b","assign","parentValueWatch","parentValue","$stateful","unwatch","$watchCollection","$on","invokeLinkFn","template","templateUrl","terminalPriority","newScopeDirective","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","$compileNode","$template","childTranscludeFn","$$start","$$end","directiveValue","assertNoDuplicate","$$tlb","createComment","replaceWith","replaceDirective","contents","denormalizeTemplate","removeComments","templateNamespace","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectivesAsIsolate","mergeTemplateAttributes","compileTemplateUrl","Math","max","tDirectives","startAttrName","endAttrName","multiElement","srcAttr","dstAttr","$set","tAttrs","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","then","content","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","$$destroyed","oldClasses","delayedNodeLinkFn","ignoreChildLinkFn","diff","what","previousDirective","text","interpolateFn","textInterpolateCompileFn","templateNode","templateNodeParent","hasCompileParent","$$addBindingClass","textInterpolateLinkFn","$$addBindingInfo","expressions","interpolateFnWatchAction","wrapper","getTrustedContext","attrNormalizedName","HTML","RESOURCE_URL","allOrNothing","trustedContext","attrInterpolatePreLinkFn","newValue","$$inter","oldValue","$updateClass","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","replaceChild","expando","k","kk","annotation","attributesToCopy","$normalize","$addClass","classVal","$removeClass","newClasses","toAdd","tokenDifference","toRemove","writeAttr","booleanKey","aliasedKey","observer","trimmedSrcset","srcPattern","rawUris","nbrUrisWith2parts","floor","innerIdx","lastTuple","removeAttr","listeners","startSymbol","endSymbol","binding","isolated","noTemplate","dataName","str1","str2","values","tokens1","tokens2","token","jqNodes","globals","CNTRL_REG","register","this.register","allowGlobals","this.allowGlobals","addIdentifier","expression","later","ident","$controllerMinErr","controllerPrototype","exception","cause","defaultHttpResponseTransform","headers","tempData","JSON_PROTECTION_PREFIX","contentType","jsonStart","JSON_START","JSON_ENDS","parseHeaders","line","headersGetter","headersObj","transformData","status","fns","defaults","transformResponse","transformRequest","d","common","CONTENT_TYPE_APPLICATION_JSON","patch","xsrfCookieName","xsrfHeaderName","useApplyAsync","this.useApplyAsync","interceptorFactories","interceptors","requestConfig","response","resp","reject","executeHeaderFns","headerContent","processedHeaders","headerFn","header","mergeHeaders","defHeaders","reqHeaders","defHeaderName","reqHeaderName","lowercaseDefHeaderName","chain","serverRequest","reqData","withCredentials","sendReq","promise","when","reversedInterceptors","interceptor","request","requestError","responseError","thenFn","rejectFn","success","promise.success","promise.error","done","headersString","statusText","resolveHttpPromise","resolvePromise","$applyAsync","$$phase","deferred","resolve","resolvePromiseWithResult","removePendingReq","pendingRequests","cachedResp","buildUrl","params","defaultCache","xsrfValue","urlIsSameOrigin","timeout","responseType","v","toISOString","interceptorFactory","createShortMethods","createShortMethodsWithData","createXhr","XMLHttpRequest","createHttpBackend","callbacks","$browserDefer","jsonpReq","callbackId","async","body","called","addEventListener","timeoutRequest","jsonpDone","xhr","abort","completeRequest","open","setRequestHeader","onload","xhr.onload","responseText","urlResolve","protocol","getAllResponseHeaders","onerror","onabort","send","this.startSymbol","this.endSymbol","escape","ch","mustHaveExpression","unescapeText","escapedStartRegexp","escapedEndRegexp","parseStringifyInterceptor","getTrusted","valueOf","newErr","$interpolateMinErr","endIndex","parseFns","textLength","expressionPositions","startSymbolLength","exp","endSymbolLength","compute","interpolationFn","$$watchDelegate","objectEquality","$watchGroup","interpolateFnWatcher","oldValues","currValue","$interpolate.startSymbol","$interpolate.endSymbol","count","invokeApply","setInterval","clearInterval","iteration","skipApply","$$intervalId","tick","notify","intervals","interval.cancel","NUMBER_FORMATS","DECIMAL_SEP","GROUP_SEP","PATTERNS","minInt","minFrac","maxFrac","posPre","posSuf","negPre","negSuf","gSize","lgSize","CURRENCY_SYM","DATETIME_FORMATS","MONTH","SHORTMONTH","DAY","SHORTDAY","AMPMS","medium","fullDate","longDate","mediumDate","shortDate","mediumTime","shortTime","ERANAMES","ERAS","pluralCat","num","encodePath","segments","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","$$protocol","$$host","hostname","$$port","port","DEFAULT_PORTS","parseAppUrl","relativeUrl","prefixed","$$path","pathname","$$search","search","$$hash","beginsWith","begin","whole","trimEmptyHash","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","$$html5","$$parse","this.$$parse","pathUrl","$locationMinErr","$$compose","this.$$compose","$$url","$$absUrl","$$parseLinkUrl","this.$$parseLinkUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","windowsFilePathExp","base","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationGetter","property","locationGetterSetter","preprocess","html5Mode","requireBase","rewriteLinks","this.hashPrefix","this.html5Mode","setBrowserUrlWithFallback","oldUrl","oldState","$$state","afterLocationChange","$broadcast","absUrl","LocationMode","initialUrl","lastIndexOf","IGNORE_URI_REGEXP","ctrlKey","metaKey","shiftKey","which","button","target","absHref","preventDefault","initializing","newUrl","newState","$digest","$locationWatch","currentReplace","$$replace","urlOrStateChanged","debug","debugEnabled","this.debugEnabled","flag","formatError","Error","sourceURL","consoleLog","console","logFn","log","hasApply","arg1","arg2","ensureSafeMemberName","fullExpression","$parseMinErr","getStringValue","ensureSafeObject","children","isConstant","setter","setValue","fullExp","propertyObj","isPossiblyDangerousMemberName","cspSafeGetterFn","key0","key1","key2","key3","key4","expensiveChecks","eso","o","eso0","eso1","eso2","eso3","eso4","cspSafeGetter","pathVal","getterFnWithEnsureSafeObject","s","getterFn","getterFnCache","getterFnCacheExpensive","getterFnCacheDefault","pathKeys","pathKeysLength","code","needsEnsureSafeObject","lookupJs","evaledFnGetter","Function","sharedGetter","fn.assign","getValueOf","objectValueOf","cacheDefault","cacheExpensive","wrapSharedExpression","wrapped","collectExpressionInputs","inputs","expressionInputDirtyCheck","oldValueOfValue","inputsWatchDelegate","parsedExpression","inputExpressions","$$inputs","lastResult","oldInputValue","expressionInputWatch","newInputValue","oldInputValueOfValues","expressionInputsWatch","changed","oneTimeWatchDelegate","oneTimeWatch","oneTimeListener","old","$$postDigest","oneTimeLiteralWatchDelegate","isAllDefined","allDefined","constantWatchDelegate","constantWatch","constantListener","addInterceptor","interceptorFn","watchDelegate","regularInterceptedExpression","oneTimeInterceptedExpression","$parseOptions","$parseOptionsExpensive","oneTime","cacheKey","parseOptions","lexer","Lexer","parser","Parser","qFactory","nextTick","exceptionHandler","callOnce","resolveFn","Promise","simpleBind","scheduleProcessQueue","processScheduled","pending","Deferred","$qMinErr","TypeError","onFulfilled","onRejected","progressBack","catch","finally","handleCallback","$$reject","$$resolve","progress","makePromise","resolved","isResolved","callbackOutput","errback","$Q","Q","resolver","all","promises","results","flush","taskQueue","task","taskCount","queueFn","asyncFn","cancelLastRAF","rafFn","cancelQueueFn","requestAnimationFrame","webkitRequestAnimationFrame","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","rafSupported","timer","createChildScopeClass","ChildScope","$$watchers","$$nextSibling","$$childHead","$$childTail","$$listeners","$$listenerCount","$id","$$ChildScope","TTL","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","digestTtl","this.digestTtl","destroyChildScope","$event","currentScope","Scope","$parent","$$prevSibling","$root","beginPhase","phase","decrementListenerCount","current","initWatchVal","flushApplyAsync","applyAsyncQueue","scheduleApplyAsync","isolate","child","watchExp","watcher","last","eq","deregisterWatch","watchExpressions","watchGroupAction","changeReactionScheduled","firstRun","newValues","deregisterFns","shouldCall","deregisterWatchGroup","expr","unwatchFn","watchGroupSubAction","$watchCollectionInterceptor","_value","bothNaN","newItem","oldItem","internalArray","oldLength","changeDetected","newLength","internalObject","veryOldValue","trackVeryOldValue","changeDetector","initRun","$watchCollectionAction","watch","watchers","dirty","ttl","watchLog","logIdx","asyncTask","asyncQueue","$eval","isNaN","msg","next","postDigestQueue","eventName","this.$watchGroup","$applyAsyncExpression","namedListeners","indexOfListener","$emit","targetScope","listenerArgs","$$asyncQueue","$$postDigestQueue","$$applyAsyncQueue","sanitizeUri","uri","isImage","regex","normalizedVal","adjustMatcher","matcher","$sceMinErr","escapeForRegexp","adjustMatchers","matchers","adjustedMatchers","SCE_CONTEXTS","resourceUrlWhitelist","resourceUrlBlacklist","this.resourceUrlWhitelist","this.resourceUrlBlacklist","matchUrl","generateHolderType","Base","holderType","trustedValue","$$unwrapTrustedValue","this.$$unwrapTrustedValue","holderType.prototype.valueOf","holderType.prototype.toString","htmlSanitizer","trustedValueHolderBase","byType","CSS","URL","JS","trustAs","Constructor","maybeTrusted","allowed","this.enabled","msie","sce","isEnabled","sce.isEnabled","sce.getTrusted","parseAs","sce.parseAs","enumValue","lName","eventSupport","android","userAgent","navigator","boxee","vendorPrefix","vendorRegex","bodyStyle","transitions","animations","webkitTransition","webkitAnimation","pushState","hasEvent","divElm","handleRequestFn","tpl","ignoreRequestError","totalPendingRequests","getTrustedResourceUrl","transformer","httpOptions","handleError","testability","testability.findBindings","opt_exactMatch","getElementsByClassName","matches","dataBinding","bindingName","testability.findModels","prefixes","attributeEquals","testability.getLocation","testability.setLocation","testability.whenStable","deferreds","$$timeoutId","timeout.cancel","urlParsingNode","requestUrl","originUrl","filters","suffix","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","matchAgainstAnyProp","expressionType","predicateFn","createPredicateFn","shouldMatchPrimitives","actual","expected","item","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","$locale","formats","amount","currencySymbol","fractionSize","formatNumber","number","groupSep","decimalSep","isFinite","isNegative","abs","numStr","formatedText","hasExponent","toFixed","parseFloat","fractionLen","min","round","fraction","lgroup","group","padNumber","digits","neg","dateGetter","date","dateStrGetter","shortForm","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getDay","weekGetter","firstThurs","getFullYear","thisThurs","getMonth","getDate","eraGetter","jsonStringToDate","string","R_ISO8601_STR","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","m","ms","format","timezone","NUMBER_STRING","DATE_FORMATS_SPLIT","setMinutes","getMinutes","getTimezoneOffset","DATE_FORMATS","object","spacing","limit","Infinity","sortPredicate","reverseOrder","reverseComparator","comp","descending","objectToString","v1","v2","map","predicate","ngDirective","FormController","controls","parentForm","$$parentForm","nullFormCtrl","$error","$$success","$pending","$name","$dirty","$pristine","$valid","$invalid","$submitted","$addControl","$rollbackViewValue","form.$rollbackViewValue","control","$commitViewValue","form.$commitViewValue","form.$addControl","$$renameControl","form.$$renameControl","newName","oldName","$removeControl","form.$removeControl","$setValidity","addSetValidityMethod","ctrl","set","unset","$setDirty","form.$setDirty","PRISTINE_CLASS","DIRTY_CLASS","$setPristine","form.$setPristine","setClass","SUBMITTED_CLASS","$setUntouched","form.$setUntouched","$setSubmitted","form.$setSubmitted","stringBasedInputType","$formatters","$isEmpty","baseInputType","composing","ev","ngTrim","$viewValue","$$hasNativeValidators","$setViewValue","deferListener","origValue","keyCode","$render","ctrl.$render","createDateParser","mapping","iso","ISO_DATE_REGEXP","yyyy","MM","dd","HH","getHours","mm","ss","getSeconds","sss","getMilliseconds","part","NaN","createDateInputType","parseDate","dynamicDateInputType","isValidDate","parseObservedDateValue","badInputChecker","$options","previousDate","$$parserName","$parsers","parsedDate","ngModelMinErr","timezoneOffset","ngMin","minVal","$validators","ctrl.$validators.min","$validate","ngMax","maxVal","ctrl.$validators.max","validity","VALIDITY_STATE_PROPERTY","badInput","typeMismatch","parseConstantExpr","fallback","parseFn","classDirective","arrayDifference","arrayClasses","digestClassCounts","classCounts","classesToUpdate","ngClassWatchAction","$index","old$index","mod","cachedToggleClass","switchValue","classCache","toggleValidationCss","validationErrorKey","isValid","VALID_CLASS","INVALID_CLASS","setValidity","isObjectEmpty","PENDING_CLASS","combinedState","REGEX_STRING_REGEXP","documentMode","isActive_","active","full","major","minor","dot","codeName","JQLite._data","MOUSE_EVENT_MAP","mouseleave","mouseenter","optgroup","tbody","tfoot","colgroup","caption","thead","th","td","ready","trigger","fired","removeData","removeAttribute","css","NODE_TYPE_ATTRIBUTE","lowercasedName","specified","getNamedItem","ret","getText","$dv","multiple","selected","nodeCount","jqLiteOn","types","related","relatedTarget","contains","off","one","onFn","replaceNode","insertBefore","contentDocument","prepend","wrapNode","detach","after","newElement","toggleClass","condition","classCondition","nextElementSibling","getElementsByTagName","extraParameters","dummyEvent","handlerArgs","eventFnsCopy","arg3","unbind","FN_ARG_SPLIT","FN_ARG","argDecl","underscore","$animateMinErr","$$selectors","classNameFilter","this.classNameFilter","$$classNameFilter","runAnimationPostDigest","cancelFn","$$cancelFn","defer.promise.$$cancelFn","ngAnimatePostDigest","ngAnimateNotifyComplete","resolveElementClasses","hasClasses","cachedClassManipulation","op","asyncPromise","currentDefer","applyStyles","styles","from","to","animate","enter","leave","move","$$addClassImmediately","$$removeClassImmediately","add","createdCache","STORAGE_KEY","$$setClassImmediately","APPLICATION_JSON","PATH_MATCH","locationPrototype","paramValue","Location","Location.prototype.state","CALL","APPLY","BIND","CONSTANTS","null","true","false","constantGetter","OPERATORS","+","-","*","/","%","===","!==","==","!=","<",">","<=",">=","&&","||","!","ESCAPE","lex","tokens","readString","peek","readNumber","isIdent","readIdent","is","isWhitespace","ch2","ch3","op2","op3","op1","operator","throwError","chars","isExpOperator","start","end","colStr","peekCh","quote","rawString","hex","String","fromCharCode","rep","ZERO","statements","primary","expect","filterChain","consume","arrayDeclaration","functionCall","objectIndex","fieldAccess","peekToken","e1","e2","e3","e4","peekAhead","t","unaryFn","right","$parseUnaryFn","binaryFn","left","isBranching","$parseBinaryFn","$parseConstant","$parseStatements","inputFn","argsFn","$parseFilter","every","assignment","ternary","$parseAssignment","logicalOR","middle","$parseTernary","logicalAND","equality","relational","additive","multiplicative","unary","$parseFieldAccess","indexFn","$parseObjectIndex","fnGetter","contextGetter","expressionText","$parseFunctionCall","elementFns","$parseArrayLiteral","valueFns","$parseObjectLiteral","yy","y","MMMM","MMM","M","H","hh","EEEE","EEE","ampmGetter","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","xlinkHref","propName","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","ngFormCompile","formElement","nameAttr","ngFormPreLink","handleFormSubmission","parentFormCtrl","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","minutes","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","ctrls","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","tElement","ngBindHtmlGetter","ngBindHtmlWatch","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","newScope","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","that","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","lhs","rhs","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","itemKey","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","tempClasses","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","ngOptionsMinErr","NG_OPTIONS_REGEXP","nullModelCtrl","optionsMap","ngModelCtrl","unknownOption","databound","init","self.init","ngModelCtrl_","nullOption_","unknownOption_","addOption","self.addOption","removeOption","self.removeOption","hasOption","renderUnknownOption","self.renderUnknownOption","unknownVal","self.hasOption","setupAsSingle","selectElement","selectCtrl","ngModelCtrl.$render","emptyOption","setupAsMultiple","lastView","selectMultipleWatch","setupAsOptions","callExpression","exprFn","valueName","keyName","createIsSelectedFn","selectedSet","trackFn","trackIndex","isSelected","compareValueFn","selectAsFn","scheduleRendering","renderScheduled","render","updateLabelMap","labelMap","label","added","optionGroups","optionGroupNames","optionGroupName","optionGroup","existingParent","existingOptions","existingOption","valuesFn","anySelected","optionId","trackKeysCache","groupByFn","displayFn","nullOption","groupIndex","groupLength","optionGroupsCache","optGroupTemplate","lastElement","optionTemplate","optionsExp","selectAs","track","selectionChanged","selectedKey","viewValueFn","getLabels","toDisplay","ngModelCtrl.$isEmpty","nullSelectCtrl","selectCtrlName","interpolateWatchAction","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","$$csp","head"]
+}
diff --git a/afb-client/bower_components/angular/bower.json b/afb-client/bower_components/angular/bower.json
new file mode 100644
index 0000000..5bde08c
--- /dev/null
+++ b/afb-client/bower_components/angular/bower.json
@@ -0,0 +1,8 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "main": "./angular.js",
+ "ignore": [],
+ "dependencies": {
+ }
+}
diff --git a/afb-client/bower_components/angular/index.js b/afb-client/bower_components/angular/index.js
new file mode 100644
index 0000000..5c1aafc
--- /dev/null
+++ b/afb-client/bower_components/angular/index.js
@@ -0,0 +1,2 @@
+require('./angular');
+module.exports = angular;
diff --git a/afb-client/bower_components/angular/package.json b/afb-client/bower_components/angular/package.json
new file mode 100644
index 0000000..563bd60
--- /dev/null
+++ b/afb-client/bower_components/angular/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "description": "HTML enhanced for web apps",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular/angular.js.git"
+ },
+ "keywords": [
+ "angular",
+ "framework",
+ "browser",
+ "client-side"
+ ],
+ "author": "Angular Core Team <angular-core+npm@google.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/angular/angular.js/issues"
+ },
+ "homepage": "http://angularjs.org"
+}
diff --git a/afb-client/bower_components/fastclick/.bower.json b/afb-client/bower_components/fastclick/.bower.json
new file mode 100644
index 0000000..1021ae4
--- /dev/null
+++ b/afb-client/bower_components/fastclick/.bower.json
@@ -0,0 +1,23 @@
+{
+ "name": "fastclick",
+ "main": "lib/fastclick.js",
+ "ignore": [
+ "**/.*",
+ "component.json",
+ "package.json",
+ "Makefile",
+ "tests",
+ "examples"
+ ],
+ "homepage": "https://github.com/ftlabs/fastclick",
+ "version": "1.0.6",
+ "_release": "1.0.6",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.0.6",
+ "commit": "2ac7258407619398005ca720596f0d36ce66a6c8"
+ },
+ "_source": "git://github.com/ftlabs/fastclick.git",
+ "_target": "~1.0.3",
+ "_originalSource": "fastclick"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/fastclick/LICENSE b/afb-client/bower_components/fastclick/LICENSE
new file mode 100644
index 0000000..459a20d
--- /dev/null
+++ b/afb-client/bower_components/fastclick/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 The Financial Times Ltd.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/afb-client/bower_components/fastclick/README.md b/afb-client/bower_components/fastclick/README.md
new file mode 100644
index 0000000..074895d
--- /dev/null
+++ b/afb-client/bower_components/fastclick/README.md
@@ -0,0 +1,140 @@
+# FastClick #
+
+FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a `click` event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic.
+
+FastClick is developed by [FT Labs](http://labs.ft.com/), part of the Financial Times.
+
+[Explication en français](http://maxime.sh/2013/02/supprimer-le-lag-des-clics-sur-mobile-avec-fastclick/).
+
+[日本語で説明](https://developer.mozilla.org/ja/docs/Mozilla/Firefox_OS/Apps/Tips_and_techniques#Make_events_immediate)。
+
+## Why does the delay exist? ##
+
+According to [Google](https://developers.google.com/mobile/articles/fast_buttons):
+
+> ...mobile browsers will wait approximately 300ms from the time that you tap the button to fire the click event. The reason for this is that the browser is waiting to see if you are actually performing a double tap.
+
+## Compatibility ##
+
+The library has been deployed as part of the [FT Web App](http://app.ft.com/) and is tried and tested on the following mobile browsers:
+
+* Mobile Safari on iOS 3 and upwards
+* Chrome on iOS 5 and upwards
+* Chrome on Android (ICS)
+* Opera Mobile 11.5 and upwards
+* Android Browser since Android 2
+* PlayBook OS 1 and upwards
+
+## When it isn't needed ##
+
+FastClick doesn't attach any listeners on desktop browsers.
+
+Chrome 32+ on Android with `width=device-width` in the [viewport meta tag](https://developer.mozilla.org/en-US/docs/Mobile/Viewport_meta_tag) doesn't have a 300ms delay, therefore listeners aren't attached.
+
+```html
+<meta name="viewport" content="width=device-width, initial-scale=1">
+```
+
+Same goes for Chrome on Android (all versions) with `user-scalable=no` in the viewport meta tag. But be aware that `user-scalable=no` also disables pinch zooming, which may be an accessibility concern.
+
+For IE11+, you can use `touch-action: manipulation;` to disable double-tap-to-zoom on certain elements (like links and buttons). For IE10 use `-ms-touch-action: manipulation`.
+
+## Usage ##
+
+Include fastclick.js in your JavaScript bundle or add it to your HTML page like this:
+
+```html
+<script type='application/javascript' src='/path/to/fastclick.js'></script>
+```
+
+The script must be loaded prior to instantiating FastClick on any element of the page.
+
+To instantiate FastClick on the `body`, which is the recommended method of use:
+
+```js
+if ('addEventListener' in document) {
+ document.addEventListener('DOMContentLoaded', function() {
+ FastClick.attach(document.body);
+ }, false);
+}
+```
+
+Or, if you're using jQuery:
+
+```js
+$(function() {
+ FastClick.attach(document.body);
+});
+```
+
+If you're using Browserify or another CommonJS-style module system, the `FastClick.attach` function will be returned when you call `require('fastclick')`. As a result, the easiest way to use FastClick with these loaders is as follows:
+
+```js
+var attachFastClick = require('fastclick');
+attachFastClick(document.body);
+```
+
+### Minified ###
+
+Run `make` to build a minified version of FastClick using the Closure Compiler REST API. The minified file is saved to `build/fastclick.min.js` or you can [download a pre-minified version](http://build.origami.ft.com/bundles/js?modules=fastclick).
+
+Note: the pre-minified version is built using [our build service](http://origami.ft.com/docs/developer-guide/build-service/) which exposes the `FastClick` object through `Origami.fastclick` and will have the Browserify/CommonJS API (see above).
+
+```js
+var attachFastClick = Origami.fastclick;
+attachFastClick(document.body);
+```
+
+### AMD ###
+
+FastClick has AMD (Asynchronous Module Definition) support. This allows it to be lazy-loaded with an AMD loader, such as [RequireJS](http://requirejs.org/). Note that when using the AMD style require, the full `FastClick` object will be returned, _not_ `FastClick.attach`
+
+```js
+var FastClick = require('fastclick');
+FastClick.attach(document.body, options);
+```
+
+### Package managers ###
+
+You can install FastClick using [Component](https://github.com/component/component), [npm](https://npmjs.org/package/fastclick) or [Bower](http://bower.io/).
+
+For Ruby, there's a third-party gem called [fastclick-rails](http://rubygems.org/gems/fastclick-rails). For .NET there's a [NuGet package](http://nuget.org/packages/FastClick).
+
+## Advanced ##
+
+### Ignore certain elements with `needsclick` ###
+
+Sometimes you need FastClick to ignore certain elements. You can do this easily by adding the `needsclick` class.
+```html
+<a class="needsclick">Ignored by FastClick</a>
+```
+
+#### Use case 1: non-synthetic click required ####
+
+Internally, FastClick uses `document.createEvent` to fire a synthetic `click` event as soon as `touchend` is fired by the browser. It then suppresses the additional `click` event created by the browser after that. In some cases, the non-synthetic `click` event created by the browser is required, as described in the [triggering focus example](http://ftlabs.github.com/fastclick/examples/focus.html).
+
+This is where the `needsclick` class comes in. Add the class to any element that requires a non-synthetic click.
+
+#### Use case 2: Twitter Bootstrap 2.2.2 dropdowns ####
+
+Another example of when to use the `needsclick` class is with dropdowns in Twitter Bootstrap 2.2.2. Bootstrap add its own `touchstart` listener for dropdowns, so you want to tell FastClick to ignore those. If you don't, touch devices will automatically close the dropdown as soon as it is clicked, because both FastClick and Bootstrap execute the synthetic click, one opens the dropdown, the second closes it immediately after.
+
+```html
+<a class="dropdown-toggle needsclick" data-toggle="dropdown">Dropdown</a>
+```
+
+## Examples ##
+
+FastClick is designed to cope with many different browser oddities. Here are some examples to illustrate this:
+
+* [basic use](http://ftlabs.github.com/fastclick/examples/layer.html) showing the increase in perceived responsiveness
+* [triggering focus](http://ftlabs.github.com/fastclick/examples/focus.html) on an input element from a `click` handler
+* [input element](http://ftlabs.github.com/fastclick/examples/input.html) which never receives clicks but gets fast focus
+
+## Tests ##
+
+There are no automated tests. The files in `tests/` are manual reduced test cases. We've had a think about how best to test these cases, but they tend to be very browser/device specific and sometimes subjective which means it's not so trivial to test.
+
+## Credits and collaboration ##
+
+FastClick is maintained by [Rowan Beentje](http://twitter.com/rowanbeentje), [Matthew Caruana Galizia](http://twitter.com/mcaruanagalizia) and [Matthew Andrews](http://twitter.com/andrewsmatt) at [FT Labs](http://labs.ft.com). All open source code released by FT Labs is licenced under the MIT licence. We welcome comments, feedback and suggestions. Please feel free to raise an issue or pull request.
diff --git a/afb-client/bower_components/fastclick/bower.json b/afb-client/bower_components/fastclick/bower.json
new file mode 100644
index 0000000..18e1abd
--- /dev/null
+++ b/afb-client/bower_components/fastclick/bower.json
@@ -0,0 +1,12 @@
+{
+ "name": "fastclick",
+ "main": "lib/fastclick.js",
+ "ignore": [
+ "**/.*",
+ "component.json",
+ "package.json",
+ "Makefile",
+ "tests",
+ "examples"
+ ]
+}
diff --git a/afb-client/bower_components/fastclick/lib/fastclick.js b/afb-client/bower_components/fastclick/lib/fastclick.js
new file mode 100644
index 0000000..3af4f9d
--- /dev/null
+++ b/afb-client/bower_components/fastclick/lib/fastclick.js
@@ -0,0 +1,841 @@
+;(function () {
+ 'use strict';
+
+ /**
+ * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
+ *
+ * @codingstandard ftlabs-jsv2
+ * @copyright The Financial Times Limited [All Rights Reserved]
+ * @license MIT License (see LICENSE.txt)
+ */
+
+ /*jslint browser:true, node:true*/
+ /*global define, Event, Node*/
+
+
+ /**
+ * Instantiate fast-clicking listeners on the specified layer.
+ *
+ * @constructor
+ * @param {Element} layer The layer to listen on
+ * @param {Object} [options={}] The options to override the defaults
+ */
+ function FastClick(layer, options) {
+ var oldOnClick;
+
+ options = options || {};
+
+ /**
+ * Whether a click is currently being tracked.
+ *
+ * @type boolean
+ */
+ this.trackingClick = false;
+
+
+ /**
+ * Timestamp for when click tracking started.
+ *
+ * @type number
+ */
+ this.trackingClickStart = 0;
+
+
+ /**
+ * The element being tracked for a click.
+ *
+ * @type EventTarget
+ */
+ this.targetElement = null;
+
+
+ /**
+ * X-coordinate of touch start event.
+ *
+ * @type number
+ */
+ this.touchStartX = 0;
+
+
+ /**
+ * Y-coordinate of touch start event.
+ *
+ * @type number
+ */
+ this.touchStartY = 0;
+
+
+ /**
+ * ID of the last touch, retrieved from Touch.identifier.
+ *
+ * @type number
+ */
+ this.lastTouchIdentifier = 0;
+
+
+ /**
+ * Touchmove boundary, beyond which a click will be cancelled.
+ *
+ * @type number
+ */
+ this.touchBoundary = options.touchBoundary || 10;
+
+
+ /**
+ * The FastClick layer.
+ *
+ * @type Element
+ */
+ this.layer = layer;
+
+ /**
+ * The minimum time between tap(touchstart and touchend) events
+ *
+ * @type number
+ */
+ this.tapDelay = options.tapDelay || 200;
+
+ /**
+ * The maximum time for a tap
+ *
+ * @type number
+ */
+ this.tapTimeout = options.tapTimeout || 700;
+
+ if (FastClick.notNeeded(layer)) {
+ return;
+ }
+
+ // Some old versions of Android don't have Function.prototype.bind
+ function bind(method, context) {
+ return function() { return method.apply(context, arguments); };
+ }
+
+
+ var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
+ var context = this;
+ for (var i = 0, l = methods.length; i < l; i++) {
+ context[methods[i]] = bind(context[methods[i]], context);
+ }
+
+ // Set up event handlers as required
+ if (deviceIsAndroid) {
+ layer.addEventListener('mouseover', this.onMouse, true);
+ layer.addEventListener('mousedown', this.onMouse, true);
+ layer.addEventListener('mouseup', this.onMouse, true);
+ }
+
+ layer.addEventListener('click', this.onClick, true);
+ layer.addEventListener('touchstart', this.onTouchStart, false);
+ layer.addEventListener('touchmove', this.onTouchMove, false);
+ layer.addEventListener('touchend', this.onTouchEnd, false);
+ layer.addEventListener('touchcancel', this.onTouchCancel, false);
+
+ // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+ // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
+ // layer when they are cancelled.
+ if (!Event.prototype.stopImmediatePropagation) {
+ layer.removeEventListener = function(type, callback, capture) {
+ var rmv = Node.prototype.removeEventListener;
+ if (type === 'click') {
+ rmv.call(layer, type, callback.hijacked || callback, capture);
+ } else {
+ rmv.call(layer, type, callback, capture);
+ }
+ };
+
+ layer.addEventListener = function(type, callback, capture) {
+ var adv = Node.prototype.addEventListener;
+ if (type === 'click') {
+ adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
+ if (!event.propagationStopped) {
+ callback(event);
+ }
+ }), capture);
+ } else {
+ adv.call(layer, type, callback, capture);
+ }
+ };
+ }
+
+ // If a handler is already declared in the element's onclick attribute, it will be fired before
+ // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
+ // adding it as listener.
+ if (typeof layer.onclick === 'function') {
+
+ // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
+ // - the old one won't work if passed to addEventListener directly.
+ oldOnClick = layer.onclick;
+ layer.addEventListener('click', function(event) {
+ oldOnClick(event);
+ }, false);
+ layer.onclick = null;
+ }
+ }
+
+ /**
+ * Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
+ *
+ * @type boolean
+ */
+ var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
+
+ /**
+ * Android requires exceptions.
+ *
+ * @type boolean
+ */
+ var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
+
+
+ /**
+ * iOS requires exceptions.
+ *
+ * @type boolean
+ */
+ var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
+
+
+ /**
+ * iOS 4 requires an exception for select elements.
+ *
+ * @type boolean
+ */
+ var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
+
+
+ /**
+ * iOS 6.0-7.* requires the target element to be manually derived
+ *
+ * @type boolean
+ */
+ var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);
+
+ /**
+ * BlackBerry requires exceptions.
+ *
+ * @type boolean
+ */
+ var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
+
+ /**
+ * Determine whether a given element requires a native click.
+ *
+ * @param {EventTarget|Element} target Target DOM element
+ * @returns {boolean} Returns true if the element needs a native click
+ */
+ FastClick.prototype.needsClick = function(target) {
+ switch (target.nodeName.toLowerCase()) {
+
+ // Don't send a synthetic click to disabled inputs (issue #62)
+ case 'button':
+ case 'select':
+ case 'textarea':
+ if (target.disabled) {
+ return true;
+ }
+
+ break;
+ case 'input':
+
+ // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
+ if ((deviceIsIOS && target.type === 'file') || target.disabled) {
+ return true;
+ }
+
+ break;
+ case 'label':
+ case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
+ case 'video':
+ return true;
+ }
+
+ return (/\bneedsclick\b/).test(target.className);
+ };
+
+
+ /**
+ * Determine whether a given element requires a call to focus to simulate click into element.
+ *
+ * @param {EventTarget|Element} target Target DOM element
+ * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
+ */
+ FastClick.prototype.needsFocus = function(target) {
+ switch (target.nodeName.toLowerCase()) {
+ case 'textarea':
+ return true;
+ case 'select':
+ return !deviceIsAndroid;
+ case 'input':
+ switch (target.type) {
+ case 'button':
+ case 'checkbox':
+ case 'file':
+ case 'image':
+ case 'radio':
+ case 'submit':
+ return false;
+ }
+
+ // No point in attempting to focus disabled inputs
+ return !target.disabled && !target.readOnly;
+ default:
+ return (/\bneedsfocus\b/).test(target.className);
+ }
+ };
+
+
+ /**
+ * Send a click event to the specified element.
+ *
+ * @param {EventTarget|Element} targetElement
+ * @param {Event} event
+ */
+ FastClick.prototype.sendClick = function(targetElement, event) {
+ var clickEvent, touch;
+
+ // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
+ if (document.activeElement && document.activeElement !== targetElement) {
+ document.activeElement.blur();
+ }
+
+ touch = event.changedTouches[0];
+
+ // Synthesise a click event, with an extra attribute so it can be tracked
+ clickEvent = document.createEvent('MouseEvents');
+ clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
+ clickEvent.forwardedTouchEvent = true;
+ targetElement.dispatchEvent(clickEvent);
+ };
+
+ FastClick.prototype.determineEventType = function(targetElement) {
+
+ //Issue #159: Android Chrome Select Box does not open with a synthetic click event
+ if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
+ return 'mousedown';
+ }
+
+ return 'click';
+ };
+
+
+ /**
+ * @param {EventTarget|Element} targetElement
+ */
+ FastClick.prototype.focus = function(targetElement) {
+ var length;
+
+ // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
+ if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
+ length = targetElement.value.length;
+ targetElement.setSelectionRange(length, length);
+ } else {
+ targetElement.focus();
+ }
+ };
+
+
+ /**
+ * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
+ *
+ * @param {EventTarget|Element} targetElement
+ */
+ FastClick.prototype.updateScrollParent = function(targetElement) {
+ var scrollParent, parentElement;
+
+ scrollParent = targetElement.fastClickScrollParent;
+
+ // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
+ // target element was moved to another parent.
+ if (!scrollParent || !scrollParent.contains(targetElement)) {
+ parentElement = targetElement;
+ do {
+ if (parentElement.scrollHeight > parentElement.offsetHeight) {
+ scrollParent = parentElement;
+ targetElement.fastClickScrollParent = parentElement;
+ break;
+ }
+
+ parentElement = parentElement.parentElement;
+ } while (parentElement);
+ }
+
+ // Always update the scroll top tracker if possible.
+ if (scrollParent) {
+ scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
+ }
+ };
+
+
+ /**
+ * @param {EventTarget} targetElement
+ * @returns {Element|EventTarget}
+ */
+ FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
+
+ // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
+ if (eventTarget.nodeType === Node.TEXT_NODE) {
+ return eventTarget.parentNode;
+ }
+
+ return eventTarget;
+ };
+
+
+ /**
+ * On touch start, record the position and scroll offset.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.onTouchStart = function(event) {
+ var targetElement, touch, selection;
+
+ // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
+ if (event.targetTouches.length > 1) {
+ return true;
+ }
+
+ targetElement = this.getTargetElementFromEventTarget(event.target);
+ touch = event.targetTouches[0];
+
+ if (deviceIsIOS) {
+
+ // Only trusted events will deselect text on iOS (issue #49)
+ selection = window.getSelection();
+ if (selection.rangeCount && !selection.isCollapsed) {
+ return true;
+ }
+
+ if (!deviceIsIOS4) {
+
+ // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
+ // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
+ // with the same identifier as the touch event that previously triggered the click that triggered the alert.
+ // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
+ // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
+ // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
+ // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
+ // random integers, it's safe to to continue if the identifier is 0 here.
+ if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
+ event.preventDefault();
+ return false;
+ }
+
+ this.lastTouchIdentifier = touch.identifier;
+
+ // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
+ // 1) the user does a fling scroll on the scrollable layer
+ // 2) the user stops the fling scroll with another tap
+ // then the event.target of the last 'touchend' event will be the element that was under the user's finger
+ // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
+ // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
+ this.updateScrollParent(targetElement);
+ }
+ }
+
+ this.trackingClick = true;
+ this.trackingClickStart = event.timeStamp;
+ this.targetElement = targetElement;
+
+ this.touchStartX = touch.pageX;
+ this.touchStartY = touch.pageY;
+
+ // Prevent phantom clicks on fast double-tap (issue #36)
+ if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+ event.preventDefault();
+ }
+
+ return true;
+ };
+
+
+ /**
+ * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.touchHasMoved = function(event) {
+ var touch = event.changedTouches[0], boundary = this.touchBoundary;
+
+ if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
+ return true;
+ }
+
+ return false;
+ };
+
+
+ /**
+ * Update the last position.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.onTouchMove = function(event) {
+ if (!this.trackingClick) {
+ return true;
+ }
+
+ // If the touch has moved, cancel the click tracking
+ if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
+ this.trackingClick = false;
+ this.targetElement = null;
+ }
+
+ return true;
+ };
+
+
+ /**
+ * Attempt to find the labelled control for the given label element.
+ *
+ * @param {EventTarget|HTMLLabelElement} labelElement
+ * @returns {Element|null}
+ */
+ FastClick.prototype.findControl = function(labelElement) {
+
+ // Fast path for newer browsers supporting the HTML5 control attribute
+ if (labelElement.control !== undefined) {
+ return labelElement.control;
+ }
+
+ // All browsers under test that support touch events also support the HTML5 htmlFor attribute
+ if (labelElement.htmlFor) {
+ return document.getElementById(labelElement.htmlFor);
+ }
+
+ // If no for attribute exists, attempt to retrieve the first labellable descendant element
+ // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
+ return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
+ };
+
+
+ /**
+ * On touch end, determine whether to send a click event at once.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.onTouchEnd = function(event) {
+ var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
+
+ if (!this.trackingClick) {
+ return true;
+ }
+
+ // Prevent phantom clicks on fast double-tap (issue #36)
+ if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+ this.cancelNextClick = true;
+ return true;
+ }
+
+ if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
+ return true;
+ }
+
+ // Reset to prevent wrong click cancel on input (issue #156).
+ this.cancelNextClick = false;
+
+ this.lastClickTime = event.timeStamp;
+
+ trackingClickStart = this.trackingClickStart;
+ this.trackingClick = false;
+ this.trackingClickStart = 0;
+
+ // On some iOS devices, the targetElement supplied with the event is invalid if the layer
+ // is performing a transition or scroll, and has to be re-detected manually. Note that
+ // for this to function correctly, it must be called *after* the event target is checked!
+ // See issue #57; also filed as rdar://13048589 .
+ if (deviceIsIOSWithBadTarget) {
+ touch = event.changedTouches[0];
+
+ // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
+ targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
+ targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
+ }
+
+ targetTagName = targetElement.tagName.toLowerCase();
+ if (targetTagName === 'label') {
+ forElement = this.findControl(targetElement);
+ if (forElement) {
+ this.focus(targetElement);
+ if (deviceIsAndroid) {
+ return false;
+ }
+
+ targetElement = forElement;
+ }
+ } else if (this.needsFocus(targetElement)) {
+
+ // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
+ // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
+ if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
+ this.targetElement = null;
+ return false;
+ }
+
+ this.focus(targetElement);
+ this.sendClick(targetElement, event);
+
+ // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
+ // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
+ if (!deviceIsIOS || targetTagName !== 'select') {
+ this.targetElement = null;
+ event.preventDefault();
+ }
+
+ return false;
+ }
+
+ if (deviceIsIOS && !deviceIsIOS4) {
+
+ // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
+ // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
+ scrollParent = targetElement.fastClickScrollParent;
+ if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
+ return true;
+ }
+ }
+
+ // Prevent the actual click from going though - unless the target node is marked as requiring
+ // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
+ if (!this.needsClick(targetElement)) {
+ event.preventDefault();
+ this.sendClick(targetElement, event);
+ }
+
+ return false;
+ };
+
+
+ /**
+ * On touch cancel, stop tracking the click.
+ *
+ * @returns {void}
+ */
+ FastClick.prototype.onTouchCancel = function() {
+ this.trackingClick = false;
+ this.targetElement = null;
+ };
+
+
+ /**
+ * Determine mouse events which should be permitted.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.onMouse = function(event) {
+
+ // If a target element was never set (because a touch event was never fired) allow the event
+ if (!this.targetElement) {
+ return true;
+ }
+
+ if (event.forwardedTouchEvent) {
+ return true;
+ }
+
+ // Programmatically generated events targeting a specific element should be permitted
+ if (!event.cancelable) {
+ return true;
+ }
+
+ // Derive and check the target element to see whether the mouse event needs to be permitted;
+ // unless explicitly enabled, prevent non-touch click events from triggering actions,
+ // to prevent ghost/doubleclicks.
+ if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
+
+ // Prevent any user-added listeners declared on FastClick element from being fired.
+ if (event.stopImmediatePropagation) {
+ event.stopImmediatePropagation();
+ } else {
+
+ // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+ event.propagationStopped = true;
+ }
+
+ // Cancel the event
+ event.stopPropagation();
+ event.preventDefault();
+
+ return false;
+ }
+
+ // If the mouse event is permitted, return true for the action to go through.
+ return true;
+ };
+
+
+ /**
+ * On actual clicks, determine whether this is a touch-generated click, a click action occurring
+ * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
+ * an actual click which should be permitted.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ FastClick.prototype.onClick = function(event) {
+ var permitted;
+
+ // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
+ if (this.trackingClick) {
+ this.targetElement = null;
+ this.trackingClick = false;
+ return true;
+ }
+
+ // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
+ if (event.target.type === 'submit' && event.detail === 0) {
+ return true;
+ }
+
+ permitted = this.onMouse(event);
+
+ // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
+ if (!permitted) {
+ this.targetElement = null;
+ }
+
+ // If clicks are permitted, return true for the action to go through.
+ return permitted;
+ };
+
+
+ /**
+ * Remove all FastClick's event listeners.
+ *
+ * @returns {void}
+ */
+ FastClick.prototype.destroy = function() {
+ var layer = this.layer;
+
+ if (deviceIsAndroid) {
+ layer.removeEventListener('mouseover', this.onMouse, true);
+ layer.removeEventListener('mousedown', this.onMouse, true);
+ layer.removeEventListener('mouseup', this.onMouse, true);
+ }
+
+ layer.removeEventListener('click', this.onClick, true);
+ layer.removeEventListener('touchstart', this.onTouchStart, false);
+ layer.removeEventListener('touchmove', this.onTouchMove, false);
+ layer.removeEventListener('touchend', this.onTouchEnd, false);
+ layer.removeEventListener('touchcancel', this.onTouchCancel, false);
+ };
+
+
+ /**
+ * Check whether FastClick is needed.
+ *
+ * @param {Element} layer The layer to listen on
+ */
+ FastClick.notNeeded = function(layer) {
+ var metaViewport;
+ var chromeVersion;
+ var blackberryVersion;
+ var firefoxVersion;
+
+ // Devices that don't support touch don't need FastClick
+ if (typeof window.ontouchstart === 'undefined') {
+ return true;
+ }
+
+ // Chrome version - zero for other browsers
+ chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
+
+ if (chromeVersion) {
+
+ if (deviceIsAndroid) {
+ metaViewport = document.querySelector('meta[name=viewport]');
+
+ if (metaViewport) {
+ // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
+ if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
+ return true;
+ }
+ // Chrome 32 and above with width=device-width or less don't need FastClick
+ if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
+ return true;
+ }
+ }
+
+ // Chrome desktop doesn't need FastClick (issue #15)
+ } else {
+ return true;
+ }
+ }
+
+ if (deviceIsBlackBerry10) {
+ blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
+
+ // BlackBerry 10.3+ does not require Fastclick library.
+ // https://github.com/ftlabs/fastclick/issues/251
+ if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
+ metaViewport = document.querySelector('meta[name=viewport]');
+
+ if (metaViewport) {
+ // user-scalable=no eliminates click delay.
+ if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
+ return true;
+ }
+ // width=device-width (or less than device-width) eliminates click delay.
+ if (document.documentElement.scrollWidth <= window.outerWidth) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
+ if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
+ return true;
+ }
+
+ // Firefox version - zero for other browsers
+ firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
+
+ if (firefoxVersion >= 27) {
+ // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896
+
+ metaViewport = document.querySelector('meta[name=viewport]');
+ if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
+ return true;
+ }
+ }
+
+ // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
+ // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
+ if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
+ return true;
+ }
+
+ return false;
+ };
+
+
+ /**
+ * Factory method for creating a FastClick object
+ *
+ * @param {Element} layer The layer to listen on
+ * @param {Object} [options={}] The options to override the defaults
+ */
+ FastClick.attach = function(layer, options) {
+ return new FastClick(layer, options);
+ };
+
+
+ if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+
+ // AMD. Register as an anonymous module.
+ define(function() {
+ return FastClick;
+ });
+ } else if (typeof module !== 'undefined' && module.exports) {
+ module.exports = FastClick.attach;
+ module.exports.FastClick = FastClick;
+ } else {
+ window.FastClick = FastClick;
+ }
+}());
diff --git a/afb-client/bower_components/foundation-apps/.bower.json b/afb-client/bower_components/foundation-apps/.bower.json
new file mode 100644
index 0000000..ff37b75
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/.bower.json
@@ -0,0 +1,57 @@
+{
+ "name": "foundation-apps",
+ "version": "1.1.0",
+ "main": [
+ "dist/css/foundation-apps.css",
+ "dist/js/foundation-apps.js"
+ ],
+ "dependencies": {
+ "viewport-units-buggyfill": "~0.4.1",
+ "tether": "~0.6.5",
+ "fastclick": "~1.0.3",
+ "angular": "~1.3.4",
+ "angular-ui-router": "~0.2.12",
+ "angular-animate": "~1.3.4",
+ "hammerjs": "~2.0.4"
+ },
+ "homepage": "https://github.com/zurb/foundation-apps",
+ "description": "A responsive, Angular-powered framework for web apps from ZURB.",
+ "keywords": [
+ "web apps",
+ "responsive design",
+ "angular"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "bower_components",
+ "build",
+ "docs",
+ "node_modules",
+ "tests",
+ "CONTRIBUTING.md",
+ "Gemfile",
+ "Gemfile.lock",
+ "gulpfile.js",
+ "karma.conf.js",
+ "package.json",
+ "scss/_includes.scss"
+ ],
+ "devDependencies": {
+ "angular-mocks": "~1.3.4",
+ "angular-highlightjs": "~0.3.2",
+ "allmighty-autocomplete": "*",
+ "marked": "~0.3.2",
+ "jsdiff": "~1.0.8",
+ "bootcamp": "~1.1.7"
+ },
+ "_release": "1.1.0",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.1.0",
+ "commit": "7fc29d6a309a7018a452bdf996e27053a32023c1"
+ },
+ "_source": "git://github.com/zurb/foundation-apps.git",
+ "_target": "~1.1.0",
+ "_originalSource": "foundation-apps"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/CHANGELOG.md b/afb-client/bower_components/foundation-apps/CHANGELOG.md
new file mode 100644
index 0000000..75f5096
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/CHANGELOG.md
@@ -0,0 +1,301 @@
+# Version 1.1 — Weisshorn
+
+*March 17, 2015*
+
+### General
+
+- **The CLI has been updated to version 1.1.** It includes a streamlined install process, better error-handling, better cross-platform support, and *no Ruby dependency*. Run `npm update -g foundation-cli` to get it.
+- **The documentation is way better.** We did a sweep of every docs page to fix typos, improve examples, and generally make things more clear. Enjoy!
+- **Foundation for Apps is now libsass-first.** We're still testing the codebase in both Ruby Sass 3.4+ and libsass 3.1+, but our documentation and template stack now compile with libsass by default. **This means Ruby is no longer a hard dependency of the framework.**
+- **Directive templates are now compiled to one file.** We're using [ng-html2js](https://github.com/yaru22/ng-html2js) to package up all of our directive templates into a single JavaScript file. This means you no longer need to include the `components` folder in a public directory! This method still works, but you can also just include the `templates.js` file and you're good to go.
+ - The templates file is included in the Bower and npm packages, under `dist/js/foundation-apps-templates.js`.
+ - A third CDN URL has been created for the template files.
+ - Thanks to @MikaAK for submitting the pull request that implemented this!
+
+### Sass Variable Changes
+
+These Sass variables changed. If you're upgrading an existing project, you'll need to update your `_settings.scss` file manually.
+
+**Added:** `$button-background-hover: scale-color($button-background, $lightness: -15%)`
+**Added:** `$motion-class-showhide: (in: "ng-hide-remove", out: "ng-hide-add");`
+**Added:** `$motion-class-showhide-active: (in: "ng-hide-remove-active", out: "ng-hide-add-active");`
+**Added:** `$input-background-disabled: smartscale($input-background)`
+**Added:** `$input-cursor-disabled: not-allowed`
+**Changed:** `$button-tag-selector` is now `false` (previously `true`)
+**Removed:** `$panel-animation-speed`
+
+**You don't need to add the new variables to your settings file,** unless you want to change their default values.
+
+**The old variables are still in the codebase, but aren't being used.** They'll be permanently removed in version 1.2.
+
+### Template Changes
+
+- Sass is now compiled using libsass.
+- Directive templates are compiled into a `templates.js` file, instead of being referenced using hardcoded paths to HTML files.
+- **If you have an existing project, you don't need to change anything to upgrade to v1.1.**
+
+### New Features
+
+- **Improved view animation!** In and out animations on views will now play simultaneously. Thanks to @AntJanus, @stryju, and @jeanieshark for all their hard work in solving this difficult problem!
+- `ui-view` elements no longer need the attribute `ng-class="['ui-animation']"` to animate properly; just having `ui-view` is enough.
+- Prior to v1.1, view animations only worked if the states were created using our front matter routing plugin. Now you can enable view animation in manually-defined states by adding an `animation` property to the state object.
+
+```js
+$stateProvider
+ .state('home', {
+ url: '/',
+ templateUrl: 'templates/home.html',
+ animation: {
+ enter: 'slideInDown',
+ leave: 'fadeOut'
+ }
+ });
+```
+
+- #461: Added a `$background-hover` parameter to the `button-style()` mixin. You can pass in a color, or the `auto` keyword to automatically set a color based on the `$background` parameter.
+- #462: Added styles for disabled form elements. They're automatically applied to any `<input>` element with the `disabled` or `readonly` attributes, or a `<fieldset>` with `disabled`. The styles can also be added manually by adding the `.disabled` class.
+- #475: The path the `zf-iconic` directive uses to search for icon files can now be changed width the `IconicProvider` provider. Use `IconicProvider.setAssetPath(path)` to set the path. Thanks to @gjungb for implementing this!
+- #495: The front matter routing plugin now supports ui-router's abstract states. Just add `abstract: true` to a view template to make it go.
+- Added support for ngAnimate's "show" and "hide" events. This means you can now use Motion UI classes with `ng-show` and `ng-hide`.
+- Added a `.noscroll` class for grid blocks and content blocks. I bet you can guess what it does!
+- You can now pass a scope to a modal created with `ModalFactory`, by passing it through the `contentScope` property on the modal's configuration object.
+
+### Bug Fixes
+
+- #191: `<input type="range">` elements are properly styled in Internet Explorer 10+.
+- #396: Prevent a `$digest already in progress` error from occuring with panels and off-canvas.
+- #397: The `FoundationApi` service now has an `unsubscribe` method, which allows us to remove event listeners from elements that have been removed from the DOM.
+- #467: The settings variables for buttons were placed above button group, which prevents an issue with undefined variables.
+- #472: Fixed the `color` attribute of static notifications not applying.
+- #478: Fixed an issue with modals where `scope.$root` could be `null` after a state change.
+- #483: Fixed notifications with `autoclose` not automatically closing under some circumstances.
+- #486: The `ModalFactory` factory will fetch the modal template before initialization.
+- #489: Deprecated `$panel-animation-speed`, an unused Sass variable for panels. It will be removed in a future version of the framework.
+- #511: Panels that have converted into a block won't play their in/out animations if triggered by an open or close event.
+- #530: Visibility classes will not conflict with Angular's `.ng-hide` class.
+- The `<button>` tag is no longer styled as a `.button` element by default.
+- Any element with `zf-open`, `zf-close`, or `zf-toggle` applied gets the `cursor: pointer` property.
+- Removed the dropdown arrow that Internet Explorer 10+ adds to `<select>` elements.
+- Prevented ghosting issues in WebKit with views that are mid-transition, by adding `-webkit-transform-style: preserve3d`.
+- Fixed landscape/portrait visibility classes not hiding properly.
+- Images inside cards will stretch to the width of the container.
+- Added a missing secondary coloring class to Iconic (`.iconic-color-secondary`).
+
+*The British physicist John Tyndall was the first person to ascend Weisshorn. When the climb was at its most bleak, Tyndall strengthened his resolve with patriotic thoughts:*
+
+> I thought of Englishmen in battle, of the qualities which had made them famous: it was mainly the quality of not knowing when to yield - of fighting for duty even after they had ceased to be animated by hope. Such thoughts helped to lift me over the rocks.
+
+# Version 1.0.3
+
+*February 16, 2015*
+
+### General
+
+- The Bower and npm packages now include a `dist` folder, which contains compiled CSS and JavaScript files, in minified and unminified flavors.
+- The Sass is now fully compatible with libsass. It's been tested in node-sass 1.2.3. Eventually our documentation and template stack will be compiled with node-sass instead of Ruby Sass, but we'll continue to test both.
+
+### Breaking Changes
+
+These Sass variables changed. If you're updating an existing project, you'll need to update your `_settings.scss` file manually.
+
+- **Added:** `$badge-diameter: 1.5rem`
+- **Renamed:** `$badge-font-color` is now `$badge-color`
+- **Removed:** `$badge-padding`
+- **Removed:** `$badge-radius`
+
+The old variables are still in the codebase but aren't being used. They'll be permanently removed in version 1.1.
+
+### Template Changes
+
+The Gulpfile used in the [template stack](https://github.com/zurb/foundation-apps-template) now uses the `gulp-load-plugins` library to streamline use of plugins. **If you have an existing project, you don't need to change anything to upgrade.**
+
+### New Features
+
+- **Stacking notifications.** (#388) Dynamically-called notifications will now stack when you call more than one.
+- **Responsive Iconic icons.** (#408) Iconic icons are now fluid by default, which means they will adjust their geometry based on the width of the parent container.
+- **Staggered animations.** (#394) When using our motion classes in conjunction with the `ng-repeat`, you can now add a stagger class to make items animate in sequence. Add the class `.stagger`, `.short-stagger`, or `.long-stagger` to an element to enable the stagger effect.
+- #376: Added `.info` and `.dark` coloring classes to buttons.
+- #436: The items in a menu bar can be aligned with `.align-right`, `.align-center`, `.align-justify`, or `.align-spaced`. These classes mimic the behavior of the grid alignment classes.
+- Notifications can now be assigned a timeout by adding the `autoclose` attribute. The value of `autoclose` is the number of milliseconds to wait before closing.
+- The speed of all animations has been increased slightly. The default felt just a *little* too slow.
+
+### Bug Fixes
+
+**CSS:**
+
+- #194: Fixed modals not scrolling when they overflow their parent.
+- #412: `<button>` and `<input>` elements can be used as prefix/postfix elements in forms now, in addition to `<a>`.
+- #417: Added padding to `<select>` elements to prevent the text from overlapping with the arrow.
+- #435: Fixed a misnamed parameter in the `grid-block()` mixin.
+- #438: Fixed display issues with `<select>` elements in Firefox.
+- #453: Fixed block list checkboxes being misaligned.
+- Fixed the `.dialog` class and sizing classes of modals not working.
+- The CSS for badges was refactored so they're sized with width and height instead of padding.
+- The pointer cursor is now used when hovering over any anchor (`<a>`) or any element with the `ui-sref` attribute.
+
+**JavaScript:**
+
+- #363: Fixed `zf-close` not working when placed outside of a component.
+- #420: Fixed panel/block animations triggering even though the element is in block mode.
+- #427: Fixed the `pin-at` directive not passing its value to Tether.
+- #448: Fixed invalid `$scope.params` property on the DefaultController controller.
+- If a component is closed or opened while a transition is in progress, the transition will reverse.
+
+# Version 1.0.2
+
+*December 23, 2014*
+
+**Foundation for Apps is now on npm!** `npm install foundation-apps`
+
+**Upgrading from an older version?** We changed how our Angular plugins are structured, which means an existing app's build process will need to be changed slightly.
+
+- **If you're using our template stack as-is:**
+ - Replace your existing `Gulpfile.js` with the [new Gulpfile](https://github.com/zurb/foundation-apps-template/blob/master/gulpfile.js).
+ - Copy the [new app.js](https://github.com/zurb/foundation-apps-template/blob/master/client/assets/js/app.js) file into the folder `client/assets/js/`.
+- If you need to upgrade a project with a custom build process:
+ - To capture every plugin's JavaScript files in a single blob, use `bower_components/foundation-apps/js/angular/**/*.js`.
+ - The Bower package no longer includes an `app.js` file. You can use our template stack's file as a baseline to write your own.
+ - To capture every plugin's HTML template, use `bower_components/foundation-apps/js/angular/components/**/*.html`.
+
+**Codebase changes:**
+
+- #282: The Angular code has been refactored to be more streamlined and more modular. Each UI component now has its own folder, which includes the component's JavaScript and HTML template. The template stack has been updated to properly compile the new asset structure. **If you're upgrading an existing project, follow the above instructions to get everything set.**
+ - The Bower package no longer includes an `app.js` file. Instead, a sample file has been included in the `client` folder of the template stack.
+- #108: Every Sass function now has a unit test. Run `gulp sass:test` to run the test suite.
+- #338: The Sass settings file is now automatically generated based on the variables inside each component's Sass file, with the command `gulp settings`. The [settings parser plguin](https://github.com/zurb/foundation-settings-parser) will be maintained as a separate codebase. The plugin pulls the variables out of each Sass file, after which:
+ - Every component's variables are combined into one settings file, organized by component.
+ - Each individual component's variables are output as an HTML partial, to be displayed on that component's documentation.
+
+**New features:**
+
+- **Touch support!** We added the [Hammer.js Angular library](http://ryanmullins.github.io/angular-hammer/) to our codebase, which allows you to trigger functions with touch gestures, using directives like `hm-swipeup` and `hm-pinchin`.
+ - We added one custom directive, `zf-touch-close`, which allows you to trigger the `close` event on an element by swiping. We'll add more features in future versions.
+- #301: Menu bars can now switch between the expanded and condensed styles at different screen sizes, using these classes: `condense`, `medium-condense`, `large-condense`, `medium-expand`, `large-expand`.
+- #335: Menu bars can now be wrapped in a `menu-bar-group` container, which allows two menu bars to sit on the same row, aligned to the left and the right. Learn more [here](http://foundation.zurb.com/apps/docs/#!/menu-bar).
+- #342: The `src` attribute of an Iconic icon can now be dynamically inserted. Instead of `data-src`, define the icon's source with the `dyn-src` attribute on a `zf-iconic` element.
+
+**Bug fixes:**
+
+- Added proper styles for checkboxes, radio buttons, and their text labels.
+- Fixed a bug with IE10 and 11 where the last item in a wrapping grid would wrap to the next line.
+- Fixed an issue with panels not properly functioning as grid containers.
+- #320: Fixed the `clearall` event for notifications not removing elements from the view.
+- #321: Fixed `zf-hard-toggle` not closing open action sheets.
+- #328: Fixed an issue with collapible items in accordions.
+- #331: Allow action sheets to be closed with `zf-hard-toggle`.
+- #337: Improved the behavior of components animating in and out when toggled on and off rapidly.
+- #343: The settings file now imports the functions file, to make `rem-calc()` and other functions accessible when modifying settings.
+- #351: Fixed a bug where images were not added to notifications created with the publish API.
+- #326: Fixed detached off-canvas menus overlapping with regular ones.
+- #356: Fixed `$small-font-color` not being properly applied to `<small>` elements.
+
+# Version 1.0.1
+
+*December 12, 2014*
+
+Lots of fixes for the Sass, JavaScript, and documentation. Thanks so much to everyone who's been giving feedback, reporting bugs, and most importantly, *fixing our typos* this past week.
+
+## CSS
+
+- Fixed an alignment issue with action sheet dropdowns.
+- #157: Fixed misbehaving box shadows on panels.
+- #180: Added a PNG fallback for the SVG icons used in block lists, for IE10.
+- #212: Corrected a misused parameter in the `grid-frame()` and `grid-block()` mixins.
+- #215: Removed unused text direction variables.
+- #225: Fixed some components not working inside of an off-canvas menu because of selector specificity.
+- #226: Configured the Gulpfile to catch Sass errors instead of exiting.
+- #268: Changed `map-serialize()` to escape quotes in the outputted JSON.
+- #247: Set the `$accordion-title-background-active` variable to be relative to `$accordion-title-background`.
+ - #261: `$tab-title-background-active` got the same treatment.
+- #295: Fixed a error that came up when creating a media query with `@include breakpoint(xxlarge only)`.
+- #326: Fixed detached off-canvas menus overlapping with regular ones.
+
+## JavaScript
+
+- Added the `zf-hard-toggle` directive, to force other open components to close when the targeted component opens.
+- Integrated the FastClick library.
+- #199: Modals can be configured to not close when clicked outside of.
+- #258: Accordions can be set to allow every item to be closed at once with `collapsible="true"`.
+- #260: Added the element restriction to action sheets.
+- #274: Added a timeout to hide elements that are missing an animationOut class.
+- #290: Updated the Gulpfile to properly run `copy` when template pages are added or removed.
+
+# Version 1.0.0 — Matterhorn
+
+Welcome to Foundation for Apps 1.0.0! Thanks for swinging by to try it out.
+
+Our initial release of the framework includes:
+
+ - **An awesome, responsive flexbox-based grid** for creating robust, responsive app layouts.
+ - **The Motion UI library** for easily animating pages and components. You can also use our mixins to write custom animations.
+ - **Our Gulp-powered Angular helpers** which allow you to harness the power of the Angular UI Router library without writing any JavaScript.
+
+The framework also includes these sweet components:
+ - Block list
+ - Button
+ - Button group
+ - Card
+ - Forms
+ - Label and badge
+ - Menu bar
+ - Switch
+ - Title bar
+ - Typography
+ - Visibility and utility classes
+
+These components are also available as Angular directives:
+ - Accordion
+ - Action sheet
+ - Modal
+ - Notification
+ - Off-canvas
+ - Panel
+ - Popup
+ - Tabs
+
+## How to Contribute
+
+We love feedback! Help us find bugs and suggest improvements or new features. Follow us on Twitter at [@ZURBFoundation](https://twitter.com/zurbfoundation) to keep up-to-date with what's new, or to just shoot the breeze.
+
+If you find a problem or have an idea, open a [new issue](https://github.com/zurb/foundation-apps/issues) on GitHub. When filing a bug report, make sure you specify the browser and operating system you're on, and toss us a screenshot or show us how we can recreate the issue.
+
+## Known Issues
+
+ - Some issues with the flexbox grid in IE10
+ - Mobile Safari doesn't place fixed-position elements (modals, notifications) at the right z-index — #190
+ - Range sliders aren't properly styled in IE10+ — #191
+
+*The iconic Matterhorn gets its name from the German words Matte, meaning "meadow", and Horn, which means "peak".*
+
+# Version 1.0.0 RC1 — Mont Blanc
+
+It's our 1.0 release candidate! Thanks for stopping by to take a look.
+
+## How to mess with it
+
+If you want a quick way to jump in, check out our [starter template](https://github.com/zurb/foundation-apps-template), which has a basic directory structure and a blank index file for you to work with. Follow the instructions in the [readme](https://github.com/zurb/foundation-apps-template/blob/master/readme.md) to get going.
+
+The first thing you'll probably want to check out is the grid. If you compile this repo on your machine, you can find the grid documentation at <http://localhost:8080/#!/grid>. You can also view the source of that file [here](https://github.com/zurb/foundation-apps/blob/master/docs/templates/grid.html).
+
+To incorporate our Sass components and Angular directives into your own project, install Foundation using Bower:
+
+```bash
+bower install zurb/foundation-apps
+```
+
+The JavaScript is organized into common components, specific directives, and vendor files. There's also a sample `app.js` that shows how to import the Foundation modules, but you'll likely want to set up your Angular application your own way.
+
+## How to contribute
+
+We love feedback! We have a few [discussion topics](https://github.com/zurb/foundation-apps/issues?q=is%3Aopen+is%3Aissue+label%3Adiscussion) open on our issue tracker, but if you have more specific feedback, please open a new issue! If you encounter any bugs, let us know as well. Be sure to specify the browser and operating system you're using, and show us how we can recreate the issue. Code samples are great!
+
+## What's left
+
+The codebase is very close to feature-complete. Here are the things we're still working on:
+ - Fully-working motion classes (see #113)
+ - Loose ends on components (see #109, #110, #111)
+ - Animation on directives (see #107)
+ - Unit tests for Angular and Sass (see #106)
+ - A finished settings file
+ - The command-line interface (being built in a separate repo, currently private)
+ - Testing, testing, testing \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/LICENSE b/afb-client/bower_components/foundation-apps/LICENSE
new file mode 100644
index 0000000..3b15ebc
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 ZURB, inc.
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/afb-client/bower_components/foundation-apps/README.md b/afb-client/bower_components/foundation-apps/README.md
new file mode 100755
index 0000000..336a9bb
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/README.md
@@ -0,0 +1,83 @@
+# Foundation for Apps
+
+[![Build Status](https://travis-ci.org/zurb/foundation-apps.svg)](https://travis-ci.org/zurb/foundation-apps)
+
+This is [Foundation for Apps](http://foundation.zurb.com/apps), an Angular-powered framework for building powerful responsive web apps, from your friends at [ZURB](http://zurb.com).
+
+## Requirements
+
+You'll need the following software installed to get started.
+
+ * [Node.js](http://nodejs.org): Use the installer provided on the NodeJS website.
+ * [Git](http://git-scm.com/downloads): Use the installer for your OS.
+ * Windows users can also try [Git for Windows](http://git-for-windows.github.io/).
+ * [Ruby](https://www.ruby-lang.org/en/): Use the installer for your OS. For Windows users, [JRuby](http://jruby.org/) is a popular alternative.
+ * With Ruby installed, run `gem install bundler sass`.
+ * [Gulp](http://gulpjs.com/) and [Bower](http://bower.io): Run `[sudo] npm install -g gulp bower`
+
+## Get Started
+
+The Sass and JavaScript components are available on Bower and npm.
+```
+bower install foundation-apps --save
+npm install foundation-apps --save
+```
+
+You can also use our command-line interface to quickly setup a basic Foundation for Apps project. It includes a pre-built Gulpfile that compiles an Angular-powered web app for you.
+
+Install it with this command:
+```
+npm install -g foundation-cli bower gulp
+```
+
+Now you can make a new project:
+```
+foundation-apps new myApp
+cd myApp
+```
+
+While working on your project, run:
+```
+npm start
+```
+
+This will assemble the templates, static assets, Sass, and JavaScript. You can view the test server at this URL:
+```
+http://localhost:8080
+```
+
+## Building this Repo
+
+If you want to work with the source code directly or compile our documentation, follow these steps:
+```
+git clone https://github.com/zurb/foundation-apps.git
+cd foundation-apps
+npm install
+```
+
+While you're working on the code, run:
+```
+npm start
+```
+
+The documentation can be viewed at the same URL as above.
+
+### Directory Structure
+
+* `build`: This is where our documentation is assembled. **Don't edit these files directly, as they're overwritten every time you make a change!**
+* `docs`: The Foundation for Apps documentation.
+* `scss`: The Sass components.
+* `js`: The Angular modules and directives, and other external libraries.
+* `iconic`: A set of 24 icons from the folks at [Iconic](https://useiconic.com/).
+* `dist`: Compiled CSS and JavaScript files, in minified and unmified flavors.
+* `tests`: Unit tests for the Angular modules.
+
+## Versioning
+
+Foundation for Apps follows semver, so we won't introduce breaking changes in minor or patch versions. The `master` branch will always have the newest changes, so it's not necessarily production ready. The `stable` branch will always have the most recent stable version of the framework.
+
+## Contributing
+
+We love feedback! Help us find bugs and suggest improvements or new features. Follow us on Twitter at [@ZURBFoundation](https://twitter.com/zurbfoundation) to keep up-to-date with what's new, or to just shoot the breeze.
+
+If you find a problem or have an idea, open a [new issue](https://github.com/zurb/foundation-apps/issues) on GitHub. When filing a bug report, make sure you specify the browser and operating system you're on, and toss us a screenshot or show us how we can recreate the issue.
diff --git a/afb-client/bower_components/foundation-apps/bin/gulp-dynamic-routing.js b/afb-client/bower_components/foundation-apps/bin/gulp-dynamic-routing.js
new file mode 100644
index 0000000..3dc5350
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/bin/gulp-dynamic-routing.js
@@ -0,0 +1,56 @@
+var through = require('through2');
+var gutil = require('gulp-util');
+var fm = require('front-matter');
+var PluginError = gutil.PluginError;
+var path = require('path');
+var fs = require('fs');
+
+module.exports = function(options) {
+ var configs = [];
+ var directory = options.dir || process.cwd();
+
+ function bufferContents(file, enc, cb) {
+ var config;
+ var content;
+
+ if(file.isNull()) return cb(null, file);
+
+ if(file.isBuffer()) {
+ try {
+ content = fm(String(file.contents));
+ } catch (e) {
+ return cb(new PluginError('Gulp Dynamic Routing', e));
+ }
+
+ if(content.attributes.name) {
+ file.contents = new Buffer(content.body);
+ config = content.attributes;
+ var relativePath = path.relative(directory + path.sep + options.root, file.path);
+ config.path = relativePath.split(path.sep).join('/');
+ configs.push(config);
+ }
+ }
+
+ this.push(file);
+
+ return cb();
+ }
+
+ function endStream(cb) {
+ var self = this;
+ var appPath = options.path;
+
+ configs.sort(function(a, b) {
+ return a.url < b.url;
+ });
+
+
+ fs.writeFile(appPath, 'var foundationRoutes = ' + JSON.stringify(configs) + '; \n', function(err) {
+ if(err) throw err;
+ cb();
+ });
+
+ }
+
+ return through.obj(bufferContents, endStream);
+};
diff --git a/afb-client/bower_components/foundation-apps/bower.json b/afb-client/bower_components/foundation-apps/bower.json
new file mode 100755
index 0000000..3a1f1d5
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/bower.json
@@ -0,0 +1,48 @@
+{
+ "name": "foundation-apps",
+ "version": "1.1.0",
+ "main": [
+ "dist/css/foundation-apps.css",
+ "dist/js/foundation-apps.js"
+ ],
+ "dependencies": {
+ "viewport-units-buggyfill": "~0.4.1",
+ "tether": "~0.6.5",
+ "fastclick": "~1.0.3",
+ "angular": "~1.3.4",
+ "angular-ui-router": "~0.2.12",
+ "angular-animate": "~1.3.4",
+ "hammerjs": "~2.0.4"
+ },
+ "homepage": "https://github.com/zurb/foundation-apps",
+ "description": "A responsive, Angular-powered framework for web apps from ZURB.",
+ "keywords": [
+ "web apps",
+ "responsive design",
+ "angular"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "bower_components",
+ "build",
+ "docs",
+ "node_modules",
+ "tests",
+ "CONTRIBUTING.md",
+ "Gemfile",
+ "Gemfile.lock",
+ "gulpfile.js",
+ "karma.conf.js",
+ "package.json",
+ "scss/_includes.scss"
+ ],
+ "devDependencies": {
+ "angular-mocks": "~1.3.4",
+ "angular-highlightjs": "~0.3.2",
+ "allmighty-autocomplete": "*",
+ "marked": "~0.3.2",
+ "jsdiff": "~1.0.8",
+ "bootcamp": "~1.1.7"
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.css b/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.css
new file mode 100755
index 0000000..8e9b0c9
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.css
@@ -0,0 +1,6146 @@
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+html {
+ font-family: sans-serif;
+ /* 1 */
+ -ms-text-size-adjust: 100%;
+ /* 2 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */ }
+
+/**
+ * Remove default margin.
+ */
+body {
+ margin: 0; }
+
+/* HTML5 display definitions
+ ========================================================================== */
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary {
+ display: block; }
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+audio, canvas, progress, video {
+ display: inline-block;
+ /* 1 */
+ vertical-align: baseline;
+ /* 2 */ }
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+audio:not([controls]) {
+ display: none;
+ height: 0; }
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+[hidden], template {
+ display: none; }
+
+/* Links
+ ========================================================================== */
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+a {
+ background: transparent; }
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+a:active, a:hover {
+ outline: 0; }
+
+/* Text-level semantics
+ ========================================================================== */
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+abbr[title] {
+ border-bottom: 1px dotted; }
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+b, strong {
+ font-weight: bold; }
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+dfn {
+ font-style: italic; }
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0; }
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+mark {
+ background: #ff0;
+ color: #000; }
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+small {
+ font-size: 80%; }
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+sub, sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline; }
+
+sup {
+ top: -0.5em; }
+
+sub {
+ bottom: -0.25em; }
+
+/* Embedded content
+ ========================================================================== */
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+img {
+ border: 0; }
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+svg:not(:root) {
+ overflow: hidden; }
+
+/* Grouping content
+ ========================================================================== */
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+figure {
+ margin: 1em 40px; }
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+hr {
+ box-sizing: content-box;
+ height: 0; }
+
+/**
+ * Contain overflow in all browsers.
+ */
+pre {
+ overflow: auto; }
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+code, kbd, pre, samp {
+ font-family: monospace, monospace;
+ font-size: 1em; }
+
+/* Forms
+ ========================================================================== */
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+button, input, optgroup, select, textarea {
+ color: inherit;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+ margin: 0;
+ /* 3 */ }
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+button {
+ overflow: visible; }
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+button, select {
+ text-transform: none; }
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+button, html input[type="button"], input[type="reset"], input[type="submit"] {
+ -webkit-appearance: button;
+ /* 2 */
+ cursor: pointer;
+ /* 3 */ }
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+button[disabled], html input[disabled] {
+ cursor: default; }
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+button::-moz-focus-inner, input::-moz-focus-inner {
+ border: 0;
+ padding: 0; }
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+input {
+ line-height: normal; }
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+input[type="checkbox"], input[type="radio"] {
+ box-sizing: border-box;
+ /* 1 */
+ padding: 0;
+ /* 2 */ }
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button {
+ height: auto; }
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+input[type="search"] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ /* 2 */
+ box-sizing: content-box; }
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none; }
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em; }
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+legend {
+ border: 0;
+ /* 1 */
+ padding: 0;
+ /* 2 */ }
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+textarea {
+ overflow: auto; }
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+optgroup {
+ font-weight: bold; }
+
+/* Tables
+ ========================================================================== */
+/**
+ * Remove most spacing between table cells.
+ */
+table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+td, th {
+ padding: 0; }
+
+meta.foundation-version {
+ font-family: "1.1.0"; }
+
+meta.foundation-mq {
+ font-family: "small=0&medium=40rem&large=75rem&xlarge=90rem&xxlarge=120rem"; }
+
+/*
+ GLOBAL
+ ------
+
+ Global styles and settings for Foundation for Apps are stored here. This file must always
+ be imported, no matter what.
+
+ Includes:
+ -
+*/
+html, body {
+ height: 100%;
+ font-size: 100%; }
+
+html {
+ box-sizing: border-box; }
+
+*, *:before, *:after {
+ box-sizing: inherit; }
+
+body {
+ background: #fff;
+ color: #222;
+ padding: 0;
+ margin: 0;
+ font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+ font-weight: normal;
+ font-style: normal;
+ line-height: 1;
+ position: relative;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale; }
+
+img {
+ max-width: 100%;
+ height: auto;
+ -ms-interpolation-mode: bicubic;
+ display: inline-block;
+ vertical-align: middle; }
+
+a, [ui-sref], [zf-open], [zf-close], [zf-toggle] {
+ cursor: pointer; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object {
+ max-width: none !important; }
+
+.padding {
+ padding: 1rem; }
+
+.iconic {
+ width: 1rem;
+ height: 1rem;
+ vertical-align: middle; }
+ a > .iconic {
+ margin-top: -2px;
+ margin-right: 0.25rem; }
+ a > .iconic * {
+ fill: #00558b;
+ stroke: #00558b; }
+ a > .iconic *.iconic-property-accent {
+ fill: #00558b;
+ stroke: #00558b; }
+
+.iconic * {
+ fill: #00558b;
+ stroke: #00558b; }
+ .iconic *.iconic-property-accent {
+ fill: #00558b;
+ stroke: #00558b; }
+
+.iconic-color-primary * {
+ fill: #00558b;
+ stroke: #00558b; }
+ .iconic-color-primary *.iconic-property-accent {
+ fill: #00558b;
+ stroke: #00558b; }
+
+.iconic-color-success * {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+ .iconic-color-success *.iconic-property-accent {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+
+.iconic-color-warning * {
+ fill: #F08A24;
+ stroke: #F08A24; }
+ .iconic-color-warning *.iconic-property-accent {
+ fill: #F08A24;
+ stroke: #F08A24; }
+
+.iconic-color-alert * {
+ fill: #F04124;
+ stroke: #F04124; }
+ .iconic-color-alert *.iconic-property-accent {
+ fill: #F04124;
+ stroke: #F04124; }
+
+.iconic-color-dark * {
+ fill: #232323;
+ stroke: #232323; }
+ .iconic-color-dark *.iconic-property-accent {
+ fill: #232323;
+ stroke: #232323; }
+
+.iconic-color-secondary * {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+ .iconic-color-secondary *.iconic-property-accent {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+
+/*
+ ACTION SHEET
+ ------------
+
+ A dropdown menu that sticks to the bottom of the screen on small devices, and becomes a dropdown menu on larger devices.
+*/
+/*
+ Styles for the list inside an action sheet.
+ Don't include this mixin if you want to build custom controls inside the sheet.
+*/
+/*
+ Styles for the action sheet container. Action sheets pin to the top or bottom of the screen.
+*/
+.action-sheet-container {
+ position: relative;
+ display: inline-block; }
+ .action-sheet-container .button {
+ margin-left: 0;
+ margin-right: 0; }
+
+.action-sheet {
+ position: fixed;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ padding: 1rem;
+ background: white;
+ text-align: center;
+ transition-property: -webkit-transform opacity;
+ transition-property: transform opacity;
+ transition-duration: 0.25s;
+ transition-timing-function: ease-out;
+ box-shadow: 0 -3px 10px rgba(0, 0, 0, 0.25);
+ bottom: 0;
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%); }
+ .action-sheet.is-active {
+ -webkit-transform: translateY(0%);
+ transform: translateY(0%); }
+ .action-sheet ul {
+ margin: -1rem;
+ margin-top: 0;
+ list-style-type: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .action-sheet ul:first-child {
+ margin-top: -1rem; }
+ .action-sheet ul:first-child li:first-child {
+ border-top: 0; }
+ .action-sheet ul a {
+ display: block;
+ padding: 0.8rem;
+ line-height: 1;
+ color: #000;
+ border-top: 1px solid #ccc; }
+ .action-sheet ul a:hover {
+ color: #000;
+ background: #f2f2f2; }
+ .action-sheet ul .alert > a {
+ color: #F04124; }
+ .action-sheet ul .disabled > a {
+ pointer-events: none;
+ color: #999; }
+ @media only screen and (min-width: 40em) {
+ .action-sheet {
+ /*
+ Core styles
+ */
+ position: absolute;
+ left: 50%;
+ width: 300px;
+ border-radius: 4px;
+ opacity: 0;
+ pointer-events: none;
+ /*
+ Menu shadow
+ */
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
+ /*
+ Active state
+ */
+ /*
+ Menu tail
+ */
+ /*
+ Positioning
+ */
+ top: auto;
+ bottom: 0;
+ -webkit-transform: translateX(-50%) translateY(110%);
+ transform: translateX(-50%) translateY(110%); }
+ .action-sheet.is-active {
+ opacity: 1;
+ pointer-events: auto; }
+ .action-sheet::before, .action-sheet::after {
+ content: '';
+ position: absolute;
+ left: 50%;
+ display: block;
+ width: 0px;
+ height: 0px;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ margin-left: -10px; }
+ .action-sheet.is-active {
+ -webkit-transform: translateX(-50%) translateY(100%);
+ transform: translateX(-50%) translateY(100%); }
+ .action-sheet::before, .action-sheet::after {
+ top: -10px;
+ bottom: auto;
+ border-top: 0;
+ border-bottom: 10px solid white; }
+ .action-sheet::before {
+ top: -12px;
+ border-bottom-color: rgba(0, 0, 0, 0.15); }
+ .action-sheet.top {
+ /*
+ Core styles
+ */
+ position: absolute;
+ left: 50%;
+ width: 300px;
+ border-radius: 4px;
+ opacity: 0;
+ pointer-events: none;
+ /*
+ Menu shadow
+ */
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
+ /*
+ Active state
+ */
+ /*
+ Menu tail
+ */
+ /*
+ Positioning
+ */
+ top: 0;
+ bottom: auto;
+ -webkit-transform: translateX(-50%) translateY(-120%);
+ transform: translateX(-50%) translateY(-120%); }
+ .action-sheet.top.is-active {
+ opacity: 1;
+ pointer-events: auto; }
+ .action-sheet.top::before, .action-sheet.top::after {
+ content: '';
+ position: absolute;
+ left: 50%;
+ display: block;
+ width: 0px;
+ height: 0px;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ margin-left: -10px; }
+ .action-sheet.top.is-active {
+ -webkit-transform: translateX(-50%) translateY(-110%);
+ transform: translateX(-50%) translateY(-110%); }
+ .action-sheet.top::before, .action-sheet.top::after {
+ top: auto;
+ bottom: -10px;
+ border-top: 10px solid white;
+ border-bottom: 0; }
+ .action-sheet.top::before {
+ bottom: -12px;
+ border-top-color: rgba(0, 0, 0, 0.15); } }
+ .action-sheet.primary {
+ background: #00558b;
+ color: #fff;
+ border: 0; }
+ .action-sheet.primary::before {
+ display: none; }
+ .action-sheet.primary::before, .action-sheet.primary::after {
+ border-top-color: #00558b; }
+ .action-sheet.primary.top::before, .action-sheet.primary.top::after {
+ border-bottom-color: #00558b; }
+ .action-sheet.primary ul {
+ margin: -1rem;
+ margin-top: 0;
+ list-style-type: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .action-sheet.primary ul:first-child {
+ margin-top: -1rem; }
+ .action-sheet.primary ul:first-child li:first-child {
+ border-top: 0; }
+ .action-sheet.primary ul a {
+ display: block;
+ padding: 0.8rem;
+ line-height: 1;
+ color: #fff;
+ border-top: 1px solid #006cb0; }
+ .action-sheet.primary ul a:hover {
+ color: #fff;
+ background: #00609e; }
+ .action-sheet.primary ul .alert > a {
+ color: #F04124; }
+ .action-sheet.primary ul .disabled > a {
+ pointer-events: none;
+ color: #999; }
+ .action-sheet.dark {
+ background: #232323;
+ color: #fff;
+ border: 0; }
+ .action-sheet.dark::before {
+ display: none; }
+ .action-sheet.dark::before, .action-sheet.dark::after {
+ border-top-color: #232323; }
+ .action-sheet.dark.top::before, .action-sheet.dark.top::after {
+ border-bottom-color: #232323; }
+ .action-sheet.dark ul {
+ margin: -1rem;
+ margin-top: 0;
+ list-style-type: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .action-sheet.dark ul:first-child {
+ margin-top: -1rem; }
+ .action-sheet.dark ul:first-child li:first-child {
+ border-top: 0; }
+ .action-sheet.dark ul a {
+ display: block;
+ padding: 0.8rem;
+ line-height: 1;
+ color: #fff;
+ border-top: 1px solid #393939; }
+ .action-sheet.dark ul a:hover {
+ color: #fff;
+ background: #2e2e2e; }
+ .action-sheet.dark ul .alert > a {
+ color: #F04124; }
+ .action-sheet.dark ul .disabled > a {
+ pointer-events: none;
+ color: #999; }
+
+/*
+ BLOCK LIST
+ ----------
+
+ A generic list component that can accomodate a variety of styles and controls.
+
+ Features:
+ - Icons
+ - Labels
+ - Chevrons
+ - Text fields
+ - Dropdown menus
+ - Checkbox/radio inputs
+*/
+/*
+ Adds styles for a block list container.
+
+ $font-size: global font size for the list.
+ $full-bleed: when "true", the margins of the list invert to line it up with the edge of a padded element.
+*/
+.block-list {
+ margin-bottom: 1rem;
+ line-height: 1;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .block-list, .block-list ul {
+ list-style-type: none; }
+ .block-list ul {
+ margin-left: 0; }
+
+/*
+ Styles block list headers on the selector you include this mixin in (normally a <header>).
+
+ $color - color of the header.
+ $font-size - font size of the header.
+ $offset - left margin to add to the header, to line it up with the list items.
+*/
+/*
+ Styles block list items on the selector you include this mixin in (normally an <li>).
+
+ $color - color of items.
+ $color-hover - color of items on hover.
+ $background - background of items.
+ $background-hover - background of items on hover.
+ $border - border between items.
+ $padding - padding on items.
+*/
+/*
+ Adds label styles to the class you include this mixin in.
+
+ $color - color of the label.
+ $left-class - extra class to flip the orientation of the label.
+ $left-padding - left padding to use for left-hand labels.
+*/
+/*
+ Adds support for chevrons, which appear on the right-hand side of the item.
+
+ $color - color of the chevron.
+ $padding - include the global padding of block list items here.
+*/
+/*
+ Adds icon styles. Call this mixin on a block list container.
+
+ $size - size of the icon as a percentage (decimal) of the list item's height.
+ $item-selector - overrides the 'li' selector used for list items.
+*/
+/*
+ Adds support for text fields, select menus, and checkbox/radio groups in block lists.
+
+ $color - color of select menu arrow.
+ $background-hover - color of select menu when hovered over.
+ $padding - include the global padding of block list items here.
+ $dropdown-class - class to use for list items that contain a dropdown.
+ $switch-class - class to use for switches inside list items.
+*/
+.block-list {
+ font-size: 1rem;
+ margin-left: -1rem;
+ margin-right: -1rem; }
+ .block-list input[type="text"], .block-list input[type="password"], .block-list input[type="date"], .block-list input[type="datetime"], .block-list input[type="datetime-local"], .block-list input[type="month"], .block-list input[type="week"], .block-list input[type="email"], .block-list input[type="number"], .block-list input[type="search"], .block-list input[type="tel"], .block-list input[type="time"], .block-list input[type="url"], .block-list input[type="color"], .block-list textarea {
+ margin: 0;
+ border: 0;
+ line-height: 1;
+ height: auto;
+ padding: 0.8rem 1rem;
+ color: inherit; }
+ .block-list input[type="text"]:hover, .block-list input[type="text"]:focus, .block-list input[type="password"]:hover, .block-list input[type="password"]:focus, .block-list input[type="date"]:hover, .block-list input[type="date"]:focus, .block-list input[type="datetime"]:hover, .block-list input[type="datetime"]:focus, .block-list input[type="datetime-local"]:hover, .block-list input[type="datetime-local"]:focus, .block-list input[type="month"]:hover, .block-list input[type="month"]:focus, .block-list input[type="week"]:hover, .block-list input[type="week"]:focus, .block-list input[type="email"]:hover, .block-list input[type="email"]:focus, .block-list input[type="number"]:hover, .block-list input[type="number"]:focus, .block-list input[type="search"]:hover, .block-list input[type="search"]:focus, .block-list input[type="tel"]:hover, .block-list input[type="tel"]:focus, .block-list input[type="time"]:hover, .block-list input[type="time"]:focus, .block-list input[type="url"]:hover, .block-list input[type="url"]:focus, .block-list input[type="color"]:hover, .block-list input[type="color"]:focus, .block-list textarea:hover, .block-list textarea:focus {
+ border: 0; }
+ .block-list li > input[type="checkbox"], .block-list li > input[type="radio"] {
+ position: absolute;
+ left: -9999px; }
+ .block-list li > input[type="checkbox"] + label, .block-list li > input[type="radio"] + label {
+ display: block;
+ font-size: 1rem;
+ margin: 0; }
+ .block-list li > input[type="checkbox"]:checked + label::before, .block-list li > input[type="radio"]:checked + label::before {
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="32" viewBox="0 0 32 32"><path fill="black" d="M16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zm6.906 8.875l2.219 2.031-12.063 13.281-6.188-6.188 2.125-2.125 3.938 3.938 9.969-10.938z"/></svg>');
+ content: '';
+ background-size: 100% 100%;
+ width: 1.5em;
+ height: 1.5em;
+ color: #00558b;
+ float: right;
+ pointer-events: none;
+ margin-top: -0.25em; }
+ @media screen and (min-width: 0\0) {
+ .block-list li > input[type="checkbox"]:checked + label::before, .block-list li > input[type="radio"]:checked + label::before {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUeNrMl0FugzAQRY3TRZeoFyhVL0BOkGTXJezaHZwguUnECaCrdFd6gqQnCN11Uyk5QekNOlONJWMVGMCgfGlkEIY3HnsG2xFM3d96PjQB2AJsWdPtAPYOln+dTwXnuw4DHEGzBvNFN6EDCTiS9XIAwB40acNoucKoxODIie0AwAOCu8KOSnIiNx/MakK+A7sW9oTferxx3fP3T1nURoBG/irGVahHwjHm/Ggx7E3TMVdrQmoP0gngghhpZQ3QvG/EdPLUelARWI8Aycjq9Md0qMIdbcNhjmOKLoY7quk3l1Rebeqg4AwFkmq7LWGOh1pmNY0etZAWSq0OX8HoS4JvWuCopbSY26EGR/CW86K0BF+pwkLwlPuyHJhOCl5oe4ZtF++vOqST+GdOYwO+71pN2VNAjmQGPCe42weuHDg0PI8olUwnYrXTGQJH9gxq8l1LKvrQx4O6/YY32Kp/ugb3ey7gZ4xAzuhYiYTxB/UHZFAuaREVXZ2g6yFlvEC2yoKEmbsRZYNgVLk2JeaOaG+xLHN+WCszDWMqLGOrJFa1DlApjSdwoHJGqGzLIb0+cas0wh5Bh780ngswx8GJD7h8sHg2wLA/mfDLPZpdxOF0quP5rwADAAFIzSRvu1m5AAAAAElFTkSuQmCC'); } }
+ .block-list .with-dropdown {
+ color: inherit; }
+ .block-list .with-dropdown select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ outline: 0;
+ background: 0;
+ border: 0;
+ height: auto;
+ padding: 0.8rem 1rem;
+ margin: 0;
+ font-size: 1em;
+ line-height: 1;
+ color: inherit;
+ background-color: transparent; }
+ .block-list .switch {
+ position: absolute;
+ top: 50%;
+ right: 1rem;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%); }
+ .block-list.with-icons li > a, .block-list.with-icons li > span, .block-list.with-icons li > label {
+ padding-left: 2.8rem; }
+ .block-list.with-icons li img, .block-list.with-icons li .iconic {
+ position: absolute;
+ top: 0.26rem;
+ left: 0.26rem;
+ width: 2.08rem;
+ height: 2.08rem;
+ border-radius: 8px;
+ pointer-events: none; }
+ .block-list header {
+ margin-top: 1em;
+ color: #666666;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ margin-left: 1rem;
+ font-size: 0.8em;
+ cursor: default;
+ text-transform: uppercase; }
+ .block-list li {
+ position: relative;
+ border-bottom: 1px solid #d0d0d0; }
+ .block-list li:first-child {
+ border-top: 1px solid #d0d0d0; }
+ .block-list li > a, .block-list li > span, .block-list li > label {
+ display: block;
+ padding: 0.8rem 1rem;
+ padding-left: 1rem;
+ color: #000;
+ line-height: 1; }
+ .block-list li > span {
+ cursor: default; }
+ .block-list li > a, .block-list li > label {
+ cursor: pointer; }
+ .block-list li > a:hover, .block-list li > label:hover {
+ color: #000; }
+ .block-list li > a:hover, .block-list li > label:hover, .block-list li select:hover {
+ background: #f4f4f4; }
+ .block-list li.caution > a, .block-list li.caution > a:hover {
+ color: #F04124; }
+ .block-list li.disabled > a {
+ cursor: default; }
+ .block-list li.disabled > a, .block-list li.disabled > a:hover {
+ color: #999; }
+ .block-list li.disabled > a:hover {
+ background: transparent; }
+ .block-list li.with-chevron::after {
+ content: '\203A';
+ display: block;
+ position: absolute;
+ right: 1rem;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+ font-weight: bold;
+ color: #666666;
+ font-size: 2em; }
+ .block-list li.with-chevron .block-list-label {
+ padding-right: 1.5rem; }
+ .block-list li .block-list-label {
+ display: inline-block;
+ float: right;
+ padding: 0;
+ color: #999999;
+ pointer-events: none; }
+ .block-list li .block-list-label.left {
+ margin-left: 0.8rem;
+ float: none; }
+
+.button, .button-group > li > a, .button-group > li > label, .button-group > li > button {
+ display: inline-block;
+ border: 0;
+ text-align: center;
+ line-height: 1;
+ cursor: pointer;
+ -webkit-appearance: none;
+ -webkit-font-smoothing: antialiased;
+ transition: background 0.25s ease-out;
+ vertical-align: middle;
+ padding: 0.85em 1em;
+ margin: 0 1rem 1rem 0;
+ font-size: 0.9rem;
+ border-radius: 0; }
+
+.button {
+ font-size: 0.9rem;
+ display: inline-block;
+ width: auto;
+ margin: 0 1rem 1rem 0;
+ background: #00558b;
+ color: #fff; }
+ .button .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; }
+ .button:hover, .button:focus {
+ background: #004876;
+ color: #fff; }
+ .button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button.tiny {
+ font-size: 0.63rem; }
+ .button.tiny .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; }
+ .button.small {
+ font-size: 0.72rem; }
+ .button.small .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; }
+ .button.large {
+ font-size: 1.17rem; }
+ .button.large .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; }
+ .button.expand {
+ display: block;
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0; }
+ .button.secondary {
+ background: #f1f1f1;
+ color: #000; }
+ .button.secondary:hover, .button.secondary:focus {
+ background: #cdcdcd;
+ color: #000; }
+ .button.secondary .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .button.secondary .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .button.success {
+ background: #43AC6A;
+ color: #fff; }
+ .button.success:hover, .button.success:focus {
+ background: #39925a;
+ color: #fff; }
+ .button.success .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button.success .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button.warning {
+ background: #F08A24;
+ color: #fff; }
+ .button.warning:hover, .button.warning:focus {
+ background: #dc750f;
+ color: #fff; }
+ .button.warning .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button.warning .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button.alert {
+ background: #F04124;
+ color: #fff; }
+ .button.alert:hover, .button.alert:focus {
+ background: #dc2c0f;
+ color: #fff; }
+ .button.alert .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button.alert .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button.info {
+ background: #A0D3E8;
+ color: #000; }
+ .button.info:hover, .button.info:focus {
+ background: #71bddd;
+ color: #000; }
+ .button.info .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .button.info .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .button.dark {
+ background: #232323;
+ color: #fff; }
+ .button.dark:hover, .button.dark:focus {
+ background: #1e1e1e;
+ color: #fff; }
+ .button.dark .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button.dark .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button.hollow {
+ border: 1px solid #00558b;
+ background: transparent;
+ color: #00558b; }
+ .button.hollow:hover, .button.hollow:focus {
+ border-color: #008ee8;
+ background: transparent;
+ color: #008ee8; }
+ .button.hollow .iconic * {
+ fill: #00558b;
+ stroke: #00558b; }
+ .button.hollow .iconic *.iconic-property-accent {
+ fill: #00558b;
+ stroke: #00558b; }
+ .button.hollow:hover .iconic * {
+ fill: #008ee8;
+ stroke: #008ee8; }
+ .button.hollow:hover .iconic *.iconic-property-accent {
+ fill: #008ee8;
+ stroke: #008ee8; }
+ .button.hollow.secondary {
+ border: 1px solid #f1f1f1;
+ background: transparent;
+ color: #f1f1f1; }
+ .button.hollow.secondary:hover, .button.hollow.secondary:focus {
+ border-color: #f4f4f4;
+ background: transparent;
+ color: #f4f4f4; }
+ .button.hollow.secondary .iconic * {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+ .button.hollow.secondary .iconic *.iconic-property-accent {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+ .button.hollow.secondary:hover .iconic * {
+ fill: #f4f4f4;
+ stroke: #f4f4f4; }
+ .button.hollow.secondary:hover .iconic *.iconic-property-accent {
+ fill: #f4f4f4;
+ stroke: #f4f4f4; }
+ .button.hollow.success {
+ border: 1px solid #43AC6A;
+ background: transparent;
+ color: #43AC6A; }
+ .button.hollow.success:hover, .button.hollow.success:focus {
+ border-color: #6dc68e;
+ background: transparent;
+ color: #6dc68e; }
+ .button.hollow.success .iconic * {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+ .button.hollow.success .iconic *.iconic-property-accent {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+ .button.hollow.success:hover .iconic * {
+ fill: #6dc68e;
+ stroke: #6dc68e; }
+ .button.hollow.success:hover .iconic *.iconic-property-accent {
+ fill: #6dc68e;
+ stroke: #6dc68e; }
+ .button.hollow.warning {
+ border: 1px solid #F08A24;
+ background: transparent;
+ color: #F08A24; }
+ .button.hollow.warning:hover, .button.hollow.warning:focus {
+ border-color: #f4a75b;
+ background: transparent;
+ color: #f4a75b; }
+ .button.hollow.warning .iconic * {
+ fill: #F08A24;
+ stroke: #F08A24; }
+ .button.hollow.warning .iconic *.iconic-property-accent {
+ fill: #F08A24;
+ stroke: #F08A24; }
+ .button.hollow.warning:hover .iconic * {
+ fill: #f4a75b;
+ stroke: #f4a75b; }
+ .button.hollow.warning:hover .iconic *.iconic-property-accent {
+ fill: #f4a75b;
+ stroke: #f4a75b; }
+ .button.hollow.alert {
+ border: 1px solid #F04124;
+ background: transparent;
+ color: #F04124; }
+ .button.hollow.alert:hover, .button.hollow.alert:focus {
+ border-color: #f4715b;
+ background: transparent;
+ color: #f4715b; }
+ .button.hollow.alert .iconic * {
+ fill: #F04124;
+ stroke: #F04124; }
+ .button.hollow.alert .iconic *.iconic-property-accent {
+ fill: #F04124;
+ stroke: #F04124; }
+ .button.hollow.alert:hover .iconic * {
+ fill: #f4715b;
+ stroke: #f4715b; }
+ .button.hollow.alert:hover .iconic *.iconic-property-accent {
+ fill: #f4715b;
+ stroke: #f4715b; }
+ .button.hollow.info {
+ border: 1px solid #A0D3E8;
+ background: transparent;
+ color: #A0D3E8; }
+ .button.hollow.info:hover, .button.hollow.info:focus {
+ border-color: #b8deee;
+ background: transparent;
+ color: #b8deee; }
+ .button.hollow.info .iconic * {
+ fill: #A0D3E8;
+ stroke: #A0D3E8; }
+ .button.hollow.info .iconic *.iconic-property-accent {
+ fill: #A0D3E8;
+ stroke: #A0D3E8; }
+ .button.hollow.info:hover .iconic * {
+ fill: #b8deee;
+ stroke: #b8deee; }
+ .button.hollow.info:hover .iconic *.iconic-property-accent {
+ fill: #b8deee;
+ stroke: #b8deee; }
+ .button.hollow.dark {
+ border: 1px solid #232323;
+ background: transparent;
+ color: #232323; }
+ .button.hollow.dark:hover, .button.hollow.dark:focus {
+ border-color: #5a5a5a;
+ background: transparent;
+ color: #5a5a5a; }
+ .button.hollow.dark .iconic * {
+ fill: #232323;
+ stroke: #232323; }
+ .button.hollow.dark .iconic *.iconic-property-accent {
+ fill: #232323;
+ stroke: #232323; }
+ .button.hollow.dark:hover .iconic * {
+ fill: #5a5a5a;
+ stroke: #5a5a5a; }
+ .button.hollow.dark:hover .iconic *.iconic-property-accent {
+ fill: #5a5a5a;
+ stroke: #5a5a5a; }
+ .button.disabled {
+ opacity: 0.5;
+ cursor: default;
+ pointer-events: none; }
+
+.button-group {
+ margin: 0;
+ margin-bottom: 1rem;
+ list-style-type: none;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ border-radius: 0;
+ overflow: hidden;
+ font-size: 0.9rem; }
+ .button-group > li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .button-group > li > a, .button-group > li > label, .button-group > li > button {
+ border-radius: 0;
+ font-size: inherit;
+ display: block;
+ margin: 0; }
+ .button-group > li > input + label {
+ margin-left: 0; }
+ .button-group > li:not(:last-child) > a, .button-group > li:not(:last-child) > label, .button-group > li:not(:last-child) > button {
+ border-right: 1px solid #004068; }
+ .button-group .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; }
+
+.button-group.segmented, .button-group.segmented.secondary, .button-group.segmented.success, .button-group.segmented.warning, .button-group.segmented.alert {
+ border: 1px solid #00558b;
+ transition-property: background color; }
+ .button-group.segmented > li > input[type="radio"] {
+ position: absolute;
+ left: -9999px; }
+ .button-group.segmented > li > a, .button-group.segmented.secondary > li > a, .button-group.segmented.success > li > a, .button-group.segmented.warning > li > a, .button-group.segmented.alert > li > a, .button-group.segmented > li > label, .button-group.segmented.secondary > li > label, .button-group.segmented.success > li > label, .button-group.segmented.warning > li > label, .button-group.segmented.alert > li > label, .button-group.segmented > li > button, .button-group.segmented.secondary > li > button, .button-group.segmented.success > li > button, .button-group.segmented.warning > li > button, .button-group.segmented.alert > li > button {
+ margin-right: 0;
+ background: transparent; }
+
+.button-group {
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ border-radius: 0; }
+ .button-group > li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .button-group > li > a, .button-group > li > label, .button-group > li > button {
+ background: #00558b;
+ color: #fff;
+ border-color: #004876; }
+ .button-group > li > a:hover, .button-group > li > a:focus, .button-group > li > label:hover, .button-group > li > label:focus, .button-group > li > button:hover, .button-group > li > button:focus {
+ background: #004876;
+ color: #fff; }
+ .button-group > li > a .iconic *, .button-group > li > label .iconic *, .button-group > li > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li > a .iconic *.iconic-property-accent, .button-group > li > label .iconic *.iconic-property-accent, .button-group > li > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.is-active > a, .button-group > li.is-active > label, .button-group > li.is-active > button {
+ background: #004876; }
+ .button-group.secondary > li > a, .button-group.secondary > li > label, .button-group.secondary > li > button {
+ background: #f1f1f1;
+ color: #000;
+ border-color: #cdcdcd; }
+ .button-group.secondary > li > a:hover, .button-group.secondary > li > a:focus, .button-group.secondary > li > label:hover, .button-group.secondary > li > label:focus, .button-group.secondary > li > button:hover, .button-group.secondary > li > button:focus {
+ background: #cdcdcd;
+ color: #000; }
+ .button-group.secondary > li > a .iconic *, .button-group.secondary > li > label .iconic *, .button-group.secondary > li > button .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .button-group.secondary > li > a .iconic *.iconic-property-accent, .button-group.secondary > li > label .iconic *.iconic-property-accent, .button-group.secondary > li > button .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .button-group.secondary > li.is-active > a, .button-group.secondary > li.is-active > label, .button-group.secondary > li.is-active > button {
+ background: #cdcdcd; }
+ .button-group.success > li > a, .button-group.success > li > label, .button-group.success > li > button {
+ background: #43AC6A;
+ color: #fff;
+ border-color: #39925a; }
+ .button-group.success > li > a:hover, .button-group.success > li > a:focus, .button-group.success > li > label:hover, .button-group.success > li > label:focus, .button-group.success > li > button:hover, .button-group.success > li > button:focus {
+ background: #39925a;
+ color: #fff; }
+ .button-group.success > li > a .iconic *, .button-group.success > li > label .iconic *, .button-group.success > li > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.success > li > a .iconic *.iconic-property-accent, .button-group.success > li > label .iconic *.iconic-property-accent, .button-group.success > li > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.success > li.is-active > a, .button-group.success > li.is-active > label, .button-group.success > li.is-active > button {
+ background: #39925a; }
+ .button-group.warning > li > a, .button-group.warning > li > label, .button-group.warning > li > button {
+ background: #F08A24;
+ color: #fff;
+ border-color: #dc750f; }
+ .button-group.warning > li > a:hover, .button-group.warning > li > a:focus, .button-group.warning > li > label:hover, .button-group.warning > li > label:focus, .button-group.warning > li > button:hover, .button-group.warning > li > button:focus {
+ background: #dc750f;
+ color: #fff; }
+ .button-group.warning > li > a .iconic *, .button-group.warning > li > label .iconic *, .button-group.warning > li > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.warning > li > a .iconic *.iconic-property-accent, .button-group.warning > li > label .iconic *.iconic-property-accent, .button-group.warning > li > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.warning > li.is-active > a, .button-group.warning > li.is-active > label, .button-group.warning > li.is-active > button {
+ background: #dc750f; }
+ .button-group.alert > li > a, .button-group.alert > li > label, .button-group.alert > li > button {
+ background: #F04124;
+ color: #fff;
+ border-color: #dc2c0f; }
+ .button-group.alert > li > a:hover, .button-group.alert > li > a:focus, .button-group.alert > li > label:hover, .button-group.alert > li > label:focus, .button-group.alert > li > button:hover, .button-group.alert > li > button:focus {
+ background: #dc2c0f;
+ color: #fff; }
+ .button-group.alert > li > a .iconic *, .button-group.alert > li > label .iconic *, .button-group.alert > li > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.alert > li > a .iconic *.iconic-property-accent, .button-group.alert > li > label .iconic *.iconic-property-accent, .button-group.alert > li > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.alert > li.is-active > a, .button-group.alert > li.is-active > label, .button-group.alert > li.is-active > button {
+ background: #dc2c0f; }
+ .button-group > li.secondary > a, .button-group > li.secondary > label, .button-group > li.secondary > button {
+ background: #f1f1f1;
+ color: #000;
+ border-color: #f1f1f1; }
+ .button-group > li.secondary > a:hover, .button-group > li.secondary > a:focus, .button-group > li.secondary > label:hover, .button-group > li.secondary > label:focus, .button-group > li.secondary > button:hover, .button-group > li.secondary > button:focus {
+ background: #cdcdcd;
+ color: #000; }
+ .button-group > li.secondary > a:hover, .button-group > li.secondary > a:focus, .button-group > li.secondary > label:hover, .button-group > li.secondary > label:focus, .button-group > li.secondary > button:hover, .button-group > li.secondary > button:focus {
+ border-color: #b5b5b5; }
+ .button-group > li.secondary > a .iconic *, .button-group > li.secondary > label .iconic *, .button-group > li.secondary > button .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .button-group > li.secondary > a .iconic *.iconic-property-accent, .button-group > li.secondary > label .iconic *.iconic-property-accent, .button-group > li.secondary > button .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .button-group > li.success > a, .button-group > li.success > label, .button-group > li.success > button {
+ background: #43AC6A;
+ color: #fff;
+ border-color: #43AC6A; }
+ .button-group > li.success > a:hover, .button-group > li.success > a:focus, .button-group > li.success > label:hover, .button-group > li.success > label:focus, .button-group > li.success > button:hover, .button-group > li.success > button:focus {
+ background: #39925a;
+ color: #fff; }
+ .button-group > li.success > a:hover, .button-group > li.success > a:focus, .button-group > li.success > label:hover, .button-group > li.success > label:focus, .button-group > li.success > button:hover, .button-group > li.success > button:focus {
+ border-color: #32814f; }
+ .button-group > li.success > a .iconic *, .button-group > li.success > label .iconic *, .button-group > li.success > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.success > a .iconic *.iconic-property-accent, .button-group > li.success > label .iconic *.iconic-property-accent, .button-group > li.success > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.warning > a, .button-group > li.warning > label, .button-group > li.warning > button {
+ background: #F08A24;
+ color: #fff;
+ border-color: #F08A24; }
+ .button-group > li.warning > a:hover, .button-group > li.warning > a:focus, .button-group > li.warning > label:hover, .button-group > li.warning > label:focus, .button-group > li.warning > button:hover, .button-group > li.warning > button:focus {
+ background: #dc750f;
+ color: #fff; }
+ .button-group > li.warning > a:hover, .button-group > li.warning > a:focus, .button-group > li.warning > label:hover, .button-group > li.warning > label:focus, .button-group > li.warning > button:hover, .button-group > li.warning > button:focus {
+ border-color: #c2670d; }
+ .button-group > li.warning > a .iconic *, .button-group > li.warning > label .iconic *, .button-group > li.warning > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.warning > a .iconic *.iconic-property-accent, .button-group > li.warning > label .iconic *.iconic-property-accent, .button-group > li.warning > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.alert > a, .button-group > li.alert > label, .button-group > li.alert > button {
+ background: #F04124;
+ color: #fff;
+ border-color: #F04124; }
+ .button-group > li.alert > a:hover, .button-group > li.alert > a:focus, .button-group > li.alert > label:hover, .button-group > li.alert > label:focus, .button-group > li.alert > button:hover, .button-group > li.alert > button:focus {
+ background: #dc2c0f;
+ color: #fff; }
+ .button-group > li.alert > a:hover, .button-group > li.alert > a:focus, .button-group > li.alert > label:hover, .button-group > li.alert > label:focus, .button-group > li.alert > button:hover, .button-group > li.alert > button:focus {
+ border-color: #c2270d; }
+ .button-group > li.alert > a .iconic *, .button-group > li.alert > label .iconic *, .button-group > li.alert > button .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group > li.alert > a .iconic *.iconic-property-accent, .button-group > li.alert > label .iconic *.iconic-property-accent, .button-group > li.alert > button .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented {
+ border-color: #00558b; }
+ .button-group.segmented > li > a, .button-group.segmented > li > label, .button-group.segmented > li > button {
+ border-color: #00558b;
+ color: #00558b; }
+ .button-group.segmented > li > a:hover, .button-group.segmented > li > label:hover, .button-group.segmented > li > button:hover {
+ background: rgba(0, 85, 139, 0.25);
+ color: #00558b; }
+ .button-group.segmented > li > a .iconic *, .button-group.segmented > li > label .iconic *, .button-group.segmented > li > button .iconic * {
+ fill: #00558b;
+ stroke: #00558b; }
+ .button-group.segmented > li > a .iconic *.iconic-property-accent, .button-group.segmented > li > label .iconic *.iconic-property-accent, .button-group.segmented > li > button .iconic *.iconic-property-accent {
+ fill: #00558b;
+ stroke: #00558b; }
+ .button-group.segmented > li.is-active > a, .button-group.segmented > li.is-active > a:hover, .button-group.segmented > li > input:checked + label, .button-group.segmented > li > input:checked + label:hover {
+ background: #00558b;
+ color: #fff; }
+ .button-group.segmented > li.is-active > a .iconic *, .button-group.segmented > li > input:checked + label .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented > li.is-active > a .iconic *.iconic-property-accent, .button-group.segmented > li > input:checked + label .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.secondary {
+ border-color: #f1f1f1; }
+ .button-group.segmented.secondary > li > a, .button-group.segmented.secondary > li > label, .button-group.segmented.secondary > li > button {
+ border-color: #f1f1f1;
+ color: #f1f1f1; }
+ .button-group.segmented.secondary > li > a:hover, .button-group.segmented.secondary > li > label:hover, .button-group.segmented.secondary > li > button:hover {
+ background: rgba(241, 241, 241, 0.25);
+ color: #f1f1f1; }
+ .button-group.segmented.secondary > li > a .iconic *, .button-group.segmented.secondary > li > label .iconic *, .button-group.segmented.secondary > li > button .iconic * {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+ .button-group.segmented.secondary > li > a .iconic *.iconic-property-accent, .button-group.segmented.secondary > li > label .iconic *.iconic-property-accent, .button-group.segmented.secondary > li > button .iconic *.iconic-property-accent {
+ fill: #f1f1f1;
+ stroke: #f1f1f1; }
+ .button-group.segmented.secondary > li.is-active > a, .button-group.segmented.secondary > li.is-active > a:hover, .button-group.segmented.secondary > li > input:checked + label, .button-group.segmented.secondary > li > input:checked + label:hover {
+ background: #f1f1f1;
+ color: #000; }
+ .button-group.segmented.secondary > li.is-active > a .iconic *, .button-group.segmented.secondary > li > input:checked + label .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .button-group.segmented.secondary > li.is-active > a .iconic *.iconic-property-accent, .button-group.segmented.secondary > li > input:checked + label .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .button-group.segmented.success {
+ border-color: #43AC6A; }
+ .button-group.segmented.success > li > a, .button-group.segmented.success > li > label, .button-group.segmented.success > li > button {
+ border-color: #43AC6A;
+ color: #43AC6A; }
+ .button-group.segmented.success > li > a:hover, .button-group.segmented.success > li > label:hover, .button-group.segmented.success > li > button:hover {
+ background: rgba(67, 172, 106, 0.25);
+ color: #43AC6A; }
+ .button-group.segmented.success > li > a .iconic *, .button-group.segmented.success > li > label .iconic *, .button-group.segmented.success > li > button .iconic * {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+ .button-group.segmented.success > li > a .iconic *.iconic-property-accent, .button-group.segmented.success > li > label .iconic *.iconic-property-accent, .button-group.segmented.success > li > button .iconic *.iconic-property-accent {
+ fill: #43AC6A;
+ stroke: #43AC6A; }
+ .button-group.segmented.success > li.is-active > a, .button-group.segmented.success > li.is-active > a:hover, .button-group.segmented.success > li > input:checked + label, .button-group.segmented.success > li > input:checked + label:hover {
+ background: #43AC6A;
+ color: #fff; }
+ .button-group.segmented.success > li.is-active > a .iconic *, .button-group.segmented.success > li > input:checked + label .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.success > li.is-active > a .iconic *.iconic-property-accent, .button-group.segmented.success > li > input:checked + label .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.warning {
+ border-color: #F08A24; }
+ .button-group.segmented.warning > li > a, .button-group.segmented.warning > li > label, .button-group.segmented.warning > li > button {
+ border-color: #F08A24;
+ color: #F08A24; }
+ .button-group.segmented.warning > li > a:hover, .button-group.segmented.warning > li > label:hover, .button-group.segmented.warning > li > button:hover {
+ background: rgba(240, 138, 36, 0.25);
+ color: #F08A24; }
+ .button-group.segmented.warning > li > a .iconic *, .button-group.segmented.warning > li > label .iconic *, .button-group.segmented.warning > li > button .iconic * {
+ fill: #F08A24;
+ stroke: #F08A24; }
+ .button-group.segmented.warning > li > a .iconic *.iconic-property-accent, .button-group.segmented.warning > li > label .iconic *.iconic-property-accent, .button-group.segmented.warning > li > button .iconic *.iconic-property-accent {
+ fill: #F08A24;
+ stroke: #F08A24; }
+ .button-group.segmented.warning > li.is-active > a, .button-group.segmented.warning > li.is-active > a:hover, .button-group.segmented.warning > li > input:checked + label, .button-group.segmented.warning > li > input:checked + label:hover {
+ background: #F08A24;
+ color: #fff; }
+ .button-group.segmented.warning > li.is-active > a .iconic *, .button-group.segmented.warning > li > input:checked + label .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.warning > li.is-active > a .iconic *.iconic-property-accent, .button-group.segmented.warning > li > input:checked + label .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.alert {
+ border-color: #F04124; }
+ .button-group.segmented.alert > li > a, .button-group.segmented.alert > li > label, .button-group.segmented.alert > li > button {
+ border-color: #F04124;
+ color: #F04124; }
+ .button-group.segmented.alert > li > a:hover, .button-group.segmented.alert > li > label:hover, .button-group.segmented.alert > li > button:hover {
+ background: rgba(240, 65, 36, 0.25);
+ color: #F04124; }
+ .button-group.segmented.alert > li > a .iconic *, .button-group.segmented.alert > li > label .iconic *, .button-group.segmented.alert > li > button .iconic * {
+ fill: #F04124;
+ stroke: #F04124; }
+ .button-group.segmented.alert > li > a .iconic *.iconic-property-accent, .button-group.segmented.alert > li > label .iconic *.iconic-property-accent, .button-group.segmented.alert > li > button .iconic *.iconic-property-accent {
+ fill: #F04124;
+ stroke: #F04124; }
+ .button-group.segmented.alert > li.is-active > a, .button-group.segmented.alert > li.is-active > a:hover, .button-group.segmented.alert > li > input:checked + label, .button-group.segmented.alert > li > input:checked + label:hover {
+ background: #F04124;
+ color: #fff; }
+ .button-group.segmented.alert > li.is-active > a .iconic *, .button-group.segmented.alert > li > input:checked + label .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.segmented.alert > li.is-active > a .iconic *.iconic-property-accent, .button-group.segmented.alert > li > input:checked + label .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .button-group.tiny {
+ font-size: 0.63rem; }
+ .button-group.small {
+ font-size: 0.72rem; }
+ .button-group.large {
+ font-size: 1.17rem; }
+ .button-group.expand {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex; }
+ .button-group.expand > li {
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1; }
+ .button-group.expand > li > a, .button-group.expand > li > label, .button-group.expand > li > button {
+ display: block;
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0; }
+ .button-group li.disabled > a, .button-group li.disabled > label, .button-group li.disabled > button {
+ opacity: 0.5;
+ cursor: default;
+ pointer-events: none; }
+
+/*
+ Cards
+
+ Structure:
+
+ titles
+ lists
+*/
+.card {
+ border: 1px solid #ededed;
+ margin-bottom: 0.5rem;
+ background: #fff;
+ color: #000;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card h1, .card h2, .card h3, .card h4, .card h5, .card h6 {
+ color: inherit; }
+ .card ul {
+ margin-bottom: 0; }
+ .card img {
+ width: 100%; }
+ .card.primary {
+ border: 0;
+ margin-bottom: 0.5rem;
+ background: #00558b;
+ color: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card.primary h1, .card.primary h2, .card.primary h3, .card.primary h4, .card.primary h5, .card.primary h6 {
+ color: inherit; }
+ .card.primary ul {
+ margin-bottom: 0; }
+ .card.primary img {
+ width: 100%; }
+ .card.primary .card-divider {
+ background: #0065a5;
+ padding: 1rem; }
+ .card.success {
+ border: 0;
+ margin-bottom: 0.5rem;
+ background: #43AC6A;
+ color: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card.success h1, .card.success h2, .card.success h3, .card.success h4, .card.success h5, .card.success h6 {
+ color: inherit; }
+ .card.success ul {
+ margin-bottom: 0; }
+ .card.success img {
+ width: 100%; }
+ .card.success .card-divider {
+ background: #4ab873;
+ padding: 1rem; }
+ .card.warning {
+ border: 0;
+ margin-bottom: 0.5rem;
+ background: #F08A24;
+ color: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card.warning h1, .card.warning h2, .card.warning h3, .card.warning h4, .card.warning h5, .card.warning h6 {
+ color: inherit; }
+ .card.warning ul {
+ margin-bottom: 0; }
+ .card.warning img {
+ width: 100%; }
+ .card.warning .card-divider {
+ background: #f19233;
+ padding: 1rem; }
+ .card.alert {
+ border: 0;
+ margin-bottom: 0.5rem;
+ background: #F04124;
+ color: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card.alert h1, .card.alert h2, .card.alert h3, .card.alert h4, .card.alert h5, .card.alert h6 {
+ color: inherit; }
+ .card.alert ul {
+ margin-bottom: 0; }
+ .card.alert img {
+ width: 100%; }
+ .card.alert .card-divider {
+ background: #f14e33;
+ padding: 1rem; }
+ .card.dark {
+ border: 0;
+ margin-bottom: 0.5rem;
+ background: #232323;
+ color: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ overflow: hidden; }
+ .card.dark h1, .card.dark h2, .card.dark h3, .card.dark h4, .card.dark h5, .card.dark h6 {
+ color: inherit; }
+ .card.dark ul {
+ margin-bottom: 0; }
+ .card.dark img {
+ width: 100%; }
+ .card.dark .card-divider {
+ background: #323232;
+ padding: 1rem; }
+
+.card-divider {
+ background: #ededed;
+ padding: 1rem; }
+
+.card-section {
+ padding: 1rem; }
+
+/*
+ Odds and ends.
+*/
+.close-button {
+ position: absolute;
+ color: #999;
+ top: 1rem;
+ right: 1rem;
+ font-size: 2em;
+ line-height: 0.5;
+ cursor: pointer; }
+ .close-button:hover {
+ color: #333; }
+
+.thumbnail, ul.thumbnails > li img {
+ padding: 0.5rem;
+ box-shadow: 0 3px 15px rgba(0, 0, 0, 0.25); }
+
+ul.thumbnails > li {
+ margin-bottom: 1rem; }
+ ul.thumbnails > li a {
+ display: block; }
+
+/*
+ FORMS
+ -----
+
+ Our form styles include basic resets for text fields, select menus, and so on, along with some of our own custom components.
+
+ Includes:
+ - Text fields
+ - Text areas
+ - Select menus
+ - Checkboxes and radio buttons
+ - Range slider
+ - Progress bars and meters
+*/
+input[type="text"], input[type="password"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="week"], input[type="email"], input[type="number"], input[type="search"], input[type="tel"], input[type="time"], input[type="url"], input[type="color"], textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: block;
+ width: 100%;
+ height: 2.4rem;
+ padding: 0.5rem;
+ margin: 0 0 1rem 0;
+ border: 1px solid #ccc;
+ border-radius: 0;
+ background: #fff;
+ color: #000;
+ font-size: 1rem;
+ -webkit-font-smoothing: antialiased;
+ vertical-align: middle; }
+ input[type="text"]:hover, input[type="password"]:hover, input[type="date"]:hover, input[type="datetime"]:hover, input[type="datetime-local"]:hover, input[type="month"]:hover, input[type="week"]:hover, input[type="email"]:hover, input[type="number"]:hover, input[type="search"]:hover, input[type="tel"]:hover, input[type="time"]:hover, input[type="url"]:hover, input[type="color"]:hover, textarea:hover {
+ border: 1px solid #bbb;
+ background: #fff;
+ color: #000; }
+ input[type="text"]:focus, input[type="password"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="week"]:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="time"]:focus, input[type="url"]:focus, input[type="color"]:focus, textarea:focus {
+ outline: 0;
+ border: 1px solid #999;
+ background: #fff;
+ color: #000; }
+ label > input[type="text"], label > input[type="password"], label > input[type="date"], label > input[type="datetime"], label > input[type="datetime-local"], label > input[type="month"], label > input[type="week"], label > input[type="email"], label > input[type="number"], label > input[type="search"], label > input[type="tel"], label > input[type="time"], label > input[type="url"], label > input[type="color"], label > textarea {
+ margin-top: 0.5rem; }
+
+input[type="search"] {
+ box-sizing: border-box; }
+
+input.disabled, input[disabled], input[readonly], fieldset[disabled] input {
+ cursor: false; }
+ input.disabled, input.disabled:hover, input[disabled], input[disabled]:hover, input[readonly], input[readonly]:hover, fieldset[disabled] input, fieldset[disabled] input:hover {
+ background-color: #f2f2f2; }
+
+label {
+ display: block;
+ font-size: 0.9rem;
+ margin-bottom: 0.5rem;
+ color: #333; }
+ label > input, label > textarea {
+ margin-top: 0.5rem; }
+
+input[type="checkbox"], input[type="radio"] {
+ width: 1rem;
+ height: 1rem; }
+ label > input[type="checkbox"], label > input[type="radio"] {
+ margin-right: 0.25rem; }
+ input[type="checkbox"] + label, input[type="radio"] + label {
+ display: inline-block;
+ margin-left: 0.5rem;
+ margin-right: 1rem;
+ margin-bottom: 0;
+ vertical-align: baseline; }
+
+.inline-label {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ margin-bottom: 1rem; }
+ label > .inline-label {
+ margin-top: 0.5rem; }
+ .inline-label > input, .inline-label > select {
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ margin: 0; }
+ .inline-label > .form-label {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto;
+ background: #eee;
+ color: #333;
+ border: 1px solid #ccc;
+ padding: 0 0.5rem;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .inline-label > .form-label:first-child {
+ border-right: 0; }
+ .inline-label > .form-label:last-child {
+ border-left: 0; }
+ .inline-label > a, .inline-label > button, .inline-label > input[type="button"], .inline-label > input[type="submit"] {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin: 0;
+ border-radius: 0; }
+
+textarea {
+ height: auto;
+ width: 100%;
+ min-height: 50px; }
+
+select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: block;
+ width: 100%;
+ height: 2.4rem;
+ padding: 0.5rem;
+ margin: 0 0 1rem 0;
+ font-size: 1rem;
+ color: #000;
+ border-radius: 0;
+ border: 1px solid #ccc;
+ background: #fafafa url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="24" viewBox="0 0 32 24"><polygon points="0,0 32,0 16,24" style="fill: black"></polygon></svg>') right 10px center no-repeat;
+ background-size: 8px 8px;
+ padding-right: 1.625rem; }
+ select:hover {
+ background-color: #f0f0f0; }
+ select:focus {
+ outline: 0; }
+ select::-ms-expand {
+ display: none; }
+
+input[type="range"] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: block;
+ width: 100%;
+ height: auto;
+ cursor: pointer;
+ margin-top: 0.25rem;
+ margin-bottom: 0.25rem;
+ border: 0;
+ line-height: 1; }
+ input[type="range"]:focus {
+ outline: 0; }
+ input[type="range"]::-webkit-slider-runnable-track {
+ height: 1rem;
+ background: #ddd; }
+ input[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ background: #00558b;
+ width: 1.5rem;
+ height: 1.5rem;
+ margin-top: -0.25rem; }
+ input[type="range"]::-moz-range-track {
+ -moz-appearance: none;
+ height: 1rem;
+ background: #ccc; }
+ input[type="range"]::-moz-range-thumb {
+ -moz-appearance: none;
+ background: #00558b;
+ width: 1.5rem;
+ height: 1.5rem;
+ margin-top: -0.25rem; }
+ input[type="range"]::-ms-track {
+ height: 1rem;
+ background: #ddd;
+ color: transparent;
+ border: 0;
+ overflow: visible;
+ border-top: 0.25rem solid #fff;
+ border-bottom: 0.25rem solid #fff; }
+ input[type="range"]::-ms-thumb {
+ background: #00558b;
+ width: 1.5rem;
+ height: 1.5rem;
+ border: 0; }
+ input[type="range"]::-ms-fill-lower, input[type="range"]::-ms-fill-upper {
+ background: #ddd; }
+
+output {
+ line-height: 1.5rem;
+ vertical-align: middle;
+ margin-left: 0.5em; }
+
+input[type="number"]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ background: #00558b; }
+
+progress, meter {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: block;
+ width: 100%;
+ height: 1.5rem;
+ margin-bottom: 1rem;
+ background: #ccc;
+ border: 0; }
+
+progress::-webkit-progress-bar {
+ background: #ccc; }
+progress::-webkit-progress-value {
+ background: #00558b; }
+progress::-moz-progress-bar {
+ background: #00558b; }
+progress.high::-webkit-progress-value {
+ background: #43AC6A; }
+progress.high::-moz-progress-bar {
+ background: #43AC6A; }
+progress.medium::-webkit-progress-value {
+ background: #e7cf00; }
+progress.medium::-moz-progress-bar {
+ background: #e7cf00; }
+progress.low::-webkit-progress-value {
+ background: #F04124; }
+progress.low::-moz-progress-bar {
+ background: #F04124; }
+
+meter {
+ background: #ccc; }
+ meter::-webkit-meter-bar {
+ background: #ccc; }
+ meter::-webkit-meter-optimum-value {
+ background: #43AC6A; }
+ meter::-webkit-meter-suboptimum-value {
+ background: #e7cf00; }
+ meter::-webkit-meter-even-less-good-value {
+ background: #F04124; }
+ meter::-moz-meter-bar {
+ background: #00558b; }
+ meter:-moz-meter-optimum::-moz-meter-bar {
+ background: #43AC6A; }
+ meter:-moz-meter-sub-optimum::-moz-meter-bar {
+ background: #e7cf00; }
+ meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
+ background: #F04124; }
+
+/*
+ PANEL
+ -----
+
+ The friendly panel is an all-purpose container for hiding content off-screen.
+
+ Features:
+ - Position at top, right, bottom, or left
+ - Anchor to grid block or window
+ - Define max width or height
+ - Transform into grid block depending on screen size
+*/
+.panel {
+ display: block;
+ position: absolute;
+ z-index: 100;
+ overflow-y: auto;
+ display: none; }
+ .is-active.panel {
+ display: block; }
+
+.panel {
+ /*
+ Basic styles
+ */
+ padding: 0;
+ background: #fff; }
+
+.panel-top {
+ /*
+ Direction
+ */
+ top: 0;
+ left: 0;
+ width: 100%;
+ /*
+ Sizing
+ */
+ height: 300px;
+ /*
+ Shadows
+ */ }
+ .panel-top.is-active {
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25); }
+
+.panel-right {
+ /*
+ Direction
+ */
+ top: 0;
+ right: 0;
+ height: 100%;
+ /*
+ Sizing
+ */
+ width: 100%;
+ /*
+ Shadows
+ */ }
+ @media only screen and (min-width: 18.75em) {
+ .panel-right {
+ width: 300px; } }
+ .panel-right.is-active {
+ box-shadow: -3px 0 10px rgba(0, 0, 0, 0.25); }
+
+.panel-bottom {
+ /*
+ Direction
+ */
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ /*
+ Sizing
+ */
+ height: 300px;
+ /*
+ Shadows
+ */ }
+ .panel-bottom.is-active {
+ box-shadow: 2px -3px 10px rgba(0, 0, 0, 0.25); }
+
+.panel-left {
+ /*
+ Direction
+ */
+ top: 0;
+ left: 0;
+ height: 100%;
+ /*
+ Sizing
+ */
+ width: 100%;
+ /*
+ Shadows
+ */ }
+ @media only screen and (min-width: 18.75em) {
+ .panel-left {
+ width: 300px; } }
+ .panel-left.is-active {
+ box-shadow: 3px 0 10px rgba(0, 0, 0, 0.25); }
+
+.panel-fixed {
+ position: fixed; }
+
+/*
+ THE GRID
+ --------
+
+ Foundation's magical, flexbox-powered grid.
+
+ Features:
+ - Horizontal or vertical grids
+ - Auto-sizing or percentage width grid blocks
+ - Independently-scrollable blocks
+ - Column alignment
+ - Source ordering
+ - Offsets
+*/
+/*
+ Define the size of a grid block. Blocks are flex items. By default, they stretch to fill all available space, based on the size of sibling blocks. This is the "expand" behavior.
+
+ If set to "shrink", the block will contract and only fill as much space as it needs for its content.
+
+ If set to a number, the block will be given a percentage width, based on the total number of columns (12 by default). Percentage widths don't work if a block is inside a vertical grid.
+
+ @group grid
+
+ @param {number|string} $size - Sizing behavior of the block. Should be expand, shrink, or a number.
+
+ @output The flex-basis, flex-grow, and flex-shrink properties.
+*/
+/*
+ Set the orientation of blocks within this block. The grid is re-oriented by changing the flex direction of the block.
+
+ @group grid
+
+ @param {string} $orientation - Direction of the grid, either horizontal or vertical.
+
+ @output A flex-flow property to match the direction given.
+*/
+/*
+ Stretch a grid's child blocks across its cross-axis, making every column appear to have the same height.
+
+ @group grid
+
+ @param {bool} $stretch - Stretch blocks if true, or align blocks to top if false.
+
+ @output Sets align-items to "stretch" if $stretch is true, or "flex-start" (the default value) if false.
+*/
+/*
+ Set the alignment of blocks within a grid.
+
+ left: Items align to the left.
+ right: Items align to the right.
+ center: Items align to the center.
+ justify: Items are spaced equally apart so they occupy the space of the entire grid.
+ spaced: Items are given equal space to their left and right.
+
+ @group grid
+
+ @param {string} $align - Alignment to use.
+
+ @output An appropriate justify-content value.
+*/
+/*
+ Set the source order of a block. Items with lower numbers appear first. If multiple items have the same number, the one in the HTML first will appear first.
+
+ @group grid
+
+ @param {number} $order - Position in source order.
+
+ @output An order property.
+*/
+/*
+ Collapse a content block by removing the padding.
+
+ @group grid
+
+ @param {bool} $collapse - Collapses the block if true.
+
+ @output A padding value.
+
+ @todo No way to reverse collapse using this mixin. Solution:
+ - If true, add padding: 0;
+ - If false, add padding: 1rem;
+ - If null, add nothing, to cut down on CSS output
+ - Make null the default value
+*/
+/*
+ Constrain the size of a block to the size of the average grid row, and center-align it. This imitates the behavior of ordinary Foundation rows.
+
+ @group grid
+
+ @param {bool} $container - Adds container styles if true.
+
+ @output A maximum width and the good old margin: 0 auto for center alignment.
+*/
+/*
+ Add negative margins to a block, equal to the padding of a content block. This aligns the edges of a block nested inside a content block.
+
+ @group grid
+
+ @param {bool} $nest - Adds negative margins if true.
+
+ @output Negative margin values.
+*/
+/*
+ Offset a block by adding a left margin.
+
+ @group grid
+
+ @param {number | bool} $offset - If false, nothing is output. If a number, offsets the column by the specified number of columns.
+
+ @output A left margin based on the number of columns specified, and the global number of columns.
+*/
+/*
+ Resets styles set by panels. Use this when a panel transforms into a block on larger screens.
+
+ @group grid
+
+ @output Resets to transform, position, and a few visual styles.
+*/
+/*
+ Frames are containers that stretch to the full dimmensions of the browser window.
+*/
+/*
+ Groups are collections of content items. They're the "rows" of Foundation for Apps.
+*/
+/*
+ Blocks are containers for actual content. They're the "columns" of Foundation for Apps.
+*/
+.vertical.grid-frame, .vertical.grid-block, .vertical.small-grid-block, .vertical.medium-grid-block, .vertical.large-grid-block {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch; }
+.small-vertical.grid-frame, .small-vertical.grid-block, .small-vertical.small-grid-block, .small-vertical.medium-grid-block, .small-vertical.large-grid-block {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch; }
+.small-horizontal.grid-frame, .small-horizontal.grid-block, .small-horizontal.small-grid-block, .small-horizontal.medium-grid-block, .small-horizontal.large-grid-block {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap; }
+@media only screen and (min-width: 40em) {
+ .medium-vertical.grid-frame, .medium-vertical.grid-block, .medium-vertical.small-grid-block, .medium-vertical.medium-grid-block, .medium-vertical.large-grid-block {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch; }
+ .medium-horizontal.grid-frame, .medium-horizontal.grid-block, .medium-horizontal.small-grid-block, .medium-horizontal.medium-grid-block, .medium-horizontal.large-grid-block {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap; } }
+@media only screen and (min-width: 75em) {
+ .large-vertical.grid-frame, .large-vertical.grid-block, .large-vertical.small-grid-block, .large-vertical.medium-grid-block, .large-vertical.large-grid-block {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch; }
+ .large-horizontal.grid-frame, .large-horizontal.grid-block, .large-horizontal.small-grid-block, .large-horizontal.medium-grid-block, .large-horizontal.large-grid-block {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap; } }
+.align-right.grid-frame, .align-right.grid-block, .align-right.small-grid-block, .align-right.medium-grid-block, .align-right.large-grid-block {
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+.align-center.grid-frame, .align-center.grid-block, .align-center.small-grid-block, .align-center.medium-grid-block, .align-center.large-grid-block {
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+.align-justify.grid-frame, .align-justify.grid-block, .align-justify.small-grid-block, .align-justify.medium-grid-block, .align-justify.large-grid-block {
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+.align-spaced.grid-frame, .align-spaced.grid-block, .align-spaced.small-grid-block, .align-spaced.medium-grid-block, .align-spaced.large-grid-block {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around; }
+.wrap.grid-frame, .wrap.grid-block, .wrap.small-grid-block, .wrap.medium-grid-block, .wrap.large-grid-block {
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+ -webkit-align-items: flex-start;
+ -ms-flex-align: start;
+ align-items: flex-start; }
+
+.shrink.grid-block, .shrink.grid-content, .shrink.small-grid-block, .shrink.small-grid-content, .shrink.medium-grid-block, .shrink.medium-grid-content, .shrink.large-grid-block, .shrink.large-grid-content {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+.noscroll.grid-block, .noscroll.grid-content, .noscroll.small-grid-block, .noscroll.small-grid-content, .noscroll.medium-grid-block, .noscroll.medium-grid-content, .noscroll.large-grid-block, .noscroll.large-grid-content {
+ overflow: hidden; }
+
+.grid-frame {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-order: 0;
+ -ms-flex-order: 0;
+ order: 0; }
+
+.grid-block {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-order: 0;
+ -ms-flex-order: 0;
+ order: 0;
+ height: auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar; }
+
+.grid-content {
+ display: block;
+ padding: 0 1rem;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .grid-content.collapse {
+ padding: 0; }
+ .grid-content .grid-block {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+ overflow: visible; }
+ .grid-content .grid-block.nowrap {
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch; }
+ .grid-content .grid-block .grid-content {
+ overflow: visible; }
+
+.grid-container {
+ max-width: 56.25rem;
+ margin: 0 auto; }
+ .grid-container.contain-left {
+ max-width: 56.25rem;
+ margin: 0 auto 0 0; }
+ .grid-container.contain-right {
+ max-width: 56.25rem;
+ margin: 0 0 0 auto; }
+
+.small-grid-block {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-order: 0;
+ -ms-flex-order: 0;
+ order: 0;
+ height: auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar; }
+ .small-grid-block.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; }
+
+.small-grid-content {
+ display: block;
+ padding: 0 1rem;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .small-grid-content.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; }
+
+@media only screen and (min-width: 40em) {
+ .medium-grid-block {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-order: 0;
+ -ms-flex-order: 0;
+ order: 0;
+ height: auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar; }
+ .medium-grid-block.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-grid-content {
+ display: block;
+ padding: 0 1rem;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .medium-grid-content.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; } }
+
+@media only screen and (min-width: 75em) {
+ .large-grid-block {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-order: 0;
+ -ms-flex-order: 0;
+ order: 0;
+ height: auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar; }
+ .large-grid-block.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; } }
+
+@media only screen and (min-width: 75em) {
+ .large-grid-content {
+ display: block;
+ padding: 0 1rem;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .large-grid-content.panel {
+ -webkit-transform: none;
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto; } }
+
+.order-1 {
+ -webkit-order: 1;
+ -ms-flex-order: 1;
+ order: 1; }
+
+.order-2 {
+ -webkit-order: 2;
+ -ms-flex-order: 2;
+ order: 2; }
+
+.order-3 {
+ -webkit-order: 3;
+ -ms-flex-order: 3;
+ order: 3; }
+
+.order-4 {
+ -webkit-order: 4;
+ -ms-flex-order: 4;
+ order: 4; }
+
+.order-5 {
+ -webkit-order: 5;
+ -ms-flex-order: 5;
+ order: 5; }
+
+.order-6 {
+ -webkit-order: 6;
+ -ms-flex-order: 6;
+ order: 6; }
+
+.order-7 {
+ -webkit-order: 7;
+ -ms-flex-order: 7;
+ order: 7; }
+
+.order-8 {
+ -webkit-order: 8;
+ -ms-flex-order: 8;
+ order: 8; }
+
+.order-9 {
+ -webkit-order: 9;
+ -ms-flex-order: 9;
+ order: 9; }
+
+.order-10 {
+ -webkit-order: 10;
+ -ms-flex-order: 10;
+ order: 10; }
+
+.order-11 {
+ -webkit-order: 11;
+ -ms-flex-order: 11;
+ order: 11; }
+
+.order-12 {
+ -webkit-order: 12;
+ -ms-flex-order: 12;
+ order: 12; }
+
+.small-1 {
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+
+.small-order-1 {
+ -webkit-order: 1;
+ -ms-flex-order: 1;
+ order: 1; }
+
+.small-offset-1 {
+ margin-left: 8.33333%; }
+
+.small-up-1 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-1 > li, .small-up-1 > div, .small-up-1 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%; }
+
+.small-2 {
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+
+.small-order-2 {
+ -webkit-order: 2;
+ -ms-flex-order: 2;
+ order: 2; }
+
+.small-offset-2 {
+ margin-left: 16.66667%; }
+
+.small-up-2 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-2 > li, .small-up-2 > div, .small-up-2 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%; }
+
+.small-3 {
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%; }
+
+.small-order-3 {
+ -webkit-order: 3;
+ -ms-flex-order: 3;
+ order: 3; }
+
+.small-offset-3 {
+ margin-left: 25%; }
+
+.small-up-3 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-3 > li, .small-up-3 > div, .small-up-3 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%; }
+
+.small-4 {
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+
+.small-order-4 {
+ -webkit-order: 4;
+ -ms-flex-order: 4;
+ order: 4; }
+
+.small-offset-4 {
+ margin-left: 33.33333%; }
+
+.small-up-4 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-4 > li, .small-up-4 > div, .small-up-4 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%; }
+
+.small-5 {
+ -webkit-flex: 0 0 41.66667%;
+ -ms-flex: 0 0 41.66667%;
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+
+.small-order-5 {
+ -webkit-order: 5;
+ -ms-flex-order: 5;
+ order: 5; }
+
+.small-offset-5 {
+ margin-left: 41.66667%; }
+
+.small-up-5 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-5 > li, .small-up-5 > div, .small-up-5 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 20%;
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%; }
+
+.small-6 {
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%; }
+
+.small-order-6 {
+ -webkit-order: 6;
+ -ms-flex-order: 6;
+ order: 6; }
+
+.small-offset-6 {
+ margin-left: 50%; }
+
+.small-up-6 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-6 > li, .small-up-6 > div, .small-up-6 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%; }
+
+.small-7 {
+ -webkit-flex: 0 0 58.33333%;
+ -ms-flex: 0 0 58.33333%;
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+
+.small-order-7 {
+ -webkit-order: 7;
+ -ms-flex-order: 7;
+ order: 7; }
+
+.small-offset-7 {
+ margin-left: 58.33333%; }
+
+.small-up-7 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-7 > li, .small-up-7 > div, .small-up-7 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 14.28571%;
+ -ms-flex: 0 0 14.28571%;
+ flex: 0 0 14.28571%; }
+
+.small-8 {
+ -webkit-flex: 0 0 66.66667%;
+ -ms-flex: 0 0 66.66667%;
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+
+.small-order-8 {
+ -webkit-order: 8;
+ -ms-flex-order: 8;
+ order: 8; }
+
+.small-offset-8 {
+ margin-left: 66.66667%; }
+
+.small-up-8 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-8 > li, .small-up-8 > div, .small-up-8 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 12.5%;
+ -ms-flex: 0 0 12.5%;
+ flex: 0 0 12.5%; }
+
+.small-9 {
+ -webkit-flex: 0 0 75%;
+ -ms-flex: 0 0 75%;
+ flex: 0 0 75%;
+ max-width: 75%; }
+
+.small-order-9 {
+ -webkit-order: 9;
+ -ms-flex-order: 9;
+ order: 9; }
+
+.small-offset-9 {
+ margin-left: 75%; }
+
+.small-up-9 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-9 > li, .small-up-9 > div, .small-up-9 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 11.11111%;
+ -ms-flex: 0 0 11.11111%;
+ flex: 0 0 11.11111%; }
+
+.small-10 {
+ -webkit-flex: 0 0 83.33333%;
+ -ms-flex: 0 0 83.33333%;
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+
+.small-order-10 {
+ -webkit-order: 10;
+ -ms-flex-order: 10;
+ order: 10; }
+
+.small-offset-10 {
+ margin-left: 83.33333%; }
+
+.small-up-10 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-10 > li, .small-up-10 > div, .small-up-10 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 10%;
+ -ms-flex: 0 0 10%;
+ flex: 0 0 10%; }
+
+.small-11 {
+ -webkit-flex: 0 0 91.66667%;
+ -ms-flex: 0 0 91.66667%;
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+
+.small-order-11 {
+ -webkit-order: 11;
+ -ms-flex-order: 11;
+ order: 11; }
+
+.small-offset-11 {
+ margin-left: 91.66667%; }
+
+.small-up-11 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-11 > li, .small-up-11 > div, .small-up-11 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 9.09091%;
+ -ms-flex: 0 0 9.09091%;
+ flex: 0 0 9.09091%; }
+
+.small-12 {
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
+ max-width: 100%; }
+
+.small-order-12 {
+ -webkit-order: 12;
+ -ms-flex-order: 12;
+ order: 12; }
+
+.small-offset-12 {
+ margin-left: 100%; }
+
+.small-up-12 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .small-up-12 > li, .small-up-12 > div, .small-up-12 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%; }
+
+@media only screen and (min-width: 40em) {
+ .medium-1 {
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .medium-order-1 {
+ -webkit-order: 1;
+ -ms-flex-order: 1;
+ order: 1; }
+ .medium-offset-1 {
+ margin-left: 8.33333%; }
+ .medium-up-1 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-1 > li, .medium-up-1 > div, .medium-up-1 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-2 {
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .medium-order-2 {
+ -webkit-order: 2;
+ -ms-flex-order: 2;
+ order: 2; }
+ .medium-offset-2 {
+ margin-left: 16.66667%; }
+ .medium-up-2 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-2 > li, .medium-up-2 > div, .medium-up-2 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-3 {
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .medium-order-3 {
+ -webkit-order: 3;
+ -ms-flex-order: 3;
+ order: 3; }
+ .medium-offset-3 {
+ margin-left: 25%; }
+ .medium-up-3 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-3 > li, .medium-up-3 > div, .medium-up-3 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-4 {
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .medium-order-4 {
+ -webkit-order: 4;
+ -ms-flex-order: 4;
+ order: 4; }
+ .medium-offset-4 {
+ margin-left: 33.33333%; }
+ .medium-up-4 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-4 > li, .medium-up-4 > div, .medium-up-4 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-5 {
+ -webkit-flex: 0 0 41.66667%;
+ -ms-flex: 0 0 41.66667%;
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .medium-order-5 {
+ -webkit-order: 5;
+ -ms-flex-order: 5;
+ order: 5; }
+ .medium-offset-5 {
+ margin-left: 41.66667%; }
+ .medium-up-5 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-5 > li, .medium-up-5 > div, .medium-up-5 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 20%;
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-6 {
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .medium-order-6 {
+ -webkit-order: 6;
+ -ms-flex-order: 6;
+ order: 6; }
+ .medium-offset-6 {
+ margin-left: 50%; }
+ .medium-up-6 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-6 > li, .medium-up-6 > div, .medium-up-6 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-7 {
+ -webkit-flex: 0 0 58.33333%;
+ -ms-flex: 0 0 58.33333%;
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .medium-order-7 {
+ -webkit-order: 7;
+ -ms-flex-order: 7;
+ order: 7; }
+ .medium-offset-7 {
+ margin-left: 58.33333%; }
+ .medium-up-7 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-7 > li, .medium-up-7 > div, .medium-up-7 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 14.28571%;
+ -ms-flex: 0 0 14.28571%;
+ flex: 0 0 14.28571%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-8 {
+ -webkit-flex: 0 0 66.66667%;
+ -ms-flex: 0 0 66.66667%;
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .medium-order-8 {
+ -webkit-order: 8;
+ -ms-flex-order: 8;
+ order: 8; }
+ .medium-offset-8 {
+ margin-left: 66.66667%; }
+ .medium-up-8 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-8 > li, .medium-up-8 > div, .medium-up-8 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 12.5%;
+ -ms-flex: 0 0 12.5%;
+ flex: 0 0 12.5%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-9 {
+ -webkit-flex: 0 0 75%;
+ -ms-flex: 0 0 75%;
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .medium-order-9 {
+ -webkit-order: 9;
+ -ms-flex-order: 9;
+ order: 9; }
+ .medium-offset-9 {
+ margin-left: 75%; }
+ .medium-up-9 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-9 > li, .medium-up-9 > div, .medium-up-9 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 11.11111%;
+ -ms-flex: 0 0 11.11111%;
+ flex: 0 0 11.11111%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-10 {
+ -webkit-flex: 0 0 83.33333%;
+ -ms-flex: 0 0 83.33333%;
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .medium-order-10 {
+ -webkit-order: 10;
+ -ms-flex-order: 10;
+ order: 10; }
+ .medium-offset-10 {
+ margin-left: 83.33333%; }
+ .medium-up-10 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-10 > li, .medium-up-10 > div, .medium-up-10 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 10%;
+ -ms-flex: 0 0 10%;
+ flex: 0 0 10%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-11 {
+ -webkit-flex: 0 0 91.66667%;
+ -ms-flex: 0 0 91.66667%;
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .medium-order-11 {
+ -webkit-order: 11;
+ -ms-flex-order: 11;
+ order: 11; }
+ .medium-offset-11 {
+ margin-left: 91.66667%; }
+ .medium-up-11 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-11 > li, .medium-up-11 > div, .medium-up-11 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 9.09091%;
+ -ms-flex: 0 0 9.09091%;
+ flex: 0 0 9.09091%; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-12 {
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .medium-order-12 {
+ -webkit-order: 12;
+ -ms-flex-order: 12;
+ order: 12; }
+ .medium-offset-12 {
+ margin-left: 100%; }
+ .medium-up-12 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .medium-up-12 > li, .medium-up-12 > div, .medium-up-12 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-1 {
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .large-order-1 {
+ -webkit-order: 1;
+ -ms-flex-order: 1;
+ order: 1; }
+ .large-offset-1 {
+ margin-left: 8.33333%; }
+ .large-up-1 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-1 > li, .large-up-1 > div, .large-up-1 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-2 {
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .large-order-2 {
+ -webkit-order: 2;
+ -ms-flex-order: 2;
+ order: 2; }
+ .large-offset-2 {
+ margin-left: 16.66667%; }
+ .large-up-2 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-2 > li, .large-up-2 > div, .large-up-2 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-3 {
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .large-order-3 {
+ -webkit-order: 3;
+ -ms-flex-order: 3;
+ order: 3; }
+ .large-offset-3 {
+ margin-left: 25%; }
+ .large-up-3 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-3 > li, .large-up-3 > div, .large-up-3 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-4 {
+ -webkit-flex: 0 0 33.33333%;
+ -ms-flex: 0 0 33.33333%;
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .large-order-4 {
+ -webkit-order: 4;
+ -ms-flex-order: 4;
+ order: 4; }
+ .large-offset-4 {
+ margin-left: 33.33333%; }
+ .large-up-4 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-4 > li, .large-up-4 > div, .large-up-4 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-5 {
+ -webkit-flex: 0 0 41.66667%;
+ -ms-flex: 0 0 41.66667%;
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .large-order-5 {
+ -webkit-order: 5;
+ -ms-flex-order: 5;
+ order: 5; }
+ .large-offset-5 {
+ margin-left: 41.66667%; }
+ .large-up-5 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-5 > li, .large-up-5 > div, .large-up-5 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 20%;
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-6 {
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .large-order-6 {
+ -webkit-order: 6;
+ -ms-flex-order: 6;
+ order: 6; }
+ .large-offset-6 {
+ margin-left: 50%; }
+ .large-up-6 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-6 > li, .large-up-6 > div, .large-up-6 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 16.66667%;
+ -ms-flex: 0 0 16.66667%;
+ flex: 0 0 16.66667%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-7 {
+ -webkit-flex: 0 0 58.33333%;
+ -ms-flex: 0 0 58.33333%;
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .large-order-7 {
+ -webkit-order: 7;
+ -ms-flex-order: 7;
+ order: 7; }
+ .large-offset-7 {
+ margin-left: 58.33333%; }
+ .large-up-7 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-7 > li, .large-up-7 > div, .large-up-7 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 14.28571%;
+ -ms-flex: 0 0 14.28571%;
+ flex: 0 0 14.28571%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-8 {
+ -webkit-flex: 0 0 66.66667%;
+ -ms-flex: 0 0 66.66667%;
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .large-order-8 {
+ -webkit-order: 8;
+ -ms-flex-order: 8;
+ order: 8; }
+ .large-offset-8 {
+ margin-left: 66.66667%; }
+ .large-up-8 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-8 > li, .large-up-8 > div, .large-up-8 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 12.5%;
+ -ms-flex: 0 0 12.5%;
+ flex: 0 0 12.5%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-9 {
+ -webkit-flex: 0 0 75%;
+ -ms-flex: 0 0 75%;
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .large-order-9 {
+ -webkit-order: 9;
+ -ms-flex-order: 9;
+ order: 9; }
+ .large-offset-9 {
+ margin-left: 75%; }
+ .large-up-9 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-9 > li, .large-up-9 > div, .large-up-9 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 11.11111%;
+ -ms-flex: 0 0 11.11111%;
+ flex: 0 0 11.11111%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-10 {
+ -webkit-flex: 0 0 83.33333%;
+ -ms-flex: 0 0 83.33333%;
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .large-order-10 {
+ -webkit-order: 10;
+ -ms-flex-order: 10;
+ order: 10; }
+ .large-offset-10 {
+ margin-left: 83.33333%; }
+ .large-up-10 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-10 > li, .large-up-10 > div, .large-up-10 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 10%;
+ -ms-flex: 0 0 10%;
+ flex: 0 0 10%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-11 {
+ -webkit-flex: 0 0 91.66667%;
+ -ms-flex: 0 0 91.66667%;
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .large-order-11 {
+ -webkit-order: 11;
+ -ms-flex-order: 11;
+ order: 11; }
+ .large-offset-11 {
+ margin-left: 91.66667%; }
+ .large-up-11 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-11 > li, .large-up-11 > div, .large-up-11 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 9.09091%;
+ -ms-flex: 0 0 9.09091%;
+ flex: 0 0 9.09091%; } }
+
+@media only screen and (min-width: 75em) {
+ .large-12 {
+ -webkit-flex: 0 0 100%;
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .large-order-12 {
+ -webkit-order: 12;
+ -ms-flex-order: 12;
+ order: 12; }
+ .large-offset-12 {
+ margin-left: 100%; }
+ .large-up-12 {
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none; }
+ .large-up-12 > li, .large-up-12 > div, .large-up-12 > section {
+ padding: 0 1rem 1rem;
+ -webkit-flex: 0 0 8.33333%;
+ -ms-flex: 0 0 8.33333%;
+ flex: 0 0 8.33333%; } }
+
+.grid-content .modal .grid-block {
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap; }
+
+/*
+ TITLE BAR
+ ---------
+
+ A navigational component which can display the current screen the user is on, along with additional controls or menu items.
+
+ The title bar includes classes to create center, left, and right sections, which can be used in any combination. However, in the markup, the sections must come in this order:
+ - Center
+ - Left
+ - Right
+*/
+.title-bar {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ overflow: visible; }
+ .title-bar .title {
+ font-weight: bold; }
+ .title-bar .left, .title-bar .center, .title-bar .right {
+ display: block;
+ white-space: nowrap;
+ overflow: visible; }
+ .title-bar .left:first-child:last-child, .title-bar .center:first-child:last-child, .title-bar .right:first-child:last-child {
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ margin: 0; }
+ .title-bar .left {
+ -webkit-order: 1;
+ -ms-flex-order: 1;
+ order: 1;
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%; }
+ .title-bar .center {
+ -webkit-order: 2;
+ -ms-flex-order: 2;
+ order: 2;
+ -webkit-flex: 0 0 50%;
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ text-align: center; }
+ .title-bar .right {
+ -webkit-order: 3;
+ -ms-flex-order: 3;
+ order: 3;
+ -webkit-flex: 0 0 25%;
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ text-align: right; }
+ .title-bar .left:first-child {
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .title-bar .left:first-child + .right:last-child {
+ -webkit-flex: 1 1 auto;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto; }
+ .title-bar .center:first-child:not(:last-child) {
+ margin-left: 25%; }
+ .title-bar .center + .left {
+ margin-right: -25%; }
+
+.title-bar {
+ background: #eee;
+ color: #000;
+ padding: 1rem;
+ border-bottom: 1px solid #ccc; }
+ .title-bar.primary {
+ background: #00558b;
+ color: #fff;
+ padding: 1rem;
+ border-bottom: 1px solid #ccc; }
+ .title-bar.primary a, .title-bar.primary a:hover {
+ color: #fff; }
+ .title-bar.primary .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .title-bar.primary .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .title-bar.dark {
+ background: #232323;
+ color: #fff;
+ padding: 1rem;
+ border-bottom: 1px solid #ccc; }
+ .title-bar.dark a, .title-bar.dark a:hover {
+ color: #fff; }
+ .title-bar.dark .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .title-bar.dark .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+
+.title-bar-bottom {
+ border-bottom: 0;
+ border-top: 1px solid #ccc; }
+
+/*
+ Label
+*/
+.label {
+ line-height: 1;
+ white-space: nowrap;
+ display: inline-block;
+ cursor: default; }
+
+.label {
+ font-size: 0.8rem;
+ padding: 0.33333rem 0.5rem;
+ background: #00558b;
+ border-radius: 0;
+ color: #fff; }
+ .label.primary {
+ background: #00558b;
+ border-radius: 0;
+ color: #fff; }
+ .label.success {
+ background: #43AC6A;
+ border-radius: 0;
+ color: #fff; }
+ .label.warning {
+ background: #F08A24;
+ border-radius: 0;
+ color: #fff; }
+ .label.alert {
+ background: #F04124;
+ border-radius: 0;
+ color: #fff; }
+ .label.dark {
+ background: #232323;
+ border-radius: 0;
+ color: #fff; }
+
+/*
+ Badge
+*/
+.badge {
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ border-radius: 1000px; }
+
+.badge {
+ font-size: 0.8em;
+ width: 1.5rem;
+ height: 1.5rem;
+ background: #00558b;
+ color: #fff; }
+ .badge.secondary {
+ background: #f1f1f1;
+ color: #000; }
+ .badge.primary {
+ background: #00558b;
+ color: #fff; }
+ .badge.success {
+ background: #43AC6A;
+ color: #fff; }
+ .badge.warning {
+ background: #F08A24;
+ color: #fff; }
+ .badge.alert {
+ background: #F04124;
+ color: #fff; }
+ .badge.dark {
+ background: #232323;
+ color: #fff; }
+
+.inline-list {
+ list-style-type: none;
+ text-align: left; }
+ .inline-list li, .inline-list dt, .inline-list dd {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px; }
+ .inline-list li {
+ margin-right: 1rem;
+ margin-left: 0; }
+
+/*
+ MENU BAR
+ --------
+
+ A generic, flexible menu component.
+
+ Features:
+ - Orient horizontally and vertically
+ - Change orientation at certain breakpoints
+ - Items with icons above, below, or to the left or right
+ - Text labels for vertical menus and badges for horizontal menus
+*/
+.menu-bar {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ margin: 0;
+ list-style-type: none; }
+ .menu-bar > li {
+ -webkit-flex: 1 0 auto;
+ -ms-flex: 1 0 auto;
+ flex: 1 0 auto;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .menu-bar > li > a {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ padding: 1rem;
+ font-size: 1rem;
+ line-height: 1; }
+
+/*
+ Set the alignment of menu items (li) within a menu-bar
+
+ left: Items align to the left.
+ right: Items align to the right.
+ center: Items align to the center.
+ justify: Items are spaced equally apart so they occupy the space of the entire grid.
+ spaced: Items are given equal space to their left and right.
+
+ @group menu-bar
+
+ @param {string} $align - Alignment to use.
+
+ @output An appropriate justify-content value.
+*/
+/*
+ CSS output
+*/
+.menu-bar {
+ background: #fff; }
+ .menu-bar > li > a {
+ color: #000; }
+ .menu-bar > li > a:hover {
+ background: #ededed;
+ color: #000; }
+ .menu-bar .is-active > a {
+ background: #ededed;
+ color: #000; }
+ .menu-bar .iconic * {
+ fill: #000;
+ stroke: #000; }
+ .menu-bar .iconic *.iconic-property-accent {
+ fill: #000;
+ stroke: #000; }
+ .menu-bar, .menu-bar.horizontal {
+ /*
+ Orientation
+ */
+ overflow-x: hidden;
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar > li > a, .menu-bar.horizontal > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.vertical {
+ /*
+ Orientation
+ */
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.vertical > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap; }
+ .menu-bar.condense > li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .menu-bar.align-right {
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+ .menu-bar.align-center {
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+ .menu-bar.align-justify {
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+ .menu-bar.align-spaced {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around; }
+ .menu-bar.small-condense li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .menu-bar.small-expand li {
+ -webkit-flex: 1 0 auto;
+ -ms-flex: 1 0 auto;
+ flex: 1 0 auto; }
+ .menu-bar.small-align-left {
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start; }
+ .menu-bar.small-align-right {
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+ .menu-bar.small-align-center {
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+ .menu-bar.small-align-justify {
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+ .menu-bar.small-align-spaced {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around; }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-condense li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .menu-bar.medium-expand li {
+ -webkit-flex: 1 0 auto;
+ -ms-flex: 1 0 auto;
+ flex: 1 0 auto; }
+ .menu-bar.medium-align-left {
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start; }
+ .menu-bar.medium-align-right {
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+ .menu-bar.medium-align-center {
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+ .menu-bar.medium-align-justify {
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+ .menu-bar.medium-align-spaced {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-condense li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .menu-bar.large-expand li {
+ -webkit-flex: 1 0 auto;
+ -ms-flex: 1 0 auto;
+ flex: 1 0 auto; }
+ .menu-bar.large-align-left {
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start; }
+ .menu-bar.large-align-right {
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+ .menu-bar.large-align-center {
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+ .menu-bar.large-align-justify {
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+ .menu-bar.large-align-spaced {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around; } }
+ .menu-bar.small-horizontal {
+ /*
+ Orientation
+ */
+ overflow-x: hidden;
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.small-horizontal > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.small-vertical {
+ /*
+ Orientation
+ */
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.small-vertical > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap; }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-horizontal {
+ /*
+ Orientation
+ */
+ overflow-x: hidden;
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.medium-horizontal > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.medium-vertical {
+ /*
+ Orientation
+ */
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.medium-vertical > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-horizontal {
+ /*
+ Orientation
+ */
+ overflow-x: hidden;
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.large-horizontal > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.large-vertical {
+ /*
+ Orientation
+ */
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap;
+ /*
+ Stretch
+ */ }
+ .menu-bar.large-vertical > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap; } }
+ .menu-bar > li > img, .menu-bar > li > .iconic, .menu-bar.icon-top > li > img, .menu-bar.icon-top > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar > li > a, .menu-bar.icon-top > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar > li > a > img, .menu-bar > li > a > .iconic, .menu-bar.icon-top > li > a > img, .menu-bar.icon-top > li > a > .iconic {
+ margin: 0 0 1rem 0; }
+ .menu-bar.icon-right > li > img, .menu-bar.icon-right > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.icon-right > li > a {
+ -webkit-flex-flow: row-reverse nowrap;
+ -ms-flex-flow: row-reverse nowrap;
+ flex-flow: row-reverse nowrap; }
+ .menu-bar.icon-right > li > a > img, .menu-bar.icon-right > li > a > .iconic {
+ margin: 0 0 0 1rem; }
+ .menu-bar.icon-bottom > li > img, .menu-bar.icon-bottom > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.icon-bottom > li > a {
+ -webkit-flex-flow: column-reverse nowrap;
+ -ms-flex-flow: column-reverse nowrap;
+ flex-flow: column-reverse nowrap; }
+ .menu-bar.icon-bottom > li > a > img, .menu-bar.icon-bottom > li > a > .iconic {
+ margin: 1rem 0 0 0; }
+ .menu-bar.icon-left > li > img, .menu-bar.icon-left > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.icon-left > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .menu-bar.icon-left > li > a > img, .menu-bar.icon-left > li > a > .iconic {
+ margin: 0 1rem 0 0; }
+ .menu-bar.small-icon-top > li > img, .menu-bar.small-icon-top > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.small-icon-top > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.small-icon-top > li > a > img, .menu-bar.small-icon-top > li > a > .iconic {
+ margin: 0 0 1rem 0; }
+ .menu-bar.small-icon-right > li > img, .menu-bar.small-icon-right > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.small-icon-right > li > a {
+ -webkit-flex-flow: row-reverse nowrap;
+ -ms-flex-flow: row-reverse nowrap;
+ flex-flow: row-reverse nowrap; }
+ .menu-bar.small-icon-right > li > a > img, .menu-bar.small-icon-right > li > a > .iconic {
+ margin: 0 0 0 1rem; }
+ .menu-bar.small-icon-bottom > li > img, .menu-bar.small-icon-bottom > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.small-icon-bottom > li > a {
+ -webkit-flex-flow: column-reverse nowrap;
+ -ms-flex-flow: column-reverse nowrap;
+ flex-flow: column-reverse nowrap; }
+ .menu-bar.small-icon-bottom > li > a > img, .menu-bar.small-icon-bottom > li > a > .iconic {
+ margin: 1rem 0 0 0; }
+ .menu-bar.small-icon-left > li > img, .menu-bar.small-icon-left > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.small-icon-left > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .menu-bar.small-icon-left > li > a > img, .menu-bar.small-icon-left > li > a > .iconic {
+ margin: 0 1rem 0 0; }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-icon-top > li > img, .menu-bar.medium-icon-top > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.medium-icon-top > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.medium-icon-top > li > a > img, .menu-bar.medium-icon-top > li > a > .iconic {
+ margin: 0 0 1rem 0; } }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-icon-right > li > img, .menu-bar.medium-icon-right > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.medium-icon-right > li > a {
+ -webkit-flex-flow: row-reverse nowrap;
+ -ms-flex-flow: row-reverse nowrap;
+ flex-flow: row-reverse nowrap; }
+ .menu-bar.medium-icon-right > li > a > img, .menu-bar.medium-icon-right > li > a > .iconic {
+ margin: 0 0 0 1rem; } }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-icon-bottom > li > img, .menu-bar.medium-icon-bottom > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.medium-icon-bottom > li > a {
+ -webkit-flex-flow: column-reverse nowrap;
+ -ms-flex-flow: column-reverse nowrap;
+ flex-flow: column-reverse nowrap; }
+ .menu-bar.medium-icon-bottom > li > a > img, .menu-bar.medium-icon-bottom > li > a > .iconic {
+ margin: 1rem 0 0 0; } }
+ @media only screen and (min-width: 40em) {
+ .menu-bar.medium-icon-left > li > img, .menu-bar.medium-icon-left > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.medium-icon-left > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .menu-bar.medium-icon-left > li > a > img, .menu-bar.medium-icon-left > li > a > .iconic {
+ margin: 0 1rem 0 0; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-icon-top > li > img, .menu-bar.large-icon-top > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.large-icon-top > li > a {
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .menu-bar.large-icon-top > li > a > img, .menu-bar.large-icon-top > li > a > .iconic {
+ margin: 0 0 1rem 0; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-icon-right > li > img, .menu-bar.large-icon-right > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.large-icon-right > li > a {
+ -webkit-flex-flow: row-reverse nowrap;
+ -ms-flex-flow: row-reverse nowrap;
+ flex-flow: row-reverse nowrap; }
+ .menu-bar.large-icon-right > li > a > img, .menu-bar.large-icon-right > li > a > .iconic {
+ margin: 0 0 0 1rem; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-icon-bottom > li > img, .menu-bar.large-icon-bottom > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.large-icon-bottom > li > a {
+ -webkit-flex-flow: column-reverse nowrap;
+ -ms-flex-flow: column-reverse nowrap;
+ flex-flow: column-reverse nowrap; }
+ .menu-bar.large-icon-bottom > li > a > img, .menu-bar.large-icon-bottom > li > a > .iconic {
+ margin: 1rem 0 0 0; } }
+ @media only screen and (min-width: 75em) {
+ .menu-bar.large-icon-left > li > img, .menu-bar.large-icon-left > li > .iconic {
+ margin: 0;
+ width: 25px;
+ height: 25px; }
+ .menu-bar.large-icon-left > li > a {
+ -webkit-flex-flow: row nowrap;
+ -ms-flex-flow: row nowrap;
+ flex-flow: row nowrap;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center; }
+ .menu-bar.large-icon-left > li > a > img, .menu-bar.large-icon-left > li > a > .iconic {
+ margin: 0 1rem 0 0; } }
+ .menu-bar.label-side > li {
+ position: relative; }
+ .menu-bar.label-side > li > a {
+ padding-right: 3.2rem; }
+ .menu-bar.label-side .menu-bar-label {
+ display: block;
+ font-size: 0.9rem;
+ width: 1.2rem;
+ height: 1.2rem;
+ line-height: 1.2rem;
+ text-align: center;
+ border-radius: 1000px;
+ background: red;
+ color: #fff;
+ position: absolute;
+ pointer-events: none;
+ right: 1rem;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%); }
+ .menu-bar.label-corner > li {
+ position: relative; }
+ .menu-bar.label-corner > li > a {
+ padding-right: 3.2rem; }
+ .menu-bar.label-corner .menu-bar-label {
+ display: block;
+ font-size: 0.9rem;
+ width: 1.2rem;
+ height: 1.2rem;
+ line-height: 1.2rem;
+ text-align: center;
+ border-radius: 1000px;
+ background: red;
+ color: #fff;
+ position: absolute;
+ pointer-events: none;
+ right: 1rem;
+ top: 1rem; }
+ .menu-bar.primary {
+ background: #00558b; }
+ .menu-bar.primary > li > a {
+ color: #fff; }
+ .menu-bar.primary > li > a:hover {
+ background: #0065a5;
+ color: #fff; }
+ .menu-bar.primary .is-active > a {
+ background: #0065a5;
+ color: #fff; }
+ .menu-bar.primary .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-bar.primary .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-bar.dark {
+ background: #232323; }
+ .menu-bar.dark > li > a {
+ color: #fff; }
+ .menu-bar.dark > li > a:hover {
+ background: #323232;
+ color: #fff; }
+ .menu-bar.dark .is-active > a {
+ background: #323232;
+ color: #fff; }
+ .menu-bar.dark .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-bar.dark .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-bar > li.title {
+ padding: 1rem;
+ cursor: default;
+ font-weight: bold; }
+
+.menu-group {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap; }
+ @media only screen and (min-width: 40em) {
+ .menu-group {
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap; } }
+ .menu-group > .menu-group-left, .menu-group > .menu-group-right {
+ -webkit-flex: 1 1 100%;
+ -ms-flex: 1 1 100%;
+ flex: 1 1 100%; }
+ @media only screen and (min-width: 40em) {
+ .menu-group > .menu-group-left, .menu-group > .menu-group-right {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; } }
+ .menu-group .menu-bar {
+ margin: 0; }
+ .menu-group .menu-bar > li {
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto; }
+ .menu-group.primary {
+ background-color: #00558b; }
+ .menu-group.primary .menu-bar {
+ background: #00558b; }
+ .menu-group.primary .menu-bar > li > a {
+ color: #fff; }
+ .menu-group.primary .menu-bar > li > a:hover {
+ background: #0065a5;
+ color: #fff; }
+ .menu-group.primary .menu-bar .is-active > a {
+ background: #0065a5;
+ color: #fff; }
+ .menu-group.primary .menu-bar .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-group.primary .menu-bar .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-group.dark {
+ background-color: #232323; }
+ .menu-group.dark .menu-bar {
+ background: #232323; }
+ .menu-group.dark .menu-bar > li > a {
+ color: #fff; }
+ .menu-group.dark .menu-bar > li > a:hover {
+ background: #323232;
+ color: #fff; }
+ .menu-group.dark .menu-bar .is-active > a {
+ background: #323232;
+ color: #fff; }
+ .menu-group.dark .menu-bar .iconic * {
+ fill: #fff;
+ stroke: #fff; }
+ .menu-group.dark .menu-bar .iconic *.iconic-property-accent {
+ fill: #fff;
+ stroke: #fff; }
+
+/*
+ MODAL
+ -----
+
+ The humble modal hides off-canvas until summoned with an fa-open directive. Modals appear over an overlay that darkens the rest of the page, and have a maxmimum width. You can construct a grid inside a modal, or attach panels to it.
+
+ Note that the modal overlay is hardcoded into the CSS, because whether or not you build your modal semantically, the overlay is always required and will always look the same.
+*/
+.modal {
+ position: relative;
+ z-index: 1001;
+ background: #fff;
+ -webkit-flex: 0 0 auto;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto;
+ width: 100%;
+ height: 100vh;
+ max-height: 100%;
+ overflow: hidden;
+ padding: 1rem; }
+ @media only screen and (min-width: 40em) {
+ .modal {
+ height: auto;
+ max-width: 600px; } }
+ .modal .grid-content, .modal .grid-block {
+ margin: 0; }
+ .modal .close-button, .modal [fa-close] {
+ z-index: 1001; }
+
+.modal {
+ max-width: 600px;
+ border-radius: 0px; }
+ .tiny > .modal {
+ max-width: 300px; }
+ .small > .modal {
+ max-width: 500px; }
+ .large > .modal {
+ max-width: 800px; }
+ .dialog > .modal {
+ height: auto; }
+ .collapse > .modal {
+ padding: 0; }
+
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ background-color: rgba(51, 51, 51, 0.7);
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+ .modal-overlay.is-active {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex; }
+
+@-webkit-keyframes shake {
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
+ -webkit-transform: translateX(7%);
+ transform: translateX(7%); }
+
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
+ -webkit-transform: translateX(-7%);
+ transform: translateX(-7%); }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0); } }
+
+@keyframes shake {
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
+ -webkit-transform: translateX(7%);
+ transform: translateX(7%); }
+
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
+ -webkit-transform: translateX(-7%);
+ transform: translateX(-7%); }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0); } }
+
+@-webkit-keyframes spin-cw {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+@keyframes spin-cw {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+@-webkit-keyframes spin-ccw {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+
+ 100% {
+ -webkit-transform: rotate(-360deg);
+ transform: rotate(-360deg); } }
+
+@keyframes spin-ccw {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+
+ 100% {
+ -webkit-transform: rotate(-360deg);
+ transform: rotate(-360deg); } }
+
+@-webkit-keyframes wiggle {
+ 40%, 50%, 60% {
+ -webkit-transform: rotate(7deg);
+ transform: rotate(7deg); }
+
+ 35%, 45%, 55%, 65% {
+ -webkit-transform: rotate(-7deg);
+ transform: rotate(-7deg); }
+
+ 0%, 30%, 70%, 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+@keyframes wiggle {
+ 40%, 50%, 60% {
+ -webkit-transform: rotate(7deg);
+ transform: rotate(7deg); }
+
+ 35%, 45%, 55%, 65% {
+ -webkit-transform: rotate(-7deg);
+ transform: rotate(-7deg); }
+
+ 0%, 30%, 70%, 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+/*
+ Transitions
+ */
+.slideInDown.ng-enter, .slideInDown.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%); }
+.slideInDown.ng-enter.ng-enter-active, .slideInDown.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+
+.slideInLeft.ng-enter, .slideInLeft.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(100%);
+ transform: translateX(100%); }
+.slideInLeft.ng-enter.ng-enter-active, .slideInLeft.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+
+.slideInUp.ng-enter, .slideInUp.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%); }
+.slideInUp.ng-enter.ng-enter-active, .slideInUp.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+
+.slideInRight.ng-enter, .slideInRight.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%); }
+.slideInRight.ng-enter.ng-enter-active, .slideInRight.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+
+.slideOutBottom.ng-leave, .slideOutBottom.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+.slideOutBottom.ng-leave.ng-leave-active, .slideOutBottom.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%); }
+
+.slideOutRight.ng-leave, .slideOutRight.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+.slideOutRight.ng-leave.ng-leave-active, .slideOutRight.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: translateX(100%);
+ transform: translateX(100%); }
+
+.slideOutUp.ng-leave, .slideOutUp.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+.slideOutUp.ng-leave.ng-leave-active, .slideOutUp.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%); }
+
+.slideOutLeft.ng-leave, .slideOutLeft.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateX(0) translateY(0);
+ transform: translateX(0) translateY(0); }
+.slideOutLeft.ng-leave.ng-leave-active, .slideOutLeft.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%); }
+
+.fadeIn.ng-enter, .fadeIn.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: opacity;
+ opacity: 0; }
+.fadeIn.ng-enter.ng-enter-active, .fadeIn.ng-hide-remove.ng-hide-remove-active {
+ opacity: 1; }
+
+.fadeOut.ng-leave, .fadeOut.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: opacity;
+ opacity: 1; }
+.fadeOut.ng-leave.ng-leave-active, .fadeOut.ng-hide-add.ng-hide-add-active {
+ opacity: 0; }
+
+.hingeInFromTop.ng-enter, .hingeInFromTop.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ -webkit-transform-origin: top;
+ transform-origin: top;
+ opacity: 0; }
+.hingeInFromTop.ng-enter.ng-enter-active, .hingeInFromTop.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeInFromRight.ng-enter, .hingeInFromRight.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ -webkit-transform-origin: right;
+ transform-origin: right;
+ opacity: 0; }
+.hingeInFromRight.ng-enter.ng-enter-active, .hingeInFromRight.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeInFromBottom.ng-enter, .hingeInFromBottom.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateX(90deg);
+ transform: perspective(2000px) rotateX(90deg);
+ -webkit-transform-origin: bottom;
+ transform-origin: bottom;
+ opacity: 0; }
+.hingeInFromBottom.ng-enter.ng-enter-active, .hingeInFromBottom.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeInFromLeft.ng-enter, .hingeInFromLeft.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateY(90deg);
+ transform: perspective(2000px) rotateY(90deg);
+ -webkit-transform-origin: left;
+ transform-origin: left;
+ opacity: 0; }
+.hingeInFromLeft.ng-enter.ng-enter-active, .hingeInFromLeft.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeInFromMiddleX.ng-enter, .hingeInFromMiddleX.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ opacity: 0; }
+.hingeInFromMiddleX.ng-enter.ng-enter-active, .hingeInFromMiddleX.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeInFromMiddleY.ng-enter, .hingeInFromMiddleY.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ opacity: 0; }
+.hingeInFromMiddleY.ng-enter.ng-enter-active, .hingeInFromMiddleY.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+.hingeOutFromTop.ng-leave, .hingeOutFromTop.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: top;
+ transform-origin: top;
+ opacity: 1; }
+.hingeOutFromTop.ng-leave.ng-leave-active, .hingeOutFromTop.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ opacity: 0; }
+
+.hingeOutFromRight.ng-leave, .hingeOutFromRight.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right;
+ transform-origin: right;
+ opacity: 1; }
+.hingeOutFromRight.ng-leave.ng-leave-active, .hingeOutFromRight.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ opacity: 0; }
+
+.hingeOutFromBottom.ng-leave, .hingeOutFromBottom.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: bottom;
+ transform-origin: bottom;
+ opacity: 1; }
+.hingeOutFromBottom.ng-leave.ng-leave-active, .hingeOutFromBottom.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateX(90deg);
+ transform: perspective(2000px) rotateX(90deg);
+ opacity: 0; }
+
+.hingeOutFromLeft.ng-leave, .hingeOutFromLeft.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: left;
+ transform-origin: left;
+ opacity: 1; }
+.hingeOutFromLeft.ng-leave.ng-leave-active, .hingeOutFromLeft.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateY(90deg);
+ transform: perspective(2000px) rotateY(90deg);
+ opacity: 0; }
+
+.hingeOutFromMiddleX.ng-leave, .hingeOutFromMiddleX.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ opacity: 1; }
+.hingeOutFromMiddleX.ng-leave.ng-leave-active, .hingeOutFromMiddleX.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ opacity: 0; }
+
+.hingeOutFromMiddleY.ng-leave, .hingeOutFromMiddleY.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ opacity: 1; }
+.hingeOutFromMiddleY.ng-leave.ng-leave-active, .hingeOutFromMiddleY.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ opacity: 0; }
+
+.zoomIn.ng-enter, .zoomIn.ng-hide-remove {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, property;
+ transition-property: transform, property;
+ -webkit-transform: scale(1.5);
+ transform: scale(1.5);
+ opacity: 0; }
+.zoomIn.ng-enter.ng-enter-active, .zoomIn.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ opacity: 1; }
+
+.zoomOut.ng-leave, .zoomOut.ng-hide-add {
+ transition-duration: 500ms;
+ transition-timing-function: ease;
+ transition-delay: 0;
+ transition-property: -webkit-transform, property;
+ transition-property: transform, property;
+ -webkit-transform: scale(0.5);
+ transform: scale(0.5);
+ opacity: 1; }
+.zoomOut.ng-leave.ng-leave-active, .zoomOut.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ opacity: 0; }
+
+.spinIn.ng-enter, .spinIn.ng-hide-remove {
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(-270deg);
+ transform: rotate(-270deg);
+ opacity: 0; }
+.spinIn.ng-enter.ng-enter-active, .spinIn.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+
+.spinOut.ng-leave, .spinOut.ng-hide-add {
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+.spinOut.ng-leave.ng-leave-active, .spinOut.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg);
+ opacity: 0; }
+
+.spinInCCW.ng-enter, .spinInCCW.ng-hide-remove {
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg);
+ opacity: 0; }
+.spinInCCW.ng-enter.ng-enter-active, .spinInCCW.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+
+.spinOutCCW.ng-leave, .spinOutCCW.ng-hide-add {
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+.spinOutCCW.ng-leave.ng-leave-active, .spinOutCCW.ng-hide-add.ng-hide-add-active {
+ -webkit-transform: rotate(-270deg);
+ transform: rotate(-270deg);
+ opacity: 0; }
+
+/*
+ Transition modifiers
+ */
+.slow {
+ transition-duration: 750ms !important; }
+
+.fast {
+ transition-duration: 250ms !important; }
+
+.linear {
+ transition-timing-function: linear !important; }
+
+.ease {
+ transition-timing-function: ease !important; }
+
+.easeIn {
+ transition-timing-function: ease-in !important; }
+
+.easeOut {
+ transition-timing-function: ease-out !important; }
+
+.easeInOut {
+ transition-timing-function: ease-in-out !important; }
+
+.bounceIn {
+ transition-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important; }
+
+.bounceOut {
+ transition-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important; }
+
+.bounceInOut {
+ transition-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important; }
+
+.delay {
+ transition-delay: 300ms !important; }
+
+.long-delay {
+ transition-delay: 700ms !important; }
+
+/*
+ Animations
+ */
+.shake {
+ -webkit-animation-name: shake;
+ animation-name: shake;
+ -webkit-animation-duration: 500ms;
+ animation-duration: 500ms;
+ -webkit-animation-timing-function: ease;
+ animation-timing-function: ease;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-animation-delay: 0;
+ animation-delay: 0; }
+
+.spin-cw {
+ -webkit-animation-name: spin-cw;
+ animation-name: spin-cw;
+ -webkit-animation-duration: 500ms;
+ animation-duration: 500ms;
+ -webkit-animation-timing-function: ease;
+ animation-timing-function: ease;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-animation-delay: 0;
+ animation-delay: 0; }
+
+.spin-ccw {
+ -webkit-animation-name: spin-ccw;
+ animation-name: spin-ccw;
+ -webkit-animation-duration: 500ms;
+ animation-duration: 500ms;
+ -webkit-animation-timing-function: ease;
+ animation-timing-function: ease;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-animation-delay: 0;
+ animation-delay: 0; }
+
+.wiggle {
+ -webkit-animation-name: wiggle;
+ animation-name: wiggle;
+ -webkit-animation-duration: 500ms;
+ animation-duration: 500ms;
+ -webkit-animation-timing-function: ease;
+ animation-timing-function: ease;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-animation-delay: 0;
+ animation-delay: 0; }
+
+/*
+ Animation modifiers
+ */
+.shake.infinite, .spin-cw.infinite, .spin-ccw.infinite, .wiggle.infinite {
+ -webkit-animation-iteration-count: infinite;
+ animation-iteration-count: infinite; }
+.shake.linear, .spin-cw.linear, .spin-ccw.linear, .wiggle.linear {
+ -webkit-animation-timing-function: linear !important;
+ animation-timing-function: linear !important; }
+.shake.ease, .spin-cw.ease, .spin-ccw.ease, .wiggle.ease {
+ -webkit-animation-timing-function: ease !important;
+ animation-timing-function: ease !important; }
+.shake.easeIn, .spin-cw.easeIn, .spin-ccw.easeIn, .wiggle.easeIn {
+ -webkit-animation-timing-function: ease-in !important;
+ animation-timing-function: ease-in !important; }
+.shake.easeOut, .spin-cw.easeOut, .spin-ccw.easeOut, .wiggle.easeOut {
+ -webkit-animation-timing-function: ease-out !important;
+ animation-timing-function: ease-out !important; }
+.shake.easeInOut, .spin-cw.easeInOut, .spin-ccw.easeInOut, .wiggle.easeInOut {
+ -webkit-animation-timing-function: ease-in-out !important;
+ animation-timing-function: ease-in-out !important; }
+.shake.bounceIn, .spin-cw.bounceIn, .spin-ccw.bounceIn, .wiggle.bounceIn {
+ -webkit-animation-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important;
+ animation-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important; }
+.shake.bounceOut, .spin-cw.bounceOut, .spin-ccw.bounceOut, .wiggle.bounceOut {
+ -webkit-animation-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important;
+ animation-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important; }
+.shake.bounceInOut, .spin-cw.bounceInOut, .spin-ccw.bounceInOut, .wiggle.bounceInOut {
+ -webkit-animation-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important;
+ animation-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important; }
+.shake.slow, .spin-cw.slow, .spin-ccw.slow, .wiggle.slow {
+ -webkit-animation-duration: 750ms !important;
+ animation-duration: 750ms !important; }
+.shake.fast, .spin-cw.fast, .spin-ccw.fast, .wiggle.fast {
+ -webkit-animation-duration: 250ms !important;
+ animation-duration: 250ms !important; }
+.shake.delay, .spin-cw.delay, .spin-ccw.delay, .wiggle.delay {
+ -webkit-animation-delay: 300ms !important;
+ animation-delay: 300ms !important; }
+.shake.long-delay, .spin-cw.long-delay, .spin-ccw.long-delay, .wiggle.long-delay {
+ -webkit-animation-delay: 700ms !important;
+ animation-delay: 700ms !important; }
+
+.stagger {
+ transition-delay: 150ms;
+ transition-duration: 0; }
+
+.stort-stagger {
+ transition-delay: 150ms;
+ transition-duration: 0; }
+
+.long-stagger {
+ transition-delay: 150ms;
+ transition-duration: 0; }
+
+.position-absolute {
+ overflow: hidden;
+ position: relative; }
+
+.ui-animation.ng-enter-active, .ui-animation.ng-leave-active {
+ position: absolute !important;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform-style: preserve-3d;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0; }
+
+/*
+ NOTIFICATION
+ ------------
+
+ An alert that pins to the corner of the screen when triggered by JavaScript. It can be set to disappear after a certain period of time, or to stay put until the user clicks on it. A custom action can be asigned to a notification as well.
+
+ Optionally, the notifications directive can also tap into the browser's native notification support, if it exists.
+*/
+.notification, .static-notification {
+ z-index: 1000;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ position: relative;
+ margin-top: .5rem;
+ margin-bottom: .5rem;
+ display: none; }
+ .notification h1, .static-notification h1 {
+ font-size: 1.25em;
+ margin: 0; }
+ .notification p, .static-notification p {
+ margin: 0; }
+ .is-active.notification, .is-active.static-notification {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex; }
+ .notification .close-button, .static-notification .close-button {
+ color: white; }
+
+.notification-container {
+ z-index: 3000;
+ position: fixed;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column; }
+
+/*
+ CSS Output
+*/
+.notification {
+ background: #00558b;
+ padding: 1rem;
+ border-radius: 4px; }
+ .notification, .notification h1, .notification h2, .notification h3, .notification h4, .notification h5, .notification h6 {
+ color: white; }
+ .notification.success {
+ background: #43AC6A;
+ padding: 1rem;
+ border-radius: 4px; }
+ .notification.success, .notification.success h1, .notification.success h2, .notification.success h3, .notification.success h4, .notification.success h5, .notification.success h6 {
+ color: white; }
+ .notification.warning {
+ background: #F08A24;
+ padding: 1rem;
+ border-radius: 4px; }
+ .notification.warning, .notification.warning h1, .notification.warning h2, .notification.warning h3, .notification.warning h4, .notification.warning h5, .notification.warning h6 {
+ color: white; }
+ .notification.alert {
+ background: #F04124;
+ padding: 1rem;
+ border-radius: 4px; }
+ .notification.alert, .notification.alert h1, .notification.alert h2, .notification.alert h3, .notification.alert h4, .notification.alert h5, .notification.alert h6 {
+ color: white; }
+ .notification.dark {
+ background: #232323;
+ padding: 1rem;
+ border-radius: 4px; }
+ .notification.dark, .notification.dark h1, .notification.dark h2, .notification.dark h3, .notification.dark h4, .notification.dark h5, .notification.dark h6 {
+ color: #fff; }
+
+.static-notification {
+ background: #00558b;
+ padding: 1rem;
+ border-radius: 4px;
+ position: fixed !important; }
+ .static-notification, .static-notification h1, .static-notification h2, .static-notification h3, .static-notification h4, .static-notification h5, .static-notification h6 {
+ color: white; }
+ .static-notification.top-right {
+ width: 25rem;
+ right: 1rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.top-right {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.top-left {
+ width: 25rem;
+ left: 1rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.top-left {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.top-middle {
+ width: 25rem;
+ left: 50%;
+ margin-left: -12.5rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.top-middle {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.bottom-right {
+ width: 25rem;
+ right: 1rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.bottom-right {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.bottom-left {
+ width: 25rem;
+ left: 1rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.bottom-left {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.bottom-middle {
+ width: 25rem;
+ left: 50%;
+ margin-left: -12.5rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .static-notification.bottom-middle {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .static-notification.success {
+ background: #43AC6A;
+ padding: 1rem;
+ border-radius: 4px; }
+ .static-notification.success, .static-notification.success h1, .static-notification.success h2, .static-notification.success h3, .static-notification.success h4, .static-notification.success h5, .static-notification.success h6 {
+ color: white; }
+ .static-notification.warning {
+ background: #F08A24;
+ padding: 1rem;
+ border-radius: 4px; }
+ .static-notification.warning, .static-notification.warning h1, .static-notification.warning h2, .static-notification.warning h3, .static-notification.warning h4, .static-notification.warning h5, .static-notification.warning h6 {
+ color: white; }
+ .static-notification.alert {
+ background: #F04124;
+ padding: 1rem;
+ border-radius: 4px; }
+ .static-notification.alert, .static-notification.alert h1, .static-notification.alert h2, .static-notification.alert h3, .static-notification.alert h4, .static-notification.alert h5, .static-notification.alert h6 {
+ color: white; }
+ .static-notification.dark {
+ background: #232323;
+ padding: 1rem;
+ border-radius: 4px; }
+ .static-notification.dark, .static-notification.dark h1, .static-notification.dark h2, .static-notification.dark h3, .static-notification.dark h4, .static-notification.dark h5, .static-notification.dark h6 {
+ color: #fff; }
+
+.notification-container {
+ width: 25rem;
+ right: 1rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.top-right {
+ width: 25rem;
+ right: 1rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.top-right {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.top-left {
+ width: 25rem;
+ left: 1rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.top-left {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.top-middle {
+ width: 25rem;
+ left: 50%;
+ margin-left: -12.5rem;
+ top: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.top-middle {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.bottom-right {
+ width: 25rem;
+ right: 1rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.bottom-right {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.bottom-left {
+ width: 25rem;
+ left: 1rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.bottom-left {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+ .notification-container.bottom-middle {
+ width: 25rem;
+ left: 50%;
+ margin-left: -12.5rem;
+ top: auto;
+ bottom: 1rem; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .notification-container.bottom-middle {
+ width: auto;
+ left: 1rem;
+ right: 1rem;
+ margin-left: 0; } }
+
+.notification-icon {
+ -webkit-flex: 0 0 60px;
+ -ms-flex: 0 0 60px;
+ flex: 0 0 60px;
+ margin-right: 1rem;
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start; }
+ .notification-icon img {
+ width: 100%;
+ height: auto; }
+
+.notification-content {
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1; }
+
+/*
+ Off-canvas menu
+ ---------------
+
+ A generic container that stays fixed to the left, top, right, or bottom of the screen, and is summoned when needed. When an off-canvas panel is open, the app frame shifts over to reveal the menu.
+*/
+.off-canvas {
+ position: fixed;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+ transition: -webkit-transform 0.25s ease-out;
+ transition: transform 0.25s ease-out;
+ z-index: 2; }
+ .is-active.off-canvas {
+ -webkit-transform: translate(0, 0) !important;
+ transform: translate(0, 0) !important; }
+ .off-canvas ~ .grid-frame {
+ -webkit-transform: translate(0, 0, 0);
+ transform: translate(0, 0, 0);
+ transition: -webkit-transform 0.25s ease-out;
+ transition: transform 0.25s ease-out;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ background: white; }
+
+.off-canvas {
+ /*
+ Get shadow values for later use
+ */
+ /*
+ Sizing
+ */
+ width: 250px;
+ height: 100%;
+ /*
+ Positioning
+ */
+ top: 0;
+ left: 0;
+ box-shadow: inset -3px 0 10px rgba(0, 0, 0, 0.25);
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%);
+ background: #fff;
+ color: #000; }
+ .off-canvas.is-active ~ .grid-frame {
+ -webkit-transform: translateX(250px) !important;
+ transform: translateX(250px) !important; }
+ .off-canvas.top {
+ /*
+ Get shadow values for later use
+ */
+ /*
+ Sizing
+ */
+ height: 250px;
+ width: 100%;
+ /*
+ Positioning
+ */
+ top: 0;
+ left: 0;
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%);
+ box-shadow: inset 0 -3px 10px rgba(0, 0, 0, 0.25); }
+ .off-canvas.top.is-active ~ .grid-frame {
+ -webkit-transform: translateY(250px) !important;
+ transform: translateY(250px) !important; }
+ .off-canvas.right {
+ /*
+ Get shadow values for later use
+ */
+ /*
+ Sizing
+ */
+ width: 250px;
+ height: 100%;
+ /*
+ Positioning
+ */
+ left: auto;
+ top: 0;
+ right: 0;
+ box-shadow: inset 3px 0 10px rgba(0, 0, 0, 0.25);
+ -webkit-transform: translateX(100%);
+ transform: translateX(100%); }
+ .off-canvas.right.is-active ~ .grid-frame {
+ -webkit-transform: translateX(-250px) !important;
+ transform: translateX(-250px) !important; }
+ .off-canvas.bottom {
+ /*
+ Get shadow values for later use
+ */
+ /*
+ Sizing
+ */
+ height: 250px;
+ width: 100%;
+ /*
+ Positioning
+ */
+ top: auto;
+ bottom: 0;
+ left: 0;
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%);
+ box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.25); }
+ .off-canvas.bottom.is-active ~ .grid-frame {
+ -webkit-transform: translateY(-250px) !important;
+ transform: translateY(-250px) !important; }
+ .off-canvas.left {
+ /*
+ Get shadow values for later use
+ */
+ /*
+ Sizing
+ */
+ width: 250px;
+ height: 100%;
+ /*
+ Positioning
+ */
+ top: 0;
+ left: 0;
+ box-shadow: inset -3px 0 10px rgba(0, 0, 0, 0.25);
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%); }
+ .off-canvas.left.is-active ~ .grid-frame {
+ -webkit-transform: translateX(250px) !important;
+ transform: translateX(250px) !important; }
+ .off-canvas.detached {
+ z-index: 0;
+ box-shadow: none; }
+ .off-canvas.detached, .off-canvas.detached.is-active {
+ -webkit-transform: none;
+ transform: none; }
+ .off-canvas.detached ~ .grid-frame {
+ z-index: 1;
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.5); }
+ .off-canvas.primary {
+ background: #00558b;
+ color: #fff; }
+ .off-canvas.dark {
+ background: #232323;
+ color: #fff; }
+
+/*
+ POPUP
+ -----
+
+ A floating container that can anchor to any other on-screen element, and contain any content, including grid blocks or panels.
+*/
+.popup {
+ position: absolute;
+ z-index: 1000;
+ opacity: 0;
+ overflow: hidden;
+ transition: opacity 0.25s ease-out;
+ pointer-events: none; }
+ .tether-enabled.popup {
+ opacity: 1;
+ pointer-events: auto; }
+
+.popup {
+ width: 18.75rem;
+ background: #fff;
+ border-radius: 0;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
+ border: 0; }
+ .popup.dark {
+ background: #232323;
+ border-radius: 0;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
+ border: 0; }
+ .popup.primary {
+ background: #00558b;
+ border-radius: 0;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
+ border: 0; }
+
+/*
+ SWITCH
+ ------
+*/
+.switch {
+ position: relative;
+ overflow: hidden;
+ display: inline-block; }
+ .switch > input {
+ position: absolute;
+ left: -9999px;
+ outline: none; }
+ .switch > label {
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ display: block;
+ width: 100%;
+ height: 100%;
+ cursor: pointer;
+ margin: 0; }
+ .switch > label::after {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0; }
+
+/*
+ Defines the dimmensions of the switch.
+
+ $width - width of the switch.
+ $height - height of the switch.
+*/
+.switch {
+ width: 3.125rem;
+ height: 2rem;
+ border-radius: 9999px; }
+ .switch > label::after {
+ width: 2rem;
+ height: 2rem; }
+ .switch input:checked + label::after {
+ left: 1.125rem; }
+ .switch > label {
+ background: #ccc; }
+ .switch > label::after {
+ background: white;
+ border-radius: 9999px;
+ transition: left 0.15s ease-out;
+ border: 4px solid #ccc; }
+ .switch input:checked + label {
+ background: #00558b;
+ margin: 0; }
+ .switch input:checked + label::after {
+ border-color: #00558b; }
+ .switch.small {
+ width: 2.5rem;
+ height: 1.625rem; }
+ .switch.small > label::after {
+ width: 1.625rem;
+ height: 1.625rem; }
+ .switch.small input:checked + label::after {
+ left: 0.875rem; }
+ .switch.large {
+ width: 3.75rem;
+ height: 2.375rem; }
+ .switch.large > label::after {
+ width: 2.375rem;
+ height: 2.375rem; }
+ .switch.large input:checked + label::after {
+ left: 1.375rem; }
+
+/*
+ TABS
+ ----
+*/
+.tabs {
+ /*
+ Container styles
+ */
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ background: transparent;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap; }
+ .tabs.vertical {
+ /*
+ Container styles
+ */
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ background: transparent;
+ -webkit-flex-flow: column nowrap;
+ -ms-flex-flow: column nowrap;
+ flex-flow: column nowrap; }
+ .tabs .tab-item {
+ background: #f3f3f3;
+ padding: 1rem;
+ line-height: 1;
+ margin: 0;
+ -webkit-flex: 0 1 auto;
+ -ms-flex: 0 1 auto;
+ flex: 0 1 auto;
+ cursor: pointer;
+ color: #000; }
+ .tabs .tab-item.is-active {
+ background: #ececec;
+ color: #000; }
+ .tabs .tab-item.is-active:hover {
+ background: #e7e7e7; }
+ .tabs .tab-item:hover {
+ background: #e7e7e7; }
+
+.tab-contents {
+ padding: 1rem; }
+ .tab-contents .tab-content {
+ display: none; }
+ .tab-contents .tab-content.is-active {
+ display: block; }
+
+/*
+ ACCORDION
+ ---------
+
+ The trusy accordion allows you to create a series of vertical tabs.
+*/
+.accordion {
+ border: 1px solid #cbcbcb; }
+
+.accordion-title {
+ padding: 1rem;
+ background: #f3f3f3;
+ color: #000;
+ line-height: 1;
+ cursor: pointer; }
+ .accordion-title:hover {
+ background: #e7e7e7; }
+ .is-active > .accordion-title {
+ background: #ececec;
+ color: #000; }
+
+.accordion-content {
+ padding: 1rem;
+ display: none; }
+ .is-active > .accordion-content {
+ display: block; }
+
+/*
+ TYPOGRAPHY
+ ----------
+
+ Includes typographic resets for many common elements, and a few helper classes.
+ - Headers
+ - Subheaders
+ - Lead paragraphs
+ - Ordered/unordered lists
+ - Code samples
+ - Anchors
+ - Dividers
+ - Blockquotes
+ - Acronyms
+*/
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, p, blockquote, th, td {
+ margin: 0;
+ padding: 0; }
+
+/* Default Link Styles */
+a {
+ color: #00558b;
+ text-decoration: none;
+ line-height: inherit; }
+ a[ui-sref] {
+ cursor: pointer; }
+ a:hover, a:focus {
+ color: #004978; }
+ a img {
+ border: none; }
+
+/* Default paragraph styles */
+p {
+ font-family: inherit;
+ font-weight: normal;
+ font-size: 1rem;
+ line-height: 1.6;
+ margin-bottom: 1.25rem;
+ text-rendering: optimizeLegibility; }
+ p.lead {
+ font-size: 1.21875rem;
+ line-height: 1.6; }
+ p aside {
+ font-size: 0.875rem;
+ line-height: 1.35;
+ font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, h4, h5, h6 {
+ font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+ font-weight: normal;
+ font-style: normal;
+ color: #222;
+ text-rendering: optimizeLegibility;
+ margin-top: 0.2rem;
+ margin-bottom: 0.5rem;
+ line-height: 1.4; }
+ h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
+ font-size: 60%;
+ color: #6f6f6f;
+ line-height: 0; }
+
+h1 {
+ font-size: 2.125rem; }
+
+h2 {
+ font-size: 1.6875rem; }
+
+h3 {
+ font-size: 1.375rem; }
+
+h4 {
+ font-size: 1.125rem; }
+
+h5 {
+ font-size: 1.125rem; }
+
+h6 {
+ font-size: 1rem; }
+
+.subheader {
+ line-height: 1.4;
+ color: #6f6f6f;
+ font-weight: normal;
+ margin-top: 0.2rem;
+ margin-bottom: 0.5rem; }
+
+hr {
+ border: solid #ddd;
+ border-width: 1px 0 0;
+ clear: both;
+ margin: 1.25rem 0 1.1875rem;
+ height: 0; }
+
+/* Helpful Typography Defaults */
+em, i {
+ font-style: italic;
+ line-height: inherit; }
+
+strong, b {
+ font-weight: bold;
+ line-height: inherit; }
+
+small {
+ font-size: 60%;
+ color: #6f6f6f;
+ line-height: inherit; }
+
+code {
+ font-family: Consolas, 'Liberation Mono', Courier, monospace;
+ font-weight: normal;
+ color: #464646;
+ background-color: #fbfbfb;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #e2e2e2;
+ padding: 0.125rem 0.3125rem 0.0625rem; }
+
+/* Lists */
+ul, ol, dl {
+ font-size: 1rem;
+ line-height: 1.6;
+ margin-bottom: 1.25rem;
+ list-style-position: outside;
+ font-family: inherit; }
+
+/* Lists */
+ul, ol {
+ margin-left: 1.1rem; }
+ ul li ul, ul li ol, ol li ul, ol li ol {
+ margin-left: 1.25rem;
+ margin-bottom: 0; }
+
+/* Lists without bullets */
+ul.no-bullet {
+ margin-left: 0; }
+ ul.no-bullet, ul.no-bullet li ul, ul.no-bullet li ol {
+ list-style-type: none; }
+
+/* Definition Lists */
+dl dt {
+ margin-bottom: 0.3rem;
+ font-weight: bold; }
+dl dd {
+ margin-bottom: 0.75rem; }
+
+/* Abbreviations */
+abbr, acronym {
+ text-transform: uppercase;
+ font-size: 90%;
+ color: #222;
+ border-bottom: 1px dotted #ddd;
+ cursor: help; }
+
+abbr {
+ text-transform: none; }
+
+/* Blockquotes */
+blockquote {
+ margin: 0 0 1.25rem;
+ padding: 0.5625rem 1.25rem 0 1.1875rem;
+ border-left: 1px solid #ddd; }
+ blockquote cite {
+ display: block;
+ font-size: 0.8125rem;
+ color: #555555; }
+ blockquote cite:before {
+ content: "\2014 \0020"; }
+ blockquote cite a, blockquote cite a:visited {
+ color: #555555; }
+
+blockquote, blockquote p {
+ line-height: 1.6;
+ color: #6f6f6f; }
+
+@media only screen and (min-width: 40em) {
+ h1, h2, h3, h4, h5, h6 {
+ line-height: 1.4; }
+ h1 {
+ font-size: 2.75rem; }
+ h2 {
+ font-size: 2.3125rem; }
+ h3 {
+ font-size: 1.6875rem; }
+ h4 {
+ font-size: 1.4375rem; }
+ h5 {
+ font-size: 1.125rem; }
+ h6 {
+ font-size: 1rem; } }
+
+/*
+ UTILITIES
+ ---------
+
+ Responsive helper classes to assist you in quickly doing basic formatting and layout.
+
+ Features:
+ - Vertical alignment
+ - Visibility
+ - Text alignment
+ - Floating
+*/
+.v-align {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+ .v-align .align-top {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start; }
+ .v-align .align-center {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center; }
+ .v-align .align-bottom {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end; }
+ .v-align .small-align-top {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start; }
+ .v-align .small-align-center {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center; }
+ .v-align .small-align-bottom {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end; }
+ @media only screen and (min-width: 40em) {
+ .v-align .medium-align-top {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start; } }
+ @media only screen and (min-width: 40em) {
+ .v-align .medium-align-center {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center; } }
+ @media only screen and (min-width: 40em) {
+ .v-align .medium-align-bottom {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end; } }
+ @media only screen and (min-width: 75em) {
+ .v-align .large-align-top {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start; } }
+ @media only screen and (min-width: 75em) {
+ .v-align .large-align-center {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center; } }
+ @media only screen and (min-width: 75em) {
+ .v-align .large-align-bottom {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end; } }
+
+.hide {
+ display: none !important; }
+
+.invisible {
+ visibility: hidden; }
+
+.hide-for-small:not(.ng-hide) {
+ display: block !important;
+ display: none !important; }
+.hide-for-small[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important;
+ display: none !important; }
+
+.show-for-small:not(.ng-hide) {
+ display: none !important;
+ display: block !important; }
+.show-for-small[class*="grid-block"]:not(.ng-hide) {
+ display: none !important;
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+
+.hide-for-small-only:not(.ng-hide) {
+ display: block !important; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .hide-for-small-only:not(.ng-hide) {
+ display: none !important; } }
+.hide-for-small-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .hide-for-small-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; } }
+
+.show-for-small-only:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .show-for-small-only:not(.ng-hide) {
+ display: block !important; } }
+.show-for-small-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .show-for-small-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.hide-for-medium:not(.ng-hide) {
+ display: block !important; }
+ @media only screen and (min-width: 40em) {
+ .hide-for-medium:not(.ng-hide) {
+ display: none !important; } }
+.hide-for-medium[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+ @media only screen and (min-width: 40em) {
+ .hide-for-medium[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; } }
+
+.show-for-medium:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 40em) {
+ .show-for-medium:not(.ng-hide) {
+ display: block !important; } }
+.show-for-medium[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 40em) {
+ .show-for-medium[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.hide-for-medium-only:not(.ng-hide) {
+ display: block !important; }
+ @media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .hide-for-medium-only:not(.ng-hide) {
+ display: none !important; } }
+.hide-for-medium-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+ @media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .hide-for-medium-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; } }
+
+.show-for-medium-only:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .show-for-medium-only:not(.ng-hide) {
+ display: block !important; } }
+.show-for-medium-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .show-for-medium-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.hide-for-large:not(.ng-hide) {
+ display: block !important; }
+ @media only screen and (min-width: 75em) {
+ .hide-for-large:not(.ng-hide) {
+ display: none !important; } }
+.hide-for-large[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+ @media only screen and (min-width: 75em) {
+ .hide-for-large[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; } }
+
+.show-for-large:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 75em) {
+ .show-for-large:not(.ng-hide) {
+ display: block !important; } }
+.show-for-large[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 75em) {
+ .show-for-large[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.hide-for-large-only:not(.ng-hide) {
+ display: block !important; }
+ @media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .hide-for-large-only:not(.ng-hide) {
+ display: none !important; } }
+.hide-for-large-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; }
+ @media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .hide-for-large-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; } }
+
+.show-for-large-only:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .show-for-large-only:not(.ng-hide) {
+ display: block !important; } }
+.show-for-large-only[class*="grid-block"]:not(.ng-hide) {
+ display: none !important; }
+ @media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .show-for-large-only[class*="grid-block"]:not(.ng-hide) {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+@media only screen and (orientation: portrait) {
+ .hide-for-portrait {
+ display: none !important; }
+ .hide-for-portrait[class*="grid-block"] {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.show-for-portrait {
+ display: none !important; }
+ @media only screen and (orientation: portrait) {
+ .show-for-portrait {
+ display: block !important; }
+ .show-for-portrait[class*="grid-block"] {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+@media only screen and (orientation: landscape) {
+ .hide-for-landscape {
+ display: none !important; }
+ .hide-for-landscape[class*="grid-block"] {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+.show-for-landscape {
+ display: none !important; }
+ @media only screen and (orientation: landscape) {
+ .show-for-landscape {
+ display: block !important; }
+ .show-for-landscape[class*="grid-block"] {
+ display: -webkit-flex !important;
+ display: -ms-flexbox !important;
+ display: flex !important; } }
+
+/*
+ Text alignment
+ */
+.text-left {
+ text-align: left; }
+
+.small-text-left {
+ text-align: left; }
+
+@media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .small-only-text-left {
+ text-align: left; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-text-left {
+ text-align: left; } }
+
+@media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .medium-only-text-left {
+ text-align: left; } }
+
+@media only screen and (min-width: 75em) {
+ .large-text-left {
+ text-align: left; } }
+
+@media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .large-only-text-left {
+ text-align: left; } }
+
+.text-right {
+ text-align: right; }
+
+.small-text-right {
+ text-align: right; }
+
+@media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .small-only-text-right {
+ text-align: right; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-text-right {
+ text-align: right; } }
+
+@media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .medium-only-text-right {
+ text-align: right; } }
+
+@media only screen and (min-width: 75em) {
+ .large-text-right {
+ text-align: right; } }
+
+@media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .large-only-text-right {
+ text-align: right; } }
+
+.text-center {
+ text-align: center; }
+
+.small-text-center {
+ text-align: center; }
+
+@media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .small-only-text-center {
+ text-align: center; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-text-center {
+ text-align: center; } }
+
+@media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .medium-only-text-center {
+ text-align: center; } }
+
+@media only screen and (min-width: 75em) {
+ .large-text-center {
+ text-align: center; } }
+
+@media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .large-only-text-center {
+ text-align: center; } }
+
+.text-justify {
+ text-align: justify; }
+
+.small-text-justify {
+ text-align: justify; }
+
+@media only screen and (min-width: 0em) and (max-width: 39.9375rem) {
+ .small-only-text-justify {
+ text-align: justify; } }
+
+@media only screen and (min-width: 40em) {
+ .medium-text-justify {
+ text-align: justify; } }
+
+@media only screen and (min-width: 40em) and (max-width: 74.9375rem) {
+ .medium-only-text-justify {
+ text-align: justify; } }
+
+@media only screen and (min-width: 75em) {
+ .large-text-justify {
+ text-align: justify; } }
+
+@media only screen and (min-width: 75em) and (max-width: 89.9375rem) {
+ .large-only-text-justify {
+ text-align: justify; } }
+
+/*
+ Floating
+ */
+.clearfix:before, .clearfix:after {
+ content: " ";
+ display: table; }
+.clearfix:after {
+ clear: both; }
+
+.float-left {
+ float: left; }
+
+.float-right {
+ float: right; }
+
+.float-none {
+ float: none; }
diff --git a/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.min.css b/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.min.css
new file mode 100755
index 0000000..2f93f18
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/css/foundation-apps.min.css
@@ -0,0 +1 @@
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}dfn{font-style:italic}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}meta.foundation-version{font-family:"1.1.0"}meta.foundation-mq{font-family:"small=0&medium=40rem&large=75rem&xlarge=90rem&xxlarge=120rem"}body,html{height:100%;font-size:100%}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{background:#fff;color:#222;padding:0;margin:0;font-family:"Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1;position:relative;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{max-width:100%;height:auto;-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}[ui-sref],[zf-close],[zf-open],[zf-toggle],a{cursor:pointer}#map_canvas embed,#map_canvas img,#map_canvas object,.map_canvas embed,.map_canvas img,.map_canvas object{max-width:none!important}.padding{padding:1rem}.iconic{width:1rem;height:1rem;vertical-align:middle}a>.iconic{margin-top:-2px;margin-right:.25rem}.iconic *,.iconic .iconic-property-accent,.iconic-color-primary *,.iconic-color-primary .iconic-property-accent,a>.iconic *,a>.iconic .iconic-property-accent{fill:#00558b;stroke:#00558b}.iconic-color-success *,.iconic-color-success .iconic-property-accent{fill:#43AC6A;stroke:#43AC6A}.iconic-color-warning *,.iconic-color-warning .iconic-property-accent{fill:#F08A24;stroke:#F08A24}.iconic-color-alert *,.iconic-color-alert .iconic-property-accent{fill:#F04124;stroke:#F04124}.iconic-color-dark *,.iconic-color-dark .iconic-property-accent{fill:#232323;stroke:#232323}.iconic-color-secondary *,.iconic-color-secondary .iconic-property-accent{fill:#f1f1f1;stroke:#f1f1f1}.action-sheet-container{position:relative;display:inline-block}.action-sheet-container .button{margin-left:0;margin-right:0}.action-sheet{position:fixed;left:0;z-index:1000;width:100%;padding:1rem;background:#fff;text-align:center;transition-property:-webkit-transform opacity;transition-property:transform opacity;transition-duration:.25s;transition-timing-function:ease-out;box-shadow:0 -3px 10px rgba(0,0,0,.25);bottom:0;-webkit-transform:translateY(100%);transform:translateY(100%)}.action-sheet.is-active{-webkit-transform:translateY(0);transform:translateY(0)}.action-sheet ul{margin:0 -1rem -1rem;list-style-type:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.action-sheet ul:first-child{margin-top:-1rem}.action-sheet ul:first-child li:first-child{border-top:0}.action-sheet ul a{display:block;padding:.8rem;line-height:1;color:#000;border-top:1px solid #ccc}.action-sheet ul a:hover{color:#000;background:#f2f2f2}.action-sheet ul .alert>a{color:#F04124}.action-sheet ul .disabled>a{pointer-events:none;color:#999}@media only screen and (min-width:40em){.action-sheet{position:absolute;left:50%;width:300px;border-radius:4px;opacity:0;pointer-events:none;box-shadow:0 0 10px rgba(0,0,0,.25);top:auto;bottom:0;-webkit-transform:translateX(-50%) translateY(110%);transform:translateX(-50%) translateY(110%)}.action-sheet.is-active{opacity:1;pointer-events:auto}.action-sheet::after,.action-sheet::before{content:'';position:absolute;left:50%;display:block;width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;margin-left:-10px}.action-sheet.is-active{-webkit-transform:translateX(-50%) translateY(100%);transform:translateX(-50%) translateY(100%)}.action-sheet::after,.action-sheet::before{top:-10px;bottom:auto;border-top:0;border-bottom:10px solid #fff}.action-sheet::before{top:-12px;border-bottom-color:rgba(0,0,0,.15)}.action-sheet.top{position:absolute;left:50%;width:300px;border-radius:4px;opacity:0;pointer-events:none;box-shadow:0 0 10px rgba(0,0,0,.25);top:0;bottom:auto;-webkit-transform:translateX(-50%) translateY(-120%);transform:translateX(-50%) translateY(-120%)}.action-sheet.top.is-active{opacity:1;pointer-events:auto}.action-sheet.top::after,.action-sheet.top::before{content:'';position:absolute;left:50%;display:block;width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;margin-left:-10px}.action-sheet.top.is-active{-webkit-transform:translateX(-50%) translateY(-110%);transform:translateX(-50%) translateY(-110%)}.action-sheet.top::after,.action-sheet.top::before{top:auto;bottom:-10px;border-top:10px solid #fff;border-bottom:0}.action-sheet.top::before{bottom:-12px;border-top-color:rgba(0,0,0,.15)}}.action-sheet.primary{background:#00558b;color:#fff;border:0}.action-sheet.primary::before{display:none}.action-sheet.primary::after,.action-sheet.primary::before{border-top-color:#00558b}.action-sheet.primary.top::after,.action-sheet.primary.top::before{border-bottom-color:#00558b}.action-sheet.primary ul{margin:0 -1rem -1rem;list-style-type:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.action-sheet.primary ul:first-child{margin-top:-1rem}.action-sheet.primary ul:first-child li:first-child{border-top:0}.action-sheet.primary ul a{display:block;padding:.8rem;line-height:1;color:#fff;border-top:1px solid #006cb0}.action-sheet.primary ul a:hover{color:#fff;background:#00609e}.action-sheet.primary ul .alert>a{color:#F04124}.action-sheet.primary ul .disabled>a{pointer-events:none;color:#999}.action-sheet.dark{background:#232323;color:#fff;border:0}.action-sheet.dark::before{display:none}.action-sheet.dark::after,.action-sheet.dark::before{border-top-color:#232323}.action-sheet.dark.top::after,.action-sheet.dark.top::before{border-bottom-color:#232323}.action-sheet.dark ul{margin:0 -1rem -1rem;list-style-type:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.action-sheet.dark ul:first-child{margin-top:-1rem}.action-sheet.dark ul:first-child li:first-child{border-top:0}.action-sheet.dark ul a{display:block;padding:.8rem;line-height:1;color:#fff;border-top:1px solid #393939}.action-sheet.dark ul a:hover{color:#fff;background:#2e2e2e}.action-sheet.dark ul .alert>a{color:#F04124}.action-sheet.dark ul .disabled>a{pointer-events:none;color:#999}.block-list{margin-bottom:1rem;line-height:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.block-list,.block-list ul{list-style-type:none}.block-list ul{margin-left:0}.block-list{font-size:1rem;margin-left:-1rem;margin-right:-1rem}.block-list input[type=text],.block-list input[type=password],.block-list input[type=date],.block-list input[type=datetime],.block-list input[type=datetime-local],.block-list input[type=month],.block-list input[type=week],.block-list input[type=email],.block-list input[type=tel],.block-list input[type=time],.block-list input[type=url],.block-list input[type=color],.block-list input[type=number],.block-list input[type=search],.block-list textarea{margin:0;border:0;line-height:1;height:auto;padding:.8rem 1rem;color:inherit}.block-list input[type=text]:focus,.block-list input[type=text]:hover,.block-list input[type=password]:focus,.block-list input[type=password]:hover,.block-list input[type=date]:focus,.block-list input[type=date]:hover,.block-list input[type=datetime]:focus,.block-list input[type=datetime]:hover,.block-list input[type=datetime-local]:focus,.block-list input[type=datetime-local]:hover,.block-list input[type=month]:focus,.block-list input[type=month]:hover,.block-list input[type=week]:focus,.block-list input[type=week]:hover,.block-list input[type=email]:focus,.block-list input[type=email]:hover,.block-list input[type=tel]:focus,.block-list input[type=tel]:hover,.block-list input[type=time]:focus,.block-list input[type=time]:hover,.block-list input[type=url]:focus,.block-list input[type=url]:hover,.block-list input[type=color]:focus,.block-list input[type=color]:hover,.block-list input[type=number]:focus,.block-list input[type=number]:hover,.block-list input[type=search]:focus,.block-list input[type=search]:hover,.block-list textarea:focus,.block-list textarea:hover{border:0}.block-list li>input[type=checkbox],.block-list li>input[type=radio]{position:absolute;left:-9999px}.block-list li>input[type=checkbox]+label,.block-list li>input[type=radio]+label{display:block;font-size:1rem;margin:0}.block-list li>input[type=checkbox]:checked+label::before,.block-list li>input[type=radio]:checked+label::before{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="32" viewBox="0 0 32 32"><path fill="black" d="M16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zm6.906 8.875l2.219 2.031-12.063 13.281-6.188-6.188 2.125-2.125 3.938 3.938 9.969-10.938z"/></svg>');content:'';background-size:100% 100%;width:1.5em;height:1.5em;color:#00558b;float:right;pointer-events:none;margin-top:-.25em}@media screen and (min-width:0\0){.block-list li>input[type=checkbox]:checked+label::before,.block-list li>input[type=radio]:checked+label::before{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUeNrMl0FugzAQRY3TRZeoFyhVL0BOkGTXJezaHZwguUnECaCrdFd6gqQnCN11Uyk5QekNOlONJWMVGMCgfGlkEIY3HnsG2xFM3d96PjQB2AJsWdPtAPYOln+dTwXnuw4DHEGzBvNFN6EDCTiS9XIAwB40acNoucKoxODIie0AwAOCu8KOSnIiNx/MakK+A7sW9oTferxx3fP3T1nURoBG/irGVahHwjHm/Ggx7E3TMVdrQmoP0gngghhpZQ3QvG/EdPLUelARWI8Aycjq9Md0qMIdbcNhjmOKLoY7quk3l1Rebeqg4AwFkmq7LWGOh1pmNY0etZAWSq0OX8HoS4JvWuCopbSY26EGR/CW86K0BF+pwkLwlPuyHJhOCl5oe4ZtF++vOqST+GdOYwO+71pN2VNAjmQGPCe42weuHDg0PI8olUwnYrXTGQJH9gxq8l1LKvrQx4O6/YY32Kp/ugb3ey7gZ4xAzuhYiYTxB/UHZFAuaREVXZ2g6yFlvEC2yoKEmbsRZYNgVLk2JeaOaG+xLHN+WCszDWMqLGOrJFa1DlApjSdwoHJGqGzLIb0+cas0wh5Bh780ngswx8GJD7h8sHg2wLA/mfDLPZpdxOF0quP5rwADAAFIzSRvu1m5AAAAAElFTkSuQmCC)}}.block-list .with-dropdown{color:inherit}.block-list .with-dropdown select{-webkit-appearance:none;-moz-appearance:none;outline:0;background:0;border:0;height:auto;padding:.8rem 1rem;margin:0;font-size:1em;line-height:1;color:inherit}.block-list .switch{position:absolute;top:50%;right:1rem;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.block-list.with-icons li>a,.block-list.with-icons li>label,.block-list.with-icons li>span{padding-left:2.8rem}.block-list.with-icons li .iconic,.block-list.with-icons li img{position:absolute;top:.26rem;left:.26rem;width:2.08rem;height:2.08rem;border-radius:8px;pointer-events:none}.block-list header{margin-top:1em;color:#666;font-weight:700;margin-bottom:.5em;margin-left:1rem;font-size:.8em;cursor:default;text-transform:uppercase}.block-list li{position:relative;border-bottom:1px solid #d0d0d0}.block-list li:first-child{border-top:1px solid #d0d0d0}.block-list li>a,.block-list li>label,.block-list li>span{display:block;padding:.8rem 1rem;color:#000;line-height:1}.block-list li>span{cursor:default}.block-list li>a,.block-list li>label{cursor:pointer}.block-list li>a:hover,.block-list li>label:hover{color:#000}.block-list li select:hover,.block-list li>a:hover,.block-list li>label:hover{background:#f4f4f4}.block-list li.caution>a,.block-list li.caution>a:hover{color:#F04124}.block-list li.disabled>a{cursor:default}.block-list li.disabled>a,.block-list li.disabled>a:hover{color:#999}.block-list li.disabled>a:hover{background:0 0}.block-list li.with-chevron::after{content:'\203A';display:block;position:absolute;right:1rem;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);font-weight:700;color:#666;font-size:2em}.block-list li.with-chevron .block-list-label{padding-right:1.5rem}.block-list li .block-list-label{display:inline-block;float:right;padding:0;color:#999;pointer-events:none}.block-list li .block-list-label.left{margin-left:.8rem;float:none}.button,.button-group>li>a,.button-group>li>button,.button-group>li>label{display:inline-block;border:0;text-align:center;line-height:1;cursor:pointer;-webkit-appearance:none;-webkit-font-smoothing:antialiased;transition:background .25s ease-out;vertical-align:middle;padding:.85em 1em;margin:0 1rem 1rem 0;font-size:.9rem;border-radius:0}.button{font-size:.9rem;display:inline-block;width:auto;margin:0 1rem 1rem 0;background:#00558b;color:#fff}.button .iconic{width:1em;height:1em;vertical-align:middle;margin-right:.25em;margin-top:-2px}.button:focus,.button:hover{background:#004876;color:#fff}.button .iconic *,.button .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button.tiny{font-size:.63rem}.button.tiny .iconic{width:1em;height:1em;vertical-align:middle;margin-right:.25em;margin-top:-2px}.button.small{font-size:.72rem}.button.small .iconic{width:1em;height:1em;vertical-align:middle;margin-right:.25em;margin-top:-2px}.button.large{font-size:1.17rem}.button.large .iconic{width:1em;height:1em;vertical-align:middle;margin-right:.25em;margin-top:-2px}.button.expand{display:block;width:100%;margin-left:0;margin-right:0}.button.secondary{background:#f1f1f1;color:#000}.button.secondary:focus,.button.secondary:hover{background:#cdcdcd;color:#000}.button.secondary .iconic *,.button.secondary .iconic .iconic-property-accent{fill:#000;stroke:#000}.button.success{background:#43AC6A;color:#fff}.button.success:focus,.button.success:hover{background:#39925a;color:#fff}.button.success .iconic *,.button.success .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button.warning{background:#F08A24;color:#fff}.button.warning:focus,.button.warning:hover{background:#dc750f;color:#fff}.button.warning .iconic *,.button.warning .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button.alert{background:#F04124;color:#fff}.button.alert:focus,.button.alert:hover{background:#dc2c0f;color:#fff}.button.alert .iconic *,.button.alert .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button.info{background:#A0D3E8;color:#000}.button.info:focus,.button.info:hover{background:#71bddd;color:#000}.button.info .iconic *,.button.info .iconic .iconic-property-accent{fill:#000;stroke:#000}.button.dark{background:#232323;color:#fff}.button.dark:focus,.button.dark:hover{background:#1e1e1e;color:#fff}.button.dark .iconic *,.button.dark .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button.hollow{border:1px solid #00558b;background:0 0;color:#00558b}.button.hollow:focus,.button.hollow:hover{border-color:#008ee8;background:0 0;color:#008ee8}.button.hollow .iconic *,.button.hollow .iconic .iconic-property-accent{fill:#00558b;stroke:#00558b}.button.hollow:hover .iconic *,.button.hollow:hover .iconic .iconic-property-accent{fill:#008ee8;stroke:#008ee8}.button.hollow.secondary{border:1px solid #f1f1f1;background:0 0;color:#f1f1f1}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#f4f4f4;background:0 0;color:#f4f4f4}.button.hollow.secondary .iconic *,.button.hollow.secondary .iconic .iconic-property-accent{fill:#f1f1f1;stroke:#f1f1f1}.button.hollow.secondary:hover .iconic *,.button.hollow.secondary:hover .iconic .iconic-property-accent{fill:#f4f4f4;stroke:#f4f4f4}.button.hollow.success{border:1px solid #43AC6A;background:0 0;color:#43AC6A}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#6dc68e;background:0 0;color:#6dc68e}.button.hollow.success .iconic *,.button.hollow.success .iconic .iconic-property-accent{fill:#43AC6A;stroke:#43AC6A}.button.hollow.success:hover .iconic *,.button.hollow.success:hover .iconic .iconic-property-accent{fill:#6dc68e;stroke:#6dc68e}.button.hollow.warning{border:1px solid #F08A24;background:0 0;color:#F08A24}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#f4a75b;background:0 0;color:#f4a75b}.button.hollow.warning .iconic *,.button.hollow.warning .iconic .iconic-property-accent{fill:#F08A24;stroke:#F08A24}.button.hollow.warning:hover .iconic *,.button.hollow.warning:hover .iconic .iconic-property-accent{fill:#f4a75b;stroke:#f4a75b}.button.hollow.alert{border:1px solid #F04124;background:0 0;color:#F04124}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#f4715b;background:0 0;color:#f4715b}.button.hollow.alert .iconic *,.button.hollow.alert .iconic .iconic-property-accent{fill:#F04124;stroke:#F04124}.button.hollow.alert:hover .iconic *,.button.hollow.alert:hover .iconic .iconic-property-accent{fill:#f4715b;stroke:#f4715b}.button.hollow.info{border:1px solid #A0D3E8;background:0 0;color:#A0D3E8}.button.hollow.info:focus,.button.hollow.info:hover{border-color:#b8deee;background:0 0;color:#b8deee}.button.hollow.info .iconic *,.button.hollow.info .iconic .iconic-property-accent{fill:#A0D3E8;stroke:#A0D3E8}.button.hollow.info:hover .iconic *,.button.hollow.info:hover .iconic .iconic-property-accent{fill:#b8deee;stroke:#b8deee}.button.hollow.dark{border:1px solid #232323;background:0 0;color:#232323}.button.hollow.dark:focus,.button.hollow.dark:hover{border-color:#5a5a5a;background:0 0;color:#5a5a5a}.button.hollow.dark .iconic *,.button.hollow.dark .iconic .iconic-property-accent{fill:#232323;stroke:#232323}.button.hollow.dark:hover .iconic *,.button.hollow.dark:hover .iconic .iconic-property-accent{fill:#5a5a5a;stroke:#5a5a5a}.button.disabled{opacity:.5;cursor:default;pointer-events:none}.button-group{margin:0 0 1rem;list-style-type:none;overflow:hidden;font-size:.9rem}.button-group>li>a,.button-group>li>button,.button-group>li>label{border-radius:0;font-size:inherit;display:block;margin:0}.button-group>li>input+label{margin-left:0}.button-group>li:not(:last-child)>a,.button-group>li:not(:last-child)>button,.button-group>li:not(:last-child)>label{border-right:1px solid #004068}.button-group .iconic{width:1em;height:1em;vertical-align:middle;margin-right:.25em;margin-top:-2px}.button-group.segmented,.button-group.segmented.alert,.button-group.segmented.secondary,.button-group.segmented.success,.button-group.segmented.warning{border:1px solid #00558b;transition-property:background color}.button-group.segmented>li>input[type=radio]{position:absolute;left:-9999px}.button-group.segmented.alert>li>a,.button-group.segmented.alert>li>button,.button-group.segmented.alert>li>label,.button-group.segmented.secondary>li>a,.button-group.segmented.secondary>li>button,.button-group.segmented.secondary>li>label,.button-group.segmented.success>li>a,.button-group.segmented.success>li>button,.button-group.segmented.success>li>label,.button-group.segmented.warning>li>a,.button-group.segmented.warning>li>button,.button-group.segmented.warning>li>label,.button-group.segmented>li>a,.button-group.segmented>li>button,.button-group.segmented>li>label{margin-right:0;background:0 0}.button-group{display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;border-radius:0}.button-group>li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.button-group>li>a,.button-group>li>button,.button-group>li>label{background:#00558b;color:#fff;border-color:#004876}.button-group>li>a:focus,.button-group>li>a:hover,.button-group>li>button:focus,.button-group>li>button:hover,.button-group>li>label:focus,.button-group>li>label:hover{background:#004876;color:#fff}.button-group>li>a .iconic *,.button-group>li>a .iconic .iconic-property-accent,.button-group>li>button .iconic *,.button-group>li>button .iconic .iconic-property-accent,.button-group>li>label .iconic *,.button-group>li>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group>li.is-active>a,.button-group>li.is-active>button,.button-group>li.is-active>label{background:#004876}.button-group.secondary>li>a,.button-group.secondary>li>button,.button-group.secondary>li>label{background:#f1f1f1;color:#000;border-color:#cdcdcd}.button-group.secondary>li>a:focus,.button-group.secondary>li>a:hover,.button-group.secondary>li>button:focus,.button-group.secondary>li>button:hover,.button-group.secondary>li>label:focus,.button-group.secondary>li>label:hover{background:#cdcdcd;color:#000}.button-group.secondary>li>a .iconic *,.button-group.secondary>li>a .iconic .iconic-property-accent,.button-group.secondary>li>button .iconic *,.button-group.secondary>li>button .iconic .iconic-property-accent,.button-group.secondary>li>label .iconic *,.button-group.secondary>li>label .iconic .iconic-property-accent{fill:#000;stroke:#000}.button-group.secondary>li.is-active>a,.button-group.secondary>li.is-active>button,.button-group.secondary>li.is-active>label{background:#cdcdcd}.button-group.success>li>a,.button-group.success>li>button,.button-group.success>li>label{background:#43AC6A;color:#fff;border-color:#39925a}.button-group.success>li>a:focus,.button-group.success>li>a:hover,.button-group.success>li>button:focus,.button-group.success>li>button:hover,.button-group.success>li>label:focus,.button-group.success>li>label:hover{background:#39925a;color:#fff}.button-group.success>li>a .iconic *,.button-group.success>li>a .iconic .iconic-property-accent,.button-group.success>li>button .iconic *,.button-group.success>li>button .iconic .iconic-property-accent,.button-group.success>li>label .iconic *,.button-group.success>li>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.success>li.is-active>a,.button-group.success>li.is-active>button,.button-group.success>li.is-active>label{background:#39925a}.button-group.warning>li>a,.button-group.warning>li>button,.button-group.warning>li>label{background:#F08A24;color:#fff;border-color:#dc750f}.button-group.warning>li>a:focus,.button-group.warning>li>a:hover,.button-group.warning>li>button:focus,.button-group.warning>li>button:hover,.button-group.warning>li>label:focus,.button-group.warning>li>label:hover{background:#dc750f;color:#fff}.button-group.warning>li>a .iconic *,.button-group.warning>li>a .iconic .iconic-property-accent,.button-group.warning>li>button .iconic *,.button-group.warning>li>button .iconic .iconic-property-accent,.button-group.warning>li>label .iconic *,.button-group.warning>li>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.warning>li.is-active>a,.button-group.warning>li.is-active>button,.button-group.warning>li.is-active>label{background:#dc750f}.button-group.alert>li>a,.button-group.alert>li>button,.button-group.alert>li>label{background:#F04124;color:#fff;border-color:#dc2c0f}.button-group.alert>li>a:focus,.button-group.alert>li>a:hover,.button-group.alert>li>button:focus,.button-group.alert>li>button:hover,.button-group.alert>li>label:focus,.button-group.alert>li>label:hover{background:#dc2c0f;color:#fff}.button-group.alert>li>a .iconic *,.button-group.alert>li>a .iconic .iconic-property-accent,.button-group.alert>li>button .iconic *,.button-group.alert>li>button .iconic .iconic-property-accent,.button-group.alert>li>label .iconic *,.button-group.alert>li>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.alert>li.is-active>a,.button-group.alert>li.is-active>button,.button-group.alert>li.is-active>label{background:#dc2c0f}.button-group>li.secondary>a,.button-group>li.secondary>button,.button-group>li.secondary>label{background:#f1f1f1;color:#000;border-color:#f1f1f1}.button-group>li.secondary>a:focus,.button-group>li.secondary>a:hover,.button-group>li.secondary>button:focus,.button-group>li.secondary>button:hover,.button-group>li.secondary>label:focus,.button-group>li.secondary>label:hover{background:#cdcdcd;color:#000;border-color:#b5b5b5}.button-group>li.secondary>a .iconic *,.button-group>li.secondary>a .iconic .iconic-property-accent,.button-group>li.secondary>button .iconic *,.button-group>li.secondary>button .iconic .iconic-property-accent,.button-group>li.secondary>label .iconic *,.button-group>li.secondary>label .iconic .iconic-property-accent{fill:#000;stroke:#000}.button-group>li.success>a,.button-group>li.success>button,.button-group>li.success>label{background:#43AC6A;color:#fff;border-color:#43AC6A}.button-group>li.success>a:focus,.button-group>li.success>a:hover,.button-group>li.success>button:focus,.button-group>li.success>button:hover,.button-group>li.success>label:focus,.button-group>li.success>label:hover{background:#39925a;color:#fff;border-color:#32814f}.button-group>li.success>a .iconic *,.button-group>li.success>a .iconic .iconic-property-accent,.button-group>li.success>button .iconic *,.button-group>li.success>button .iconic .iconic-property-accent,.button-group>li.success>label .iconic *,.button-group>li.success>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group>li.warning>a,.button-group>li.warning>button,.button-group>li.warning>label{background:#F08A24;color:#fff;border-color:#F08A24}.button-group>li.warning>a:focus,.button-group>li.warning>a:hover,.button-group>li.warning>button:focus,.button-group>li.warning>button:hover,.button-group>li.warning>label:focus,.button-group>li.warning>label:hover{background:#dc750f;color:#fff;border-color:#c2670d}.button-group>li.warning>a .iconic *,.button-group>li.warning>a .iconic .iconic-property-accent,.button-group>li.warning>button .iconic *,.button-group>li.warning>button .iconic .iconic-property-accent,.button-group>li.warning>label .iconic *,.button-group>li.warning>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group>li.alert>a,.button-group>li.alert>button,.button-group>li.alert>label{background:#F04124;color:#fff;border-color:#F04124}.button-group>li.alert>a:focus,.button-group>li.alert>a:hover,.button-group>li.alert>button:focus,.button-group>li.alert>button:hover,.button-group>li.alert>label:focus,.button-group>li.alert>label:hover{background:#dc2c0f;color:#fff;border-color:#c2270d}.button-group>li.alert>a .iconic *,.button-group>li.alert>a .iconic .iconic-property-accent,.button-group>li.alert>button .iconic *,.button-group>li.alert>button .iconic .iconic-property-accent,.button-group>li.alert>label .iconic *,.button-group>li.alert>label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.segmented{border-color:#00558b}.button-group.segmented>li>a,.button-group.segmented>li>button,.button-group.segmented>li>label{border-color:#00558b;color:#00558b}.button-group.segmented>li>a:hover,.button-group.segmented>li>button:hover,.button-group.segmented>li>label:hover{background:rgba(0,85,139,.25);color:#00558b}.button-group.segmented>li>a .iconic *,.button-group.segmented>li>a .iconic .iconic-property-accent,.button-group.segmented>li>button .iconic *,.button-group.segmented>li>button .iconic .iconic-property-accent,.button-group.segmented>li>label .iconic *,.button-group.segmented>li>label .iconic .iconic-property-accent{fill:#00558b;stroke:#00558b}.button-group.segmented>li.is-active>a,.button-group.segmented>li.is-active>a:hover,.button-group.segmented>li>input:checked+label,.button-group.segmented>li>input:checked+label:hover{background:#00558b;color:#fff}.button-group.segmented>li.is-active>a .iconic *,.button-group.segmented>li.is-active>a .iconic .iconic-property-accent,.button-group.segmented>li>input:checked+label .iconic *,.button-group.segmented>li>input:checked+label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.segmented.secondary{border-color:#f1f1f1}.button-group.segmented.secondary>li>a,.button-group.segmented.secondary>li>button,.button-group.segmented.secondary>li>label{border-color:#f1f1f1;color:#f1f1f1}.button-group.segmented.secondary>li>a:hover,.button-group.segmented.secondary>li>button:hover,.button-group.segmented.secondary>li>label:hover{background:rgba(241,241,241,.25);color:#f1f1f1}.button-group.segmented.secondary>li>a .iconic *,.button-group.segmented.secondary>li>a .iconic .iconic-property-accent,.button-group.segmented.secondary>li>button .iconic *,.button-group.segmented.secondary>li>button .iconic .iconic-property-accent,.button-group.segmented.secondary>li>label .iconic *,.button-group.segmented.secondary>li>label .iconic .iconic-property-accent{fill:#f1f1f1;stroke:#f1f1f1}.button-group.segmented.secondary>li.is-active>a,.button-group.segmented.secondary>li.is-active>a:hover,.button-group.segmented.secondary>li>input:checked+label,.button-group.segmented.secondary>li>input:checked+label:hover{background:#f1f1f1;color:#000}.button-group.segmented.secondary>li.is-active>a .iconic *,.button-group.segmented.secondary>li.is-active>a .iconic .iconic-property-accent,.button-group.segmented.secondary>li>input:checked+label .iconic *,.button-group.segmented.secondary>li>input:checked+label .iconic .iconic-property-accent{fill:#000;stroke:#000}.button-group.segmented.success{border-color:#43AC6A}.button-group.segmented.success>li>a,.button-group.segmented.success>li>button,.button-group.segmented.success>li>label{border-color:#43AC6A;color:#43AC6A}.button-group.segmented.success>li>a:hover,.button-group.segmented.success>li>button:hover,.button-group.segmented.success>li>label:hover{background:rgba(67,172,106,.25);color:#43AC6A}.button-group.segmented.success>li>a .iconic *,.button-group.segmented.success>li>a .iconic .iconic-property-accent,.button-group.segmented.success>li>button .iconic *,.button-group.segmented.success>li>button .iconic .iconic-property-accent,.button-group.segmented.success>li>label .iconic *,.button-group.segmented.success>li>label .iconic .iconic-property-accent{fill:#43AC6A;stroke:#43AC6A}.button-group.segmented.success>li.is-active>a,.button-group.segmented.success>li.is-active>a:hover,.button-group.segmented.success>li>input:checked+label,.button-group.segmented.success>li>input:checked+label:hover{background:#43AC6A;color:#fff}.button-group.segmented.success>li.is-active>a .iconic *,.button-group.segmented.success>li.is-active>a .iconic .iconic-property-accent,.button-group.segmented.success>li>input:checked+label .iconic *,.button-group.segmented.success>li>input:checked+label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.segmented.warning{border-color:#F08A24}.button-group.segmented.warning>li>a,.button-group.segmented.warning>li>button,.button-group.segmented.warning>li>label{border-color:#F08A24;color:#F08A24}.button-group.segmented.warning>li>a:hover,.button-group.segmented.warning>li>button:hover,.button-group.segmented.warning>li>label:hover{background:rgba(240,138,36,.25);color:#F08A24}.button-group.segmented.warning>li>a .iconic *,.button-group.segmented.warning>li>a .iconic .iconic-property-accent,.button-group.segmented.warning>li>button .iconic *,.button-group.segmented.warning>li>button .iconic .iconic-property-accent,.button-group.segmented.warning>li>label .iconic *,.button-group.segmented.warning>li>label .iconic .iconic-property-accent{fill:#F08A24;stroke:#F08A24}.button-group.segmented.warning>li.is-active>a,.button-group.segmented.warning>li.is-active>a:hover,.button-group.segmented.warning>li>input:checked+label,.button-group.segmented.warning>li>input:checked+label:hover{background:#F08A24;color:#fff}.button-group.segmented.warning>li.is-active>a .iconic *,.button-group.segmented.warning>li.is-active>a .iconic .iconic-property-accent,.button-group.segmented.warning>li>input:checked+label .iconic *,.button-group.segmented.warning>li>input:checked+label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.segmented.alert{border-color:#F04124}.button-group.segmented.alert>li>a,.button-group.segmented.alert>li>button,.button-group.segmented.alert>li>label{border-color:#F04124;color:#F04124}.button-group.segmented.alert>li>a:hover,.button-group.segmented.alert>li>button:hover,.button-group.segmented.alert>li>label:hover{background:rgba(240,65,36,.25);color:#F04124}.button-group.segmented.alert>li>a .iconic *,.button-group.segmented.alert>li>a .iconic .iconic-property-accent,.button-group.segmented.alert>li>button .iconic *,.button-group.segmented.alert>li>button .iconic .iconic-property-accent,.button-group.segmented.alert>li>label .iconic *,.button-group.segmented.alert>li>label .iconic .iconic-property-accent{fill:#F04124;stroke:#F04124}.button-group.segmented.alert>li.is-active>a,.button-group.segmented.alert>li.is-active>a:hover,.button-group.segmented.alert>li>input:checked+label,.button-group.segmented.alert>li>input:checked+label:hover{background:#F04124;color:#fff}.button-group.segmented.alert>li.is-active>a .iconic *,.button-group.segmented.alert>li.is-active>a .iconic .iconic-property-accent,.button-group.segmented.alert>li>input:checked+label .iconic *,.button-group.segmented.alert>li>input:checked+label .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.button-group.tiny{font-size:.63rem}.button-group.small{font-size:.72rem}.button-group.large{font-size:1.17rem}.button-group.expand{display:-webkit-flex;display:-ms-flexbox;display:flex}.button-group.expand>li{-webkit-flex:1;-ms-flex:1;flex:1}.button-group.expand>li>a,.button-group.expand>li>button,.button-group.expand>li>label{display:block;width:100%;margin-left:0;margin-right:0}.button-group li.disabled>a,.button-group li.disabled>button,.button-group li.disabled>label{opacity:.5;cursor:default;pointer-events:none}.card{border:1px solid #ededed;margin-bottom:.5rem;background:#fff;color:#000;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card h1,.card h2,.card h3,.card h4,.card h5,.card h6{color:inherit}.card ul{margin-bottom:0}.card img{width:100%}.card.primary{border:0;margin-bottom:.5rem;background:#00558b;color:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card.primary h1,.card.primary h2,.card.primary h3,.card.primary h4,.card.primary h5,.card.primary h6{color:inherit}.card.primary ul{margin-bottom:0}.card.primary img{width:100%}.card.primary .card-divider{background:#0065a5;padding:1rem}.card.success{border:0;margin-bottom:.5rem;background:#43AC6A;color:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card.success h1,.card.success h2,.card.success h3,.card.success h4,.card.success h5,.card.success h6{color:inherit}.card.success ul{margin-bottom:0}.card.success img{width:100%}.card.success .card-divider{background:#4ab873;padding:1rem}.card.warning{border:0;margin-bottom:.5rem;background:#F08A24;color:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card.warning h1,.card.warning h2,.card.warning h3,.card.warning h4,.card.warning h5,.card.warning h6{color:inherit}.card.warning ul{margin-bottom:0}.card.warning img{width:100%}.card.warning .card-divider{background:#f19233;padding:1rem}.card.alert{border:0;margin-bottom:.5rem;background:#F04124;color:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card.alert h1,.card.alert h2,.card.alert h3,.card.alert h4,.card.alert h5,.card.alert h6{color:inherit}.card.alert ul{margin-bottom:0}.card.alert img{width:100%}.card.alert .card-divider{background:#f14e33;padding:1rem}.card.dark{border:0;margin-bottom:.5rem;background:#232323;color:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);overflow:hidden}.card.dark h1,.card.dark h2,.card.dark h3,.card.dark h4,.card.dark h5,.card.dark h6{color:inherit}.card.dark ul{margin-bottom:0}.card.dark img{width:100%}.card.dark .card-divider{background:#323232;padding:1rem}.card-divider{background:#ededed;padding:1rem}.card-section{padding:1rem}.close-button{position:absolute;color:#999;top:1rem;right:1rem;font-size:2em;line-height:.5;cursor:pointer}.close-button:hover{color:#333}.thumbnail,ul.thumbnails>li img{padding:.5rem;box-shadow:0 3px 15px rgba(0,0,0,.25)}ul.thumbnails>li{margin-bottom:1rem}ul.thumbnails>li a{display:block}input[type=text],input[type=password],input[type=date],input[type=datetime],input[type=datetime-local],input[type=month],input[type=week],input[type=email],input[type=tel],input[type=time],input[type=url],input[type=color],input[type=number],input[type=search],textarea{-webkit-appearance:none;-moz-appearance:none;display:block;width:100%;height:2.4rem;padding:.5rem;margin:0 0 1rem;border:1px solid #ccc;border-radius:0;background:#fff;color:#000;font-size:1rem;-webkit-font-smoothing:antialiased;vertical-align:middle}input[type=text]:hover,input[type=password]:hover,input[type=date]:hover,input[type=datetime]:hover,input[type=datetime-local]:hover,input[type=month]:hover,input[type=week]:hover,input[type=email]:hover,input[type=tel]:hover,input[type=time]:hover,input[type=url]:hover,input[type=color]:hover,input[type=number]:hover,input[type=search]:hover,textarea:hover{border:1px solid #bbb;background:#fff;color:#000}input[type=text]:focus,input[type=password]:focus,input[type=date]:focus,input[type=datetime]:focus,input[type=datetime-local]:focus,input[type=month]:focus,input[type=week]:focus,input[type=email]:focus,input[type=tel]:focus,input[type=time]:focus,input[type=url]:focus,input[type=color]:focus,input[type=number]:focus,input[type=search]:focus,textarea:focus{outline:0;border:1px solid #999;background:#fff;color:#000}label>input[type=text],label>input[type=password],label>input[type=date],label>input[type=datetime],label>input[type=datetime-local],label>input[type=month],label>input[type=week],label>input[type=email],label>input[type=tel],label>input[type=time],label>input[type=url],label>input[type=color],label>input[type=number],label>input[type=search],label>textarea{margin-top:.5rem}input[type=search]{box-sizing:border-box}fieldset[disabled] input,input.disabled,input[disabled],input[readonly]{cursor:false}fieldset[disabled] input,fieldset[disabled] input:hover,input.disabled,input.disabled:hover,input[disabled],input[disabled]:hover,input[readonly],input[readonly]:hover{background-color:#f2f2f2}label{display:block;font-size:.9rem;margin-bottom:.5rem;color:#333}label>input,label>textarea{margin-top:.5rem}input[type=checkbox],input[type=radio]{width:1rem;height:1rem}label>input[type=checkbox],label>input[type=radio]{margin-right:.25rem}input[type=checkbox]+label,input[type=radio]+label{display:inline-block;margin-left:.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}.inline-label{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;margin-bottom:1rem}label>.inline-label{margin-top:.5rem}.inline-label>input,.inline-label>select{-webkit-flex:1;-ms-flex:1;flex:1;margin:0}.inline-label>.form-label{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;background:#eee;color:#333;border:1px solid #ccc;padding:0 .5rem;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.inline-label>.form-label:first-child{border-right:0}.inline-label>.form-label:last-child{border-left:0}.inline-label>a,.inline-label>button,.inline-label>input[type=button],.inline-label>input[type=submit]{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-top:0;padding-bottom:0;margin:0;border-radius:0}textarea{height:auto;width:100%;min-height:50px}select{-webkit-appearance:none;-moz-appearance:none;display:block;width:100%;height:2.4rem;padding:.5rem 1.625rem .5rem .5rem;margin:0 0 1rem;font-size:1rem;color:#000;border-radius:0;border:1px solid #ccc;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="24" viewBox="0 0 32 24"><polygon points="0,0 32,0 16,24" style="fill: black"></polygon></svg>') right 10px center no-repeat #fafafa;background-size:8px 8px}select:hover{background-color:#f0f0f0}select:focus{outline:0}select::-ms-expand{display:none}input[type=range]{-webkit-appearance:none;-moz-appearance:none;display:block;width:100%;height:auto;cursor:pointer;margin-top:.25rem;margin-bottom:.25rem;border:0;line-height:1}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{height:1rem;background:#ddd}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:#00558b;width:1.5rem;height:1.5rem;margin-top:-.25rem}input[type=range]::-moz-range-track{-moz-appearance:none;height:1rem;background:#ccc}input[type=range]::-moz-range-thumb{-moz-appearance:none;background:#00558b;width:1.5rem;height:1.5rem;margin-top:-.25rem}input[type=range]::-ms-track{height:1rem;background:#ddd;color:transparent;border:0;overflow:visible;border-top:.25rem solid #fff;border-bottom:.25rem solid #fff}input[type=range]::-ms-thumb{background:#00558b;width:1.5rem;height:1.5rem;border:0}input[type=range]::-ms-fill-lower,input[type=range]::-ms-fill-upper{background:#ddd}output{line-height:1.5rem;vertical-align:middle;margin-left:.5em}input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;background:#00558b}meter,progress{-webkit-appearance:none;-moz-appearance:none;display:block;width:100%;height:1.5rem;margin-bottom:1rem;background:#ccc;border:0}progress::-webkit-progress-bar{background:#ccc}progress::-webkit-progress-value{background:#00558b}progress::-moz-progress-bar{background:#00558b}progress.high::-webkit-progress-value{background:#43AC6A}progress.high::-moz-progress-bar{background:#43AC6A}progress.medium::-webkit-progress-value{background:#e7cf00}progress.medium::-moz-progress-bar{background:#e7cf00}progress.low::-webkit-progress-value{background:#F04124}progress.low::-moz-progress-bar{background:#F04124}meter{background:#ccc}meter::-webkit-meter-bar{background:#ccc}meter::-webkit-meter-optimum-value{background:#43AC6A}meter::-webkit-meter-suboptimum-value{background:#e7cf00}meter::-webkit-meter-even-less-good-value{background:#F04124}meter::-moz-meter-bar{background:#00558b}meter:-moz-meter-optimum::-moz-meter-bar{background:#43AC6A}meter:-moz-meter-sub-optimum::-moz-meter-bar{background:#e7cf00}meter:-moz-meter-sub-sub-optimum::-moz-meter-bar{background:#F04124}.panel{position:absolute;z-index:100;overflow-y:auto;display:none}.is-active.panel{display:block}.panel{padding:0;background:#fff}.panel-top{top:0;left:0;width:100%;height:300px}.panel-top.is-active{box-shadow:0 3px 10px rgba(0,0,0,.25)}.panel-right{top:0;right:0;height:100%;width:100%}@media only screen and (min-width:18.75em){.panel-right{width:300px}}.panel-right.is-active{box-shadow:-3px 0 10px rgba(0,0,0,.25)}.panel-bottom{bottom:0;left:0;width:100%;height:300px}.panel-bottom.is-active{box-shadow:2px -3px 10px rgba(0,0,0,.25)}.panel-left{top:0;left:0;height:100%;width:100%}@media only screen and (min-width:18.75em){.panel-left{width:300px}}.panel-left.is-active{box-shadow:3px 0 10px rgba(0,0,0,.25)}.panel-fixed{position:fixed}.small-vertical.grid-block,.small-vertical.grid-frame,.small-vertical.large-grid-block,.small-vertical.medium-grid-block,.small-vertical.small-grid-block,.vertical.grid-block,.vertical.grid-frame,.vertical.large-grid-block,.vertical.medium-grid-block,.vertical.small-grid-block{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.small-horizontal.grid-block,.small-horizontal.grid-frame,.small-horizontal.large-grid-block,.small-horizontal.medium-grid-block,.small-horizontal.small-grid-block{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}@media only screen and (min-width:40em){.medium-vertical.grid-block,.medium-vertical.grid-frame,.medium-vertical.large-grid-block,.medium-vertical.medium-grid-block,.medium-vertical.small-grid-block{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.medium-horizontal.grid-block,.medium-horizontal.grid-frame,.medium-horizontal.large-grid-block,.medium-horizontal.medium-grid-block,.medium-horizontal.small-grid-block{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}}@media only screen and (min-width:75em){.large-vertical.grid-block,.large-vertical.grid-frame,.large-vertical.large-grid-block,.large-vertical.medium-grid-block,.large-vertical.small-grid-block{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.large-horizontal.grid-block,.large-horizontal.grid-frame,.large-horizontal.large-grid-block,.large-horizontal.medium-grid-block,.large-horizontal.small-grid-block{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}}.align-right.grid-block,.align-right.grid-frame,.align-right.large-grid-block,.align-right.medium-grid-block,.align-right.small-grid-block{-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.align-center.grid-block,.align-center.grid-frame,.align-center.large-grid-block,.align-center.medium-grid-block,.align-center.small-grid-block{-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.align-justify.grid-block,.align-justify.grid-frame,.align-justify.large-grid-block,.align-justify.medium-grid-block,.align-justify.small-grid-block{-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.align-spaced.grid-block,.align-spaced.grid-frame,.align-spaced.large-grid-block,.align-spaced.medium-grid-block,.align-spaced.small-grid-block{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}.wrap.grid-block,.wrap.grid-frame,.wrap.large-grid-block,.wrap.medium-grid-block,.wrap.small-grid-block{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.shrink.grid-block,.shrink.grid-content,.shrink.large-grid-block,.shrink.large-grid-content,.shrink.medium-grid-block,.shrink.medium-grid-content,.shrink.small-grid-block,.shrink.small-grid-content{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.noscroll.grid-block,.noscroll.grid-content,.noscroll.large-grid-block,.noscroll.large-grid-content,.noscroll.medium-grid-block,.noscroll.medium-grid-content,.noscroll.small-grid-block,.noscroll.small-grid-content{overflow:hidden}.grid-frame{display:-webkit-flex;display:-ms-flexbox;display:flex;height:100vh;position:relative;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-order:0;-ms-flex-order:0;order:0}.grid-block{display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-order:0;-ms-flex-order:0;order:0;height:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.grid-content{display:block;padding:0 1rem;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.grid-content.collapse{padding:0}.grid-content .grid-block{margin-left:-1rem;margin-right:-1rem;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;overflow:visible}.grid-content .grid-block.nowrap{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.grid-content .grid-block .grid-content{overflow:visible}.grid-container{max-width:56.25rem;margin:0 auto}.grid-container.contain-left{max-width:56.25rem;margin:0 auto 0 0}.grid-container.contain-right{max-width:56.25rem;margin:0 0 0 auto}.small-grid-block{display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-order:0;-ms-flex-order:0;order:0;height:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.small-grid-block.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}.small-grid-content{display:block;padding:0 1rem;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.small-grid-content.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}@media only screen and (min-width:40em){.medium-grid-block{display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-order:0;-ms-flex-order:0;order:0;height:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.medium-grid-block.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}}@media only screen and (min-width:40em){.medium-grid-content{display:block;padding:0 1rem;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-grid-content.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}}@media only screen and (min-width:75em){.large-grid-block{display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-order:0;-ms-flex-order:0;order:0;height:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.large-grid-block.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}}@media only screen and (min-width:75em){.large-grid-content{display:block;padding:0 1rem;overflow-y:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-grid-content.panel{-webkit-transform:none;transform:none;position:relative;width:auto;height:auto;z-index:auto;box-shadow:none;background:0 0;top:auto;right:auto;bottom:auto;left:auto}}.order-1{-webkit-order:1;-ms-flex-order:1;order:1}.order-2{-webkit-order:2;-ms-flex-order:2;order:2}.order-3{-webkit-order:3;-ms-flex-order:3;order:3}.order-4{-webkit-order:4;-ms-flex-order:4;order:4}.order-5{-webkit-order:5;-ms-flex-order:5;order:5}.order-6{-webkit-order:6;-ms-flex-order:6;order:6}.order-7{-webkit-order:7;-ms-flex-order:7;order:7}.order-8{-webkit-order:8;-ms-flex-order:8;order:8}.order-9{-webkit-order:9;-ms-flex-order:9;order:9}.order-10{-webkit-order:10;-ms-flex-order:10;order:10}.order-11{-webkit-order:11;-ms-flex-order:11;order:11}.order-12{-webkit-order:12;-ms-flex-order:12;order:12}.small-1{-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.small-order-1{-webkit-order:1;-ms-flex-order:1;order:1}.small-offset-1{margin-left:8.33333%}.small-up-1{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-1>div,.small-up-1>li,.small-up-1>section{padding:0 1rem 1rem;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.small-2{-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.small-order-2{-webkit-order:2;-ms-flex-order:2;order:2}.small-offset-2{margin-left:16.66667%}.small-up-2{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-2>div,.small-up-2>li,.small-up-2>section{padding:0 1rem 1rem;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%}.small-3{-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.small-order-3{-webkit-order:3;-ms-flex-order:3;order:3}.small-offset-3{margin-left:25%}.small-up-3{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-3>div,.small-up-3>li,.small-up-3>section{padding:0 1rem 1rem;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%}.small-4{-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.small-order-4{-webkit-order:4;-ms-flex-order:4;order:4}.small-offset-4{margin-left:33.33333%}.small-up-4{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-4>div,.small-up-4>li,.small-up-4>section{padding:0 1rem 1rem;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%}.small-5{-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.small-order-5{-webkit-order:5;-ms-flex-order:5;order:5}.small-offset-5{margin-left:41.66667%}.small-up-5{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-5>div,.small-up-5>li,.small-up-5>section{padding:0 1rem 1rem;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%}.small-6{-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.small-order-6{-webkit-order:6;-ms-flex-order:6;order:6}.small-offset-6{margin-left:50%}.small-up-6{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-6>div,.small-up-6>li,.small-up-6>section{padding:0 1rem 1rem;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%}.small-7{-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.small-order-7{-webkit-order:7;-ms-flex-order:7;order:7}.small-offset-7{margin-left:58.33333%}.small-up-7{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-7>div,.small-up-7>li,.small-up-7>section{padding:0 1rem 1rem;-webkit-flex:0 0 14.28571%;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%}.small-8{-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.small-order-8{-webkit-order:8;-ms-flex-order:8;order:8}.small-offset-8{margin-left:66.66667%}.small-up-8{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-8>div,.small-up-8>li,.small-up-8>section{padding:0 1rem 1rem;-webkit-flex:0 0 12.5%;-ms-flex:0 0 12.5%;flex:0 0 12.5%}.small-9{-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.small-order-9{-webkit-order:9;-ms-flex-order:9;order:9}.small-offset-9{margin-left:75%}.small-up-9{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-9>div,.small-up-9>li,.small-up-9>section{padding:0 1rem 1rem;-webkit-flex:0 0 11.11111%;-ms-flex:0 0 11.11111%;flex:0 0 11.11111%}.small-10{-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.small-order-10{-webkit-order:10;-ms-flex-order:10;order:10}.small-offset-10{margin-left:83.33333%}.small-up-10{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-10>div,.small-up-10>li,.small-up-10>section{padding:0 1rem 1rem;-webkit-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%}.small-11{-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.small-order-11{-webkit-order:11;-ms-flex-order:11;order:11}.small-offset-11{margin-left:91.66667%}.small-up-11{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-11>div,.small-up-11>li,.small-up-11>section{padding:0 1rem 1rem;-webkit-flex:0 0 9.09091%;-ms-flex:0 0 9.09091%;flex:0 0 9.09091%}.small-12{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.small-order-12{-webkit-order:12;-ms-flex-order:12;order:12}.small-offset-12{margin-left:100%}.small-up-12{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.small-up-12>div,.small-up-12>li,.small-up-12>section{padding:0 1rem 1rem;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%}@media only screen and (min-width:40em){.medium-1{-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.medium-order-1{-webkit-order:1;-ms-flex-order:1;order:1}.medium-offset-1{margin-left:8.33333%}.medium-up-1{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-1>div,.medium-up-1>li,.medium-up-1>section{padding:0 1rem 1rem;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}}@media only screen and (min-width:40em){.medium-2{-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.medium-order-2{-webkit-order:2;-ms-flex-order:2;order:2}.medium-offset-2{margin-left:16.66667%}.medium-up-2{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-2>div,.medium-up-2>li,.medium-up-2>section{padding:0 1rem 1rem;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%}}@media only screen and (min-width:40em){.medium-3{-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.medium-order-3{-webkit-order:3;-ms-flex-order:3;order:3}.medium-offset-3{margin-left:25%}.medium-up-3{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-3>div,.medium-up-3>li,.medium-up-3>section{padding:0 1rem 1rem;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%}}@media only screen and (min-width:40em){.medium-4{-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.medium-order-4{-webkit-order:4;-ms-flex-order:4;order:4}.medium-offset-4{margin-left:33.33333%}.medium-up-4{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-4>div,.medium-up-4>li,.medium-up-4>section{padding:0 1rem 1rem;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%}}@media only screen and (min-width:40em){.medium-5{-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.medium-order-5{-webkit-order:5;-ms-flex-order:5;order:5}.medium-offset-5{margin-left:41.66667%}.medium-up-5{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-5>div,.medium-up-5>li,.medium-up-5>section{padding:0 1rem 1rem;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%}}@media only screen and (min-width:40em){.medium-6{-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.medium-order-6{-webkit-order:6;-ms-flex-order:6;order:6}.medium-offset-6{margin-left:50%}.medium-up-6{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-6>div,.medium-up-6>li,.medium-up-6>section{padding:0 1rem 1rem;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%}}@media only screen and (min-width:40em){.medium-7{-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.medium-order-7{-webkit-order:7;-ms-flex-order:7;order:7}.medium-offset-7{margin-left:58.33333%}.medium-up-7{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-7>div,.medium-up-7>li,.medium-up-7>section{padding:0 1rem 1rem;-webkit-flex:0 0 14.28571%;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%}}@media only screen and (min-width:40em){.medium-8{-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.medium-order-8{-webkit-order:8;-ms-flex-order:8;order:8}.medium-offset-8{margin-left:66.66667%}.medium-up-8{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-8>div,.medium-up-8>li,.medium-up-8>section{padding:0 1rem 1rem;-webkit-flex:0 0 12.5%;-ms-flex:0 0 12.5%;flex:0 0 12.5%}}@media only screen and (min-width:40em){.medium-9{-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.medium-order-9{-webkit-order:9;-ms-flex-order:9;order:9}.medium-offset-9{margin-left:75%}.medium-up-9{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-9>div,.medium-up-9>li,.medium-up-9>section{padding:0 1rem 1rem;-webkit-flex:0 0 11.11111%;-ms-flex:0 0 11.11111%;flex:0 0 11.11111%}}@media only screen and (min-width:40em){.medium-10{-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.medium-order-10{-webkit-order:10;-ms-flex-order:10;order:10}.medium-offset-10{margin-left:83.33333%}.medium-up-10{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-10>div,.medium-up-10>li,.medium-up-10>section{padding:0 1rem 1rem;-webkit-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%}}@media only screen and (min-width:40em){.medium-11{-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.medium-order-11{-webkit-order:11;-ms-flex-order:11;order:11}.medium-offset-11{margin-left:91.66667%}.medium-up-11{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-11>div,.medium-up-11>li,.medium-up-11>section{padding:0 1rem 1rem;-webkit-flex:0 0 9.09091%;-ms-flex:0 0 9.09091%;flex:0 0 9.09091%}}@media only screen and (min-width:40em){.medium-12{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.medium-order-12{-webkit-order:12;-ms-flex-order:12;order:12}.medium-offset-12{margin-left:100%}.medium-up-12{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.medium-up-12>div,.medium-up-12>li,.medium-up-12>section{padding:0 1rem 1rem;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%}}@media only screen and (min-width:75em){.large-1{-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.large-order-1{-webkit-order:1;-ms-flex-order:1;order:1}.large-offset-1{margin-left:8.33333%}.large-up-1{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-1>div,.large-up-1>li,.large-up-1>section{padding:0 1rem 1rem;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}}@media only screen and (min-width:75em){.large-2{-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.large-order-2{-webkit-order:2;-ms-flex-order:2;order:2}.large-offset-2{margin-left:16.66667%}.large-up-2{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-2>div,.large-up-2>li,.large-up-2>section{padding:0 1rem 1rem;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%}}@media only screen and (min-width:75em){.large-3{-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.large-order-3{-webkit-order:3;-ms-flex-order:3;order:3}.large-offset-3{margin-left:25%}.large-up-3{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-3>div,.large-up-3>li,.large-up-3>section{padding:0 1rem 1rem;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%}}@media only screen and (min-width:75em){.large-4{-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.large-order-4{-webkit-order:4;-ms-flex-order:4;order:4}.large-offset-4{margin-left:33.33333%}.large-up-4{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-4>div,.large-up-4>li,.large-up-4>section{padding:0 1rem 1rem;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%}}@media only screen and (min-width:75em){.large-5{-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.large-order-5{-webkit-order:5;-ms-flex-order:5;order:5}.large-offset-5{margin-left:41.66667%}.large-up-5{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-5>div,.large-up-5>li,.large-up-5>section{padding:0 1rem 1rem;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%}}@media only screen and (min-width:75em){.large-6{-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.large-order-6{-webkit-order:6;-ms-flex-order:6;order:6}.large-offset-6{margin-left:50%}.large-up-6{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-6>div,.large-up-6>li,.large-up-6>section{padding:0 1rem 1rem;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%}}@media only screen and (min-width:75em){.large-7{-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.large-order-7{-webkit-order:7;-ms-flex-order:7;order:7}.large-offset-7{margin-left:58.33333%}.large-up-7{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-7>div,.large-up-7>li,.large-up-7>section{padding:0 1rem 1rem;-webkit-flex:0 0 14.28571%;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%}}@media only screen and (min-width:75em){.large-8{-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.large-order-8{-webkit-order:8;-ms-flex-order:8;order:8}.large-offset-8{margin-left:66.66667%}.large-up-8{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-8>div,.large-up-8>li,.large-up-8>section{padding:0 1rem 1rem;-webkit-flex:0 0 12.5%;-ms-flex:0 0 12.5%;flex:0 0 12.5%}}@media only screen and (min-width:75em){.large-9{-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.large-order-9{-webkit-order:9;-ms-flex-order:9;order:9}.large-offset-9{margin-left:75%}.large-up-9{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-9>div,.large-up-9>li,.large-up-9>section{padding:0 1rem 1rem;-webkit-flex:0 0 11.11111%;-ms-flex:0 0 11.11111%;flex:0 0 11.11111%}}@media only screen and (min-width:75em){.large-10{-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.large-order-10{-webkit-order:10;-ms-flex-order:10;order:10}.large-offset-10{margin-left:83.33333%}.large-up-10{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-10>div,.large-up-10>li,.large-up-10>section{padding:0 1rem 1rem;-webkit-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%}}@media only screen and (min-width:75em){.large-11{-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.large-order-11{-webkit-order:11;-ms-flex-order:11;order:11}.large-offset-11{margin-left:91.66667%}.large-up-11{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-11>div,.large-up-11>li,.large-up-11>section{padding:0 1rem 1rem;-webkit-flex:0 0 9.09091%;-ms-flex:0 0 9.09091%;flex:0 0 9.09091%}}@media only screen and (min-width:75em){.large-12{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.large-order-12{-webkit-order:12;-ms-flex-order:12;order:12}.large-offset-12{margin-left:100%}.large-up-12{-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;overflow:visible;list-style-type:none}.large-up-12>div,.large-up-12>li,.large-up-12>section{padding:0 1rem 1rem;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%}}.grid-content .modal .grid-block{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.title-bar{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;overflow:visible}.title-bar .title{font-weight:700}.title-bar .center,.title-bar .left,.title-bar .right{display:block;white-space:nowrap;overflow:visible}.title-bar .center:first-child:last-child,.title-bar .left:first-child:last-child,.title-bar .right:first-child:last-child{-webkit-flex:1;-ms-flex:1;flex:1;margin:0}.title-bar .left{-webkit-order:1;-ms-flex-order:1;order:1;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%}.title-bar .center{-webkit-order:2;-ms-flex-order:2;order:2;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;text-align:center}.title-bar .right{-webkit-order:3;-ms-flex-order:3;order:3;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;text-align:right}.title-bar .left:first-child,.title-bar .left:first-child+.right:last-child{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.title-bar .center:first-child:not(:last-child){margin-left:25%}.title-bar .center+.left{margin-right:-25%}.title-bar{background:#eee;color:#000;padding:1rem;border-bottom:1px solid #ccc}.title-bar.primary{background:#00558b;color:#fff;padding:1rem;border-bottom:1px solid #ccc}.title-bar.primary a,.title-bar.primary a:hover{color:#fff}.title-bar.primary .iconic *,.title-bar.primary .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.title-bar.dark{background:#232323;color:#fff;padding:1rem;border-bottom:1px solid #ccc}.title-bar.dark a,.title-bar.dark a:hover{color:#fff}.title-bar.dark .iconic *,.title-bar.dark .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.title-bar-bottom{border-bottom:0;border-top:1px solid #ccc}.label{line-height:1;white-space:nowrap;display:inline-block;cursor:default;font-size:.8rem;padding:.33333rem .5rem;background:#00558b;border-radius:0;color:#fff}.label.primary{background:#00558b;border-radius:0;color:#fff}.label.success{background:#43AC6A;border-radius:0;color:#fff}.label.warning{background:#F08A24;border-radius:0;color:#fff}.label.alert{background:#F04124;border-radius:0;color:#fff}.label.dark{background:#232323;border-radius:0;color:#fff}.badge{-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;border-radius:1000px;font-size:.8em;width:1.5rem;height:1.5rem;background:#00558b;color:#fff}.badge.secondary{background:#f1f1f1;color:#000}.badge.primary{background:#00558b;color:#fff}.badge.success{background:#43AC6A;color:#fff}.badge.warning{background:#F08A24;color:#fff}.badge.alert{background:#F04124;color:#fff}.badge.dark{background:#232323;color:#fff}.inline-list{list-style-type:none;text-align:left}.inline-list dd,.inline-list dt,.inline-list li{display:inline-block;margin-left:-2px;margin-right:-2px}.inline-list li{margin-right:1rem;margin-left:0}.menu-bar{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;margin:0;list-style-type:none}.menu-bar>li{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.menu-bar>li>a{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:1rem;font-size:1rem;line-height:1}.menu-bar{background:#fff}.menu-bar>li>a{color:#000}.menu-bar .is-active>a,.menu-bar>li>a:hover{background:#ededed;color:#000}.menu-bar .iconic *,.menu-bar .iconic .iconic-property-accent{fill:#000;stroke:#000}.menu-bar,.menu-bar.horizontal{overflow-x:hidden;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu-bar.horizontal>li>a,.menu-bar.vertical,.menu-bar>li>a{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.vertical>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu-bar.condense>li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.menu-bar.align-right{-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.menu-bar.align-center{-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.menu-bar.align-justify{-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.menu-bar.align-spaced{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}.menu-bar.small-condense li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.menu-bar.small-expand li{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.menu-bar.small-align-left{-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.menu-bar.small-align-right{-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.menu-bar.small-align-center{-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.menu-bar.small-align-justify{-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.menu-bar.small-align-spaced{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}@media only screen and (min-width:40em){.menu-bar.medium-condense li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.menu-bar.medium-expand li{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.menu-bar.medium-align-left{-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.menu-bar.medium-align-right{-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.menu-bar.medium-align-center{-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.menu-bar.medium-align-justify{-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.menu-bar.medium-align-spaced{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}}@media only screen and (min-width:75em){.menu-bar.large-condense li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.menu-bar.large-expand li{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.menu-bar.large-align-left{-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.menu-bar.large-align-right{-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.menu-bar.large-align-center{-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.menu-bar.large-align-justify{-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.menu-bar.large-align-spaced{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}}.menu-bar.small-horizontal{overflow-x:hidden;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu-bar.small-horizontal>li>a,.menu-bar.small-vertical{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.small-vertical>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}@media only screen and (min-width:40em){.menu-bar.medium-horizontal{overflow-x:hidden;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu-bar.medium-horizontal>li>a,.menu-bar.medium-vertical{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.medium-vertical>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}}@media only screen and (min-width:75em){.menu-bar.large-horizontal{overflow-x:hidden;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu-bar.large-horizontal>li>a,.menu-bar.large-vertical{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.large-vertical>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}}.menu-bar.icon-top>li>.iconic,.menu-bar.icon-top>li>img,.menu-bar>li>.iconic,.menu-bar>li>img{margin:0;width:25px;height:25px}.menu-bar.icon-top>li>a,.menu-bar>li>a{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.icon-top>li>a>.iconic,.menu-bar.icon-top>li>a>img,.menu-bar>li>a>.iconic,.menu-bar>li>a>img{margin:0 0 1rem}.menu-bar.icon-right>li>.iconic,.menu-bar.icon-right>li>img{margin:0;width:25px;height:25px}.menu-bar.icon-right>li>a{-webkit-flex-flow:row-reverse nowrap;-ms-flex-flow:row-reverse nowrap;flex-flow:row-reverse nowrap}.menu-bar.icon-right>li>a>.iconic,.menu-bar.icon-right>li>a>img{margin:0 0 0 1rem}.menu-bar.icon-bottom>li>.iconic,.menu-bar.icon-bottom>li>img{margin:0;width:25px;height:25px}.menu-bar.icon-bottom>li>a{-webkit-flex-flow:column-reverse nowrap;-ms-flex-flow:column-reverse nowrap;flex-flow:column-reverse nowrap}.menu-bar.icon-bottom>li>a>.iconic,.menu-bar.icon-bottom>li>a>img{margin:1rem 0 0}.menu-bar.icon-left>li>.iconic,.menu-bar.icon-left>li>img{margin:0;width:25px;height:25px}.menu-bar.icon-left>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.menu-bar.icon-left>li>a>.iconic,.menu-bar.icon-left>li>a>img{margin:0 1rem 0 0}.menu-bar.small-icon-top>li>.iconic,.menu-bar.small-icon-top>li>img{margin:0;width:25px;height:25px}.menu-bar.small-icon-top>li>a{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.small-icon-top>li>a>.iconic,.menu-bar.small-icon-top>li>a>img{margin:0 0 1rem}.menu-bar.small-icon-right>li>.iconic,.menu-bar.small-icon-right>li>img{margin:0;width:25px;height:25px}.menu-bar.small-icon-right>li>a{-webkit-flex-flow:row-reverse nowrap;-ms-flex-flow:row-reverse nowrap;flex-flow:row-reverse nowrap}.menu-bar.small-icon-right>li>a>.iconic,.menu-bar.small-icon-right>li>a>img{margin:0 0 0 1rem}.menu-bar.small-icon-bottom>li>.iconic,.menu-bar.small-icon-bottom>li>img{margin:0;width:25px;height:25px}.menu-bar.small-icon-bottom>li>a{-webkit-flex-flow:column-reverse nowrap;-ms-flex-flow:column-reverse nowrap;flex-flow:column-reverse nowrap}.menu-bar.small-icon-bottom>li>a>.iconic,.menu-bar.small-icon-bottom>li>a>img{margin:1rem 0 0}.menu-bar.small-icon-left>li>.iconic,.menu-bar.small-icon-left>li>img{margin:0;width:25px;height:25px}.menu-bar.small-icon-left>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.menu-bar.small-icon-left>li>a>.iconic,.menu-bar.small-icon-left>li>a>img{margin:0 1rem 0 0}@media only screen and (min-width:40em){.menu-bar.medium-icon-top>li>.iconic,.menu-bar.medium-icon-top>li>img{margin:0;width:25px;height:25px}.menu-bar.medium-icon-top>li>a{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.medium-icon-top>li>a>.iconic,.menu-bar.medium-icon-top>li>a>img{margin:0 0 1rem}}@media only screen and (min-width:40em){.menu-bar.medium-icon-right>li>.iconic,.menu-bar.medium-icon-right>li>img{margin:0;width:25px;height:25px}.menu-bar.medium-icon-right>li>a{-webkit-flex-flow:row-reverse nowrap;-ms-flex-flow:row-reverse nowrap;flex-flow:row-reverse nowrap}.menu-bar.medium-icon-right>li>a>.iconic,.menu-bar.medium-icon-right>li>a>img{margin:0 0 0 1rem}}@media only screen and (min-width:40em){.menu-bar.medium-icon-bottom>li>.iconic,.menu-bar.medium-icon-bottom>li>img{margin:0;width:25px;height:25px}.menu-bar.medium-icon-bottom>li>a{-webkit-flex-flow:column-reverse nowrap;-ms-flex-flow:column-reverse nowrap;flex-flow:column-reverse nowrap}.menu-bar.medium-icon-bottom>li>a>.iconic,.menu-bar.medium-icon-bottom>li>a>img{margin:1rem 0 0}}@media only screen and (min-width:40em){.menu-bar.medium-icon-left>li>.iconic,.menu-bar.medium-icon-left>li>img{margin:0;width:25px;height:25px}.menu-bar.medium-icon-left>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.menu-bar.medium-icon-left>li>a>.iconic,.menu-bar.medium-icon-left>li>a>img{margin:0 1rem 0 0}}@media only screen and (min-width:75em){.menu-bar.large-icon-top>li>.iconic,.menu-bar.large-icon-top>li>img{margin:0;width:25px;height:25px}.menu-bar.large-icon-top>li>a{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu-bar.large-icon-top>li>a>.iconic,.menu-bar.large-icon-top>li>a>img{margin:0 0 1rem}}@media only screen and (min-width:75em){.menu-bar.large-icon-right>li>.iconic,.menu-bar.large-icon-right>li>img{margin:0;width:25px;height:25px}.menu-bar.large-icon-right>li>a{-webkit-flex-flow:row-reverse nowrap;-ms-flex-flow:row-reverse nowrap;flex-flow:row-reverse nowrap}.menu-bar.large-icon-right>li>a>.iconic,.menu-bar.large-icon-right>li>a>img{margin:0 0 0 1rem}}@media only screen and (min-width:75em){.menu-bar.large-icon-bottom>li>.iconic,.menu-bar.large-icon-bottom>li>img{margin:0;width:25px;height:25px}.menu-bar.large-icon-bottom>li>a{-webkit-flex-flow:column-reverse nowrap;-ms-flex-flow:column-reverse nowrap;flex-flow:column-reverse nowrap}.menu-bar.large-icon-bottom>li>a>.iconic,.menu-bar.large-icon-bottom>li>a>img{margin:1rem 0 0}}@media only screen and (min-width:75em){.menu-bar.large-icon-left>li>.iconic,.menu-bar.large-icon-left>li>img{margin:0;width:25px;height:25px}.menu-bar.large-icon-left>li>a{-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.menu-bar.large-icon-left>li>a>.iconic,.menu-bar.large-icon-left>li>a>img{margin:0 1rem 0 0}}.menu-bar.label-side>li{position:relative}.menu-bar.label-side>li>a{padding-right:3.2rem}.menu-bar.label-side .menu-bar-label{display:block;font-size:.9rem;width:1.2rem;height:1.2rem;line-height:1.2rem;text-align:center;border-radius:1000px;background:red;color:#fff;position:absolute;pointer-events:none;right:1rem;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.menu-bar.label-corner>li{position:relative}.menu-bar.label-corner>li>a{padding-right:3.2rem}.menu-bar.label-corner .menu-bar-label{display:block;font-size:.9rem;width:1.2rem;height:1.2rem;line-height:1.2rem;text-align:center;border-radius:1000px;background:red;color:#fff;position:absolute;pointer-events:none;right:1rem;top:1rem}.menu-bar.primary{background:#00558b}.menu-bar.primary>li>a{color:#fff}.menu-bar.primary .is-active>a,.menu-bar.primary>li>a:hover{background:#0065a5;color:#fff}.menu-bar.primary .iconic *,.menu-bar.primary .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.menu-bar.dark{background:#232323}.menu-bar.dark>li>a{color:#fff}.menu-bar.dark .is-active>a,.menu-bar.dark>li>a:hover{background:#323232;color:#fff}.menu-bar.dark .iconic *,.menu-bar.dark .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.menu-bar>li.title{padding:1rem;cursor:default;font-weight:700}.menu-group{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}@media only screen and (min-width:40em){.menu-group{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}}.menu-group>.menu-group-left,.menu-group>.menu-group-right{-webkit-flex:1 1 100%;-ms-flex:1 1 100%;flex:1 1 100%}@media only screen and (min-width:40em){.menu-group>.menu-group-left,.menu-group>.menu-group-right{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}}.menu-group .menu-bar{margin:0}.menu-group .menu-bar>li{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.menu-group.primary{background-color:#00558b}.menu-group.primary .menu-bar{background:#00558b}.menu-group.primary .menu-bar>li>a{color:#fff}.menu-group.primary .menu-bar .is-active>a,.menu-group.primary .menu-bar>li>a:hover{background:#0065a5;color:#fff}.menu-group.primary .menu-bar .iconic *,.menu-group.primary .menu-bar .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.menu-group.dark{background-color:#232323}.menu-group.dark .menu-bar{background:#232323}.menu-group.dark .menu-bar>li>a{color:#fff}.menu-group.dark .menu-bar .is-active>a,.menu-group.dark .menu-bar>li>a:hover{background:#323232;color:#fff}.menu-group.dark .menu-bar .iconic *,.menu-group.dark .menu-bar .iconic .iconic-property-accent{fill:#fff;stroke:#fff}.modal{position:relative;z-index:1001;background:#fff;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:100%;height:100vh;max-height:100%;overflow:hidden;padding:1rem}@media only screen and (min-width:40em){.modal{height:auto;max-width:600px}}.modal .grid-block,.modal .grid-content{margin:0}.modal .close-button,.modal [fa-close]{z-index:1001}.modal{max-width:600px;border-radius:0}.tiny>.modal{max-width:300px}.small>.modal{max-width:500px}.large>.modal{max-width:800px}.dialog>.modal{height:auto}.collapse>.modal{padding:0}.modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:none;background-color:rgba(51,51,51,.7);-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.modal-overlay.is-active{display:-webkit-flex;display:-ms-flexbox;display:flex}@-webkit-keyframes shake{0%,10%,20%,30%,40%,50%,60%,70%,80%,90%{-webkit-transform:translateX(7%);transform:translateX(7%)}15%,25%,35%,45%,5%,55%,65%,75%,85%,95%{-webkit-transform:translateX(-7%);transform:translateX(-7%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes shake{0%,10%,20%,30%,40%,50%,60%,70%,80%,90%{-webkit-transform:translateX(7%);transform:translateX(7%)}15%,25%,35%,45%,5%,55%,65%,75%,85%,95%{-webkit-transform:translateX(-7%);transform:translateX(-7%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes spin-cw{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spin-cw{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spin-ccw{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}@keyframes spin-ccw{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}@-webkit-keyframes wiggle{40%,50%,60%{-webkit-transform:rotate(7deg);transform:rotate(7deg)}35%,45%,55%,65%{-webkit-transform:rotate(-7deg);transform:rotate(-7deg)}0%,100%,30%,70%{-webkit-transform:rotate(0);transform:rotate(0)}}@keyframes wiggle{40%,50%,60%{-webkit-transform:rotate(7deg);transform:rotate(7deg)}35%,45%,55%,65%{-webkit-transform:rotate(-7deg);transform:rotate(-7deg)}0%,100%,30%,70%{-webkit-transform:rotate(0);transform:rotate(0)}}.slideInDown.ng-enter,.slideInDown.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateY(-100%);transform:translateY(-100%)}.slideInDown.ng-enter.ng-enter-active,.slideInDown.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideInLeft.ng-enter,.slideInLeft.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(100%);transform:translateX(100%)}.slideInLeft.ng-enter.ng-enter-active,.slideInLeft.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideInUp.ng-enter,.slideInUp.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%)}.slideInUp.ng-enter.ng-enter-active,.slideInUp.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideInRight.ng-enter,.slideInRight.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.slideInRight.ng-enter.ng-enter-active,.slideInRight.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideOutBottom.ng-hide-add,.slideOutBottom.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideOutBottom.ng-hide-add.ng-hide-add-active,.slideOutBottom.ng-leave.ng-leave-active{-webkit-transform:translateY(100%);transform:translateY(100%)}.slideOutRight.ng-hide-add,.slideOutRight.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideOutRight.ng-hide-add.ng-hide-add-active,.slideOutRight.ng-leave.ng-leave-active{-webkit-transform:translateX(100%);transform:translateX(100%)}.slideOutUp.ng-hide-add,.slideOutUp.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideOutUp.ng-hide-add.ng-hide-add-active,.slideOutUp.ng-leave.ng-leave-active{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.slideOutLeft.ng-hide-add,.slideOutLeft.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.slideOutLeft.ng-hide-add.ng-hide-add-active,.slideOutLeft.ng-leave.ng-leave-active{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.fadeIn.ng-enter,.fadeIn.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:opacity;opacity:0}.fadeIn.ng-enter.ng-enter-active,.fadeIn.ng-hide-remove.ng-hide-remove-active{opacity:1}.fadeOut.ng-hide-add,.fadeOut.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:opacity;opacity:1}.fadeOut.ng-hide-add.ng-hide-add-active,.fadeOut.ng-leave.ng-leave-active{opacity:0}.hingeInFromTop.ng-enter,.hingeInFromTop.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateX(-90deg);transform:perspective(2000px) rotateX(-90deg);-webkit-transform-origin:top;transform-origin:top;opacity:0}.hingeInFromTop.ng-enter.ng-enter-active,.hingeInFromTop.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeInFromRight.ng-enter,.hingeInFromRight.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateY(-90deg);transform:perspective(2000px) rotateY(-90deg);-webkit-transform-origin:right;transform-origin:right;opacity:0}.hingeInFromRight.ng-enter.ng-enter-active,.hingeInFromRight.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeInFromBottom.ng-enter,.hingeInFromBottom.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateX(90deg);transform:perspective(2000px) rotateX(90deg);-webkit-transform-origin:bottom;transform-origin:bottom;opacity:0}.hingeInFromBottom.ng-enter.ng-enter-active,.hingeInFromBottom.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeInFromLeft.ng-enter,.hingeInFromLeft.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateY(90deg);transform:perspective(2000px) rotateY(90deg);-webkit-transform-origin:left;transform-origin:left;opacity:0}.hingeInFromLeft.ng-enter.ng-enter-active,.hingeInFromLeft.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeInFromMiddleX.ng-enter,.hingeInFromMiddleX.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateX(-90deg);transform:perspective(2000px) rotateX(-90deg);-webkit-transform-origin:center;transform-origin:center;opacity:0}.hingeInFromMiddleX.ng-enter.ng-enter-active,.hingeInFromMiddleX.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeInFromMiddleY.ng-enter,.hingeInFromMiddleY.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:perspective(2000px) rotateY(-90deg);transform:perspective(2000px) rotateY(-90deg);-webkit-transform-origin:center;transform-origin:center;opacity:0}.hingeInFromMiddleY.ng-enter.ng-enter-active,.hingeInFromMiddleY.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.hingeOutFromTop.ng-hide-add,.hingeOutFromTop.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:top;transform-origin:top;opacity:1}.hingeOutFromTop.ng-hide-add.ng-hide-add-active,.hingeOutFromTop.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateX(-90deg);transform:perspective(2000px) rotateX(-90deg);opacity:0}.hingeOutFromRight.ng-hide-add,.hingeOutFromRight.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:right;transform-origin:right;opacity:1}.hingeOutFromRight.ng-hide-add.ng-hide-add-active,.hingeOutFromRight.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateY(-90deg);transform:perspective(2000px) rotateY(-90deg);opacity:0}.hingeOutFromBottom.ng-hide-add,.hingeOutFromBottom.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:bottom;transform-origin:bottom;opacity:1}.hingeOutFromBottom.ng-hide-add.ng-hide-add-active,.hingeOutFromBottom.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateX(90deg);transform:perspective(2000px) rotateX(90deg);opacity:0}.hingeOutFromLeft.ng-hide-add,.hingeOutFromLeft.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:left;transform-origin:left;opacity:1}.hingeOutFromLeft.ng-hide-add.ng-hide-add-active,.hingeOutFromLeft.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateY(90deg);transform:perspective(2000px) rotateY(90deg);opacity:0}.hingeOutFromMiddleX.ng-hide-add,.hingeOutFromMiddleX.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:center;transform-origin:center;opacity:1}.hingeOutFromMiddleX.ng-hide-add.ng-hide-add-active,.hingeOutFromMiddleX.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateX(-90deg);transform:perspective(2000px) rotateX(-90deg);opacity:0}.hingeOutFromMiddleY.ng-hide-add,.hingeOutFromMiddleY.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transform-origin:center;transform-origin:center;opacity:1}.hingeOutFromMiddleY.ng-hide-add.ng-hide-add-active,.hingeOutFromMiddleY.ng-leave.ng-leave-active{-webkit-transform:perspective(2000px) rotateY(-90deg);transform:perspective(2000px) rotateY(-90deg);opacity:0}.zoomIn.ng-enter,.zoomIn.ng-hide-remove{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,property;transition-property:transform,property;-webkit-transform:scale(1.5);transform:scale(1.5);opacity:0}.zoomIn.ng-enter.ng-enter-active,.zoomIn.ng-hide-remove.ng-hide-remove-active{-webkit-transform:scale(1);transform:scale(1);opacity:1}.zoomOut.ng-hide-add,.zoomOut.ng-leave{transition-duration:500ms;transition-timing-function:ease;transition-delay:0;transition-property:-webkit-transform,property;transition-property:transform,property;-webkit-transform:scale(.5);transform:scale(.5);opacity:1}.zoomOut.ng-hide-add.ng-hide-add-active,.zoomOut.ng-leave.ng-leave-active{-webkit-transform:scale(1);transform:scale(1);opacity:0}.spinIn.ng-enter,.spinIn.ng-hide-remove{transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(-270deg);transform:rotate(-270deg);opacity:0}.spinIn.ng-enter.ng-enter-active,.spinIn.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0);transform:rotate(0);opacity:1}.spinOut.ng-hide-add,.spinOut.ng-leave{transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}.spinOut.ng-hide-add.ng-hide-add-active,.spinOut.ng-leave.ng-leave-active{-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:0}.spinInCCW.ng-enter,.spinInCCW.ng-hide-remove{transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:0}.spinInCCW.ng-enter.ng-enter-active,.spinInCCW.ng-hide-remove.ng-hide-remove-active{-webkit-transform:rotate(0);transform:rotate(0);opacity:1}.spinOutCCW.ng-hide-add,.spinOutCCW.ng-leave{transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}.spinOutCCW.ng-hide-add.ng-hide-add-active,.spinOutCCW.ng-leave.ng-leave-active{-webkit-transform:rotate(-270deg);transform:rotate(-270deg);opacity:0}.slow{transition-duration:750ms!important}.fast{transition-duration:250ms!important}.linear{transition-timing-function:linear!important}.ease{transition-timing-function:ease!important}.easeIn{transition-timing-function:ease-in!important}.easeOut{transition-timing-function:ease-out!important}.easeInOut{transition-timing-function:ease-in-out!important}.bounceIn{transition-timing-function:cubic-bezier(.485,.155,.24,1.245)!important}.bounceOut{transition-timing-function:cubic-bezier(.485,.155,.515,.845)!important}.bounceInOut{transition-timing-function:cubic-bezier(.76,-.245,.24,1.245)!important}.delay{transition-delay:300ms!important}.long-delay{transition-delay:700ms!important}.shake{-webkit-animation-name:shake;animation-name:shake;-webkit-animation-duration:500ms;animation-duration:500ms;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-animation-delay:0;animation-delay:0}.spin-cw{-webkit-animation-name:spin-cw;animation-name:spin-cw;-webkit-animation-duration:500ms;animation-duration:500ms;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-animation-delay:0;animation-delay:0}.spin-ccw{-webkit-animation-name:spin-ccw;animation-name:spin-ccw;-webkit-animation-duration:500ms;animation-duration:500ms;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-animation-delay:0;animation-delay:0}.wiggle{-webkit-animation-name:wiggle;animation-name:wiggle;-webkit-animation-duration:500ms;animation-duration:500ms;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-animation-delay:0;animation-delay:0}.shake.infinite,.spin-ccw.infinite,.spin-cw.infinite,.wiggle.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.shake.linear,.spin-ccw.linear,.spin-cw.linear,.wiggle.linear{-webkit-animation-timing-function:linear!important;animation-timing-function:linear!important}.shake.ease,.spin-ccw.ease,.spin-cw.ease,.wiggle.ease{-webkit-animation-timing-function:ease!important;animation-timing-function:ease!important}.shake.easeIn,.spin-ccw.easeIn,.spin-cw.easeIn,.wiggle.easeIn{-webkit-animation-timing-function:ease-in!important;animation-timing-function:ease-in!important}.shake.easeOut,.spin-ccw.easeOut,.spin-cw.easeOut,.wiggle.easeOut{-webkit-animation-timing-function:ease-out!important;animation-timing-function:ease-out!important}.shake.easeInOut,.spin-ccw.easeInOut,.spin-cw.easeInOut,.wiggle.easeInOut{-webkit-animation-timing-function:ease-in-out!important;animation-timing-function:ease-in-out!important}.shake.bounceIn,.spin-ccw.bounceIn,.spin-cw.bounceIn,.wiggle.bounceIn{-webkit-animation-timing-function:cubic-bezier(.485,.155,.24,1.245)!important;animation-timing-function:cubic-bezier(.485,.155,.24,1.245)!important}.shake.bounceOut,.spin-ccw.bounceOut,.spin-cw.bounceOut,.wiggle.bounceOut{-webkit-animation-timing-function:cubic-bezier(.485,.155,.515,.845)!important;animation-timing-function:cubic-bezier(.485,.155,.515,.845)!important}.shake.bounceInOut,.spin-ccw.bounceInOut,.spin-cw.bounceInOut,.wiggle.bounceInOut{-webkit-animation-timing-function:cubic-bezier(.76,-.245,.24,1.245)!important;animation-timing-function:cubic-bezier(.76,-.245,.24,1.245)!important}.shake.slow,.spin-ccw.slow,.spin-cw.slow,.wiggle.slow{-webkit-animation-duration:750ms!important;animation-duration:750ms!important}.shake.fast,.spin-ccw.fast,.spin-cw.fast,.wiggle.fast{-webkit-animation-duration:250ms!important;animation-duration:250ms!important}.shake.delay,.spin-ccw.delay,.spin-cw.delay,.wiggle.delay{-webkit-animation-delay:300ms!important;animation-delay:300ms!important}.shake.long-delay,.spin-ccw.long-delay,.spin-cw.long-delay,.wiggle.long-delay{-webkit-animation-delay:700ms!important;animation-delay:700ms!important}.long-stagger,.stagger,.stort-stagger{transition-delay:150ms;transition-duration:0}.position-absolute{overflow:hidden;position:relative}.ui-animation.ng-enter-active,.ui-animation.ng-leave-active{position:absolute!important;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;top:0;right:0;bottom:0;left:0}.notification,.static-notification{z-index:1000;position:relative;margin-top:.5rem;margin-bottom:.5rem;display:none}.notification h1,.static-notification h1{font-size:1.25em;margin:0}.notification p,.static-notification p{margin:0}.is-active.notification,.is-active.static-notification{display:-webkit-flex;display:-ms-flexbox;display:flex}.notification .close-button,.static-notification .close-button{color:#fff}.notification-container{z-index:3000;position:fixed;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.notification{background:#00558b;padding:1rem;border-radius:4px}.notification,.notification h1,.notification h2,.notification h3,.notification h4,.notification h5,.notification h6{color:#fff}.notification.success{background:#43AC6A;padding:1rem;border-radius:4px}.notification.success,.notification.success h1,.notification.success h2,.notification.success h3,.notification.success h4,.notification.success h5,.notification.success h6{color:#fff}.notification.warning{background:#F08A24;padding:1rem;border-radius:4px}.notification.warning,.notification.warning h1,.notification.warning h2,.notification.warning h3,.notification.warning h4,.notification.warning h5,.notification.warning h6{color:#fff}.notification.alert{background:#F04124;padding:1rem;border-radius:4px}.notification.alert,.notification.alert h1,.notification.alert h2,.notification.alert h3,.notification.alert h4,.notification.alert h5,.notification.alert h6{color:#fff}.notification.dark{background:#232323;padding:1rem;border-radius:4px}.notification.dark,.notification.dark h1,.notification.dark h2,.notification.dark h3,.notification.dark h4,.notification.dark h5,.notification.dark h6{color:#fff}.static-notification{background:#00558b;padding:1rem;border-radius:4px;position:fixed!important}.static-notification,.static-notification h1,.static-notification h2,.static-notification h3,.static-notification h4,.static-notification h5,.static-notification h6{color:#fff}.static-notification.top-right{width:25rem;right:1rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.top-right{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.top-left{width:25rem;left:1rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.top-left{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.top-middle{width:25rem;left:50%;margin-left:-12.5rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.top-middle{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.bottom-right{width:25rem;right:1rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.bottom-right{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.bottom-left{width:25rem;left:1rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.bottom-left{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.bottom-middle{width:25rem;left:50%;margin-left:-12.5rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.static-notification.bottom-middle{width:auto;left:1rem;right:1rem;margin-left:0}}.static-notification.success{background:#43AC6A;padding:1rem;border-radius:4px}.static-notification.success,.static-notification.success h1,.static-notification.success h2,.static-notification.success h3,.static-notification.success h4,.static-notification.success h5,.static-notification.success h6{color:#fff}.static-notification.warning{background:#F08A24;padding:1rem;border-radius:4px}.static-notification.warning,.static-notification.warning h1,.static-notification.warning h2,.static-notification.warning h3,.static-notification.warning h4,.static-notification.warning h5,.static-notification.warning h6{color:#fff}.static-notification.alert{background:#F04124;padding:1rem;border-radius:4px}.static-notification.alert,.static-notification.alert h1,.static-notification.alert h2,.static-notification.alert h3,.static-notification.alert h4,.static-notification.alert h5,.static-notification.alert h6{color:#fff}.static-notification.dark{background:#232323;padding:1rem;border-radius:4px}.static-notification.dark,.static-notification.dark h1,.static-notification.dark h2,.static-notification.dark h3,.static-notification.dark h4,.static-notification.dark h5,.static-notification.dark h6{color:#fff}.notification-container,.notification-container.top-right{width:25rem;right:1rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container{width:auto;left:1rem;right:1rem;margin-left:0}}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.top-right{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-container.top-left{width:25rem;left:1rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.top-left{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-container.top-middle{width:25rem;left:50%;margin-left:-12.5rem;top:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.top-middle{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-container.bottom-right{width:25rem;right:1rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.bottom-right{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-container.bottom-left{width:25rem;left:1rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.bottom-left{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-container.bottom-middle{width:25rem;left:50%;margin-left:-12.5rem;top:auto;bottom:1rem}@media only screen and (min-width:0em) and (max-width:39.9375rem){.notification-container.bottom-middle{width:auto;left:1rem;right:1rem;margin-left:0}}.notification-icon{-webkit-flex:0 0 60px;-ms-flex:0 0 60px;flex:0 0 60px;margin-right:1rem;-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.notification-icon img{width:100%;height:auto}.notification-content{-webkit-flex:1;-ms-flex:1;flex:1}.off-canvas{position:fixed;overflow:auto;-webkit-overflow-scrolling:touch;transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;z-index:2}.is-active.off-canvas{-webkit-transform:translate(0,0)!important;transform:translate(0,0)!important}.off-canvas~.grid-frame{-webkit-transform:translate(0,0,0);transform:translate(0,0,0);transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#fff}.off-canvas{width:250px;height:100%;top:0;left:0;box-shadow:inset -3px 0 10px rgba(0,0,0,.25);-webkit-transform:translateX(-100%);transform:translateX(-100%);background:#fff;color:#000}.off-canvas.is-active~.grid-frame{-webkit-transform:translateX(250px)!important;transform:translateX(250px)!important}.off-canvas.top{height:250px;width:100%;top:0;left:0;-webkit-transform:translateY(-100%);transform:translateY(-100%);box-shadow:inset 0 -3px 10px rgba(0,0,0,.25)}.off-canvas.top.is-active~.grid-frame{-webkit-transform:translateY(250px)!important;transform:translateY(250px)!important}.off-canvas.right{width:250px;height:100%;left:auto;top:0;right:0;box-shadow:inset 3px 0 10px rgba(0,0,0,.25);-webkit-transform:translateX(100%);transform:translateX(100%)}.off-canvas.right.is-active~.grid-frame{-webkit-transform:translateX(-250px)!important;transform:translateX(-250px)!important}.off-canvas.bottom{height:250px;width:100%;top:auto;bottom:0;left:0;-webkit-transform:translateY(100%);transform:translateY(100%);box-shadow:inset 0 3px 10px rgba(0,0,0,.25)}.off-canvas.bottom.is-active~.grid-frame{-webkit-transform:translateY(-250px)!important;transform:translateY(-250px)!important}.off-canvas.left{width:250px;height:100%;top:0;left:0;box-shadow:inset -3px 0 10px rgba(0,0,0,.25);-webkit-transform:translateX(-100%);transform:translateX(-100%)}.off-canvas.left.is-active~.grid-frame{-webkit-transform:translateX(250px)!important;transform:translateX(250px)!important}.off-canvas.detached{z-index:0;box-shadow:none}.off-canvas.detached,.off-canvas.detached.is-active{-webkit-transform:none;transform:none}.off-canvas.detached~.grid-frame{z-index:1;box-shadow:0 0 15px rgba(0,0,0,.5)}.off-canvas.primary{background:#00558b;color:#fff}.off-canvas.dark{background:#232323;color:#fff}.popup{position:absolute;z-index:1000;opacity:0;overflow:hidden;transition:opacity .25s ease-out;pointer-events:none}.tether-enabled.popup{opacity:1;pointer-events:auto}.popup{width:18.75rem;background:#fff;border-radius:0;box-shadow:0 0 10px rgba(0,0,0,.25);border:0}.popup.dark{background:#232323;border-radius:0;box-shadow:0 0 10px rgba(0,0,0,.25);border:0}.popup.primary{background:#00558b;border-radius:0;box-shadow:0 0 10px rgba(0,0,0,.25);border:0}.switch{position:relative;overflow:hidden;display:inline-block}.switch>input{position:absolute;left:-9999px;outline:0}.switch>label{-ms-touch-action:manipulation;touch-action:manipulation;display:block;width:100%;height:100%;cursor:pointer;margin:0}.switch>label::after{content:'';display:block;position:absolute;top:0;left:0}.switch{width:3.125rem;height:2rem;border-radius:9999px}.switch>label::after{width:2rem;height:2rem}.switch input:checked+label::after{left:1.125rem}.switch>label{background:#ccc}.switch>label::after{background:#fff;border-radius:9999px;transition:left .15s ease-out;border:4px solid #ccc}.switch input:checked+label{background:#00558b;margin:0}.switch input:checked+label::after{border-color:#00558b}.switch.small{width:2.5rem;height:1.625rem}.switch.small>label::after{width:1.625rem;height:1.625rem}.switch.small input:checked+label::after{left:.875rem}.switch.large{width:3.75rem;height:2.375rem}.switch.large>label::after{width:2.375rem;height:2.375rem}.switch.large input:checked+label::after{left:1.375rem}.tabs{display:-webkit-flex;display:-ms-flexbox;display:flex;background:0 0;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.tabs.vertical{display:-webkit-flex;display:-ms-flexbox;display:flex;background:0 0;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.tabs .tab-item{background:#f3f3f3;padding:1rem;line-height:1;margin:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;cursor:pointer;color:#000}.tabs .tab-item.is-active{background:#ececec;color:#000}.tabs .tab-item.is-active:hover,.tabs .tab-item:hover{background:#e7e7e7}.tab-contents{padding:1rem}.tab-contents .tab-content{display:none}.tab-contents .tab-content.is-active{display:block}.accordion{border:1px solid #cbcbcb}.accordion-title{padding:1rem;background:#f3f3f3;color:#000;line-height:1;cursor:pointer}.accordion-title:hover{background:#e7e7e7}.is-active>.accordion-title{background:#ececec;color:#000}.accordion-content{padding:1rem;display:none}.is-active>.accordion-content{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}a{color:#00558b;text-decoration:none;line-height:inherit}a[ui-sref]{cursor:pointer}a:focus,a:hover{color:#004978}a img{border:none}p{font-family:inherit;font-weight:400;font-size:1rem;line-height:1.6;margin-bottom:1.25rem;text-rendering:optimizeLegibility}p.lead{font-size:1.21875rem;line-height:1.6}p aside{font-size:.875rem;line-height:1.35;font-style:italic}h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;color:#222;text-rendering:optimizeLegibility;margin-top:.2rem;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:60%;color:#6f6f6f;line-height:0}h1{font-size:2.125rem}h2{font-size:1.6875rem}h3{font-size:1.375rem}h4,h5{font-size:1.125rem}h6{font-size:1rem}.subheader{line-height:1.4;color:#6f6f6f;font-weight:400;margin-top:.2rem;margin-bottom:.5rem}hr{border:solid #ddd;border-width:1px 0 0;clear:both;margin:1.25rem 0 1.1875rem;height:0}em,i{font-style:italic;line-height:inherit}b,strong{font-weight:700;line-height:inherit}small{font-size:60%;color:#6f6f6f;line-height:inherit}code{font-family:Consolas,'Liberation Mono',Courier,monospace;font-weight:400;color:#464646;background-color:#fbfbfb;border-width:1px;border-style:solid;border-color:#e2e2e2;padding:.125rem .3125rem .0625rem}dl,ol,ul{font-size:1rem;line-height:1.6;margin-bottom:1.25rem;list-style-position:outside;font-family:inherit}ol,ul{margin-left:1.1rem}ol li ol,ol li ul,ul li ol,ul li ul{margin-left:1.25rem;margin-bottom:0}ul.no-bullet{margin-left:0}ul.no-bullet,ul.no-bullet li ol,ul.no-bullet li ul{list-style-type:none}dl dt{margin-bottom:.3rem;font-weight:700}dl dd{margin-bottom:.75rem}abbr,acronym{text-transform:uppercase;font-size:90%;color:#222;border-bottom:1px dotted #ddd;cursor:help}abbr{text-transform:none}blockquote{margin:0 0 1.25rem;padding:.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #ddd}blockquote cite{display:block;font-size:.8125rem;color:#555}blockquote cite:before{content:"\2014 \0020"}blockquote cite a,blockquote cite a:visited{color:#555}blockquote,blockquote p{line-height:1.6;color:#6f6f6f}@media only screen and (min-width:40em){h1,h2,h3,h4,h5,h6{line-height:1.4}h1{font-size:2.75rem}h2{font-size:2.3125rem}h3{font-size:1.6875rem}h4{font-size:1.4375rem}h5{font-size:1.125rem}h6{font-size:1rem}}.v-align{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.v-align .align-top{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.v-align .align-center{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.v-align .align-bottom{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.v-align .small-align-top{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.v-align .small-align-center{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.v-align .small-align-bottom{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}@media only screen and (min-width:40em){.v-align .medium-align-top{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}}@media only screen and (min-width:40em){.v-align .medium-align-center{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}}@media only screen and (min-width:40em){.v-align .medium-align-bottom{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}}@media only screen and (min-width:75em){.v-align .large-align-top{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}}@media only screen and (min-width:75em){.v-align .large-align-center{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}}@media only screen and (min-width:75em){.v-align .large-align-bottom{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}}.hide{display:none!important}.invisible{visibility:hidden}.hide-for-small:not(.ng-hide){display:block!important;display:none!important}.hide-for-small[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;display:none!important}.show-for-small:not(.ng-hide){display:none!important;display:block!important}.show-for-small[class*=grid-block]:not(.ng-hide){display:none!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.hide-for-small-only:not(.ng-hide){display:block!important}@media only screen and (min-width:0em) and (max-width:39.9375rem){.hide-for-small-only:not(.ng-hide){display:none!important}}.hide-for-small-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}@media only screen and (min-width:0em) and (max-width:39.9375rem){.hide-for-small-only[class*=grid-block]:not(.ng-hide){display:none!important}}.show-for-small-only:not(.ng-hide),.show-for-small-only[class*=grid-block]:not(.ng-hide){display:none!important}@media only screen and (min-width:0em) and (max-width:39.9375rem){.show-for-small-only:not(.ng-hide){display:block!important}}@media only screen and (min-width:0em) and (max-width:39.9375rem){.show-for-small-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}.hide-for-medium:not(.ng-hide){display:block!important}@media only screen and (min-width:40em){.hide-for-medium:not(.ng-hide){display:none!important}}.hide-for-medium[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}@media only screen and (min-width:40em){.hide-for-medium[class*=grid-block]:not(.ng-hide){display:none!important}}.show-for-medium:not(.ng-hide),.show-for-medium[class*=grid-block]:not(.ng-hide){display:none!important}@media only screen and (min-width:40em){.show-for-medium:not(.ng-hide){display:block!important}}@media only screen and (min-width:40em){.show-for-medium[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}.hide-for-medium-only:not(.ng-hide){display:block!important}@media only screen and (min-width:40em) and (max-width:74.9375rem){.hide-for-medium-only:not(.ng-hide){display:none!important}}.hide-for-medium-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}@media only screen and (min-width:40em) and (max-width:74.9375rem){.hide-for-medium-only[class*=grid-block]:not(.ng-hide){display:none!important}}.show-for-medium-only:not(.ng-hide),.show-for-medium-only[class*=grid-block]:not(.ng-hide){display:none!important}@media only screen and (min-width:40em) and (max-width:74.9375rem){.show-for-medium-only:not(.ng-hide){display:block!important}}@media only screen and (min-width:40em) and (max-width:74.9375rem){.show-for-medium-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}.hide-for-large:not(.ng-hide){display:block!important}@media only screen and (min-width:75em){.hide-for-large:not(.ng-hide){display:none!important}}.hide-for-large[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}@media only screen and (min-width:75em){.hide-for-large[class*=grid-block]:not(.ng-hide){display:none!important}}.show-for-large:not(.ng-hide),.show-for-large[class*=grid-block]:not(.ng-hide){display:none!important}@media only screen and (min-width:75em){.show-for-large:not(.ng-hide){display:block!important}}@media only screen and (min-width:75em){.show-for-large[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}.hide-for-large-only:not(.ng-hide){display:block!important}@media only screen and (min-width:75em) and (max-width:89.9375rem){.hide-for-large-only:not(.ng-hide){display:none!important}}.hide-for-large-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}@media only screen and (min-width:75em) and (max-width:89.9375rem){.hide-for-large-only[class*=grid-block]:not(.ng-hide){display:none!important}}.show-for-landscape,.show-for-large-only:not(.ng-hide),.show-for-large-only[class*=grid-block]:not(.ng-hide),.show-for-portrait{display:none!important}@media only screen and (min-width:75em) and (max-width:89.9375rem){.show-for-large-only:not(.ng-hide){display:block!important}}@media only screen and (min-width:75em) and (max-width:89.9375rem){.show-for-large-only[class*=grid-block]:not(.ng-hide){display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}@media only screen and (orientation:portrait){.hide-for-portrait{display:none!important}.hide-for-portrait[class*=grid-block]{display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}@media only screen and (orientation:portrait){.show-for-portrait{display:block!important}.show-for-portrait[class*=grid-block]{display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}@media only screen and (orientation:landscape){.hide-for-landscape{display:none!important}.hide-for-landscape[class*=grid-block]{display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}@media only screen and (orientation:landscape){.show-for-landscape{display:block!important}.show-for-landscape[class*=grid-block]{display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}}.small-text-left,.text-left{text-align:left}@media only screen and (min-width:0em) and (max-width:39.9375rem){.small-only-text-left{text-align:left}}@media only screen and (min-width:40em){.medium-text-left{text-align:left}}@media only screen and (min-width:40em) and (max-width:74.9375rem){.medium-only-text-left{text-align:left}}@media only screen and (min-width:75em){.large-text-left{text-align:left}}@media only screen and (min-width:75em) and (max-width:89.9375rem){.large-only-text-left{text-align:left}}.small-text-right,.text-right{text-align:right}@media only screen and (min-width:0em) and (max-width:39.9375rem){.small-only-text-right{text-align:right}}@media only screen and (min-width:40em){.medium-text-right{text-align:right}}@media only screen and (min-width:40em) and (max-width:74.9375rem){.medium-only-text-right{text-align:right}}@media only screen and (min-width:75em){.large-text-right{text-align:right}}@media only screen and (min-width:75em) and (max-width:89.9375rem){.large-only-text-right{text-align:right}}.small-text-center,.text-center{text-align:center}@media only screen and (min-width:0em) and (max-width:39.9375rem){.small-only-text-center{text-align:center}}@media only screen and (min-width:40em){.medium-text-center{text-align:center}}@media only screen and (min-width:40em) and (max-width:74.9375rem){.medium-only-text-center{text-align:center}}@media only screen and (min-width:75em){.large-text-center{text-align:center}}@media only screen and (min-width:75em) and (max-width:89.9375rem){.large-only-text-center{text-align:center}}.small-text-justify,.text-justify{text-align:justify}@media only screen and (min-width:0em) and (max-width:39.9375rem){.small-only-text-justify{text-align:justify}}@media only screen and (min-width:40em){.medium-text-justify{text-align:justify}}@media only screen and (min-width:40em) and (max-width:74.9375rem){.medium-only-text-justify{text-align:justify}}@media only screen and (min-width:75em){.large-text-justify{text-align:justify}}@media only screen and (min-width:75em) and (max-width:89.9375rem){.large-only-text-justify{text-align:justify}}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.float-left{float:left}.float-right{float:right}.float-none{float:none} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.js b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.js
new file mode 100644
index 0000000..0225773
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.js
@@ -0,0 +1,170 @@
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/accordion/accordion-item.html',
+ '<div class="accordion-item" ng-class="{\'is-active\': active}">\n' +
+ ' <div class="accordion-title" ng-click="activate()">{{ title }}</div>\n' +
+ ' <div class="accordion-content" ng-transclude></div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/accordion/accordion.html',
+ '<div class="accordion" ng-transclude>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/actionsheet/actionsheet-button.html',
+ '<div>\n' +
+ ' <a href="#"\n' +
+ ' class="button"\n' +
+ ' ng-if="title.length > 0">{{ title }}</a>\n' +
+ ' <div ng-transclude></div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/actionsheet/actionsheet-content.html',
+ '<div\n' +
+ ' class="action-sheet {{ position }}"\n' +
+ ' ng-class="{\'is-active\': active}"\n' +
+ ' >\n' +
+ ' <div\n' +
+ ' ng-transclude>\n' +
+ ' </div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/actionsheet/actionsheet.html',
+ '<div class="action-sheet-container"\n' +
+ ' ng-transclude>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/modal/modal.html',
+ '<div\n' +
+ ' class="modal-overlay"\n' +
+ ' ng-click="hideOverlay()">\n' +
+ ' <aside\n' +
+ ' class="modal"\n' +
+ ' ng-click="$event.stopPropagation();"\n' +
+ ' ng-transclude>\n' +
+ ' </aside>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/notification/notification-set.html',
+ '<div class="notification-container {{position}}">\n' +
+ ' <zf-notification ng-repeat="notification in notifications"\n' +
+ ' title="notification.title"\n' +
+ ' image="notification.image"\n' +
+ ' notif-id = "notification.id"\n' +
+ ' color="notification.color"\n' +
+ ' autoclose="notification.autoclose"\n' +
+ ' >{{ notification.content }}</zf-notification>\n' +
+ '</div>');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/notification/notification-static.html',
+ '<div zf-swipe-close="swipe" class="static-notification {{ color }} {{ position }}">\n' +
+ ' <a href="#"\n' +
+ ' class="close-button"\n' +
+ ' ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>\n' +
+ ' <div class="notification-icon" ng-if="image">\n' +
+ ' <img ng-src="{{ image }}"/>\n' +
+ ' </div>\n' +
+ ' <div class="notification-content">\n' +
+ ' <h1>{{ title }}</h1>\n' +
+ ' <p ng-transclude></p>\n' +
+ ' </div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/notification/notification.html',
+ '<div zf-swipe-close="swipe" class="notification {{ color }}">\n' +
+ ' <a href="#"\n' +
+ ' class="close-button"\n' +
+ ' ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>\n' +
+ ' <div class="notification-icon" ng-if="image">\n' +
+ ' <img ng-src="{{ image }}"/>\n' +
+ ' </div>\n' +
+ ' <div class="notification-content">\n' +
+ ' <h1>{{ title }}</h1>\n' +
+ ' <p ng-transclude></p>\n' +
+ ' </div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/offcanvas/offcanvas.html',
+ '<div\n' +
+ ' class="off-canvas {{ position }}"\n' +
+ ' ng-class="{\'is-active\': active}"\n' +
+ ' ng-transclude>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/panel/panel.html',
+ '<div\n' +
+ ' class="panel"\n' +
+ ' ng-class="positionClass"\n' +
+ ' ng-transclude\n' +
+ ' >\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/popup/popup.html',
+ '<div class="popup" ng-class="{\'is-active\': active }" ng-transclude>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/tabs/tab-content.html',
+ '<div class="tab-contents">\n' +
+ ' <div zf-tab-individual\n' +
+ ' class="tab-content"\n' +
+ ' ng-class="{\'is-active\': tab.active}"\n' +
+ ' ng-repeat="tab in tabs"\n' +
+ ' tab="tab">\n' +
+ ' </div>\n' +
+ '</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/tabs/tab.html',
+ '<div class="tab-item"\n' +
+ ' ng-class="{\'is-active\': active}"\n' +
+ ' ng-click="makeActive()">{{ title }}</div>\n' +
+ '');
+}]);
+
+angular.module('foundation').run(['$templateCache', function($templateCache) {
+ $templateCache.put('components/tabs/tabs.html',
+ '<div>\n' +
+ ' <div class="tabs" ng-transclude>\n' +
+ ' </div>\n' +
+ ' <div zf-tab-content\n' +
+ ' target="{{ id }}"\n' +
+ ' ng-if="showTabContent">\n' +
+ ' </div>\n' +
+ '</div>\n' +
+ '');
+}]);
diff --git a/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.min.js b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.min.js
new file mode 100644
index 0000000..7ab7adb
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps-templates.min.js
@@ -0,0 +1 @@
+angular.module("foundation").run(["$templateCache",function(n){n.put("components/accordion/accordion-item.html",'<div class="accordion-item" ng-class="{\'is-active\': active}">\n <div class="accordion-title" ng-click="activate()">{{ title }}</div>\n <div class="accordion-content" ng-transclude></div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/accordion/accordion.html",'<div class="accordion" ng-transclude>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/actionsheet/actionsheet-button.html",'<div>\n <a href="#"\n class="button"\n ng-if="title.length > 0">{{ title }}</a>\n <div ng-transclude></div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/actionsheet/actionsheet-content.html",'<div\n class="action-sheet {{ position }}"\n ng-class="{\'is-active\': active}"\n >\n <div\n ng-transclude>\n </div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/actionsheet/actionsheet.html",'<div class="action-sheet-container"\n ng-transclude>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/modal/modal.html",'<div\n class="modal-overlay"\n ng-click="hideOverlay()">\n <aside\n class="modal"\n ng-click="$event.stopPropagation();"\n ng-transclude>\n </aside>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/notification/notification-set.html",'<div class="notification-container {{position}}">\n <zf-notification ng-repeat="notification in notifications"\n title="notification.title"\n image="notification.image"\n notif-id = "notification.id"\n color="notification.color"\n autoclose="notification.autoclose"\n >{{ notification.content }}</zf-notification>\n</div>')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/notification/notification-static.html",'<div zf-swipe-close="swipe" class="static-notification {{ color }} {{ position }}">\n <a href="#"\n class="close-button"\n ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>\n <div class="notification-icon" ng-if="image">\n <img ng-src="{{ image }}"/>\n </div>\n <div class="notification-content">\n <h1>{{ title }}</h1>\n <p ng-transclude></p>\n </div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/notification/notification.html",'<div zf-swipe-close="swipe" class="notification {{ color }}">\n <a href="#"\n class="close-button"\n ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>\n <div class="notification-icon" ng-if="image">\n <img ng-src="{{ image }}"/>\n </div>\n <div class="notification-content">\n <h1>{{ title }}</h1>\n <p ng-transclude></p>\n </div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/offcanvas/offcanvas.html",'<div\n class="off-canvas {{ position }}"\n ng-class="{\'is-active\': active}"\n ng-transclude>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/panel/panel.html",'<div\n class="panel"\n ng-class="positionClass"\n ng-transclude\n >\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/popup/popup.html",'<div class="popup" ng-class="{\'is-active\': active }" ng-transclude>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/tabs/tab-content.html",'<div class="tab-contents">\n <div zf-tab-individual\n class="tab-content"\n ng-class="{\'is-active\': tab.active}"\n ng-repeat="tab in tabs"\n tab="tab">\n </div>\n</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/tabs/tab.html",'<div class="tab-item"\n ng-class="{\'is-active\': active}"\n ng-click="makeActive()">{{ title }}</div>\n')}]),angular.module("foundation").run(["$templateCache",function(n){n.put("components/tabs/tabs.html",'<div>\n <div class="tabs" ng-transclude>\n </div>\n <div zf-tab-content\n target="{{ id }}"\n ng-if="showTabContent">\n </div>\n</div>\n')}]); \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.js b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.js
new file mode 100755
index 0000000..1ad0c21
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.js
@@ -0,0 +1,3136 @@
+/*!
+ * iconic.js v0.4.0 - The Iconic JavaScript library
+ * Copyright (c) 2014 Waybury - http://useiconic.com
+ */
+
+!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.IconicJS=a():"undefined"!=typeof global?global.IconicJS=a():"undefined"!=typeof self&&(self.IconicJS=a())}(function(){var a;return function b(a,c,d){function e(g,h){if(!c[g]){if(!a[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};a[g][0].call(j.exports,function(b){var c=a[g][1][b];return e(c?c:b)},j,j.exports,b,a,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){var c=(a("./modules/polyfills"),a("./modules/svg-injector")),d=a("./modules/extend"),e=a("./modules/responsive"),f=a("./modules/position"),g=a("./modules/container"),h=a("./modules/log"),i={},j=window.iconicSmartIconApis={},k=("file:"===window.location.protocol,0),l=function(a,b,e){b=d({},i,b||{});var f={evalScripts:b.evalScripts,pngFallback:b.pngFallback};f.each=function(a){if(a)if("string"==typeof a)h.debug(a);else if(a instanceof SVGSVGElement){var c=a.getAttribute("data-icon");if(c&&j[c]){var d=j[c](a);for(var e in d)a[e]=d[e]}/iconic-bg-/.test(a.getAttribute("class"))&&g.addBackground(a),m(a),k++,b&&b.each&&"function"==typeof b.each&&b.each(a)}},"string"==typeof a&&(a=document.querySelectorAll(a)),c(a,f,e)},m=function(a){var b=[];a?"string"==typeof a?b=document.querySelectorAll(a):void 0!==a.length?b=a:"object"==typeof a&&b.push(a):b=document.querySelectorAll("svg.iconic"),Array.prototype.forEach.call(b,function(a){a instanceof SVGSVGElement&&(a.update&&a.update(),e.refresh(a),f.refresh(a))})},n=function(){i.debug&&console.time&&console.time("autoInjectSelector - "+i.autoInjectSelector);var a=k;l(i.autoInjectSelector,{},function(){if(i.debug&&console.timeEnd&&console.timeEnd("autoInjectSelector - "+i.autoInjectSelector),h.debug("AutoInjected: "+(k-a)),e.refreshAll(),i.autoInjectDone&&"function"==typeof i.autoInjectDone){var b=k-a;i.autoInjectDone(b)}})},o=function(a){a&&""!==a&&"complete"!==document.readyState?document.addEventListener("DOMContentLoaded",n):document.removeEventListener("DOMContentLoaded",n)},p=function(a){return a=a||{},d(i,a),o(i.autoInjectSelector),h.enableDebug(i.debug),window._Iconic?window._Iconic:{inject:l,update:m,smartIconApis:j,svgInjectedCount:k}};b.exports=p,window._Iconic=new p({autoInjectSelector:"img.iconic",evalScripts:"once",pngFallback:!1,each:null,autoInjectDone:null,debug:!1})},{"./modules/container":2,"./modules/extend":3,"./modules/log":4,"./modules/polyfills":5,"./modules/position":6,"./modules/responsive":7,"./modules/svg-injector":8}],2:[function(a,b){var c=function(a){var b=a.getAttribute("class").split(" "),c=-1!==b.indexOf("iconic-fluid"),d=[],e=["iconic-bg"];Array.prototype.forEach.call(b,function(a){switch(a){case"iconic-sm":case"iconic-md":case"iconic-lg":d.push(a),c||e.push(a.replace(/-/,"-bg-"));break;case"iconic-fluid":d.push(a),e.push(a.replace(/-/,"-bg-"));break;case"iconic-bg-circle":case"iconic-bg-rounded-rect":case"iconic-bg-badge":e.push(a);break;default:d.push(a)}}),a.setAttribute("class",d.join(" "));var f=a.parentNode,g=Array.prototype.indexOf.call(f.childNodes,a),h=document.createElement("span");h.setAttribute("class",e.join(" ")),h.appendChild(a),f.insertBefore(h,f.childNodes[g])};b.exports={addBackground:c}},{}],3:[function(a,b){b.exports=function(a){return Array.prototype.forEach.call(Array.prototype.slice.call(arguments,1),function(b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}),a}},{}],4:[function(a,b){var c=!1,d=function(a){console&&console.log&&console.log(a)},e=function(a){d("Iconic INFO: "+a)},f=function(a){d("Iconic WARNING: "+a)},g=function(a){c&&d("Iconic DEBUG: "+a)},h=function(a){c=a};b.exports={info:e,warn:f,debug:g,enableDebug:h}},{}],5:[function(){Array.prototype.forEach||(Array.prototype.forEach=function(a,b){"use strict";if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)}),function(){if(Event.prototype.preventDefault||(Event.prototype.preventDefault=function(){this.returnValue=!1}),Event.prototype.stopPropagation||(Event.prototype.stopPropagation=function(){this.cancelBubble=!0}),!Element.prototype.addEventListener){var a=[],b=function(b,c){var d=this,e=function(a){a.target=a.srcElement,a.currentTarget=d,c.handleEvent?c.handleEvent(a):c.call(d,a)};if("DOMContentLoaded"==b){var f=function(a){"complete"==document.readyState&&e(a)};if(document.attachEvent("onreadystatechange",f),a.push({object:this,type:b,listener:c,wrapper:f}),"complete"==document.readyState){var g=new Event;g.srcElement=window,f(g)}}else this.attachEvent("on"+b,e),a.push({object:this,type:b,listener:c,wrapper:e})},c=function(b,c){for(var d=0;d<a.length;){var e=a[d];if(e.object==this&&e.type==b&&e.listener==c){"DOMContentLoaded"==b?this.detachEvent("onreadystatechange",e.wrapper):this.detachEvent("on"+b,e.wrapper);break}++d}};Element.prototype.addEventListener=b,Element.prototype.removeEventListener=c,HTMLDocument&&(HTMLDocument.prototype.addEventListener=b,HTMLDocument.prototype.removeEventListener=c),Window&&(Window.prototype.addEventListener=b,Window.prototype.removeEventListener=c)}}()},{}],6:[function(a,b){var c=function(a){var b=a.getAttribute("data-position");if(b&&""!==b){var c,d,e,f,g,h,i,j=a.getAttribute("width"),k=a.getAttribute("height"),l=b.split("-"),m=a.querySelectorAll("g.iconic-container");Array.prototype.forEach.call(m,function(a){if(c=a.getAttribute("data-width"),d=a.getAttribute("data-height"),c!==j||d!==k){if(e=a.getAttribute("transform"),f=1,e){var b=e.match(/scale\((\d)/);f=b&&b[1]?b[1]:1}g=Math.floor((j/f-c)/2),h=Math.floor((k/f-d)/2),Array.prototype.forEach.call(l,function(a){switch(a){case"top":h=0;break;case"bottom":h=k/f-d;break;case"left":g=0;break;case"right":g=j/f-c;break;case"center":break;default:console&&console.log&&console.log("Unknown position: "+a)}}),i=0===h?g:g+" "+h,i="translate("+i+")",e?/translate/.test(e)?e=e.replace(/translate\(.*?\)/,i):e+=" "+i:e=i,a.setAttribute("transform",e)}})}};b.exports={refresh:c}},{}],7:[function(a,b){var c=/(iconic-sm\b|iconic-md\b|iconic-lg\b)/,d=function(a,b){var c="undefined"!=typeof window.getComputedStyle&&window.getComputedStyle(a,null).getPropertyValue(b);return!c&&a.currentStyle&&(c=a.currentStyle[b.replace(/([a-z])\-([a-z])/,function(a,b,c){return b+c.toUpperCase()})]||a.currentStyle[b]),c},e=function(a){var b=a.style.display;a.style.display="block";var c=parseFloat(d(a,"width").slice(0,-2)),e=parseFloat(d(a,"height").slice(0,-2));return a.style.display=b,{width:c,height:e}},f=function(){var a="/* Iconic Responsive Support Styles */\n.iconic-property-fill, .iconic-property-text {stroke: none !important;}\n.iconic-property-stroke {fill: none !important;}\nsvg.iconic.iconic-fluid {height:100% !important;width:100% !important;}\nsvg.iconic.iconic-sm:not(.iconic-size-md):not(.iconic-size-lg), svg.iconic.iconic-size-sm{width:16px;height:16px;}\nsvg.iconic.iconic-md:not(.iconic-size-sm):not(.iconic-size-lg), svg.iconic.iconic-size-md{width:32px;height:32px;}\nsvg.iconic.iconic-lg:not(.iconic-size-sm):not(.iconic-size-md), svg.iconic.iconic-size-lg{width:128px;height:128px;}\nsvg.iconic-sm > g.iconic-md, svg.iconic-sm > g.iconic-lg, svg.iconic-md > g.iconic-sm, svg.iconic-md > g.iconic-lg, svg.iconic-lg > g.iconic-sm, svg.iconic-lg > g.iconic-md {display: none;}\nsvg.iconic.iconic-icon-sm > g.iconic-lg, svg.iconic.iconic-icon-md > g.iconic-lg {display:none;}\nsvg.iconic-sm:not(.iconic-icon-md):not(.iconic-icon-lg) > g.iconic-sm, svg.iconic-md.iconic-icon-sm > g.iconic-sm, svg.iconic-lg.iconic-icon-sm > g.iconic-sm {display:inline;}\nsvg.iconic-md:not(.iconic-icon-sm):not(.iconic-icon-lg) > g.iconic-md, svg.iconic-sm.iconic-icon-md > g.iconic-md, svg.iconic-lg.iconic-icon-md > g.iconic-md {display:inline;}\nsvg.iconic-lg:not(.iconic-icon-sm):not(.iconic-icon-md) > g.iconic-lg, svg.iconic-sm.iconic-icon-lg > g.iconic-lg, svg.iconic-md.iconic-icon-lg > g.iconic-lg {display:inline;}";navigator&&navigator.userAgent&&/MSIE 10\.0/.test(navigator.userAgent)&&(a+="svg.iconic{zoom:1.0001;}");var b=document.createElement("style");b.id="iconic-responsive-css",b.type="text/css",b.styleSheet?b.styleSheet.cssText=a:b.appendChild(document.createTextNode(a)),(document.head||document.getElementsByTagName("head")[0]).appendChild(b)},g=function(a){if(/iconic-fluid/.test(a.getAttribute("class"))){var b,d=e(a),f=a.viewBox.baseVal.width/a.viewBox.baseVal.height;b=1===f?Math.min(d.width,d.height):1>f?d.width:d.height;var g;g=32>b?"iconic-sm":b>=32&&128>b?"iconic-md":"iconic-lg";var h=a.getAttribute("class"),i=c.test(h)?h.replace(c,g):h+" "+g;a.setAttribute("class",i)}},h=function(){var a=document.querySelectorAll(".injected-svg.iconic-fluid");Array.prototype.forEach.call(a,function(a){g(a)})};document.addEventListener("DOMContentLoaded",function(){f()}),window.addEventListener("resize",function(){h()}),b.exports={refresh:g,refreshAll:h}},{}],8:[function(b,c,d){!function(b,e){"use strict";function f(a){a=a.split(" ");for(var b={},c=a.length,d=[];c--;)b.hasOwnProperty(a[c])||(b[a[c]]=1,d.unshift(a[c]));return d.join(" ")}var g="file:"===b.location.protocol,h=e.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),i=Array.prototype.forEach||function(a,b){if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)},j={},k=0,l=[],m=[],n={},o=function(a){return a.cloneNode(!0)},p=function(a,b){m[a]=m[a]||[],m[a].push(b)},q=function(a){for(var b=0,c=m[a].length;c>b;b++)!function(b){setTimeout(function(){m[a][b](o(j[a]))},0)}(b)},r=function(a,c){if(void 0!==j[a])j[a]instanceof SVGSVGElement?c(o(j[a])):p(a,c);else{if(!b.XMLHttpRequest)return c("Browser does not support XMLHttpRequest"),!1;j[a]={},p(a,c);var d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState){if(404===d.status||null===d.responseXML)return c("Unable to load SVG file: "+a),g&&c("Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver."),c(),!1;if(!(200===d.status||g&&0===d.status))return c("There was a problem injecting the SVG: "+d.status+" "+d.statusText),!1;if(d.responseXML instanceof Document)j[a]=d.responseXML.documentElement;else if(DOMParser&&DOMParser instanceof Function){var b;try{var e=new DOMParser;b=e.parseFromString(d.responseText,"text/xml")}catch(f){b=void 0}if(!b||b.getElementsByTagName("parsererror").length)return c("Unable to parse SVG file: "+a),!1;j[a]=b.documentElement}q(a)}},d.open("GET",a),d.overrideMimeType&&d.overrideMimeType("text/xml"),d.send()}},s=function(a,c,d,e){var g=a.getAttribute("data-src")||a.getAttribute("src");if(!/svg$/i.test(g))return e("Attempted to inject a file with a non-svg extension: "+g),void 0;if(!h){var j=a.getAttribute("data-fallback")||a.getAttribute("data-png");return j?(a.setAttribute("src",j),e(null)):d?(a.setAttribute("src",d+"/"+g.split("/").pop().replace(".svg",".png")),e(null)):e("This browser does not support SVG and no PNG fallback was defined."),void 0}-1===l.indexOf(a)&&(l.push(a),a.setAttribute("src",""),r(g,function(d){if("undefined"==typeof d||"string"==typeof d)return e(d),!1;var h=a.getAttribute("id");h&&d.setAttribute("id",h);var j=a.getAttribute("title");j&&d.setAttribute("title",j);var m=[].concat(d.getAttribute("class")||[],"injected-svg",a.getAttribute("class")||[]).join(" ");d.setAttribute("class",f(m));var o=a.getAttribute("style");o&&d.setAttribute("style",o);var p=[].filter.call(a.attributes,function(a){return/^data-\w[\w\-]*$/.test(a.name)});i.call(p,function(a){a.name&&a.value&&d.setAttribute(a.name,a.value)});for(var q,r=d.querySelectorAll("defs clipPath[id]"),s=0,t=r.length;t>s;s++){q=r[s].id+"-"+k;for(var u=d.querySelectorAll('[clip-path*="'+r[s].id+'"]'),v=0,w=u.length;w>v;v++)u[v].setAttribute("clip-path","url(#"+q+")");r[s].id=q}d.removeAttribute("xmlns:a");for(var x,y,z=d.querySelectorAll("script"),A=[],B=0,C=z.length;C>B;B++)y=z[B].getAttribute("type"),y&&"application/ecmascript"!==y&&"application/javascript"!==y||(x=z[B].innerText||z[B].textContent,A.push(x),d.removeChild(z[B]));if(A.length>0&&("always"===c||"once"===c&&!n[g])){for(var D=0,E=A.length;E>D;D++)new Function(A[D])(b);n[g]=!0}a.parentNode.replaceChild(d,a),delete l[l.indexOf(a)],a=null,k++,e(d)}))},t=function(a,b,c){b=b||{};var d=b.evalScripts||"always",e=b.pngFallback||!1,f=b.each;if(void 0!==a.length){var g=0;i.call(a,function(b){s(b,d,e,function(b){f&&"function"==typeof f&&f(b),c&&a.length===++g&&c(g)})})}else a?s(a,d,e,function(b){f&&"function"==typeof f&&f(b),c&&c(1),a=null}):c&&c(0)};"object"==typeof c&&"object"==typeof c.exports?c.exports=d=t:"function"==typeof a&&a.amd?a(function(){return t}):"object"==typeof b&&(b.SVGInjector=t)}(window,document)},{}]},{},[1])(1)});
+(function() {
+ 'use strict';
+
+ angular.module('foundation.core.animation', [])
+ .service('FoundationAnimation', FoundationAnimation)
+ ;
+
+ function FoundationAnimation() {
+ var animations = [];
+ var service = {};
+
+ var initClasses = ['ng-enter', 'ng-leave'];
+ var activeClasses = ['ng-enter-active', 'ng-leave-active'];
+ var activeGenericClass = 'is-active';
+ var events = [
+ 'webkitAnimationEnd', 'mozAnimationEnd',
+ 'MSAnimationEnd', 'oanimationend',
+ 'animationend', 'webkitTransitionEnd',
+ 'otransitionend', 'transitionend'
+ ];
+
+ service.animate = animate;
+ service.toggleAnimation = toggleAnimation;
+
+ return service;
+
+ function toggleAnimation(element, futureState) {
+ if(futureState) {
+ element.addClass(activeGenericClass);
+ } else {
+ element.removeClass(activeGenericClass);
+ }
+ }
+
+ function animate(element, futureState, animationIn, animationOut) {
+ var timedOut = true;
+ var self = this;
+ self.cancelAnimation = cancelAnimation;
+
+ var animationClass = futureState ? animationIn: animationOut;
+ var activation = futureState;
+ var initClass = activation ? initClasses[0] : initClasses[1];
+ var activeClass = activation ? activeClasses[0] : activeClasses[1];
+ //stop animation
+ registerElement(element);
+ reset();
+ element.addClass(animationClass);
+ element.addClass(initClass);
+
+ element.addClass(activeGenericClass);
+
+ //force a "tick"
+ reflow();
+
+ //activate
+ element[0].style.transitionDuration = '';
+ element.addClass(activeClass);
+
+ element.one(events.join(' '), function() {
+ finishAnimation();
+ });
+
+ setTimeout(function() {
+ if(timedOut) {
+ finishAnimation();
+ }
+ }, 3000);
+
+ function finishAnimation() {
+ deregisterElement(element);
+ reset(); //reset all classes
+ element[0].style.transitionDuration = '';
+ element.removeClass(!activation ? activeGenericClass : ''); //if not active, remove active class
+ reflow();
+ timedOut = false;
+ }
+
+
+ function cancelAnimation(element) {
+ deregisterElement(element);
+ angular.element(element).off(events.join(' ')); //kill all animation event handlers
+ timedOut = false;
+ }
+
+ function registerElement(el) {
+ var elObj = {
+ el: el,
+ animation: self
+ };
+
+ //kill in progress animations
+ var inProgress = animations.filter(function(obj) {
+ return obj.el === el;
+ });
+ if(inProgress.length > 0) {
+ var target = inProgress[0].el[0];
+
+ inProgress[0].animation.cancelAnimation(target);
+ }
+
+ animations.push(elObj);
+ }
+
+ function deregisterElement(el) {
+ var index;
+ var currentAnimation = animations.filter(function(obj, ind) {
+ if(obj.el === el) {
+ index = ind;
+ }
+ });
+
+ if(index >= 0) {
+ animations.splice(index, 1);
+ }
+
+ }
+
+ function reflow() {
+ return element[0].offsetWidth;
+ }
+
+ function reset() {
+ element[0].style.transitionDuration = 0;
+ element.removeClass(initClasses.join(' ') + ' ' + activeClasses.join(' ') + ' ' + animationIn + ' ' + animationOut);
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.core', [
+ 'foundation.core.animation'
+ ])
+ .service('FoundationApi', FoundationApi)
+ .service('FoundationAdapter', FoundationAdapter)
+ .factory('Utils', Utils)
+ ;
+
+ FoundationApi.$inject = ['FoundationAnimation'];
+
+ function FoundationApi(FoundationAnimation) {
+ var listeners = {};
+ var settings = {};
+ var uniqueIds = [];
+ var service = {};
+
+ service.subscribe = subscribe;
+ service.unsubscribe = unsubscribe;
+ service.publish = publish;
+ service.getSettings = getSettings;
+ service.modifySettings = modifySettings;
+ service.generateUuid = generateUuid;
+ service.toggleAnimate = toggleAnimate;
+ service.closeActiveElements = closeActiveElements;
+ service.animate = animate;
+
+ return service;
+
+ function subscribe(name, callback) {
+ if (!listeners[name]) {
+ listeners[name] = [];
+ }
+
+ listeners[name].push(callback);
+ return true;
+ }
+
+ function unsubscribe(name, callback) {
+ if (listeners[name] !== undefined) {
+ delete listeners[name];
+ }
+ if (typeof callback == 'function') {
+ callback.call(this);
+ }
+ }
+
+ function publish(name, msg) {
+ if (!listeners[name]) {
+ listeners[name] = [];
+ }
+
+ listeners[name].forEach(function(cb) {
+ cb(msg);
+ });
+
+ return;
+ }
+
+ function getSettings() {
+ return settings;
+ }
+
+ function modifySettings(tree) {
+ settings = angular.extend(settings, tree);
+ return settings;
+ }
+
+ function generateUuid() {
+ var uuid = '';
+
+ //little trick to produce semi-random IDs
+ do {
+ uuid += 'zf-uuid-';
+ for (var i=0; i<15; i++) {
+ uuid += Math.floor(Math.random()*16).toString(16);
+ }
+ } while(!uniqueIds.indexOf(uuid));
+
+ uniqueIds.push(uuid);
+ return uuid;
+ }
+
+ function toggleAnimate(element, futureState) {
+ FoundationAnimation.toggleAnimate(element, futureState);
+ }
+
+ function closeActiveElements(options) {
+ var self = this;
+ options = options || {};
+ var activeElements = document.querySelectorAll('.is-active[zf-closable]');
+ // action sheets are nested zf-closable elements, so we have to target the parent
+ var nestedActiveElements = document.querySelectorAll('[zf-closable] > .is-active')
+
+ if (activeElements.length) {
+ angular.forEach(activeElements, function(el) {
+ if (options.exclude !== el.id) {
+ self.publish(el.id, 'close');
+ }
+ });
+ }
+ if (nestedActiveElements.length) {
+ angular.forEach(nestedActiveElements, function(el) {
+ var parentId = el.parentNode.id;
+ if (options.exclude !== parentId) {
+ self.publish(parentId, 'close');
+ }
+ })
+ }
+ }
+
+ function animate(element, futureState, animationIn, animationOut) {
+ FoundationAnimation.animate(element, futureState, animationIn, animationOut);
+ }
+ }
+
+ FoundationAdapter.$inject = ['FoundationApi'];
+
+ function FoundationAdapter(foundationApi) {
+
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+
+ function Utils() {
+ var utils = {};
+
+ utils.throttle = throttleUtil;
+
+ return utils;
+
+ function throttleUtil(func, delay) {
+ var timer = null;
+
+ return function () {
+ var context = this, args = arguments;
+
+ if (timer === null) {
+ timer = setTimeout(function () {
+ func.apply(context, args);
+ timer = null;
+ }, delay);
+ }
+ };
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.dynamicRouting.animations', ['foundation.dynamicRouting'])
+ .directive('uiView', uiView)
+ ;
+
+ uiView.$inject = ['$rootScope', '$state'];
+
+ function uiView($rootScope, $state) {
+ var directive = {
+ restrict : 'ECA',
+ priority : -400,
+ link : link
+ };
+
+ return directive;
+
+ function link(scope, element) {
+ var animation = {};
+ var animationEnded = false;
+ var presetHeight;
+
+ var cleanup = [
+ $rootScope.$on('$stateChangeStart', onStateChangeStart),
+ $rootScope.$on('$stateChangeError', onStateChangeError),
+ scope.$on('$stateChangeSuccess', onStateChangeSuccess),
+ scope.$on('$viewContentAnimationEnded', onViewContentAnimationEnded)
+ ];
+
+ var destroyed = scope.$on('$destroy', function onDestroy() {
+ angular.forEach(cleanup, function (cb) {
+ if (angular.isFunction(cb)) {
+ cb();
+ }
+ });
+
+ destroyed();
+ });
+
+ function onStateChangeStart(event, toState, toParams, fromState, fromParams) {
+
+ if (fromState.animation) {
+ if (!fromState.animation.leave && !toState.animation.leave) {
+ return;
+ }
+ else {
+ animationRouter(event, toState, fromState);
+ }
+ }
+ }
+
+ function animationRouter(event, toState, fromState) {
+ if (!animationEnded) {
+ resetParent();
+ prepareParent();
+
+ element.removeClass(fromState.animation.leave);
+ }
+ else {
+ prepareParent();
+
+ element.addClass(fromState.animation.leave);
+ }
+
+ }
+
+ function onStateChangeError() {
+ if(animation.leave) {
+ element.removeClass(animation.leave);
+ }
+
+ resetParent(); //reset parent if state change fails
+ }
+
+ function onStateChangeSuccess() {
+ resetParent();
+ if ($state.includes(getState()) && animation.enter) {
+ element.addClass(animation.enter);
+ }
+ }
+
+ function onViewContentAnimationEnded(event) {
+ if (event.targetScope === scope && animation.enter) {
+ element.removeClass(animation.enter);
+ }
+
+ animationEnded = true;
+
+ }
+
+ function getState() {
+ var view = element.data('$uiView');
+ var state = view && view.state && view.state.self;
+
+ if (state) {
+ angular.extend(animation, state.animation);
+ }
+
+ return state;
+ }
+
+ function resetParent() {
+ element.parent().removeClass('position-absolute');
+ if(presetHeight !== true) {
+ element.parent()[0].style.height = null;
+ }
+ }
+
+ function prepareParent() {
+ var parentHeight = parseInt(element.parent()[0].style.height);
+ var elHeight = parseInt(window.getComputedStyle(element[0], null).getPropertyValue('height'));
+ var tempHeight = parentHeight > 0 ? parentHeight : elHeight > 0 ? elHeight : '';
+
+ if(parentHeight > 0) {
+ presetHeight = true;
+ }
+
+ element.parent()[0].style.height = tempHeight + 'px';
+ element.parent().addClass('position-absolute');
+ }
+ }
+ }
+
+})();
+(function() {
+ 'use strict';
+
+ angular.module('foundation.dynamicRouting', ['ui.router'])
+ .provider('$FoundationState', FoundationState)
+ .controller('DefaultController', DefaultController)
+ .config(DynamicRoutingConfig)
+ .run(DynamicRoutingRun)
+ ;
+
+ FoundationState.$inject = ['$stateProvider'];
+
+ function FoundationState($stateProvider) {
+ var complexViews = {};
+
+ this.registerDynamicRoutes = function(routes) {
+ var dynamicRoutes = routes || foundationRoutes;
+
+ angular.forEach(dynamicRoutes, function(page) {
+ if (page.hasComposed) {
+ if (!angular.isDefined(complexViews[page.parent])) {
+ complexViews[page.parent] = { children: {} };
+ }
+
+ if (page.controller) {
+ page.controller = getController(page);
+ }
+
+ complexViews[page.parent].children[page.name] = page;
+
+ } else if (page.composed) {
+ if(!angular.isDefined(complexViews[page.name])) {
+ complexViews[page.name] = { children: {} };
+ }
+
+ if (page.controller) {
+ page.controller = getController(page);
+ }
+
+ angular.extend(complexViews[page.name], page);
+ } else {
+ var state = {
+ url: page.url,
+ templateUrl: page.path,
+ abstract: page.abstract || false,
+ parent: page.parent || '',
+ controller: getController(page),
+ data: getData(page),
+ animation: buildAnimations(page),
+ };
+
+ $stateProvider.state(page.name, state);
+ }
+ });
+
+ angular.forEach(complexViews, function(page) {
+ var state = {
+ url: page.url,
+ parent: page.parent || '',
+ abstract: page.abstract || false,
+ data: getData(page),
+ animation: buildAnimations(page),
+ views: {
+ '': buildState(page.path, page)
+ }
+ };
+
+ angular.forEach(page.children, function(sub) {
+ state.views[sub.name + '@' + page.name] = buildState(sub.path, page);
+ });
+
+ $stateProvider.state(page.name, state);
+ });
+ };
+
+ this.$get = angular.noop;
+
+ function getData(page) {
+ var data = { vars: {} };
+ if (page.data) {
+ if (typeof page.data.vars === "object") {
+ data.vars = page.data.vars;
+ }
+ delete page.data.vars;
+ angular.extend(data, page.data);
+ }
+ delete page.data;
+ angular.extend(data.vars, page);
+ return data;
+ }
+
+ function buildState(path, state) {
+ return {
+ templateUrl: path,
+ controller: getController(state),
+ };
+ }
+
+ function getController(state) {
+ var ctrl = state.controller || 'DefaultController';
+
+ if (!/\w\s+as\s+\w/.test(ctrl)) {
+ ctrl += ' as PageCtrl';
+ }
+
+ return ctrl;
+ }
+
+ function buildAnimations(state) {
+ var animations = {};
+
+ if (state.animationIn) {
+ animations.enter = state.animationIn;
+ }
+
+ if (state.animationOut) {
+ animations.leave = state.animationOut;
+ }
+
+ return animations;
+ }
+ }
+
+ DefaultController.$inject = ['$scope', '$stateParams', '$state'];
+
+ function DefaultController($scope, $stateParams, $state) {
+ var params = {};
+ angular.forEach($stateParams, function(value, key) {
+ params[key] = value;
+ });
+
+ $scope.params = params;
+ $scope.current = $state.current.name;
+
+ if($state.current.views) {
+ $scope.vars = $state.current.data.vars;
+ $scope.composed = $state.current.data.vars.children;
+ } else {
+ $scope.vars = $state.current.data.vars;
+ }
+ }
+
+ DynamicRoutingConfig.$inject = ['$FoundationStateProvider'];
+
+ function DynamicRoutingConfig(FoundationStateProvider) {
+ FoundationStateProvider.registerDynamicRoutes(foundationRoutes);
+ }
+
+ DynamicRoutingRun.$inject = ['$rootScope', '$state', '$stateParams'];
+
+ function DynamicRoutingRun($rootScope, $state, $stateParams) {
+ $rootScope.$state = $state;
+ $rootScope.$stateParams = $stateParams;
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.mediaquery', ['foundation.core'])
+ .run(mqInitRun)
+ .factory('FoundationMQInit', FoundationMQInit)
+ .factory('mqHelpers', mqHelpers)
+ .service('FoundationMQ', FoundationMQ)
+ ;
+
+ mqInitRun.$inject = ['FoundationMQInit'];
+
+ function mqInitRun(mqInit) {
+ mqInit.init();
+ }
+
+ FoundationMQInit.$inject = ['mqHelpers', 'FoundationApi', 'Utils'];
+
+ function FoundationMQInit(helpers, foundationApi, u){
+ var factory = {};
+ var namedQueries = {
+ 'default' : 'only screen',
+ landscape : 'only screen and (orientation: landscape)',
+ portrait : 'only screen and (orientation: portrait)',
+ retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
+ 'only screen and (min--moz-device-pixel-ratio: 2),' +
+ 'only screen and (-o-min-device-pixel-ratio: 2/1),' +
+ 'only screen and (min-device-pixel-ratio: 2),' +
+ 'only screen and (min-resolution: 192dpi),' +
+ 'only screen and (min-resolution: 2dppx)'
+ };
+
+ factory.init = init;
+
+ return factory;
+
+ function init() {
+ var mediaQueries;
+ var extractedMedia;
+ var mediaObject;
+
+ helpers.headerHelper(['foundation-mq']);
+ extractedMedia = helpers.getStyle('.foundation-mq', 'font-family');
+
+ mediaQueries = helpers.parseStyleToObject((extractedMedia));
+
+ for(var key in mediaQueries) {
+ mediaQueries[key] = 'only screen and (min-width: ' + mediaQueries[key].replace('rem', 'em') + ')';
+ }
+
+
+ foundationApi.modifySettings({
+ mediaQueries: angular.extend(mediaQueries, namedQueries)
+ });
+
+ window.addEventListener('resize', u.throttle(function() {
+ foundationApi.publish('resize', 'window resized');
+ }, 50));
+
+ }
+ }
+
+
+ function mqHelpers() {
+ var factory = {};
+
+ factory.headerHelper = headerHelper;
+ factory.getStyle = getStyle;
+ factory.parseStyleToObject = parseStyleToObject;
+
+ return factory;
+
+ function headerHelper(classArray) {
+ var i = classArray.length;
+ var head = angular.element(document.querySelectorAll('head'));
+
+ while(i--) {
+ head.append('<meta class="' + classArray[i] + '" />');
+ }
+
+ return;
+ }
+
+ function getStyle(selector, styleName) {
+ var elem = document.querySelectorAll(selector)[0];
+ var style = window.getComputedStyle(elem, null);
+
+ return style.getPropertyValue('font-family');
+ }
+
+ // https://github.com/sindresorhus/query-string
+ function parseStyleToObject(str) {
+ var styleObject = {};
+
+ if (typeof str !== 'string') {
+ return styleObject;
+ }
+
+ str = str.trim().slice(1, -1); // browsers re-quote string style values
+
+ if (!str) {
+ return styleObject;
+ }
+
+ styleObject = str.split('&').reduce(function(ret, param) {
+ var parts = param.replace(/\+/g, ' ').split('=');
+ var key = parts[0];
+ var val = parts[1];
+ key = decodeURIComponent(key);
+
+ // missing `=` should be `null`:
+ // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
+ val = val === undefined ? null : decodeURIComponent(val);
+
+ if (!ret.hasOwnProperty(key)) {
+ ret[key] = val;
+ } else if (Array.isArray(ret[key])) {
+ ret[key].push(val);
+ } else {
+ ret[key] = [ret[key], val];
+ }
+ return ret;
+ }, {});
+
+ return styleObject;
+ }
+ }
+
+ FoundationMQ.$inject = ['FoundationApi'];
+
+ function FoundationMQ(foundationApi) {
+ var service = [];
+
+ service.getMediaQueries = getMediaQueries;
+ service.match = match;
+ service.collectScenariosFromElement = collectScenariosFromElement;
+
+ return service;
+
+ function getMediaQueries() {
+ return foundationApi.getSettings().mediaQueries;
+ }
+
+ function match(scenarios) {
+ var count = scenarios.length;
+ var queries = service.getMediaQueries();
+ var matches = [];
+
+ if (count > 0) {
+ while (count--) {
+ var mq;
+ var rule = scenarios[count].media;
+
+ if (queries[rule]) {
+ mq = matchMedia(queries[rule]);
+ } else {
+ mq = matchMedia(rule);
+ }
+
+ if (mq.matches) {
+ matches.push({ ind: count});
+ }
+ }
+ }
+
+ return matches;
+ }
+
+ // Collects a scenario object and templates from element
+ function collectScenariosFromElement(parentElement) {
+ var scenarios = [];
+ var templates = [];
+
+ var elements = parentElement.children();
+ var i = 0;
+
+ angular.forEach(elements, function(el) {
+ var elem = angular.element(el);
+
+
+ //if no source or no html, capture element itself
+ if (!elem.attr('src') || !elem.attr('src').match(/.html$/)) {
+ templates[i] = elem;
+ scenarios[i] = { media: elem.attr('media'), templ: i };
+ } else {
+ scenarios[i] = { media: elem.attr('media'), src: elem.attr('src') };
+ }
+
+ i++;
+ });
+
+ return {
+ scenarios: scenarios,
+ templates: templates
+ };
+ }
+ }
+})();
+
+angular.module('markdown', [])
+ .directive('markdown', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs, controller) {
+ element.html(marked(element.html()));
+ }
+ };
+
+});
+
+'use strict';
+
+(function(){
+ var svgDirectives = {};
+
+ angular.forEach([
+ 'clipPath',
+ 'colorProfile',
+ 'src',
+ 'cursor',
+ 'fill',
+ 'filter',
+ 'marker',
+ 'markerStart',
+ 'markerMid',
+ 'markerEnd',
+ 'mask',
+ 'stroke'
+ ],
+ function(attr) {
+ svgDirectives[attr] = [
+ '$rootScope',
+ '$location',
+ '$interpolate',
+ '$sniffer',
+ 'urlResolve',
+ 'computeSVGAttrValue',
+ 'svgAttrExpressions',
+ function(
+ $rootScope,
+ $location,
+ $interpolate,
+ $sniffer,
+ urlResolve,
+ computeSVGAttrValue,
+ svgAttrExpressions) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ var initialUrl;
+
+ //Only apply to svg elements to avoid unnecessary observing
+ //Check that is in html5Mode and that history is supported
+ if ((!svgAttrExpressions.SVG_ELEMENT.test(element[0] &&
+ element[0].toString())) ||
+ !$location.$$html5 ||
+ !$sniffer.history) return;
+
+ //Assumes no expressions, since svg is unforgiving of xml violations
+ initialUrl = attrs[attr];
+ attrs.$observe(attr, updateValue);
+ $rootScope.$on('$locationChangeSuccess', updateValue);
+
+ function updateValue () {
+ var newVal = computeSVGAttrValue(initialUrl);
+ //Prevent recursive updating
+ if (newVal && attrs[attr] !== newVal) attrs.$set(attr, newVal);
+ }
+ }
+ };
+ }];
+ });
+
+ angular.module('ngSVGAttributes', []).
+ factory('urlResolve', [function() {
+ //Duplicate of urlResolve & urlParsingNode in angular core
+ var urlParsingNode = document.createElement('a');
+ return function urlResolve(url) {
+ urlParsingNode.setAttribute('href', url);
+ return urlParsingNode;
+ };
+ }]).
+ value('svgAttrExpressions', {
+ FUNC_URI: /^url\((.*)\)$/,
+ SVG_ELEMENT: /SVG[a-zA-Z]*Element/,
+ HASH_PART: /#.*/
+ }).
+ factory('computeSVGAttrValue', [
+ '$location', '$sniffer', 'svgAttrExpressions', 'urlResolve',
+ function($location, $sniffer, svgAttrExpressions, urlResolve) {
+ return function computeSVGAttrValue(url) {
+ var match, fullUrl;
+ if (match = svgAttrExpressions.FUNC_URI.exec(url)) {
+ //hash in html5Mode, forces to be relative to current url instead of base
+ if (match[1].indexOf('#') === 0) {
+ fullUrl = $location.absUrl().
+ replace(svgAttrExpressions.HASH_PART, '') +
+ match[1];
+ }
+ //Presumably links to external SVG document
+ else {
+ fullUrl = urlResolve(match[1]);
+ }
+ }
+ return fullUrl ? 'url(' + fullUrl + ')' : null;
+ };
+ }
+ ]
+ ).
+ directive(svgDirectives);
+}());
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.accordion', [])
+ .controller('ZfAccordionController', zfAccordionController)
+ .directive('zfAccordion', zfAccordion)
+ .directive('zfAccordionItem', zfAccordionItem)
+ ;
+
+ zfAccordionController.$inject = ['$scope'];
+
+ function zfAccordionController($scope) {
+ var controller = this;
+ var sections = controller.sections = $scope.sections = [];
+ var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false;
+ var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true
+ var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render
+
+ controller.select = function(selectSection) {
+ sections.forEach(function(section) {
+ //if multi open is allowed, toggle a tab
+ if(controller.multiOpen) {
+ if(section.scope === selectSection) {
+ section.scope.active = !section.scope.active;
+ }
+ } else {
+ //non multi open will close all tabs and open one
+ if(section.scope === selectSection) {
+ //if collapsible is allowed, a tab will toggle
+ section.scope.active = collapsible ? !section.scope.active : true;
+ } else {
+ section.scope.active = false;
+ }
+ }
+
+ });
+ };
+
+ controller.addSection = function addsection(sectionScope) {
+ sections.push({ scope: sectionScope });
+
+ if(sections.length === 1 && autoOpen === true) {
+ sections[0].active = true;
+ sections[0].scope.active = true;
+ }
+ };
+
+ controller.closeAll = function() {
+ sections.forEach(function(section) {
+ section.scope.active = false;
+ });
+ };
+ }
+
+ function zfAccordion() {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ replace: true,
+ templateUrl: 'components/accordion/accordion.html',
+ controller: 'ZfAccordionController',
+ scope: {
+ multiOpen: '@?',
+ collapsible: '@?',
+ autoOpen: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false;
+ scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false;
+ scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false;
+ }
+ }
+
+ //accordion item
+ function zfAccordionItem() {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/accordion/accordion-item.html',
+ transclude: true,
+ scope: {
+ title: '@'
+ },
+ require: '^zfAccordion',
+ replace: true,
+ controller: function() {},
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller, transclude) {
+ scope.active = false;
+ controller.addSection(scope);
+
+ scope.activate = function() {
+ controller.select(scope);
+ };
+
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.actionsheet', ['foundation.core'])
+ .controller('ZfActionSheetController', zfActionSheetController)
+ .directive('zfActionSheet', zfActionSheet)
+ .directive('zfAsContent', zfAsContent)
+ .directive('zfAsButton', zfAsButton)
+ .service('FoundationActionSheet', FoundationActionSheet)
+ ;
+
+ FoundationActionSheet.$inject = ['FoundationApi'];
+
+ function FoundationActionSheet(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+ zfActionSheetController.$inject = ['$scope', 'FoundationApi'];
+
+ function zfActionSheetController($scope, foundationApi) {
+ var controller = this;
+ var content = controller.content = $scope.content;
+ var container = controller.container = $scope.container;
+ var body = angular.element(document.body);
+
+ controller.registerContent = function(scope) {
+ content = scope;
+ content.active = false;
+ };
+
+ controller.registerContainer = function(scope) {
+ container = scope;
+ container.active = false;
+ };
+
+ controller.toggle = toggle;
+ controller.hide = hide;
+
+ controller.registerListener = function() {
+ document.body.addEventListener('click', listenerLogic);
+ };
+
+ controller.deregisterListener = function() {
+ document.body.removeEventListener('click', listenerLogic);
+ }
+
+ function listenerLogic(e) {
+ var el = e.target;
+ var insideActionSheet = false;
+
+ do {
+ if(el.classList && el.classList.contains('action-sheet-container')) {
+ insideActionSheet = true;
+ break;
+ }
+
+ } while ((el = el.parentNode));
+
+ if(!insideActionSheet) {
+ // if the element has a toggle attribute, do nothing
+ if (e.target.attributes['zf-toggle'] || e.target.attributes['zf-hard-toggle']) {
+ return;
+ };
+ // if the element is outside the action sheet and is NOT a toggle element, hide
+ hide();
+ }
+ }
+
+ function hide() {
+ content.hide();
+ container.hide();
+
+ content.$apply();
+ container.$apply();
+ }
+
+ function toggle() {
+ content.toggle();
+ container.toggle();
+
+ content.$apply();
+ container.$apply();
+ }
+ }
+
+ zfActionSheet.$inject = ['FoundationApi'];
+
+ function zfActionSheet(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet.html',
+ controller: 'ZfActionSheetController',
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'actionsheet');
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ var id = attrs.id || foundationApi.generateUuid();
+ attrs.$set('id', id);
+
+ scope.active = false;
+
+ foundationApi.subscribe(id, function(msg) {
+ if (msg === 'toggle') {
+ controller.toggle();
+ }
+
+ if (msg === 'hide' || msg === 'close') {
+ controller.hide();
+ }
+
+ });
+
+ controller.registerContainer(scope);
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ return;
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ return;
+ };
+ }
+ }
+ }
+
+ zfAsContent.$inject = ['FoundationApi'];
+
+ function zfAsContent(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet-content.html',
+ require: '^zfActionSheet',
+ scope: {
+ position: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.active = false;
+ scope.position = scope.position || 'bottom';
+ controller.registerContent(scope);
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ if(scope.active) {
+ controller.registerListener();
+ } else {
+ controller.deregisterListener();
+ }
+
+ return;
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ controller.deregisterListener();
+ return;
+ };
+ }
+ }
+
+ zfAsButton.$inject = ['FoundationApi'];
+
+ function zfAsButton(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet-button.html',
+ require: '^zfActionSheet',
+ scope: {
+ title: '@?'
+ },
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+
+ element.on('click', function(e) {
+ controller.toggle();
+ e.preventDefault();
+ });
+
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.common', ['foundation.core'])
+ .directive('zfClose', zfClose)
+ .directive('zfOpen', zfOpen)
+ .directive('zfToggle', zfToggle)
+ .directive('zfEscClose', zfEscClose)
+ .directive('zfSwipeClose', zfSwipeClose)
+ .directive('zfHardToggle', zfHardToggle)
+ ;
+
+ zfClose.$inject = ['FoundationApi'];
+
+ function zfClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ var targetId = '';
+ if (attrs.zfClose) {
+ targetId = attrs.zfClose;
+ } else {
+ var parentElement= false;
+ var tempElement = element.parent();
+ //find parent modal
+ while(parentElement === false) {
+ if(tempElement[0].nodeName == 'BODY') {
+ parentElement = '';
+ }
+
+ if(typeof tempElement.attr('zf-closable') !== 'undefined' && tempElement.attr('zf-closable') !== false) {
+ parentElement = tempElement;
+ }
+
+ tempElement = tempElement.parent();
+ }
+ targetId = parentElement.attr('id');
+ }
+
+ element.on('click', function(e) {
+ foundationApi.publish(targetId, 'close');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfOpen.$inject = ['FoundationApi'];
+
+ function zfOpen(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfOpen, 'open');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfToggle.$inject = ['FoundationApi'];
+
+ function zfToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfToggle, 'toggle');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfEscClose.$inject = ['FoundationApi'];
+
+ function zfEscClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('keyup', function(e) {
+ if (e.keyCode === 27) {
+ foundationApi.closeActiveElements();
+ }
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfSwipeClose.$inject = ['FoundationApi'];
+
+ function zfSwipeClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+ return directive;
+
+ function link($scope, element, attrs) {
+ var swipeDirection;
+ var hammerElem;
+ if (Hammer) {
+ hammerElem = new Hammer(element[0]);
+ // set the options for swipe (to make them a bit more forgiving in detection)
+ hammerElem.get('swipe').set({
+ direction: Hammer.DIRECTION_ALL,
+ threshold: 5, // this is how far the swipe has to travel
+ velocity: 0.5 // and this is how fast the swipe must travel
+ });
+ }
+ // detect what direction the directive is pointing
+ switch (attrs.zfSwipeClose) {
+ case 'right':
+ swipeDirection = 'swiperight';
+ break;
+ case 'left':
+ swipeDirection = 'swipeleft';
+ break;
+ case 'up':
+ swipeDirection = 'swipeup';
+ break;
+ case 'down':
+ swipeDirection = 'swipedown';
+ break;
+ default:
+ swipeDirection = 'swipe';
+ }
+ hammerElem.on(swipeDirection, function() {
+ foundationApi.publish(attrs.id, 'close');
+ });
+ }
+ }
+
+ zfHardToggle.$inject = ['FoundationApi'];
+
+ function zfHardToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.closeActiveElements({exclude: attrs.zfHardToggle});
+ foundationApi.publish(attrs.zfHardToggle, 'toggle');
+ e.preventDefault();
+ });
+ }
+ }
+
+})();
+
+(function () {
+ 'use strict';
+
+ angular.module('foundation.iconic', [])
+ .provider('Iconic', Iconic)
+ .directive('zfIconic', zfIconic)
+ ;
+
+ // iconic wrapper
+ function Iconic() {
+ // default path
+ var assetPath = 'assets/img/iconic/';
+
+ /**
+ * Sets the path used to locate the iconic SVG files
+ * @param {string} path - the base path used to locate the iconic SVG files
+ */
+ this.setAssetPath = function (path) {
+ assetPath = angular.isString(path) ? path : assetPath;
+ };
+
+ /**
+ * Service implementation
+ * @returns {{}}
+ */
+ this.$get = function () {
+ var iconicObject = new IconicJS();
+
+ var service = {
+ getAccess: getAccess,
+ getAssetPath: getAssetPath
+ };
+
+ return service;
+
+ /**
+ *
+ * @returns {Window.IconicJS}
+ */
+ function getAccess() {
+ return iconicObject;
+ }
+
+ /**
+ *
+ * @returns {string}
+ */
+ function getAssetPath() {
+ return assetPath;
+ }
+ };
+ }
+
+ zfIconic.$inject = ['Iconic', 'FoundationApi', '$compile'];
+
+ function zfIconic(iconic, foundationApi, $compile) {
+ var directive = {
+ restrict: 'A',
+ template: '<img ng-transclude>',
+ transclude: true,
+ replace: true,
+ scope: {
+ dynSrc: '=?',
+ dynIcon: '=?',
+ size: '@?',
+ icon: '@',
+ iconDir: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ var contents, assetPath;
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, element, attrs) {
+
+ if (scope.iconDir) {
+ // path set via attribute
+ assetPath = scope.iconDir;
+ } else {
+ // default path
+ assetPath = iconic.getAssetPath();
+ }
+ // make sure ends with /
+ if (assetPath.charAt(assetPath.length - 1) !== '/') {
+ assetPath += '/';
+ }
+
+ if (scope.dynSrc) {
+ attrs.$set('data-src', scope.dynSrc);
+ } else if (scope.dynIcon) {
+ attrs.$set('data-src', assetPath + scope.dynIcon + '.svg');
+ } else {
+ if (scope.icon) {
+ attrs.$set('data-src', assetPath + scope.icon + '.svg');
+ } else {
+ // To support expressions on data-src
+ attrs.$set('data-src', attrs.src);
+ }
+ }
+
+ // check if size already added as class
+ if (!element.hasClass('iconic-sm') && !element.hasClass('iconic-md') && !element.hasClass('iconic-lg')) {
+ var iconicClass;
+ switch (scope.size) {
+ case 'small':
+ iconicClass = 'iconic-sm';
+ break;
+ case 'medium':
+ iconicClass = 'iconic-md';
+ break;
+ case 'large':
+ iconicClass = 'iconic-lg';
+ break;
+ default:
+ iconicClass = 'iconic-fluid';
+ }
+ element.addClass(iconicClass);
+ }
+
+ // save contents of un-inject html, to use for dynamic re-injection
+ contents = element[0].outerHTML;
+ }
+
+ function postLink(scope, element, attrs) {
+ var svgElement, ico = iconic.getAccess();
+
+ injectSvg(element[0]);
+
+ foundationApi.subscribe('resize', function () {
+ // only run update on current element
+ ico.update(element[0]);
+ });
+
+ // handle dynamic updating of src
+ if (scope.dynSrc) {
+ scope.$watch('dynSrc', function (newVal, oldVal) {
+ if (newVal && newVal !== oldVal) {
+ reinjectSvg(scope.dynSrc);
+ }
+ });
+ }
+ // handle dynamic updating of icon
+ if (scope.dynIcon) {
+ scope.$watch('dynIcon', function (newVal, oldVal) {
+ if (newVal && newVal !== oldVal) {
+ reinjectSvg(assetPath + scope.dynIcon + '.svg');
+ }
+ });
+ }
+
+ function reinjectSvg(newSrc) {
+ if (svgElement) {
+ // set html
+ svgElement.empty();
+ svgElement.append(angular.element(contents));
+
+ // set new source
+ svgElement.attr('data-src', newSrc);
+
+ // reinject
+ injectSvg(svgElement[0]);
+ }
+ }
+
+ function injectSvg(element) {
+ ico.inject(element, {
+ each: function (injectedElem) {
+ // compile injected svg
+ var angElem = angular.element(injectedElem);
+ svgElement = $compile(angElem)(angElem.scope());
+ }
+ });
+ }
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.interchange', ['foundation.core', 'foundation.mediaquery'])
+ .directive('zfInterchange', zfInterchange)
+ ;
+
+ zfInterchange.$inject = [ '$compile', '$http', '$templateCache', 'FoundationApi', 'FoundationMQ'];
+
+ function zfInterchange($compile, $http, $templateCache, foundationApi, foundationMQ) {
+
+ var directive = {
+ restrict: 'EA',
+ transclude: 'element',
+ scope: {
+ position: '@'
+ },
+ replace: true,
+ template: '<div></div>',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var childScope, current, scenarios, innerTemplates;
+
+ var globalQueries = foundationMQ.getMediaQueries();
+
+ //setup
+ foundationApi.subscribe('resize', function(msg) {
+ transclude(function(clone, newScope) {
+ if(!scenarios || !innerTemplates) {
+ collectInformation(clone);
+ }
+
+ var ruleMatches = foundationMQ.match(scenarios);
+ var scenario = ruleMatches.length === 0 ? null : scenarios[ruleMatches[0].ind];
+
+ //this could use some love
+ if(scenario && checkScenario(scenario)) {
+ var compiled;
+
+ if(childScope) {
+ childScope.$destroy();
+ childScope = null;
+ }
+
+ if(typeof scenario.templ !== 'undefined') {
+ childScope = newScope;
+
+ //temp container
+ var tmp = document.createElement('div');
+ tmp.appendChild(innerTemplates[scenario.templ][0]);
+
+ element.html(tmp.innerHTML);
+ $compile(element.contents())(childScope);
+ current = scenario;
+ } else {
+ var loader = templateLoader(scenario.src);
+ loader.success(function(html) {
+ childScope = newScope;
+ element.html(html);
+ }).then(function(){
+ $compile(element.contents())(childScope);
+ current = scenario;
+ });
+ }
+ }
+ });
+
+ });
+
+ //init
+ foundationApi.publish('resize', 'initial resize');
+
+ function templateLoader(templateUrl) {
+ return $http.get(templateUrl, {cache: $templateCache});
+ }
+
+ function collectInformation(el) {
+ var data = foundationMQ.collectScenariosFromElement(el);
+
+ scenarios = data.scenarios;
+ innerTemplates = data.templates;
+ }
+
+ function checkScenario(scenario) {
+ return !current || current !== scenario;
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.modal', ['foundation.core'])
+ .directive('zfModal', modalDirective)
+ .factory('ModalFactory', ModalFactory)
+ ;
+
+ FoundationModal.$inject = ['FoundationApi', 'ModalFactory'];
+
+ function FoundationModal(foundationApi, ModalFactory) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+ service.newModal = newModal;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ //new modal has to be controlled via the new instance
+ function newModal(config) {
+ return new ModalFactory(config);
+ }
+ }
+
+ modalDirective.$inject = ['FoundationApi'];
+
+ function modalDirective(foundationApi) {
+
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/modal/modal.html',
+ transclude: true,
+ scope: true,
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'modal';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ }
+
+ function postLink(scope, element, attrs) {
+ var dialog = angular.element(element.children()[0]);
+
+ scope.active = scope.active || false;
+ scope.overlay = attrs.overlay === 'false' ? false : true;
+ scope.overlayClose = attrs.overlayClose === 'false' ? false : true;
+
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+
+ var overlayIn = 'fadeIn';
+ var overlayOut = 'fadeOut';
+
+ scope.hideOverlay = function() {
+ if(scope.overlayClose) {
+ scope.hide();
+ }
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ animate();
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ animate();
+ dialog.tabIndex = -1;
+ dialog[0].focus();
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ animate();
+ return;
+ };
+
+ init();
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'show' || msg === 'open') {
+ scope.show();
+ } else if (msg === 'close' || msg === 'hide') {
+ scope.hide();
+ } else if (msg === 'toggle') {
+ scope.toggle();
+ }
+
+ if (scope.$root && !scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ function animate() {
+ //animate both overlay and dialog
+ if(!scope.overlay) {
+ element.css('background', 'transparent');
+ }
+
+ foundationApi.animate(element, scope.active, overlayIn, overlayOut);
+ foundationApi.animate(dialog, scope.active, animationIn, animationOut);
+ }
+
+ function init() {
+ if(scope.active) {
+ scope.show();
+ }
+ }
+ }
+ }
+ }
+
+ ModalFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', '$q', 'FoundationApi'];
+
+ function ModalFactory($http, $templateCache, $rootScope, $compile, $timeout, $q, foundationApi) {
+ return modalFactory;
+
+ function modalFactory(config) {
+ var self = this, //for prototype functions
+ container = angular.element(config.container || document.body),
+ id = config.id || foundationApi.generateUuid(),
+ attached = false,
+ destroyed = false,
+ html,
+ element,
+ fetched,
+ scope,
+ contentScope
+ ;
+
+ var props = [
+ 'animationIn',
+ 'animationOut',
+ 'overlay',
+ 'overlayClose'
+ ];
+
+ if(config.templateUrl) {
+ //get template
+ fetched = $http.get(config.templateUrl, {
+ cache: $templateCache
+ }).then(function (response) {
+ html = response.data;
+ assembleDirective();
+ });
+
+ } else if(config.template) {
+ //use provided template
+ fetched = true;
+ html = config.template;
+ assembleDirective();
+ }
+
+ self.activate = activate;
+ self.deactivate = deactivate;
+ self.toggle = toggle;
+ self.destroy = destroy;
+
+
+ return {
+ activate: activate,
+ deactivate: deactivate,
+ toggle: toggle,
+ destroy: destroy
+ };
+
+ function checkStatus() {
+ if(destroyed) {
+ throw "Error: Modal was destroyed. Delete the object and create a new ModalFactory instance."
+ }
+ }
+
+ function activate() {
+ checkStatus();
+ $timeout(function() {
+ init(true);
+ foundationApi.publish(id, 'show');
+ }, 0, false);
+ }
+
+ function deactivate() {
+ checkStatus();
+ $timeout(function() {
+ init(false);
+ foundationApi.publish(id, 'hide');
+ }, 0, false);
+ }
+
+ function toggle() {
+ checkStatus();
+ $timeout(function() {
+ init(true);
+ foundationApi.publish(id, 'toggle');
+ }, 0, false);
+ }
+
+ function init(state) {
+ $q.when(fetched).then(function() {
+ if(!attached && html.length > 0) {
+ var modalEl = container.append(element);
+
+ scope.active = state;
+ $compile(element)(scope);
+
+ attached = true;
+ }
+ });
+ }
+
+ function assembleDirective() {
+ // check for duplicate elements to prevent factory from cloning modals
+ if (document.getElementById(id)) {
+ return;
+ }
+
+ html = '<zf-modal id="' + id + '">' + html + '</zf-modal>';
+
+ element = angular.element(html);
+
+ scope = $rootScope.$new();
+
+ // account for directive attributes
+ for(var i = 0; i < props.length; i++) {
+ var prop = props[i];
+
+ if(config[prop]) {
+ switch (prop) {
+ case 'animationIn':
+ element.attr('animation-in', config[prop]);
+ break;
+ case 'animationOut':
+ element.attr('animation-out', config[prop]);
+ break;
+ default:
+ element.attr(prop, config[prop]);
+ }
+ }
+ }
+ // access view scope variables
+ if (config.contentScope) {
+ contentScope = config.contentScope;
+ for (var prop in config.contentScope) {
+ if (config.contentScope.hasOwnProperty(prop)) {
+ scope[prop] = config.contentScope[prop];
+ }
+ }
+ }
+ }
+
+ function destroy() {
+ self.deactivate();
+ setTimeout(function() {
+ scope.$destroy();
+ element.remove();
+ destroyed = true;
+ }, 3000);
+ foundationApi.unsubscribe(id);
+ }
+
+ }
+
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.notification', ['foundation.core'])
+ .controller('ZfNotificationController', ZfNotificationController)
+ .directive('zfNotificationSet', zfNotificationSet)
+ .directive('zfNotification', zfNotification)
+ .directive('zfNotificationStatic', zfNotificationStatic)
+ .directive('zfNotify', zfNotify)
+ .factory('NotificationFactory', NotificationFactory)
+ .service('FoundationNotification', FoundationNotification)
+ ;
+
+ FoundationNotification.$inject = ['FoundationApi', 'NotificationFactory'];
+
+ function FoundationNotification(foundationApi, NotificationFactory) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target) {
+ foundationApi.publish(target, 'toggle');
+ }
+
+ function createNotificationSet(config) {
+ return new NotificationFactory(config);
+ }
+ }
+
+
+ ZfNotificationController.$inject = ['$scope', 'FoundationApi'];
+
+ function ZfNotificationController($scope, foundationApi) {
+ var controller = this;
+ controller.notifications = $scope.notifications = $scope.notifications || [];
+
+ controller.addNotification = function(info) {
+ var id = foundationApi.generateUuid();
+ info.id = id;
+ $scope.notifications.push(info);
+ };
+
+ controller.removeNotification = function(id) {
+ $scope.notifications.forEach(function(notification) {
+ if(notification.id === id) {
+ var ind = $scope.notifications.indexOf(notification);
+ $scope.notifications.splice(ind, 1);
+ }
+ });
+ };
+
+ controller.clearAll = function() {
+ while($scope.notifications.length > 0) {
+ $scope.notifications.pop();
+ }
+ };
+ }
+
+ zfNotificationSet.$inject = ['FoundationApi'];
+
+ function zfNotificationSet(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification-set.html',
+ controller: 'ZfNotificationController',
+ replace: true,
+ scope: {
+ position: '@'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right';
+
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'clearall') {
+ controller.clearAll();
+ }
+ else {
+ controller.addNotification(msg);
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+ }
+ });
+ }
+ }
+
+ zfNotification.$inject = ['FoundationApi'];
+
+ function zfNotification(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification.html',
+ replace: true,
+ transclude: true,
+ require: '^zfNotificationSet',
+ controller: function() { },
+ scope: {
+ title: '=?',
+ content: '=?',
+ image: '=?',
+ notifId: '=',
+ color: '=?',
+ autoclose: '=?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'notification');
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ scope.active = false;
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+ var hammerElem;
+
+ //due to dynamic insertion of DOM, we need to wait for it to show up and get working!
+ setTimeout(function() {
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }, 50);
+
+ scope.hide = function() {
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ setTimeout(function() {
+ controller.removeNotification(scope.notifId);
+ }, 50);
+ };
+
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ }, parseInt(scope.autoclose));
+ };
+
+ // close on swipe
+ if (Hammer) {
+ hammerElem = new Hammer(element[0]);
+ // set the options for swipe (to make them a bit more forgiving in detection)
+ hammerElem.get('swipe').set({
+ direction: Hammer.DIRECTION_ALL,
+ threshold: 5, // this is how far the swipe has to travel
+ velocity: 0.5 // and this is how fast the swipe must travel
+ });
+ }
+
+ hammerElem.on('swipe', function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ });
+ }
+ }
+ }
+
+ zfNotificationStatic.$inject = ['FoundationApi'];
+
+ function zfNotificationStatic(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification-static.html',
+ replace: true,
+ transclude: true,
+ scope: {
+ title: '@?',
+ content: '@?',
+ image: '@?',
+ color: '@?',
+ autoclose: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ var type = 'notification';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ scope.position = attrs.position ? attrs.position.split(' ').join('-') : 'top-right';
+
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg == 'show' || msg == 'open') {
+ scope.show();
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ }, parseInt(scope.autoclose));
+ };
+ } else if (msg == 'close' || msg == 'hide') {
+ scope.hide();
+ } else if (msg == 'toggle') {
+ scope.toggle();
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.toggle();
+ }
+ }, parseInt(scope.autoclose));
+ };
+ }
+
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ scope.$apply();
+
+ return;
+ });
+
+ scope.hide = function() {
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ }
+ }
+ }
+
+ zfNotify.$inject = ['FoundationApi'];
+
+ function zfNotify(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ scope: {
+ title: '@?',
+ content: '@?',
+ color: '@?',
+ image: '@?',
+ autoclose: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfNotify, {
+ title: scope.title,
+ content: scope.content,
+ color: scope.color,
+ image: scope.image,
+ autoclose: scope.autoclose
+ });
+ e.preventDefault();
+ });
+ }
+ }
+
+ NotificationFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', 'FoundationApi'];
+
+ function NotificationFactory($http, $templateCache, $rootScope, $compile, $timeout, foundationApi) {
+ return notificationFactory;
+
+ function notificationFactory(config) {
+ var self = this, //for prototype functions
+ container = angular.element(config.container || document.body),
+ id = config.id || foundationApi.generateUuid(),
+ attached = false,
+ destroyed = false,
+ html,
+ element,
+ scope,
+ contentScope
+ ;
+
+ var props = [
+ 'position'
+ ];
+
+ assembleDirective();
+
+ self.addNotification = addNotification;
+ self.clearAll = clearAll;
+ self.destroy = destroy;
+
+ return {
+ addNotification: addNotification,
+ clearAll: clearAll,
+ destroy: destroy
+ };
+
+ function checkStatus() {
+ if(destroyed) {
+ throw "Error: Notification Set was destroyed. Delete the object and create a new NotificationFactory instance."
+ }
+ }
+
+ function addNotification(notification) {
+ checkStatus();
+ $timeout(function() {
+ foundationApi.publish(id, notification);
+ }, 0, false);
+ }
+
+ function clearAll() {
+ checkStatus();
+ $timeout(function() {
+ foundationApi.publish(id, 'clearall');
+ }, 0, false);
+ }
+
+ function init(state) {
+ if(!attached && html.length > 0) {
+ var modalEl = container.append(element);
+
+ scope.active = state;
+ $compile(element)(scope);
+
+ attached = true;
+ }
+ }
+
+ function assembleDirective() {
+ // check for duplicate element to prevent factory from cloning notification sets
+ if (document.getElementById(id)) {
+ return;
+ }
+ html = '<zf-notification-set id="' + id + '"></zf-notification-set>';
+
+ element = angular.element(html);
+
+ scope = $rootScope.$new();
+
+ for(var i = 0; i < props.length; i++) {
+ if(config[props[i]]) {
+ element.attr(props[i], config[props[i]]);
+ }
+ }
+
+ // access view scope variables
+ if (config.contentScope) {
+ contentScope = config.contentScope;
+ for (var prop in contentScope) {
+ if (contentScope.hasOwnProperty(prop)) {
+ scope[prop] = contentScope[prop];
+ }
+ }
+ }
+ init(true);
+ }
+
+ function destroy() {
+ self.clearAll();
+ setTimeout(function() {
+ scope.$destroy();
+ element.remove();
+ destroyed = true;
+ }, 3000);
+ foundationApi.unsubscribe(id);
+ }
+
+ }
+
+ }
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.offcanvas', ['foundation.core'])
+ .directive('zfOffcanvas', zfOffcanvas)
+ .service('FoundationOffcanvas', FoundationOffcanvas)
+ ;
+
+ FoundationOffcanvas.$inject = ['FoundationApi'];
+
+ function FoundationOffcanvas(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target) {
+ foundationApi.publish(target, 'toggle');
+ }
+ }
+
+ zfOffcanvas.$inject = ['FoundationApi'];
+
+ function zfOffcanvas(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/offcanvas/offcanvas.html',
+ transclude: true,
+ scope: {
+ position: '@'
+ },
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'offcanvas';
+
+ return {
+ pre: preLink,
+ post: postLink
+ }
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ document.body.classList.add('has-off-canvas');
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.position = scope.position || 'left';
+
+ scope.active = false;
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'show' || msg === 'open') {
+ scope.show();
+ } else if (msg === 'close' || msg === 'hide') {
+ scope.hide();
+ } else if (msg === 'toggle') {
+ scope.toggle();
+ }
+
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ scope.hide = function() {
+ scope.active = false;
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ return;
+ };
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.panel', ['foundation.core'])
+ .directive('zfPanel', zfPanel)
+ .service('FoundationPanel', FoundationPanel)
+ ;
+
+ FoundationPanel.$inject = ['FoundationApi'];
+
+ function FoundationPanel(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+ zfPanel.$inject = ['FoundationApi', '$window'];
+
+ function zfPanel(foundationApi, $window) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/panel/panel.html',
+ transclude: true,
+ scope: {
+ position: '@?'
+ },
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'panel';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ scope.position = scope.position || 'left';
+ scope.positionClass = 'panel-' + scope.position;
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.active = false;
+ var animationIn, animationOut;
+ var globalQueries = foundationApi.getSettings().mediaQueries;
+
+ //urgh, there must be a better way
+ if(scope.position === 'left') {
+ animationIn = attrs.animationIn || 'slideInRight';
+ animationOut = attrs.animationOut || 'slideOutLeft';
+ } else if (scope.position === 'right') {
+ animationIn = attrs.animationIn || 'slideInLeft';
+ animationOut = attrs.animationOut || 'slideOutRight';
+ } else if (scope.position === 'top') {
+ animationIn = attrs.animationIn || 'slideInDown';
+ animationOut = attrs.animationOut || 'slideOutUp';
+ } else if (scope.position === 'bottom') {
+ animationIn = attrs.animationIn || 'slideInUp';
+ animationOut = attrs.animationOut || 'slideOutBottom';
+ }
+
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ var panelPosition = $window.getComputedStyle(element[0]).getPropertyValue("position");
+
+ // patch to prevent panel animation on larger screen devices
+ if (panelPosition !== 'absolute') {
+ return;
+ }
+
+ if(msg == 'show' || msg == 'open') {
+ scope.show();
+ } else if (msg == 'close' || msg == 'hide') {
+ scope.hide();
+ } else if (msg == 'toggle') {
+ scope.toggle();
+ }
+
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ scope.hide = function() {
+ if(scope.active){
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+
+ return;
+ };
+
+ scope.show = function() {
+ if(!scope.active){
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+
+ return;
+ };
+
+ element.on('click', function(e) {
+ //check sizing
+ var srcEl = e.srcElement;
+
+ if(!matchMedia(globalQueries.medium).matches && srcEl.href && srcEl.href.length > 0) {
+ //hide element if it can't match at least medium
+ scope.hide();
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+ });
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.popup', ['foundation.core'])
+ .directive('zfPopup', zfPopup)
+ .directive('zfPopupToggle', zfPopupToggle)
+ .service('FoundationPopup', FoundationPopup)
+ ;
+
+ FoundationPopup.$inject = ['FoundationApi'];
+
+ function FoundationPopup(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target, popupTarget) {
+ foundationApi.publish(target, ['toggle', popupTarget]);
+ }
+ }
+
+ zfPopup.$inject = ['FoundationApi'];
+
+ function zfPopup(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/popup/popup.html',
+ scope: {
+ pinTo: '@?',
+ pinAt: '@?',
+ target: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'popup');
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.active = false;
+ scope.target = scope.target || false;
+
+ var attachment = scope.pinTo || 'top center';
+ var targetAttachment = scope.pinAt || 'bottom center';
+ var tetherInit = false;
+ var tether = {};
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg[0] === 'show' || msg[0] === 'open') {
+ scope.show(msg[1]);
+ } else if (msg[0] === 'close' || msg[0] === 'hide') {
+ scope.hide();
+ } else if (msg[0] === 'toggle') {
+ scope.toggle(msg[1]);
+ }
+
+ scope.$apply();
+
+ return;
+ });
+
+
+ scope.hide = function() {
+ scope.active = false;
+ tetherElement();
+ tether.disable();
+ return;
+ };
+
+ scope.show = function(newTarget) {
+ scope.active = true;
+ tetherElement(newTarget);
+ tether.enable();
+
+ return;
+ };
+
+ scope.toggle = function(newTarget) {
+ scope.active = !scope.active;
+ tetherElement(newTarget);
+
+ if(scope.active) {
+ tether.enable();
+ } else {
+ tether.disable();
+ }
+
+ return;
+ };
+
+ function tetherElement(target) {
+ if(tetherInit) {
+ return;
+ }
+
+ scope.target = scope.target ? document.getElementById(scope.target) : document.getElementById(target);
+
+ tether = new Tether({
+ element: element[0],
+ target: scope.target,
+ attachment: attachment,
+ targetAttachment: targetAttachment,
+ enable: false
+ });
+
+ tetherInit = true;
+ }
+
+ }
+ }
+ }
+
+ zfPopupToggle.$inject = ['FoundationApi'];
+
+ function zfPopupToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ var target = attrs.zfPopupToggle;
+ var id = attrs.id || foundationApi.generateUuid();
+ attrs.$set('id', id);
+
+ element.on('click', function(e) {
+ foundationApi.publish(target, ['toggle', id]);
+ e.preventDefault();
+ });
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ angular.module('foundation.tabs', ['foundation.core'])
+ .controller('ZfTabsController', ZfTabsController)
+ .directive('zfTabs', zfTabs)
+ .directive('zfTabContent', zfTabContent)
+ .directive('zfTab', zfTab)
+ .directive('zfTabIndividual', zfTabIndividual)
+ .directive('zfTabHref', zfTabHref)
+ .directive('zfTabCustom', zfTabCustom)
+ .directive('zfTabContentCustom', zfTabContentCustom)
+ .service('FoundationTabs', FoundationTabs)
+ ;
+
+ FoundationTabs.$inject = ['FoundationApi'];
+
+ function FoundationTabs(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ }
+
+ ZfTabsController.$inject = ['$scope', 'FoundationApi'];
+
+ function ZfTabsController($scope, foundationApi) {
+ var controller = this;
+ var tabs = controller.tabs = $scope.tabs = [];
+ var id = '';
+
+ controller.select = function(selectTab) {
+ tabs.forEach(function(tab) {
+ tab.active = false;
+ tab.scope.active = false;
+
+ if(tab.scope === selectTab) {
+ foundationApi.publish(id, ['activate', tab]);
+
+ tab.active = true;
+ tab.scope.active = true;
+ }
+ });
+
+ };
+
+ controller.addTab = function addTab(tabScope) {
+ tabs.push({ scope: tabScope, active: false, parentContent: controller.id });
+
+ if(tabs.length === 1) {
+ tabs[0].active = true;
+ tabScope.active = true;
+ }
+ };
+
+ controller.getId = function() {
+ return id;
+ };
+
+ controller.setId = function(newId) {
+ id = newId;
+ };
+ }
+
+ zfTabs.$inject = ['FoundationApi'];
+
+ function zfTabs(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ replace: true,
+ templateUrl: 'components/tabs/tabs.html',
+ controller: 'ZfTabsController',
+ scope: {
+ displaced: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.id = attrs.id || foundationApi.generateUuid();
+ scope.showTabContent = scope.displaced !== 'true';
+ attrs.$set('id', scope.id);
+ controller.setId(scope.id);
+
+ //update tabs in case tab-content doesn't have them
+ var updateTabs = function() {
+ foundationApi.publish(scope.id + '-tabs', scope.tabs);
+ };
+
+ foundationApi.subscribe(scope.id + '-get-tabs', function() {
+ updateTabs();
+ });
+ }
+ }
+
+ zfTabContent.$inject = ['FoundationApi'];
+
+ function zfTabContent(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ transclude: 'true',
+ replace: true,
+ scope: {
+ tabs: '=?',
+ target: '@'
+ },
+ templateUrl: 'components/tabs/tab-content.html',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl) {
+ scope.tabs = scope.tabs || [];
+ var id = scope.target;
+
+ foundationApi.subscribe(id, function(msg) {
+ if(msg[0] === 'activate') {
+ var tabId = msg[1];
+ scope.tabs.forEach(function (tab) {
+ tab.scope.active = false;
+ tab.active = false;
+
+ if(tab.scope.id === id) {
+ tab.scope.active = true;
+ tab.active = true;
+ }
+ });
+ }
+ });
+
+ //if tabs empty, request tabs
+ if(scope.tabs.length === 0) {
+ foundationApi.subscribe(id + '-tabs', function(tabs) {
+ scope.tabs = tabs;
+ });
+
+ foundationApi.publish(id + '-get-tabs', '');
+ }
+ }
+ }
+
+ zfTab.$inject = ['FoundationApi'];
+
+ function zfTab(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/tabs/tab.html',
+ transclude: true,
+ scope: {
+ title: '@'
+ },
+ require: '^zfTabs',
+ replace: true,
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller, transclude) {
+ scope.id = attrs.id || foundationApi.generateUuid();
+ scope.active = false;
+ scope.transcludeFn = transclude;
+ controller.addTab(scope);
+
+ foundationApi.subscribe(scope.id, function(msg) {
+ if(msg === 'show' || msg === 'open' || msg === 'activate') {
+ scope.makeActive();
+ }
+ });
+
+ scope.makeActive = function() {
+ controller.select(scope);
+ };
+ }
+ }
+
+ zfTabIndividual.$inject = ['FoundationApi'];
+
+ function zfTabIndividual(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var tab = scope.$eval(attrs.tab);
+ var id = tab.scope.id;
+
+ tab.scope.transcludeFn(tab.scope, function(tabContent) {
+ element.append(tabContent);
+ });
+
+ foundationApi.subscribe(tab.scope.id, function(msg) {
+ foundationApi.publish(tab.parentContent, ['activate', tab.scope.id]);
+ scope.$apply();
+ });
+
+ }
+ }
+
+ //custom tabs
+
+ zfTabHref.$inject = ['FoundationApi'];
+
+ function zfTabHref(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ replace: false,
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl) {
+ var target = attrs.zfTabHref;
+
+ foundationApi.subscribe(target, function(msg) {
+ if(msg === 'activate' || msg === 'show' || msg === 'open') {
+ makeActive();
+ }
+ });
+
+
+ element.on('click', function(e) {
+ foundationApi.publish(target, 'activate');
+ makeActive();
+ e.preventDefault();
+ });
+
+ function makeActive() {
+ element.parent().children().removeClass('is-active');
+ element.addClass('is-active');
+ }
+ }
+ }
+
+ zfTabCustom.$inject = ['FoundationApi'];
+
+ function zfTabCustom(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ replace: false,
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var children = element.children();
+ angular.element(children[0]).addClass('is-active');
+ }
+ }
+
+ zfTabContentCustom.$inject = ['FoundationApi'];
+
+ function zfTabContentCustom(foundationApi) {
+ return {
+ restrict: 'A',
+ link: link
+ };
+
+ function link(scope, element, attrs) {
+ var tabs = [];
+ var children = element.children();
+
+ angular.forEach(children, function(node) {
+ if(node.id) {
+ var tabId = node.id;
+ tabs.push(tabId);
+ foundationApi.subscribe(tabId, function(msg) {
+ if(msg === 'activate' || msg === 'show' || msg === 'open') {
+ activateTabs(tabId);
+ }
+ });
+
+ if(tabs.length === 1) {
+ var el = angular.element(node);
+ el.addClass('is-active');
+ }
+ }
+ });
+
+ function activateTabs(tabId) {
+ var tabNodes = element.children();
+ angular.forEach(tabNodes, function(node) {
+ var el = angular.element(node);
+ el.removeClass('is-active');
+ if(el.attr('id') === tabId) {
+ el.addClass('is-active');
+ }
+
+ });
+ }
+ }
+ }
+
+})();
+
+(function() {
+ 'use strict';
+
+ // imports all components and dependencies under a single namespace
+
+ angular.module('foundation', [
+ 'foundation.core',
+ 'foundation.mediaquery',
+ 'foundation.accordion',
+ 'foundation.actionsheet',
+ 'foundation.common',
+ 'foundation.iconic',
+ 'foundation.interchange',
+ 'foundation.modal',
+ 'foundation.notification',
+ 'foundation.offcanvas',
+ 'foundation.panel',
+ 'foundation.popup',
+ 'foundation.tabs'
+ ]);
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.min.js b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.min.js
new file mode 100755
index 0000000..81c53e5
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/dist/js/foundation-apps.min.js
@@ -0,0 +1,2 @@
+!function(t){"object"==typeof exports?module.exports=t():"function"==typeof define&&define.amd?define(t):"undefined"!=typeof window?window.IconicJS=t():"undefined"!=typeof global?global.IconicJS=t():"undefined"!=typeof self&&(self.IconicJS=t())}(function(){var t;return function e(t,n,i){function o(a,r){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!r&&u)return u(a,!0);if(c)return c(a,!0);throw new Error("Cannot find module '"+a+"'")}var s=n[a]={exports:{}};t[a][0].call(s.exports,function(e){var n=t[a][1][e];return o(n?n:e)},s,s.exports,e,t,n,i)}return n[a].exports}for(var c="function"==typeof require&&require,a=0;a<i.length;a++)o(i[a]);return o}({1:[function(t,e){var n=(t("./modules/polyfills"),t("./modules/svg-injector")),i=t("./modules/extend"),o=t("./modules/responsive"),c=t("./modules/position"),a=t("./modules/container"),r=t("./modules/log"),u={},s=window.iconicSmartIconApis={},l=("file:"===window.location.protocol,0),f=function(t,e,o){e=i({},u,e||{});var c={evalScripts:e.evalScripts,pngFallback:e.pngFallback};c.each=function(t){if(t)if("string"==typeof t)r.debug(t);else if(t instanceof SVGSVGElement){var n=t.getAttribute("data-icon");if(n&&s[n]){var i=s[n](t);for(var o in i)t[o]=i[o]}/iconic-bg-/.test(t.getAttribute("class"))&&a.addBackground(t),d(t),l++,e&&e.each&&"function"==typeof e.each&&e.each(t)}},"string"==typeof t&&(t=document.querySelectorAll(t)),n(t,c,o)},d=function(t){var e=[];t?"string"==typeof t?e=document.querySelectorAll(t):void 0!==t.length?e=t:"object"==typeof t&&e.push(t):e=document.querySelectorAll("svg.iconic"),Array.prototype.forEach.call(e,function(t){t instanceof SVGSVGElement&&(t.update&&t.update(),o.refresh(t),c.refresh(t))})},p=function(){u.debug&&console.time&&console.time("autoInjectSelector - "+u.autoInjectSelector);var t=l;f(u.autoInjectSelector,{},function(){if(u.debug&&console.timeEnd&&console.timeEnd("autoInjectSelector - "+u.autoInjectSelector),r.debug("AutoInjected: "+(l-t)),o.refreshAll(),u.autoInjectDone&&"function"==typeof u.autoInjectDone){var e=l-t;u.autoInjectDone(e)}})},v=function(t){t&&""!==t&&"complete"!==document.readyState?document.addEventListener("DOMContentLoaded",p):document.removeEventListener("DOMContentLoaded",p)},m=function(t){return t=t||{},i(u,t),v(u.autoInjectSelector),r.enableDebug(u.debug),window._Iconic?window._Iconic:{inject:f,update:d,smartIconApis:s,svgInjectedCount:l}};e.exports=m,window._Iconic=new m({autoInjectSelector:"img.iconic",evalScripts:"once",pngFallback:!1,each:null,autoInjectDone:null,debug:!1})},{"./modules/container":2,"./modules/extend":3,"./modules/log":4,"./modules/polyfills":5,"./modules/position":6,"./modules/responsive":7,"./modules/svg-injector":8}],2:[function(t,e){var n=function(t){var e=t.getAttribute("class").split(" "),n=-1!==e.indexOf("iconic-fluid"),i=[],o=["iconic-bg"];Array.prototype.forEach.call(e,function(t){switch(t){case"iconic-sm":case"iconic-md":case"iconic-lg":i.push(t),n||o.push(t.replace(/-/,"-bg-"));break;case"iconic-fluid":i.push(t),o.push(t.replace(/-/,"-bg-"));break;case"iconic-bg-circle":case"iconic-bg-rounded-rect":case"iconic-bg-badge":o.push(t);break;default:i.push(t)}}),t.setAttribute("class",i.join(" "));var c=t.parentNode,a=Array.prototype.indexOf.call(c.childNodes,t),r=document.createElement("span");r.setAttribute("class",o.join(" ")),r.appendChild(t),c.insertBefore(r,c.childNodes[a])};e.exports={addBackground:n}},{}],3:[function(t,e){e.exports=function(t){return Array.prototype.forEach.call(Array.prototype.slice.call(arguments,1),function(e){if(e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])}),t}},{}],4:[function(t,e){var n=!1,i=function(t){console&&console.log&&console.log(t)},o=function(t){i("Iconic INFO: "+t)},c=function(t){i("Iconic WARNING: "+t)},a=function(t){n&&i("Iconic DEBUG: "+t)},r=function(t){n=t};e.exports={info:o,warn:c,debug:a,enableDebug:r}},{}],5:[function(){Array.prototype.forEach||(Array.prototype.forEach=function(t,e){"use strict";if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;var n,i=this.length>>>0;for(n=0;i>n;++n)n in this&&t.call(e,this[n],n,this)}),function(){if(Event.prototype.preventDefault||(Event.prototype.preventDefault=function(){this.returnValue=!1}),Event.prototype.stopPropagation||(Event.prototype.stopPropagation=function(){this.cancelBubble=!0}),!Element.prototype.addEventListener){var t=[],e=function(e,n){var i=this,o=function(t){t.target=t.srcElement,t.currentTarget=i,n.handleEvent?n.handleEvent(t):n.call(i,t)};if("DOMContentLoaded"==e){var c=function(t){"complete"==document.readyState&&o(t)};if(document.attachEvent("onreadystatechange",c),t.push({object:this,type:e,listener:n,wrapper:c}),"complete"==document.readyState){var a=new Event;a.srcElement=window,c(a)}}else this.attachEvent("on"+e,o),t.push({object:this,type:e,listener:n,wrapper:o})},n=function(e,n){for(var i=0;i<t.length;){var o=t[i];if(o.object==this&&o.type==e&&o.listener==n){"DOMContentLoaded"==e?this.detachEvent("onreadystatechange",o.wrapper):this.detachEvent("on"+e,o.wrapper);break}++i}};Element.prototype.addEventListener=e,Element.prototype.removeEventListener=n,HTMLDocument&&(HTMLDocument.prototype.addEventListener=e,HTMLDocument.prototype.removeEventListener=n),Window&&(Window.prototype.addEventListener=e,Window.prototype.removeEventListener=n)}}()},{}],6:[function(t,e){var n=function(t){var e=t.getAttribute("data-position");if(e&&""!==e){var n,i,o,c,a,r,u,s=t.getAttribute("width"),l=t.getAttribute("height"),f=e.split("-"),d=t.querySelectorAll("g.iconic-container");Array.prototype.forEach.call(d,function(t){if(n=t.getAttribute("data-width"),i=t.getAttribute("data-height"),n!==s||i!==l){if(o=t.getAttribute("transform"),c=1,o){var e=o.match(/scale\((\d)/);c=e&&e[1]?e[1]:1}a=Math.floor((s/c-n)/2),r=Math.floor((l/c-i)/2),Array.prototype.forEach.call(f,function(t){switch(t){case"top":r=0;break;case"bottom":r=l/c-i;break;case"left":a=0;break;case"right":a=s/c-n;break;case"center":break;default:console&&console.log&&console.log("Unknown position: "+t)}}),u=0===r?a:a+" "+r,u="translate("+u+")",o?/translate/.test(o)?o=o.replace(/translate\(.*?\)/,u):o+=" "+u:o=u,t.setAttribute("transform",o)}})}};e.exports={refresh:n}},{}],7:[function(t,e){var n=/(iconic-sm\b|iconic-md\b|iconic-lg\b)/,i=function(t,e){var n="undefined"!=typeof window.getComputedStyle&&window.getComputedStyle(t,null).getPropertyValue(e);return!n&&t.currentStyle&&(n=t.currentStyle[e.replace(/([a-z])\-([a-z])/,function(t,e,n){return e+n.toUpperCase()})]||t.currentStyle[e]),n},o=function(t){var e=t.style.display;t.style.display="block";var n=parseFloat(i(t,"width").slice(0,-2)),o=parseFloat(i(t,"height").slice(0,-2));return t.style.display=e,{width:n,height:o}},c=function(){var t="/* Iconic Responsive Support Styles */\n.iconic-property-fill, .iconic-property-text {stroke: none !important;}\n.iconic-property-stroke {fill: none !important;}\nsvg.iconic.iconic-fluid {height:100% !important;width:100% !important;}\nsvg.iconic.iconic-sm:not(.iconic-size-md):not(.iconic-size-lg), svg.iconic.iconic-size-sm{width:16px;height:16px;}\nsvg.iconic.iconic-md:not(.iconic-size-sm):not(.iconic-size-lg), svg.iconic.iconic-size-md{width:32px;height:32px;}\nsvg.iconic.iconic-lg:not(.iconic-size-sm):not(.iconic-size-md), svg.iconic.iconic-size-lg{width:128px;height:128px;}\nsvg.iconic-sm > g.iconic-md, svg.iconic-sm > g.iconic-lg, svg.iconic-md > g.iconic-sm, svg.iconic-md > g.iconic-lg, svg.iconic-lg > g.iconic-sm, svg.iconic-lg > g.iconic-md {display: none;}\nsvg.iconic.iconic-icon-sm > g.iconic-lg, svg.iconic.iconic-icon-md > g.iconic-lg {display:none;}\nsvg.iconic-sm:not(.iconic-icon-md):not(.iconic-icon-lg) > g.iconic-sm, svg.iconic-md.iconic-icon-sm > g.iconic-sm, svg.iconic-lg.iconic-icon-sm > g.iconic-sm {display:inline;}\nsvg.iconic-md:not(.iconic-icon-sm):not(.iconic-icon-lg) > g.iconic-md, svg.iconic-sm.iconic-icon-md > g.iconic-md, svg.iconic-lg.iconic-icon-md > g.iconic-md {display:inline;}\nsvg.iconic-lg:not(.iconic-icon-sm):not(.iconic-icon-md) > g.iconic-lg, svg.iconic-sm.iconic-icon-lg > g.iconic-lg, svg.iconic-md.iconic-icon-lg > g.iconic-lg {display:inline;}";navigator&&navigator.userAgent&&/MSIE 10\.0/.test(navigator.userAgent)&&(t+="svg.iconic{zoom:1.0001;}");var e=document.createElement("style");e.id="iconic-responsive-css",e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),(document.head||document.getElementsByTagName("head")[0]).appendChild(e)},a=function(t){if(/iconic-fluid/.test(t.getAttribute("class"))){var e,i=o(t),c=t.viewBox.baseVal.width/t.viewBox.baseVal.height;e=1===c?Math.min(i.width,i.height):1>c?i.width:i.height;var a;a=32>e?"iconic-sm":e>=32&&128>e?"iconic-md":"iconic-lg";var r=t.getAttribute("class"),u=n.test(r)?r.replace(n,a):r+" "+a;t.setAttribute("class",u)}},r=function(){var t=document.querySelectorAll(".injected-svg.iconic-fluid");Array.prototype.forEach.call(t,function(t){a(t)})};document.addEventListener("DOMContentLoaded",function(){c()}),window.addEventListener("resize",function(){r()}),e.exports={refresh:a,refreshAll:r}},{}],8:[function(e,n,i){!function(e,o){"use strict";function c(t){t=t.split(" ");for(var e={},n=t.length,i=[];n--;)e.hasOwnProperty(t[n])||(e[t[n]]=1,i.unshift(t[n]));return i.join(" ")}var a="file:"===e.location.protocol,r=o.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),u=Array.prototype.forEach||function(t,e){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;var n,i=this.length>>>0;for(n=0;i>n;++n)n in this&&t.call(e,this[n],n,this)},s={},l=0,f=[],d=[],p={},v=function(t){return t.cloneNode(!0)},m=function(t,e){d[t]=d[t]||[],d[t].push(e)},g=function(t){for(var e=0,n=d[t].length;n>e;e++)!function(e){setTimeout(function(){d[t][e](v(s[t]))},0)}(e)},h=function(t,n){if(void 0!==s[t])s[t]instanceof SVGSVGElement?n(v(s[t])):m(t,n);else{if(!e.XMLHttpRequest)return n("Browser does not support XMLHttpRequest"),!1;s[t]={},m(t,n);var i=new XMLHttpRequest;i.onreadystatechange=function(){if(4===i.readyState){if(404===i.status||null===i.responseXML)return n("Unable to load SVG file: "+t),a&&n("Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver."),n(),!1;if(!(200===i.status||a&&0===i.status))return n("There was a problem injecting the SVG: "+i.status+" "+i.statusText),!1;if(i.responseXML instanceof Document)s[t]=i.responseXML.documentElement;else if(DOMParser&&DOMParser instanceof Function){var e;try{var o=new DOMParser;e=o.parseFromString(i.responseText,"text/xml")}catch(c){e=void 0}if(!e||e.getElementsByTagName("parsererror").length)return n("Unable to parse SVG file: "+t),!1;s[t]=e.documentElement}g(t)}},i.open("GET",t),i.overrideMimeType&&i.overrideMimeType("text/xml"),i.send()}},b=function(t,n,i,o){var a=t.getAttribute("data-src")||t.getAttribute("src");if(!/svg$/i.test(a))return void o("Attempted to inject a file with a non-svg extension: "+a);if(!r){var s=t.getAttribute("data-fallback")||t.getAttribute("data-png");return void(s?(t.setAttribute("src",s),o(null)):i?(t.setAttribute("src",i+"/"+a.split("/").pop().replace(".svg",".png")),o(null)):o("This browser does not support SVG and no PNG fallback was defined."))}-1===f.indexOf(t)&&(f.push(t),t.setAttribute("src",""),h(a,function(i){if("undefined"==typeof i||"string"==typeof i)return o(i),!1;var r=t.getAttribute("id");r&&i.setAttribute("id",r);var s=t.getAttribute("title");s&&i.setAttribute("title",s);var d=[].concat(i.getAttribute("class")||[],"injected-svg",t.getAttribute("class")||[]).join(" ");i.setAttribute("class",c(d));var v=t.getAttribute("style");v&&i.setAttribute("style",v);var m=[].filter.call(t.attributes,function(t){return/^data-\w[\w\-]*$/.test(t.name)});u.call(m,function(t){t.name&&t.value&&i.setAttribute(t.name,t.value)});for(var g,h=i.querySelectorAll("defs clipPath[id]"),b=0,y=h.length;y>b;b++){g=h[b].id+"-"+l;for(var A=i.querySelectorAll('[clip-path*="'+h[b].id+'"]'),w=0,$=A.length;$>w;w++)A[w].setAttribute("clip-path","url(#"+g+")");h[b].id=g}i.removeAttribute("xmlns:a");for(var E,S,j=i.querySelectorAll("script"),C=[],z=0,I=j.length;I>z;z++)S=j[z].getAttribute("type"),S&&"application/ecmascript"!==S&&"application/javascript"!==S||(E=j[z].innerText||j[z].textContent,C.push(E),i.removeChild(j[z]));if(C.length>0&&("always"===n||"once"===n&&!p[a])){for(var k=0,F=C.length;F>k;k++)new Function(C[k])(e);p[a]=!0}t.parentNode.replaceChild(i,t),delete f[f.indexOf(t)],t=null,l++,o(i)}))},y=function(t,e,n){e=e||{};var i=e.evalScripts||"always",o=e.pngFallback||!1,c=e.each;if(void 0!==t.length){var a=0;u.call(t,function(e){b(e,i,o,function(e){c&&"function"==typeof c&&c(e),n&&t.length===++a&&n(a)})})}else t?b(t,i,o,function(e){c&&"function"==typeof c&&c(e),n&&n(1),t=null}):n&&n(0)};"object"==typeof n&&"object"==typeof n.exports?n.exports=i=y:"function"==typeof t&&t.amd?t(function(){return y}):"object"==typeof e&&(e.SVGInjector=y)}(window,document)},{}]},{},[1])(1)}),function(){"use strict";function t(){function t(t,e){e?t.addClass(a):t.removeClass(a)}function e(t,e,i,u){function s(){d(t),v(),t[0].style.transitionDuration="",t.removeClass(b?"":a),p(),m=!1}function l(t){d(t),angular.element(t).off(r.join(" ")),m=!1}function f(t){var e={el:t,animation:g},i=n.filter(function(e){return e.el===t});if(i.length>0){var o=i[0].el[0];i[0].animation.cancelAnimation(o)}n.push(e)}function d(t){{var e;n.filter(function(n,i){n.el===t&&(e=i)})}e>=0&&n.splice(e,1)}function p(){return t[0].offsetWidth}function v(){t[0].style.transitionDuration=0,t.removeClass(o.join(" ")+" "+c.join(" ")+" "+i+" "+u)}var m=!0,g=this;g.cancelAnimation=l;var h=e?i:u,b=e,y=b?o[0]:o[1],A=b?c[0]:c[1];f(t),v(),t.addClass(h),t.addClass(y),t.addClass(a),p(),t[0].style.transitionDuration="",t.addClass(A),t.one(r.join(" "),function(){s()}),setTimeout(function(){m&&s()},3e3)}var n=[],i={},o=["ng-enter","ng-leave"],c=["ng-enter-active","ng-leave-active"],a="is-active",r=["webkitAnimationEnd","mozAnimationEnd","MSAnimationEnd","oanimationend","animationend","webkitTransitionEnd","otransitionend","transitionend"];return i.animate=e,i.toggleAnimation=t,i}angular.module("foundation.core.animation",[]).service("FoundationAnimation",t)}(),function(){"use strict";function t(t){function e(t,e){return l[t]||(l[t]=[]),l[t].push(e),!0}function n(t,e){void 0!==l[t]&&delete l[t],"function"==typeof e&&e.call(this)}function i(t,e){l[t]||(l[t]=[]),l[t].forEach(function(t){t(e)})}function o(){return f}function c(t){return f=angular.extend(f,t)}function a(){var t="";do{t+="zf-uuid-";for(var e=0;15>e;e++)t+=Math.floor(16*Math.random()).toString(16)}while(!d.indexOf(t));return d.push(t),t}function r(e,n){t.toggleAnimate(e,n)}function u(t){var e=this;t=t||{};var n=document.querySelectorAll(".is-active[zf-closable]"),i=document.querySelectorAll("[zf-closable] > .is-active");n.length&&angular.forEach(n,function(n){t.exclude!==n.id&&e.publish(n.id,"close")}),i.length&&angular.forEach(i,function(n){var i=n.parentNode.id;t.exclude!==i&&e.publish(i,"close")})}function s(e,n,i,o){t.animate(e,n,i,o)}var l={},f={},d=[],p={};return p.subscribe=e,p.unsubscribe=n,p.publish=i,p.getSettings=o,p.modifySettings=c,p.generateUuid=a,p.toggleAnimate=r,p.closeActiveElements=u,p.animate=s,p}function e(t){function e(e){t.publish(e,"show")}function n(e){t.publish(e,"hide")}var i={};return i.activate=e,i.deactivate=n,i}function n(){function t(t,e){var n=null;return function(){var i=this,o=arguments;null===n&&(n=setTimeout(function(){t.apply(i,o),n=null},e))}}var e={};return e.throttle=t,e}angular.module("foundation.core",["foundation.core.animation"]).service("FoundationApi",t).service("FoundationAdapter",e).factory("Utils",n),t.$inject=["FoundationAnimation"],e.$inject=["FoundationApi"]}(),function(){"use strict";function t(t,e){function n(n,i){function o(t,e,n,i){if(i.animation){if(!i.animation.leave&&!e.animation.leave)return;c(t,e,i)}}function c(t,e,n){v?(f(),i.addClass(n.animation.leave)):(l(),f(),i.removeClass(n.animation.leave))}function a(){p.leave&&i.removeClass(p.leave),l()}function r(){l(),e.includes(s())&&p.enter&&i.addClass(p.enter)}function u(t){t.targetScope===n&&p.enter&&i.removeClass(p.enter),v=!0}function s(){var t=i.data("$uiView"),e=t&&t.state&&t.state.self;return e&&angular.extend(p,e.animation),e}function l(){i.parent().removeClass("position-absolute"),d!==!0&&(i.parent()[0].style.height=null)}function f(){var t=parseInt(i.parent()[0].style.height),e=parseInt(window.getComputedStyle(i[0],null).getPropertyValue("height")),n=t>0?t:e>0?e:"";t>0&&(d=!0),i.parent()[0].style.height=n+"px",i.parent().addClass("position-absolute")}var d,p={},v=!1,m=[t.$on("$stateChangeStart",o),t.$on("$stateChangeError",a),n.$on("$stateChangeSuccess",r),n.$on("$viewContentAnimationEnded",u)],g=n.$on("$destroy",function(){angular.forEach(m,function(t){angular.isFunction(t)&&t()}),g()})}var i={restrict:"ECA",priority:-400,link:n};return i}angular.module("foundation.dynamicRouting.animations",["foundation.dynamicRouting"]).directive("uiView",t),t.$inject=["$rootScope","$state"]}(),function(){"use strict";function t(t){function e(t){var e={vars:{}};return t.data&&("object"==typeof t.data.vars&&(e.vars=t.data.vars),delete t.data.vars,angular.extend(e,t.data)),delete t.data,angular.extend(e.vars,t),e}function n(t,e){return{templateUrl:t,controller:i(e)}}function i(t){var e=t.controller||"DefaultController";return/\w\s+as\s+\w/.test(e)||(e+=" as PageCtrl"),e}function o(t){var e={};return t.animationIn&&(e.enter=t.animationIn),t.animationOut&&(e.leave=t.animationOut),e}var c={};this.registerDynamicRoutes=function(a){var r=a||foundationRoutes;angular.forEach(r,function(n){if(n.hasComposed)angular.isDefined(c[n.parent])||(c[n.parent]={children:{}}),n.controller&&(n.controller=i(n)),c[n.parent].children[n.name]=n;else if(n.composed)angular.isDefined(c[n.name])||(c[n.name]={children:{}}),n.controller&&(n.controller=i(n)),angular.extend(c[n.name],n);else{var a={url:n.url,templateUrl:n.path,"abstract":n["abstract"]||!1,parent:n.parent||"",controller:i(n),data:e(n),animation:o(n)};t.state(n.name,a)}}),angular.forEach(c,function(i){var c={url:i.url,parent:i.parent||"","abstract":i["abstract"]||!1,data:e(i),animation:o(i),views:{"":n(i.path,i)}};angular.forEach(i.children,function(t){c.views[t.name+"@"+i.name]=n(t.path,i)}),t.state(i.name,c)})},this.$get=angular.noop}function e(t,e,n){var i={};angular.forEach(e,function(t,e){i[e]=t}),t.params=i,t.current=n.current.name,n.current.views?(t.vars=n.current.data.vars,t.composed=n.current.data.vars.children):t.vars=n.current.data.vars}function n(t){t.registerDynamicRoutes(foundationRoutes)}function i(t,e,n){t.$state=e,t.$stateParams=n}angular.module("foundation.dynamicRouting",["ui.router"]).provider("$FoundationState",t).controller("DefaultController",e).config(n).run(i),t.$inject=["$stateProvider"],e.$inject=["$scope","$stateParams","$state"],n.$inject=["$FoundationStateProvider"],i.$inject=["$rootScope","$state","$stateParams"]}(),function(){"use strict";function t(t){t.init()}function e(t,e,n){function i(){var i,o;t.headerHelper(["foundation-mq"]),o=t.getStyle(".foundation-mq","font-family"),i=t.parseStyleToObject(o);for(var a in i)i[a]="only screen and (min-width: "+i[a].replace("rem","em")+")";e.modifySettings({mediaQueries:angular.extend(i,c)}),window.addEventListener("resize",n.throttle(function(){e.publish("resize","window resized")},50))}var o={},c={"default":"only screen",landscape:"only screen and (orientation: landscape)",portrait:"only screen and (orientation: portrait)",retina:"only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (-o-min-device-pixel-ratio: 2/1),only screen and (min-device-pixel-ratio: 2),only screen and (min-resolution: 192dpi),only screen and (min-resolution: 2dppx)"};return o.init=i,o}function n(){function t(t){for(var e=t.length,n=angular.element(document.querySelectorAll("head"));e--;)n.append('<meta class="'+t[e]+'" />')}function e(t){var e=document.querySelectorAll(t)[0],n=window.getComputedStyle(e,null);return n.getPropertyValue("font-family")}function n(t){var e={};return"string"!=typeof t?e:(t=t.trim().slice(1,-1))?e=t.split("&").reduce(function(t,e){var n=e.replace(/\+/g," ").split("="),i=n[0],o=n[1];return i=decodeURIComponent(i),o=void 0===o?null:decodeURIComponent(o),t.hasOwnProperty(i)?Array.isArray(t[i])?t[i].push(o):t[i]=[t[i],o]:t[i]=o,t},{}):e}var i={};return i.headerHelper=t,i.getStyle=e,i.parseStyleToObject=n,i}function i(t){function e(){return t.getSettings().mediaQueries}function n(t){var e=t.length,n=o.getMediaQueries(),i=[];if(e>0)for(;e--;){var c,a=t[e].media;c=matchMedia(n[a]?n[a]:a),c.matches&&i.push({ind:e})}return i}function i(t){var e=[],n=[],i=t.children(),o=0;return angular.forEach(i,function(t){var i=angular.element(t);i.attr("src")&&i.attr("src").match(/.html$/)?e[o]={media:i.attr("media"),src:i.attr("src")}:(n[o]=i,e[o]={media:i.attr("media"),templ:o}),o++}),{scenarios:e,templates:n}}var o=[];return o.getMediaQueries=e,o.match=n,o.collectScenariosFromElement=i,o}angular.module("foundation.mediaquery",["foundation.core"]).run(t).factory("FoundationMQInit",e).factory("mqHelpers",n).service("FoundationMQ",i),t.$inject=["FoundationMQInit"],e.$inject=["mqHelpers","FoundationApi","Utils"],i.$inject=["FoundationApi"]}(),angular.module("markdown",[]).directive("markdown",function(){return{restrict:"A",link:function(t,e){e.html(marked(e.html()))}}}),function(){var t={};angular.forEach(["clipPath","colorProfile","src","cursor","fill","filter","marker","markerStart","markerMid","markerEnd","mask","stroke"],function(e){t[e]=["$rootScope","$location","$interpolate","$sniffer","urlResolve","computeSVGAttrValue","svgAttrExpressions",function(t,n,i,o,c,a,r){return{restrict:"A",link:function(i,c,u){function s(){var t=a(l);t&&u[e]!==t&&u.$set(e,t)}var l;r.SVG_ELEMENT.test(c[0]&&c[0].toString())&&n.$$html5&&o.history&&(l=u[e],u.$observe(e,s),t.$on("$locationChangeSuccess",s))}}}]}),angular.module("ngSVGAttributes",[]).factory("urlResolve",[function(){var t=document.createElement("a");return function(e){return t.setAttribute("href",e),t}}]).value("svgAttrExpressions",{FUNC_URI:/^url\((.*)\)$/,SVG_ELEMENT:/SVG[a-zA-Z]*Element/,HASH_PART:/#.*/}).factory("computeSVGAttrValue",["$location","$sniffer","svgAttrExpressions","urlResolve",function(t,e,n,i){return function(e){var o,c;return(o=n.FUNC_URI.exec(e))&&(c=0===o[1].indexOf("#")?t.absUrl().replace(n.HASH_PART,"")+o[1]:i(o[1])),c?"url("+c+")":null}}]).directive(t)}(),function(){"use strict";function t(t){var e=this,n=e.sections=t.sections=[],i=(e.multiOpen=t.multiOpen=t.multiOpen||!1,e.collapsible=t.collapsible=t.multiOpen||t.collapsible||!0),o=e.autoOpen=t.autoOpen=t.autoOpen||!0;e.select=function(t){n.forEach(function(n){e.multiOpen?n.scope===t&&(n.scope.active=!n.scope.active):n.scope.active=n.scope===t?i?!n.scope.active:!0:!1})},e.addSection=function(t){n.push({scope:t}),1===n.length&&o===!0&&(n[0].active=!0,n[0].scope.active=!0)},e.closeAll=function(){n.forEach(function(t){t.scope.active=!1})}}function e(){function t(t,e,n,i){t.multiOpen=i.multiOpen="true"===t.multiOpen?!0:!1,t.collapsible=i.collapsible="true"===t.collapsible?!0:!1,t.autoOpen=i.autoOpen="true"===t.autoOpen?!0:!1}var e={restrict:"EA",transclude:"true",replace:!0,templateUrl:"components/accordion/accordion.html",controller:"ZfAccordionController",scope:{multiOpen:"@?",collapsible:"@?",autoOpen:"@?"},link:t};return e}function n(){function t(t,e,n,i){t.active=!1,i.addSection(t),t.activate=function(){i.select(t)}}var e={restrict:"EA",templateUrl:"components/accordion/accordion-item.html",transclude:!0,scope:{title:"@"},require:"^zfAccordion",replace:!0,controller:function(){},link:t};return e}angular.module("foundation.accordion",[]).controller("ZfAccordionController",t).directive("zfAccordion",e).directive("zfAccordionItem",n),t.$inject=["$scope"]}(),function(){"use strict";function t(t){function e(e){t.publish(e,"show")}function n(e){t.publish(e,"hide")}var i={};return i.activate=e,i.deactivate=n,i}function e(t){function e(t){var e=t.target,i=!1;do if(e.classList&&e.classList.contains("action-sheet-container")){i=!0;break}while(e=e.parentNode);if(!i){if(t.target.attributes["zf-toggle"]||t.target.attributes["zf-hard-toggle"])return;n()}}function n(){c.hide(),a.hide(),c.$apply(),a.$apply()}function i(){c.toggle(),a.toggle(),c.$apply(),a.$apply()}{var o=this,c=o.content=t.content,a=o.container=t.container;angular.element(document.body)}o.registerContent=function(t){c=t,c.active=!1},o.registerContainer=function(t){a=t,a.active=!1},o.toggle=i,o.hide=n,o.registerListener=function(){document.body.addEventListener("click",e)},o.deregisterListener=function(){document.body.removeEventListener("click",e)}}function n(t){function e(){function e(t,e,n){n.$set("zf-closable","actionsheet")}function n(e,n,i,o){var c=i.id||t.generateUuid();i.$set("id",c),e.active=!1,t.subscribe(c,function(t){"toggle"===t&&o.toggle(),("hide"===t||"close"===t)&&o.hide()}),o.registerContainer(e),e.toggle=function(){e.active=!e.active},e.hide=function(){e.active=!1}}return{pre:e,post:n}}var n={restrict:"EA",transclude:!0,replace:!0,templateUrl:"components/actionsheet/actionsheet.html",controller:"ZfActionSheetController",compile:e};return n}function i(){function t(t,e,n,i){t.active=!1,t.position=t.position||"bottom",i.registerContent(t),t.toggle=function(){t.active=!t.active,t.active?i.registerListener():i.deregisterListener()},t.hide=function(){t.active=!1,i.deregisterListener()}}var e={restrict:"EA",transclude:!0,replace:!0,templateUrl:"components/actionsheet/actionsheet-content.html",require:"^zfActionSheet",scope:{position:"@?"},link:t};return e}function o(){function t(t,e,n,i){e.on("click",function(t){i.toggle(),t.preventDefault()})}var e={restrict:"EA",transclude:!0,replace:!0,templateUrl:"components/actionsheet/actionsheet-button.html",require:"^zfActionSheet",scope:{title:"@?"},link:t};return e}angular.module("foundation.actionsheet",["foundation.core"]).controller("ZfActionSheetController",e).directive("zfActionSheet",n).directive("zfAsContent",i).directive("zfAsButton",o).service("FoundationActionSheet",t),t.$inject=["FoundationApi"],e.$inject=["$scope","FoundationApi"],n.$inject=["FoundationApi"],i.$inject=["FoundationApi"],o.$inject=["FoundationApi"]}(),function(){"use strict";function t(t){function e(e,n,i){var o="";if(i.zfClose)o=i.zfClose;else{for(var c=!1,a=n.parent();c===!1;)"BODY"==a[0].nodeName&&(c=""),"undefined"!=typeof a.attr("zf-closable")&&a.attr("zf-closable")!==!1&&(c=a),a=a.parent();o=c.attr("id")}n.on("click",function(e){t.publish(o,"close"),e.preventDefault()})}var n={restrict:"A",link:e};return n}function e(t){function e(e,n,i){n.on("click",function(e){t.publish(i.zfOpen,"open"),e.preventDefault()})}var n={restrict:"A",link:e};return n}function n(t){function e(e,n,i){n.on("click",function(e){t.publish(i.zfToggle,"toggle"),e.preventDefault()})}var n={restrict:"A",link:e};return n}function i(t){function e(e,n){n.on("keyup",function(e){27===e.keyCode&&t.closeActiveElements(),e.preventDefault()})}var n={restrict:"A",link:e};return n}function o(t){function e(e,n,i){var o,c;switch(Hammer&&(c=new Hammer(n[0]),c.get("swipe").set({direction:Hammer.DIRECTION_ALL,threshold:5,velocity:.5})),i.zfSwipeClose){case"right":o="swiperight";break;case"left":o="swipeleft";break;case"up":o="swipeup";break;case"down":o="swipedown";break;default:o="swipe"}c.on(o,function(){t.publish(i.id,"close")})}var n={restrict:"A",link:e};return n}function c(t){function e(e,n,i){n.on("click",function(e){t.closeActiveElements({exclude:i.zfHardToggle}),t.publish(i.zfHardToggle,"toggle"),e.preventDefault()})}var n={restrict:"A",link:e};return n}angular.module("foundation.common",["foundation.core"]).directive("zfClose",t).directive("zfOpen",e).directive("zfToggle",n).directive("zfEscClose",i).directive("zfSwipeClose",o).directive("zfHardToggle",c),t.$inject=["FoundationApi"],e.$inject=["FoundationApi"],n.$inject=["FoundationApi"],i.$inject=["FoundationApi"],o.$inject=["FoundationApi"],c.$inject=["FoundationApi"]}(),function(){"use strict";function t(){var t="assets/img/iconic/";this.setAssetPath=function(e){t=angular.isString(e)?e:t},this.$get=function(){function e(){return i}function n(){return t}var i=new IconicJS,o={getAccess:e,getAssetPath:n};return o}}function e(t,e,n){function i(){function i(e,n,i){if(a=e.iconDir?e.iconDir:t.getAssetPath(),"/"!==a.charAt(a.length-1)&&(a+="/"),e.dynSrc?i.$set("data-src",e.dynSrc):e.dynIcon?i.$set("data-src",a+e.dynIcon+".svg"):e.icon?i.$set("data-src",a+e.icon+".svg"):i.$set("data-src",i.src),!n.hasClass("iconic-sm")&&!n.hasClass("iconic-md")&&!n.hasClass("iconic-lg")){var o;switch(e.size){case"small":o="iconic-sm";break;case"medium":o="iconic-md";break;case"large":o="iconic-lg";break;default:o="iconic-fluid"}n.addClass(o)}c=n[0].outerHTML}function o(i,o){function r(t){s&&(s.empty(),s.append(angular.element(c)),s.attr("data-src",t),u(s[0]))}function u(t){l.inject(t,{each:function(t){var e=angular.element(t);s=n(e)(e.scope())}})}var s,l=t.getAccess();u(o[0]),e.subscribe("resize",function(){l.update(o[0])}),i.dynSrc&&i.$watch("dynSrc",function(t,e){t&&t!==e&&r(i.dynSrc)}),i.dynIcon&&i.$watch("dynIcon",function(t,e){t&&t!==e&&r(a+i.dynIcon+".svg")})}var c,a;return{pre:i,post:o}}var o={restrict:"A",template:"<img ng-transclude>",transclude:!0,replace:!0,scope:{dynSrc:"=?",dynIcon:"=?",size:"@?",icon:"@",iconDir:"@?"},compile:i};return o}angular.module("foundation.iconic",[]).provider("Iconic",t).directive("zfIconic",e),e.$inject=["Iconic","FoundationApi","$compile"]}(),function(){"use strict";function t(t,e,n,i,o){function c(c,a,r,u,s){function l(t){return e.get(t,{cache:n})}function f(t){var e=o.collectScenariosFromElement(t);m=e.scenarios,g=e.templates}function d(t){return!v||v!==t}{var p,v,m,g;o.getMediaQueries()}i.subscribe("resize",function(){s(function(e,n){m&&g||f(e);var i=o.match(m),c=0===i.length?null:m[i[0].ind];if(c&&d(c)){if(p&&(p.$destroy(),p=null),"undefined"!=typeof c.templ){p=n;var r=document.createElement("div");r.appendChild(g[c.templ][0]),a.html(r.innerHTML),t(a.contents())(p),v=c}else{var u=l(c.src);u.success(function(t){p=n,a.html(t)}).then(function(){t(a.contents())(p),v=c})}}})}),i.publish("resize","initial resize")}var a={restrict:"EA",transclude:"element",scope:{position:"@"},replace:!0,template:"<div></div>",link:c};return a}angular.module("foundation.interchange",["foundation.core","foundation.mediaquery"]).directive("zfInterchange",t),t.$inject=["$compile","$http","$templateCache","FoundationApi","FoundationMQ"]}(),function(){"use strict";function t(t,e){function n(e){t.publish(e,"show")}function i(e){t.publish(e,"hide")}function o(t){return new e(t)}var c={};return c.activate=n,c.deactivate=i,c.newModal=o,c}function e(t){function e(){function e(t,e,n){n.$set("zf-closable",i)}function n(e,n,i){function o(){e.overlay||n.css("background","transparent"),t.animate(n,e.active,s,l),t.animate(a,e.active,r,u)}function c(){e.active&&e.show()}var a=angular.element(n.children()[0]);e.active=e.active||!1,e.overlay="false"===i.overlay?!1:!0,e.overlayClose="false"===i.overlayClose?!1:!0;var r=i.animationIn||"fadeIn",u=i.animationOut||"fadeOut",s="fadeIn",l="fadeOut";e.hideOverlay=function(){e.overlayClose&&e.hide()},e.hide=function(){e.active=!1,o()},e.show=function(){e.active=!0,o(),a.tabIndex=-1,a[0].focus()},e.toggle=function(){e.active=!e.active,o()},c(),t.subscribe(i.id,function(t){"show"===t||"open"===t?e.show():"close"===t||"hide"===t?e.hide():"toggle"===t&&e.toggle(),e.$root&&!e.$root.$$phase&&e.$apply()})}var i="modal";return{pre:e,post:n}}var n={restrict:"EA",templateUrl:"components/modal/modal.html",transclude:!0,scope:!0,replace:!0,compile:e};return n}function n(t,e,n,i,o,c,a){function r(r){function u(){if(S)throw"Error: Modal was destroyed. Delete the object and create a new ModalFactory instance."}function s(){u(),o(function(){d(!0),a.publish($,"show")
+},0,!1)}function l(){u(),o(function(){d(!1),a.publish($,"hide")},0,!1)}function f(){u(),o(function(){d(!0),a.publish($,"toggle")},0,!1)}function d(t){c.when(h).then(function(){if(!E&&m.length>0){{w.append(g)}b.active=t,i(g)(b),E=!0}})}function p(){if(!document.getElementById($)){m='<zf-modal id="'+$+'">'+m+"</zf-modal>",g=angular.element(m),b=n.$new();for(var t=0;t<j.length;t++){var e=j[t];if(r[e])switch(e){case"animationIn":g.attr("animation-in",r[e]);break;case"animationOut":g.attr("animation-out",r[e]);break;default:g.attr(e,r[e])}}if(r.contentScope){y=r.contentScope;for(var e in r.contentScope)r.contentScope.hasOwnProperty(e)&&(b[e]=r.contentScope[e])}}}function v(){A.deactivate(),setTimeout(function(){b.$destroy(),g.remove(),S=!0},3e3),a.unsubscribe($)}var m,g,h,b,y,A=this,w=angular.element(r.container||document.body),$=r.id||a.generateUuid(),E=!1,S=!1,j=["animationIn","animationOut","overlay","overlayClose"];return r.templateUrl?h=t.get(r.templateUrl,{cache:e}).then(function(t){m=t.data,p()}):r.template&&(h=!0,m=r.template,p()),A.activate=s,A.deactivate=l,A.toggle=f,A.destroy=v,{activate:s,deactivate:l,toggle:f,destroy:v}}return r}angular.module("foundation.modal",["foundation.core"]).directive("zfModal",e).factory("ModalFactory",n),t.$inject=["FoundationApi","ModalFactory"],e.$inject=["FoundationApi"],n.$inject=["$http","$templateCache","$rootScope","$compile","$timeout","$q","FoundationApi"]}(),function(){"use strict";function t(t,e){function n(e){t.publish(e,"show")}function i(e){t.publish(e,"hide")}var o={};return o.activate=n,o.deactivate=i,o}function e(t,e){var n=this;n.notifications=t.notifications=t.notifications||[],n.addNotification=function(n){var i=e.generateUuid();n.id=i,t.notifications.push(n)},n.removeNotification=function(e){t.notifications.forEach(function(n){if(n.id===e){var i=t.notifications.indexOf(n);t.notifications.splice(i,1)}})},n.clearAll=function(){for(;t.notifications.length>0;)t.notifications.pop()}}function n(t){function e(e,n,i,o){e.position=e.position?e.position.split(" ").join("-"):"top-right",t.subscribe(i.id,function(t){"clearall"===t?o.clearAll():(o.addNotification(t),e.$root.$$phase||e.$apply())})}var n={restrict:"EA",templateUrl:"components/notification/notification-set.html",controller:"ZfNotificationController",replace:!0,scope:{position:"@"},link:e};return n}function i(t){function e(){function e(t,e,n){n.$set("zf-closable","notification")}function n(e,n,i,o){e.active=!1;var c,a=i.animationIn||"fadeIn",r=i.animationOut||"fadeOut";setTimeout(function(){e.active=!0,t.animate(n,e.active,a,r)},50),e.hide=function(){e.active=!1,t.animate(n,e.active,a,r),setTimeout(function(){o.removeNotification(e.notifId)},50)},e.autoclose&&setTimeout(function(){e.active&&e.hide()},parseInt(e.autoclose)),Hammer&&(c=new Hammer(n[0]),c.get("swipe").set({direction:Hammer.DIRECTION_ALL,threshold:5,velocity:.5})),c.on("swipe",function(){e.active&&e.hide()})}return{pre:e,post:n}}var n={restrict:"EA",templateUrl:"components/notification/notification.html",replace:!0,transclude:!0,require:"^zfNotificationSet",controller:function(){},scope:{title:"=?",content:"=?",image:"=?",notifId:"=",color:"=?",autoclose:"=?"},compile:e};return n}function o(t){function e(){function e(t,e,n){n.$set("zf-closable",i)}function n(e,n,i){e.position=i.position?i.position.split(" ").join("-"):"top-right";var o=i.animationIn||"fadeIn",c=i.animationOut||"fadeOut";t.subscribe(i.id,function(i){"show"==i||"open"==i?(e.show(),e.autoclose&&setTimeout(function(){e.active&&e.hide()},parseInt(e.autoclose))):"close"==i||"hide"==i?e.hide():"toggle"==i&&(e.toggle(),e.autoclose&&setTimeout(function(){e.active&&e.toggle()},parseInt(e.autoclose))),t.animate(n,e.active,o,c),e.$apply()}),e.hide=function(){e.active=!1,t.animate(n,e.active,o,c)},e.show=function(){e.active=!0,t.animate(n,e.active,o,c)},e.toggle=function(){e.active=!e.active,t.animate(n,e.active,o,c)}}var i="notification";return{pre:e,post:n}}var n={restrict:"EA",templateUrl:"components/notification/notification-static.html",replace:!0,transclude:!0,scope:{title:"@?",content:"@?",image:"@?",color:"@?",autoclose:"@?"},compile:e};return n}function c(t){function e(e,n,i){n.on("click",function(n){t.publish(i.zfNotify,{title:e.title,content:e.content,color:e.color,image:e.image,autoclose:e.autoclose}),n.preventDefault()})}var n={restrict:"A",scope:{title:"@?",content:"@?",color:"@?",image:"@?",autoclose:"@?"},link:e};return n}function a(t,e,n,i,o,c){function a(t){function e(){if(y)throw"Error: Notification Set was destroyed. Delete the object and create a new NotificationFactory instance."}function a(t){e(),o(function(){c.publish(h,t)},0,!1)}function r(){e(),o(function(){c.publish(h,"clearall")},0,!1)}function u(t){if(!b&&f.length>0){{g.append(d)}p.active=t,i(d)(p),b=!0}}function s(){if(!document.getElementById(h)){f='<zf-notification-set id="'+h+'"></zf-notification-set>',d=angular.element(f),p=n.$new();for(var e=0;e<A.length;e++)t[A[e]]&&d.attr(A[e],t[A[e]]);if(t.contentScope){v=t.contentScope;for(var i in v)v.hasOwnProperty(i)&&(p[i]=v[i])}u(!0)}}function l(){m.clearAll(),setTimeout(function(){p.$destroy(),d.remove(),y=!0},3e3),c.unsubscribe(h)}var f,d,p,v,m=this,g=angular.element(t.container||document.body),h=t.id||c.generateUuid(),b=!1,y=!1,A=["position"];return s(),m.addNotification=a,m.clearAll=r,m.destroy=l,{addNotification:a,clearAll:r,destroy:l}}return a}angular.module("foundation.notification",["foundation.core"]).controller("ZfNotificationController",e).directive("zfNotificationSet",n).directive("zfNotification",i).directive("zfNotificationStatic",o).directive("zfNotify",c).factory("NotificationFactory",a).service("FoundationNotification",t),t.$inject=["FoundationApi","NotificationFactory"],e.$inject=["$scope","FoundationApi"],n.$inject=["FoundationApi"],i.$inject=["FoundationApi"],o.$inject=["FoundationApi"],c.$inject=["FoundationApi"],a.$inject=["$http","$templateCache","$rootScope","$compile","$timeout","FoundationApi"]}(),function(){"use strict";function t(t){function e(e){t.publish(e,"show")}function n(e){t.publish(e,"hide")}var i={};return i.activate=e,i.deactivate=n,i}function e(t){function e(){function e(t,e,n){n.$set("zf-closable",i),document.body.classList.add("has-off-canvas")}function n(e,n,i){e.position=e.position||"left",e.active=!1,t.subscribe(i.id,function(t){"show"===t||"open"===t?e.show():"close"===t||"hide"===t?e.hide():"toggle"===t&&e.toggle(),e.$root.$$phase||e.$apply()}),e.hide=function(){e.active=!1},e.show=function(){e.active=!0},e.toggle=function(){e.active=!e.active}}var i="offcanvas";return{pre:e,post:n}}var n={restrict:"EA",templateUrl:"components/offcanvas/offcanvas.html",transclude:!0,scope:{position:"@"},replace:!0,compile:e};return n}angular.module("foundation.offcanvas",["foundation.core"]).directive("zfOffcanvas",e).service("FoundationOffcanvas",t),t.$inject=["FoundationApi"],e.$inject=["FoundationApi"]}(),function(){"use strict";function t(t){function e(e){t.publish(e,"show")}function n(e){t.publish(e,"hide")}var i={};return i.activate=e,i.deactivate=n,i}function e(t,e){function n(){function n(t,e,n){n.$set("zf-closable",o),t.position=t.position||"left",t.positionClass="panel-"+t.position}function i(n,i,o){n.active=!1;var c,a,r=t.getSettings().mediaQueries;"left"===n.position?(c=o.animationIn||"slideInRight",a=o.animationOut||"slideOutLeft"):"right"===n.position?(c=o.animationIn||"slideInLeft",a=o.animationOut||"slideOutRight"):"top"===n.position?(c=o.animationIn||"slideInDown",a=o.animationOut||"slideOutUp"):"bottom"===n.position&&(c=o.animationIn||"slideInUp",a=o.animationOut||"slideOutBottom"),t.subscribe(o.id,function(t){var o=e.getComputedStyle(i[0]).getPropertyValue("position");"absolute"===o&&("show"==t||"open"==t?n.show():"close"==t||"hide"==t?n.hide():"toggle"==t&&n.toggle(),n.$root.$$phase||n.$apply())}),n.hide=function(){n.active&&(n.active=!1,t.animate(i,n.active,c,a))},n.show=function(){n.active||(n.active=!0,t.animate(i,n.active,c,a))},n.toggle=function(){n.active=!n.active,t.animate(i,n.active,c,a)},i.on("click",function(e){var o=e.srcElement;!matchMedia(r.medium).matches&&o.href&&o.href.length>0&&(n.hide(),t.animate(i,n.active,c,a))})}var o="panel";return{pre:n,post:i}}var i={restrict:"EA",templateUrl:"components/panel/panel.html",transclude:!0,scope:{position:"@?"},replace:!0,compile:n};return i}angular.module("foundation.panel",["foundation.core"]).directive("zfPanel",e).service("FoundationPanel",t),t.$inject=["FoundationApi"],e.$inject=["FoundationApi","$window"]}(),function(){"use strict";function t(t){function e(e){t.publish(e,"show")}function n(e){t.publish(e,"hide")}var i={};return i.activate=e,i.deactivate=n,i}function e(t){function e(){function e(t,e,n){n.$set("zf-closable","popup")}function n(e,n,i){function o(t){r||(e.target=document.getElementById(e.target?e.target:t),u=new Tether({element:n[0],target:e.target,attachment:c,targetAttachment:a,enable:!1}),r=!0)}e.active=!1,e.target=e.target||!1;var c=e.pinTo||"top center",a=e.pinAt||"bottom center",r=!1,u={};t.subscribe(i.id,function(t){"show"===t[0]||"open"===t[0]?e.show(t[1]):"close"===t[0]||"hide"===t[0]?e.hide():"toggle"===t[0]&&e.toggle(t[1]),e.$apply()}),e.hide=function(){e.active=!1,o(),u.disable()},e.show=function(t){e.active=!0,o(t),u.enable()},e.toggle=function(t){e.active=!e.active,o(t),e.active?u.enable():u.disable()}}return{pre:e,post:n}}var n={restrict:"EA",transclude:!0,replace:!0,templateUrl:"components/popup/popup.html",scope:{pinTo:"@?",pinAt:"@?",target:"@?"},compile:e};return n}function n(t){function e(e,n,i){var o=i.zfPopupToggle,c=i.id||t.generateUuid();i.$set("id",c),n.on("click",function(e){t.publish(o,["toggle",c]),e.preventDefault()})}var n={restrict:"A",link:e};return n}angular.module("foundation.popup",["foundation.core"]).directive("zfPopup",e).directive("zfPopupToggle",n).service("FoundationPopup",t),t.$inject=["FoundationApi"],e.$inject=["FoundationApi"],n.$inject=["FoundationApi"]}(),function(){"use strict";function t(t){function e(e){t.publish(e,"show")}var n={};return n.activate=e,n}function e(t,e){var n=this,i=n.tabs=t.tabs=[],o="";n.select=function(t){i.forEach(function(n){n.active=!1,n.scope.active=!1,n.scope===t&&(e.publish(o,["activate",n]),n.active=!0,n.scope.active=!0)})},n.addTab=function(t){i.push({scope:t,active:!1,parentContent:n.id}),1===i.length&&(i[0].active=!0,t.active=!0)},n.getId=function(){return o},n.setId=function(t){o=t}}function n(t){function e(e,n,i,o){e.id=i.id||t.generateUuid(),e.showTabContent="true"!==e.displaced,i.$set("id",e.id),o.setId(e.id);var c=function(){t.publish(e.id+"-tabs",e.tabs)};t.subscribe(e.id+"-get-tabs",function(){c()})}var n={restrict:"EA",transclude:"true",replace:!0,templateUrl:"components/tabs/tabs.html",controller:"ZfTabsController",scope:{displaced:"@?"},link:e};return n}function i(t){function e(e){e.tabs=e.tabs||[];var n=e.target;t.subscribe(n,function(t){if("activate"===t[0]){{t[1]}e.tabs.forEach(function(t){t.scope.active=!1,t.active=!1,t.scope.id===n&&(t.scope.active=!0,t.active=!0)})}}),0===e.tabs.length&&(t.subscribe(n+"-tabs",function(t){e.tabs=t}),t.publish(n+"-get-tabs",""))}var n={restrict:"A",transclude:"true",replace:!0,scope:{tabs:"=?",target:"@"},templateUrl:"components/tabs/tab-content.html",link:e};return n}function o(t){function e(e,n,i,o,c){e.id=i.id||t.generateUuid(),e.active=!1,e.transcludeFn=c,o.addTab(e),t.subscribe(e.id,function(t){("show"===t||"open"===t||"activate"===t)&&e.makeActive()}),e.makeActive=function(){o.select(e)}}var n={restrict:"EA",templateUrl:"components/tabs/tab.html",transclude:!0,scope:{title:"@"},require:"^zfTabs",replace:!0,link:e};return n}function c(t){function e(e,n,i){{var o=e.$eval(i.tab);o.scope.id}o.scope.transcludeFn(o.scope,function(t){n.append(t)}),t.subscribe(o.scope.id,function(){t.publish(o.parentContent,["activate",o.scope.id]),e.$apply()})}var n={restrict:"EA",transclude:"true",link:e};return n}function a(t){function e(e,n,i){function o(){n.parent().children().removeClass("is-active"),n.addClass("is-active")}var c=i.zfTabHref;t.subscribe(c,function(t){("activate"===t||"show"===t||"open"===t)&&o()}),n.on("click",function(e){t.publish(c,"activate"),o(),e.preventDefault()})}var n={restrict:"A",replace:!1,link:e};return n}function r(){function t(t,e){var n=e.children();angular.element(n[0]).addClass("is-active")}var e={restrict:"A",replace:!1,link:t};return e}function u(t){function e(e,n){function i(t){var e=n.children();angular.forEach(e,function(e){var n=angular.element(e);n.removeClass("is-active"),n.attr("id")===t&&n.addClass("is-active")})}var o=[],c=n.children();angular.forEach(c,function(e){if(e.id){var n=e.id;if(o.push(n),t.subscribe(n,function(t){("activate"===t||"show"===t||"open"===t)&&i(n)}),1===o.length){var c=angular.element(e);c.addClass("is-active")}}})}return{restrict:"A",link:e}}angular.module("foundation.tabs",["foundation.core"]).controller("ZfTabsController",e).directive("zfTabs",n).directive("zfTabContent",i).directive("zfTab",o).directive("zfTabIndividual",c).directive("zfTabHref",a).directive("zfTabCustom",r).directive("zfTabContentCustom",u).service("FoundationTabs",t),t.$inject=["FoundationApi"],e.$inject=["$scope","FoundationApi"],n.$inject=["FoundationApi"],i.$inject=["FoundationApi"],o.$inject=["FoundationApi"],c.$inject=["FoundationApi"],a.$inject=["FoundationApi"],r.$inject=["FoundationApi"],u.$inject=["FoundationApi"]}(),function(){"use strict";angular.module("foundation",["foundation.core","foundation.mediaquery","foundation.accordion","foundation.actionsheet","foundation.common","foundation.iconic","foundation.interchange","foundation.modal","foundation.notification","foundation.offcanvas","foundation.panel","foundation.popup","foundation.tabs"])}(); \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/account.svg b/afb-client/bower_components/foundation-apps/iconic/account.svg
new file mode 100755
index 0000000..500789e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/account.svg
@@ -0,0 +1,44 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="account" width="128" height="128" class="iconic iconic-account" viewBox="0 0 128 128">
+ <g><title>Sign In &amp; Out</title></g>
+ <g data-width="128" data-height="128" class="iconic-lg iconic-container" display="inline">
+ <g class="iconic-account-login">
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-entrance iconic-property-accent iconic-property-stroke" d="M46 4h78v120h-78" fill="none"/>
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-arrow iconic-account-login-arrow-line iconic-property-stroke" d="M4 64h76" fill="none"/>
+ <path d="M90.7 63.2l-21.4-12.4c-.7-.4-1.3-.1-1.3.7v25c0 .8.6 1.2 1.3.7l21.4-12.5c.7-.4.7-1 0-1.5z" class="iconic-account-login-arrow iconic-account-login-arrow-head iconic-property-fill"/>
+ </g>
+ <g class="iconic-account-logout" display="none">
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-entrance iconic-property-accent iconic-property-stroke" d="M46 4h78v120h-78" fill="none"/>
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-arrow iconic-account-logout-arrow-line iconic-property-stroke" d="M88 64h-76" fill="none"/>
+ <path d="M1.3 64.8l21.4 12.5c.7.4 1.3.1 1.3-.7v-25c0-.8-.6-1.2-1.3-.7l-21.4 12.3c-.7.5-.7 1.1 0 1.6z" class="iconic-account-logout-arrow iconic-account-logout-arrow-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="31" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-account-login">
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-entrance iconic-property-accent iconic-property-stroke" d="M12.5 1.5h18v28h-18" fill="none"/>
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-arrow iconic-account-login-arrow-line iconic-property-stroke" d="M1.5 15.5h14.5" fill="none"/>
+ <path d="M20.6 15.8l-5.2 3.9c-.2.2-.4.1-.4-.2v-8c0-.3.2-.4.4-.2l5.2 3.9c.2.2.2.4 0 .6z" class="iconic-account-login-arrow iconic-account-login-arrow-head iconic-property-fill"/>
+ </g>
+ <g class="iconic-account-logout" display="none">
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-entrance iconic-property-accent iconic-property-stroke" d="M12.5 1.5h18v28h-18" fill="none"/>
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-arrow iconic-account-logout-arrow-line iconic-property-stroke" d="M19.5 15.5h-14.5" fill="none"/>
+ <path d="M.4 15.2l5.2-3.9c.2-.2.4-.1.4.2v8c0 .3-.2.4-.4.2l-5.2-3.9c-.2-.2-.2-.4 0-.6z" class="iconic-account-logout-arrow iconic-account-logout-arrow-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <g class="iconic-account-login">
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-entrance iconic-property-accent iconic-property-stroke" d="M7 1h8v14h-8" fill="none"/>
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-login-arrow iconic-account-login-arrow-line iconic-property-stroke" d="M1 8h9" fill="none"/>
+ <path class="iconic-account-login-arrow iconic-account-login-arrow-head iconic-property-fill" d="M12 8l-4-4v8z"/>
+ </g>
+ <g class="iconic-account-logout" display="none">
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-entrance iconic-property-accent iconic-property-stroke" d="M7 1h8v14h-8" fill="none"/>
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-account-logout-arrow iconic-account-logout-arrow-line iconic-property-stroke" d="M11 8h-9" fill="none"/>
+ <path class="iconic-account-logout-arrow iconic-account-logout-arrow-head iconic-property-fill" d="M0 8l4 4v-8z"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["account"]=iconicApis["account"]||function(t){var i=function(i){t.setAttribute("data-state",i);var e,n=t.querySelectorAll(".iconic-account-login"),o=t.querySelectorAll(".iconic-account-logout");if("logout"===i){for(e=0;e<n.length;e++)n[e].setAttribute("display","none");for(e=0;e<o.length;e++)o[e].setAttribute("display","inline")}else{for(e=0;e<n.length;e++)n[e].setAttribute("display","inline");for(e=0;e<o.length;e++)o[e].setAttribute("display","none")}},e=function(){var e=t.getAttribute("data-state");e&&i(e)};return{update:e,setState:i}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/action.svg b/afb-client/bower_components/foundation-apps/iconic/action.svg
new file mode 100755
index 0000000..cb8765e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/action.svg
@@ -0,0 +1,38 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="action" width="128" height="128" class="iconic iconic-action" viewBox="0 0 128 128">
+ <g><title>Action</title></g>
+ <g data-width="128" data-height="96" class="iconic-lg iconic-container" display="inline" transform="translate(0 16)">
+ <g class="iconic-action-undo">
+ <path d="M30 59c0-27.1 21.9-49 49-49s49 21.9 49 49c0-32.6-26.4-59-59-59s-59 26.4-59 59v11h20v-11z" class="iconic-action-undo-stem iconic-property-fill"/>
+ <path d="M19.2 94.7l-18.4-29.4c-.4-.7-.1-1.3.7-1.3h37c.8 0 1.1.6.7 1.3l-18.4 29.4c-.4.7-1.2.7-1.6 0z" class="iconic-action-undo-arrowhead iconic-property-fill"/>
+ </g>
+ <g class="iconic-action-redo" display="none">
+ <path d="M98 59c0-27.1-21.9-49-49-49s-49 21.9-49 49c0-32.6 26.4-59 59-59s59 26.4 59 59v11h-20v-11z" class="iconic-action-redo-stem iconic-property-fill"/>
+ <path d="M108.8 94.7l18.4-29.5c.4-.7.1-1.3-.7-1.3h-37c-.8 0-1.1.6-.7 1.3l18.4 29.5c.4.7 1.2.7 1.6 0z" class="iconic-action-redo-arrowhead iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="24" class="iconic-md iconic-container" display="none" transform="scale(4) translate(0 4)">
+ <g class="iconic-action-undo">
+ <path d="M9 14.5c0-6.4 5.1-11.5 11.5-11.5 6 0 10.9 4.7 11.4 10.5-.6-7.5-6.8-13.5-14.4-13.5-8 0-14.5 6.5-14.5 14.5v2.5h6v-2.5z" class="iconic-action-undo-stem iconic-property-fill"/>
+ <path d="M6.3 23.6l5.4-7.2c.2-.2.1-.4-.2-.4h-11c-.3 0-.4.2-.2.4l5.4 7.2c.2.2.4.2.6 0z" class="iconic-action-undo-arrowhead iconic-property-fill"/>
+ </g>
+ <g class="iconic-action-redo" display="none">
+ <path d="M23 14.5c0-6.4-5.1-11.5-11.5-11.5-6 0-10.9 4.7-11.5 10.5.6-7.5 6.9-13.5 14.5-13.5 8 0 14.5 6.5 14.5 14.5v2.5h-6v-2.5z" class="iconic-action-redo-stem iconic-property-fill"/>
+ <path d="M25.7 23.6l-5.4-7.2c-.2-.2-.1-.4.2-.4h11c.3 0 .4.2.2.4l-5.4 7.2c-.2.2-.4.2-.6 0z" class="iconic-action-redo-arrowhead iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="12" class="iconic-sm iconic-container" display="none" transform="scale(8) translate(0 2)">
+ <g class="iconic-action-undo">
+ <path d="M2 9v-2c0-3.9 3.1-7 7-7s7 3.1 7 7c0-2.8-2.2-5-5-5s-5 2.2-5 5v2h-4z" class="iconic-action-undo-stem iconic-property-fill"/>
+ <path class="iconic-action-undo-arrowhead iconic-property-fill" d="M0 8l4 4 4-4z"/>
+ </g>
+ <g class="iconic-action-redo" display="none">
+ <path d="M10 9v-2c0-2.8-2.2-5-5-5s-5 2.2-5 5c0-3.9 3.1-7 7-7s7 3.1 7 7v2h-4z" class="iconic-action-redo-stem iconic-property-fill"/>
+ <path class="iconic-action-redo-arrowhead iconic-property-fill" d="M8 8l4 4 4-4z"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["action"]=iconicApis["action"]||function(t){var i=function(i){t.setAttribute("data-state",i);var n,e,o=t.querySelectorAll(".iconic-action-undo"),c=t.querySelectorAll(".iconic-action-redo");n=e="none","redo"===i?e="inline":n="inline";for(var a=0;a<o.length;a++)o[a].setAttribute("display",n),c[a].setAttribute("display",e)},n=function(){var n=t.getAttribute("data-state");n&&i(n)};return{update:n,setState:i}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/ban.svg b/afb-client/bower_components/foundation-apps/iconic/ban.svg
new file mode 100755
index 0000000..070d3cf
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/ban.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-ban" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Ban</title>
+ </g>
+ <g class="iconic-ban-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
+ <path stroke="#000" stroke-width="8" class="iconic-ban-strike iconic-property-accent iconic-property-stroke" d="M107.841 20.159l-87.674 87.674" fill="none" />
+ <circle stroke="#000" stroke-width="8" cx="64" cy="64" r="60" class="iconic-ban-circle iconic-property-stroke" fill="none" />
+ </g>
+ <g class="iconic-ban-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <path stroke="#000" stroke-width="3" class="iconic-ban-strike iconic-property-accent iconic-property-stroke" d="M26.59 5.41l-21.197 21.197" fill="none" />
+ <circle stroke="#000" stroke-width="3" cx="16" cy="16" r="14.5" class="iconic-ban-circle iconic-property-stroke" fill="none" />
+ </g>
+ <g class="iconic-ban-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path stroke="#000" stroke-width="2" stroke-linejoin="round" class="iconic-ban-strike iconic-property-accent iconic-property-stroke" d="M13 3l-10 10" fill="none" />
+ <circle stroke="#000" stroke-width="2" stroke-linejoin="round" cx="8" cy="8" r="7" class="iconic-ban-circle iconic-property-stroke" fill="none" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/bell.svg b/afb-client/bower_components/foundation-apps/iconic/bell.svg
new file mode 100755
index 0000000..10dd239
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/bell.svg
@@ -0,0 +1,22 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-bell" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Bell</title>
+ </g>
+ <g class="iconic-bell-lg iconic-container iconic-lg" data-width="112" data-height="128" display="inline" transform="translate(8)">
+ <circle cx="56" cy="6" r="6" class="iconic-bell-crown iconic-property-fill" />
+ <path d="M100 82.033c-14.828-10.22-16-24.339-16-39.934v-4.098c0-15.464-12.536-28-28-28s-28 12.536-28 28v4.098c0 15.595-1.172 29.714-16 39.934-7.414 5.11-12 12.169-12 19.967v2h112v-2c0-7.798-4.586-14.857-12-19.967z" class="iconic-bell-body iconic-property-fill"
+ />
+ <path d="M41.174 106c-.751 1.854-1.174 3.877-1.174 6 0 8.836 7.163 16 16 16s16-7.163 16-16c0-2.123-.423-4.146-1.174-6h-29.652z" class="iconic-bell-clapper iconic-property-accent iconic-property-fill" />
+ </g>
+ <g class="iconic-bell-md iconic-container iconic-md" data-width="28" data-height="32" display="none" transform="scale(4) translate(2)">
+ <path d="M10 28c0 2.209 1.791 4 4 4s4-1.791 4-4h-8z" class="iconic-bell-clapper iconic-property-force-fill iconic-property-accent iconic-property-fill" />
+ <circle cx="14" cy="2" r="2" class="iconic-bell-crown iconic-property-force-fill iconic-property-fill" />
+ <path d="M27.972 25.622c-.139-1.798-1.24-3.42-2.972-4.614-3.707-2.555-4-6.085-4-9.984v-1.025c0-3.866-3.134-7-7-7s-7 3.134-7 7v1.025c0 3.899-.293 7.429-4 9.984-1.732 1.194-2.834 2.816-2.972 4.614h-.007v.094c-.005.095-.021.188-.021.284h.021v1h27.979v-1.378h-.028z"
+ class="iconic-bell-body iconic-property-fill" />
+ </g>
+ <g class="iconic-bell-sm iconic-container iconic-sm" data-width="14" data-height="16" display="none" transform="scale(8) translate(1)">
+ <path d="M5 14c0 1.105.895 2 2 2s2-.895 2-2h-4z" class="iconic-bell-clapper iconic-property-force-fill iconic-property-accent iconic-property-fill" />
+ <circle cx="7" cy="1" r="1" class="iconic-bell-crown iconic-property-force-fill iconic-property-fill" />
+ <path d="M0 13c0-1.04.509-1.981 1.333-2.662 1.648-1.363 1.667-3.245 1.667-5.325v-.013c0-2.209 1.791-4 4-4s4 1.791 4 4v.013c0 2.079.019 3.962 1.667 5.325.824.681 1.333 1.623 1.333 2.662h-14z" class="iconic-bell-body iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/bookmark.svg b/afb-client/bower_components/foundation-apps/iconic/bookmark.svg
new file mode 100755
index 0000000..abe94d8
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/bookmark.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-bookmark" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Bookmark</title>
+ </g>
+ <g class="iconic-bookmark-lg iconic-container iconic-lg" data-width="44" data-height="128" display="inline" transform="translate(42)">
+ <path class="iconic-property-fill" d="M0 0v128l22-14.247 22 14.247v-128z" />
+ </g>
+ <g class="iconic-bookmark-md iconic-container iconic-md" data-width="14" data-height="32" display="none" transform="scale(4) translate(9)">
+ <path d="M0 .5v31c0 .276.182.37.407.209l6.186-4.419c.225-.161.589-.161.814 0l6.186 4.419c.225.161.407.067.407-.209v-31c0-.276-.224-.5-.5-.5h-13c-.276 0-.5.224-.5.5z" class="iconic-property-fill" />
+ </g>
+ <g class="iconic-bookmark-sm iconic-container iconic-sm" data-width="8" data-height="16" display="none" transform="scale(8) translate(4)">
+ <path d="M0 .25v15.5c0 .138.079.171.177.073l3.646-3.646c.098-.098.256-.098.354 0l3.646 3.646c.098.098.177.065.177-.073v-15.5c0-.138-.112-.25-.25-.25h-7.5c-.138 0-.25.112-.25.25z" class="iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/cart.svg b/afb-client/bower_components/foundation-apps/iconic/cart.svg
new file mode 100755
index 0000000..06098dc
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/cart.svg
@@ -0,0 +1,35 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-cart" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Cart</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-cart-clip-0">
+ <path d="M0 0v106h22.695c-2.835-1.992-4.695-5.28-4.695-9 0-6.065 4.935-11 11-11s11 4.935 11 11c0 3.72-1.861 7.008-4.695 9h61.391c-2.835-1.992-4.695-5.28-4.695-9 0-6.065 4.935-11 11-11s11 4.935 11 11c0 3.72-1.861 7.008-4.695 9h18.695v-106h-128z" />
+ </clipPath>
+ <clipPath id="iconic-size-md-cart-clip-0">
+ <path d="M0 0v28h5.058c-.651-.636-1.058-1.52-1.058-2.5 0-1.93 1.57-3.5 3.5-3.5s3.5 1.57 3.5 3.5c0 .98-.407 1.864-1.058 2.5h14.116c-.651-.636-1.058-1.52-1.058-2.5 0-1.93 1.57-3.5 3.5-3.5s3.5 1.57 3.5 3.5c0 .98-.407 1.864-1.058 2.5h3.058v-28h-32z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-cart-lg iconic-container iconic-lg" data-width="128" data-height="106" display="inline" transform="translate(0 11)">
+ <path d="M31.176 65.115l-14.352-50.231c-.455-1.593.519-2.885 2.176-2.885h106c1.657 0 2.719 1.313 2.371 2.933l-10.743 50.133c-.347 1.62-1.972 2.933-3.629 2.933h-78c-1.657 0-3.369-1.291-3.824-2.885z" class="iconic-cart-basket iconic-property-fill" />
+ <circle cx="29" cy="97" r="9" class="iconic-cart-wheel iconic-cart-wheel-back iconic-property-fill" />
+ <circle cx="103" cy="97" r="9" class="iconic-cart-wheel iconic-cart-wheel-front iconic-property-fill" />
+ <path clip-path="url(#iconic-size-lg-cart-clip-0)" stroke="#000" stroke-width="4" d="M106 92h-81.25c-.414 0-.621-.31-.462-.692l9.423-22.615c.159-.382.196-1.015.081-1.413l-18.585-64.559c-.115-.398-.543-.721-.957-.721h-11.25" class="iconic-cart-body iconic-property-stroke"
+ fill="none" />
+ <circle cx="3" cy="3" r="3" class="iconic-cart-handle iconic-property-fill" />
+ </g>
+ <g class="iconic-cart-md iconic-container iconic-md" data-width="32" data-height="28" display="none" transform="scale(4) translate(0 2)">
+ <path d="M8.742 17.034l-3.485-13.068c-.142-.534.19-.966.742-.966h25c.552 0 .912.439.804.981l-2.608 13.039c-.108.542-.644.981-1.196.981h-18c-.552 0-1.115-.433-1.258-.966z" class="iconic-cart-basket iconic-property-fill" />
+ <circle cx="7.5" cy="25.5" r="2.5" class="iconic-cart-wheel iconic-cart-wheel-back iconic-property-fill" />
+ <circle cx="26.5" cy="25.5" r="2.5" class="iconic-cart-wheel iconic-cart-wheel-front iconic-property-fill" />
+ <path clip-path="url(#iconic-size-md-cart-clip-0)" stroke="#000" d="M27 24.5h-20c-.276 0-.42-.209-.321-.467l2.141-5.567c.099-.258.124-.683.055-.951l-4.251-16.531c-.069-.267-.348-.484-.625-.484h-3" class="iconic-cart-body iconic-property-stroke" fill="none"
+ />
+ <circle cx="1" cy="1" r="1" class="iconic-cart-handle iconic-property-fill" />
+ </g>
+ <g class="iconic-cart-sm iconic-container iconic-sm" data-width="16" data-height="14" display="none" transform="scale(8) translate(0 1)">
+ <circle cx="3.5" cy="12.5" r="1.5" class="iconic-cart-wheel iconic-cart-wheel-back iconic-property-fill" />
+ <circle cx="13.5" cy="12.5" r="1.5" class="iconic-cart-wheel iconic-cart-wheel-front iconic-property-fill" />
+ <path d="M3.929 8.505l-.858-6.005c-.039-.273.153-.495.429-.495l12-.004c.276 0 .468.221.429.495l-.859 6.01c-.039.273-.295.495-.571.495h-10c-.276 0-.532-.222-.571-.495z" class="iconic-cart-basket iconic-property-fill" />
+ <path stroke="#000" stroke-linecap="square" d="M.5.5h2.25c.138 0 .274.109.302.244l1.395 6.511c.029.135.03.354.003.49l-.902 4.51c-.027.135.063.245.201.245h9.75" class="iconic-cart-body iconic-property-stroke" fill="none" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/chevron.svg b/afb-client/bower_components/foundation-apps/iconic/chevron.svg
new file mode 100755
index 0000000..9fa4b9b
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/chevron.svg
@@ -0,0 +1,28 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="chevron" width="128" height="128" class="iconic iconic-chevron" viewBox="0 0 128 128">
+ <g><title>Chevron</title></g>
+ <defs>
+ <clipPath id="iconic-size-lg-chevron-clip-0">
+ <path d="M0 0h88v128h-88z"/>
+ </clipPath>
+ <clipPath id="iconic-size-md-chevron-clip-0">
+ <path d="M0 0h26v32h-26z"/>
+ </clipPath>
+ <clipPath id="iconic-size-sm-chevron-clip-0">
+ <path d="M0 0h14v16h-14z"/>
+ </clipPath>
+ </defs>
+ <g data-width="128" data-height="128" class="iconic-lg iconic-container" display="inline" transform="translate(12)">
+ <path clip-path="url(#iconic-size-lg-chevron-clip-0)" stroke="#000" stroke-width="16" stroke-linecap="square" stroke-miterlimit="10" class="iconic-property-stroke" d="M-8-20l84 84-84 84" fill="none"/>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4) translate(1)">
+ <path clip-path="url(#iconic-size-md-chevron-clip-0)" stroke="#000" stroke-width="6" stroke-linecap="square" stroke-miterlimit="10" class="iconic-property-stroke" d="M-1-6l22 22-22 22" fill="none"/>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <path clip-path="url(#iconic-size-sm-chevron-clip-0)" stroke="#000" stroke-width="4" stroke-linecap="square" stroke-miterlimit="10" class="iconic-property-stroke" d="M1.7-1.3l9.3 9.3-13.1 13.1" fill="none"/>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["chevron"]=iconicApis["chevron"]||function(t){function e(e){t.setAttribute("data-direction",e);var n=0;switch(e){case"top":n=270;break;case"left":n=180;break;case"bottom":n=90;break;default:n=0}r.setAttribute("transform","rotate("+n+" 64 64) translate(12) "),a.setAttribute("transform","scale(4) rotate("+n+" 16 16) translate(1)"),i.setAttribute("transform","scale(8) rotate("+n+" 8 8)")}var r=t.querySelector(".iconic-lg"),a=t.querySelector(".iconic-md"),i=t.querySelector(".iconic-sm"),n=function(){var r=t.getAttribute("data-direction")||"";e(r)};return{update:n,setDirection:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/circle-check.svg b/afb-client/bower_components/foundation-apps/iconic/circle-check.svg
new file mode 100755
index 0000000..46accc2
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/circle-check.svg
@@ -0,0 +1,25 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-circle-check" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Circle Check</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-circle-check-clip-0">
+ <path d="M0 0v128h128v-128h-128zm54.196 92.201l-23.853-23.853 5.657-5.657 17.891 17.891 39.813-44.23 5.946 5.352-45.453 50.498z" />
+ </clipPath>
+ <clipPath id="iconic-size-md-circle-check-clip-0">
+ <path d="M0 0v32h32v-32h-32zm13.052 24.173l-6.173-6.173 2.121-2.121 3.948 3.948 9.951-10.946 2.22 2.018-12.067 13.274z" />
+ </clipPath>
+ <clipPath id="iconic-size-sm-circle-check-clip-0">
+ <path d="M0 0v16h16v-16h-16zm7 11.414l-3.414-3.414 1.414-1.414 2 2 4-4 1.414 1.414-5.414 5.414z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-circle-check-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
+ <circle cx="64" cy="64" r="64" clip-path="url(#iconic-size-lg-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
+ </g>
+ <g class="iconic-circle-check-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <circle cx="16" cy="16" r="16" clip-path="url(#iconic-size-md-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
+ </g>
+ <g class="iconic-circle-check-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <circle cx="8" cy="8" r="8" clip-path="url(#iconic-size-sm-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/circle-x.svg b/afb-client/bower_components/foundation-apps/iconic/circle-x.svg
new file mode 100755
index 0000000..347b608
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/circle-x.svg
@@ -0,0 +1,25 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-circle-x" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Circle X</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-circle-x-clip-0">
+ <path d="M0 0v128h128v-128h-128zm90.657 85l-5.657 5.657-21-21-21 21-5.657-5.657 21-21-21-21 5.657-5.657 21 21 21-21 5.657 5.657-21 21 21 21z" />
+ </clipPath>
+ <clipPath id="iconic-size-md-circle-x-clip-0">
+ <path d="M0 0v32h32v-32h-32zm23.121 21l-2.121 2.121-5-5-5 5-2.121-2.121 5-5-5-5 2.121-2.121 5 5 5-5 2.121 2.121-5 5 5 5z" />
+ </clipPath>
+ <clipPath id="iconic-size-sm-circle-x-clip-0">
+ <path d="M0 0v16h16v-16h-16zm11.414 10l-1.414 1.414-2-2-2 2-1.414-1.414 2-2-2-2 1.414-1.414 2 2 2-2 1.414 1.414-2 2 2 2z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-circle-x-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
+ <circle cx="64" cy="64" r="64" clip-path="url(#iconic-size-lg-circle-x-clip-0)" class="iconic-circle-x-body iconic-property-fill" />
+ </g>
+ <g class="iconic-circle-x-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <circle cx="16" cy="16" r="16" clip-path="url(#iconic-size-md-circle-x-clip-0)" class="iconic-circle-x-body iconic-property-fill" />
+ </g>
+ <g class="iconic-circle-x-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <circle cx="8" cy="8" r="8" clip-path="url(#iconic-size-sm-circle-x-clip-0)" class="iconic-circle-x-body iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/cog.svg b/afb-client/bower_components/foundation-apps/iconic/cog.svg
new file mode 100755
index 0000000..269f3d9
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/cog.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-cog" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Cog</title>
+ </g>
+ <g class="iconic-cog-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
+ <path d="M128 73.875v-19.875l-14.323-3.581c-1.156-4.239-2.841-8.257-4.979-11.986l7.539-12.706-14.054-14.054-12.666 7.599c-3.731-2.133-7.751-3.814-11.992-4.966l-3.651-14.308h-19.875l-3.581 14.323c-4.239 1.156-8.257 2.841-11.986 4.978l-12.706-7.539-14.054 14.054 7.599 12.666c-2.133 3.731-3.814 7.751-4.966 11.992l-14.308 3.651v19.875l14.323 3.581c1.156 4.239 2.841 8.257 4.979 11.986l-7.539 12.706 14.054 14.054 12.666-7.599c3.731 2.133 7.751 3.814 11.992 4.966l3.651 14.308h19.875l3.581-14.323c4.239-1.156 8.257-2.841 11.986-4.979l12.705 7.539 14.054-14.054-7.599-12.666c2.133-3.731 3.814-7.751 4.966-11.992l14.308-3.651zm-64 24.125c-18.778 0-34-15.222-34-34s15.222-34 34-34 34 15.222 34 34-15.222 34-34 34z"
+ class="iconic-cog-body iconic-property-fill" />
+ </g>
+ <g class="iconic-cog-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <path d="M32 17.969v-3.969l-3.96-1.32c-.278-1.01-.675-1.969-1.183-2.86l1.849-3.742-2.806-2.807-3.73 1.865c-.891-.507-1.851-.903-2.861-1.18l-1.339-3.957h-3.969l-1.32 3.96c-1.01.278-1.969.675-2.86 1.183l-3.742-1.849-2.806 2.806 1.865 3.73c-.507.891-.903 1.851-1.18 2.861l-3.957 1.339v3.969l3.96 1.32c.278 1.01.675 1.969 1.183 2.86l-1.849 3.742 2.806 2.806 3.73-1.865c.891.507 1.851.903 2.861 1.18l1.34 3.957h3.969l1.32-3.96c1.01-.278 1.969-.675 2.86-1.183l3.742 1.849 2.806-2.806-1.865-3.73c.507-.891.903-1.851 1.18-2.861l3.957-1.34zm-16 5.031c-3.866 0-7-3.134-7-7s3.134-7 7-7 7 3.134 7 7-3.134 7-7 7z"
+ class="iconic-cog-body iconic-property-fill" />
+ </g>
+ <g class="iconic-cog-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path d="M16 8.984v-1.984l-1.971-.986c-.099-.3-.221-.59-.362-.869l.833-2.146-1.5-1.5-2.146.833c-.279-.141-.568-.263-.869-.362l-1.001-1.971h-1.984l-.986 1.971c-.3.099-.59.221-.869.362l-2.146-.833-1.5 1.5.833 2.146c-.141.279-.263.568-.362.869l-1.971 1.001v1.984l1.971.986c.099.3.221.59.362.868l-.833 2.146 1.5 1.5 2.146-.833c.279.141.568.263.869.362l1.001 1.971h1.984l.986-1.971c.3-.099.59-.221.869-.362l2.146.833 1.5-1.5-.833-2.146c.141-.279.263-.568.362-.869l1.971-1.001zm-8 2.016c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z"
+ class="iconic-cog-body iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/comment-square.svg b/afb-client/bower_components/foundation-apps/iconic/comment-square.svg
new file mode 100755
index 0000000..07d0c96
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/comment-square.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-comment-square" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Comment Square</title>
+ </g>
+ <g class="iconic-comment-square-lg iconic-container iconic-lg" data-width="128" data-height="110" display="inline" transform="translate(0 9)">
+ <path d="M0 1.5v85c0 .828.672 1.5 1.5 1.5h103c.828 0 1.975.475 2.561 1.061l19.879 19.879c.586.586 1.061.389 1.061-.439v-107c0-.828-.672-1.5-1.5-1.5h-125c-.828 0-1.5.672-1.5 1.5z" class="iconic-property-fill" />
+ </g>
+ <g class="iconic-comment-square-md iconic-container iconic-md" data-width="32" data-height="29" display="none" transform="scale(4) translate(0 1)">
+ <path d="M0 .5v22c0 .276.224.5.5.5h25c.276 0 .658.158.854.354l5.293 5.293c.195.195.354.13.354-.146v-28c0-.276-.224-.5-.5-.5h-31c-.276 0-.5.224-.5.5z" class="iconic-property-fill" />
+ </g>
+ <g class="iconic-comment-square-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path class="iconic-property-fill" d="M16 0h-16v12h12l4 4z" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/dashboard.svg b/afb-client/bower_components/foundation-apps/iconic/dashboard.svg
new file mode 100755
index 0000000..f41ef7d
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/dashboard.svg
@@ -0,0 +1,38 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-dashboard" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Dashboard</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-dashboard-clip-0">
+ <path d="M0 0v122h128v-122h-128zm73.9 73.9c-2.644 2.644-6.16 4.1-9.9 4.1s-7.255-1.456-9.899-4.101c-4.01-4.01-25.253-37.144-29.471-43.746-1.011-1.582-.785-3.655.542-4.982.772-.772 1.796-1.172 2.83-1.172.743 0 1.49.206 2.152.629 6.601 4.218 39.736 25.461 43.746 29.471 2.645 2.644 4.101 6.16 4.101 9.9s-1.456 7.255-4.1 9.9z"
+ />
+ </clipPath>
+ <clipPath id="iconic-size-md-dashboard-clip-0">
+ <path d="M0 0v30h32v-30h-32zm19.626 19.626c-.885.885-2.061 1.372-3.313 1.372-1.251 0-2.428-.487-3.313-1.372-1.091-1.091-5.745-8.451-7.696-11.565-.495-.79-.378-1.818.281-2.477.386-.386.898-.585 1.414-.585.366 0 .735.101 1.063.306 3.126 1.963 10.51 6.642 11.563 7.695 1.796 1.796 1.796 4.83 0 6.625z"
+ />
+ </clipPath>
+ <clipPath id="iconic-size-sm-dashboard-clip-0">
+ <path d="M0 0v15h16v-15h-16zm9.313 9.313c-.442.442-1.031.686-1.656.686s-1.657-.999-1.657-.999l-2-1s-1.018-4.396-.706-4.708c.192-.192.448-.292.707-.292.161 0 4 1 4 1l1 2s1.211 2.415.313 3.313z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-dashboard-lg iconic-container iconic-lg" data-width="128" data-height="122" display="inline" transform="translate(0 3)">
+ <path stroke="#000" stroke-width="8" d="M90 118.001c2.562-1.244 5.204-2.666 7.547-4.248 3.192-2.156 6.165-4.612 8.88-7.327 2.715-2.715 5.17-5.688 7.327-8.88 2.156-3.192 4.014-6.603 5.532-10.192s2.697-7.357 3.496-11.263 1.219-7.95 1.219-12.092-.42-8.186-1.219-12.092-1.978-7.673-3.496-11.263c-1.518-3.589-3.376-7-5.532-10.192s-4.612-6.165-7.327-8.88c-2.715-2.715-5.688-5.17-8.88-7.327-3.192-2.156-6.603-4.014-10.192-5.532s-7.357-2.697-11.263-3.496-7.95-1.219-12.092-1.219-8.186.42-12.092 1.219-7.673 1.978-11.263 3.496c-3.589 1.518-7 3.376-10.192 5.532s-6.165 4.612-8.88 7.327-5.17 5.688-7.327 8.88-4.014 6.603-5.532 10.192c-1.518 3.589-2.697 7.357-3.496 11.263s-1.219 7.95-1.219 12.092.42 8.186 1.219 12.092 1.978 7.673 3.496 11.263 3.376 7 5.532 10.192 4.612 6.165 7.327 8.88c2.715 2.715 5.688 5.17 8.88 7.327 2.397 1.619 4.918 2.982 7.544 4.247l52.002.001z"
+ class="iconic-dashboard-body iconic-property-stroke" fill="none" />
+ <path clip-path="url(#iconic-size-lg-dashboard-clip-0)" stroke="#000" stroke-width="4" stroke-linecap="round" d="M32.887 94.779c-3.981-3.981-7.203-8.722-9.43-13.986-2.227-5.264-3.458-11.052-3.458-17.127s1.231-11.863 3.458-17.127 5.448-10.005 9.43-13.986c3.981-3.981 8.722-7.203 13.986-9.43s11.052-3.458 17.127-3.458 11.863 1.231 17.127 3.458c5.264 2.227 10.005 5.448 13.986 9.43 3.981 3.981 7.203 8.722 9.43 13.986 2.226 5.264 3.458 11.052 3.458 17.127s-1.231 11.863-3.458 17.127c-2.227 5.264-5.448 10.005-9.43 13.986"
+ class="iconic-dashboard-values iconic-property-accent iconic-property-stroke" fill="none" />
+ <path d="M71.071 56.929c-3.905-3.905-43.071-28.929-43.071-28.929s25.024 39.166 28.929 43.071c3.905 3.905 10.237 3.905 14.142 0 3.905-3.905 3.905-10.237 0-14.142zm-7.071 9.071c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2z" class="iconic-dashboard-needle iconic-property-fill"
+ />
+ </g>
+ <g class="iconic-dashboard-md iconic-container iconic-md" data-width="32" data-height="30" display="none" transform="scale(4) translate(0 1)">
+ <path stroke="#000" stroke-width="3" d="M9.001 28.5c-4.472-2.448-7.501-7.03-7.501-12.5 0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5c0 5.469-3.028 10.052-7.499 12.5h-14z" class="iconic-dashboard-body iconic-property-stroke" fill="none" />
+ <path d="M14.415 18.212c1.048 1.048 2.748 1.048 3.797 0s1.007-2.79 0-3.797c-1.007-1.007-11.212-7.415-11.212-7.415s6.367 10.164 7.415 11.212z" class="iconic-dashboard-needle iconic-property-fill" />
+ <path clip-path="url(#iconic-size-md-dashboard-clip-0)" stroke="#000" stroke-linecap="round" d="M9.283 22.718c-1.719-1.719-2.783-4.094-2.783-6.718s1.063-4.998 2.783-6.718 4.094-2.782 6.717-2.782 4.998 1.063 6.718 2.783 2.782 4.094 2.782 6.717-1.063 4.998-2.783 6.718"
+ class="iconic-dashboard-values iconic-property-accent iconic-property-stroke" fill="none" />
+ </g>
+ <g class="iconic-dashboard-sm iconic-container iconic-sm" data-width="16" data-height="15" display="none" transform="scale(8)">
+ <path stroke="#000" stroke-width="2" d="M4.5 14c-2.081-1.213-3.5-3.418-3.5-6 0-3.866 3.134-7 7-7s7 3.134 7 7c0 2.59-1.407 4.79-3.498 6h-7.002z" class="iconic-dashboard-body iconic-property-stroke" fill="none" />
+ <path d="M6.708 8.606c.524.524 1.374.524 1.899 0s.503-1.395 0-1.899c-.503-.503-4.606-2.708-4.606-2.708s2.183 4.082 2.708 4.606z" class="iconic-dashboard-needle iconic-property-fill" />
+ <path clip-path="url(#iconic-size-sm-dashboard-clip-0)" stroke="#000" stroke-linecap="round" d="M5.525 10.475c-.633-.633-1.025-1.508-1.025-2.475s.392-1.841 1.025-2.475 1.508-1.025 2.475-1.025 1.841.392 2.475 1.025 1.025 1.508 1.025 2.475-.392 1.841-1.025 2.475"
+ class="iconic-dashboard-values iconic-property-accent iconic-property-stroke" fill="none" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/document.svg b/afb-client/bower_components/foundation-apps/iconic/document.svg
new file mode 100755
index 0000000..50b847a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/document.svg
@@ -0,0 +1,28 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-document" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Document</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-document-clip-0">
+ <path d="M70 28v-28h-70v128h98v-100h-28zm-58 30h60v4h-60v-4zm0 36h68v4h-68v-4zm74 22h-74v-4h74v4zm0-36h-74v-4h74v4zm0-36h-74v-4h74v4z" />
+ </clipPath>
+ <clipPath id="iconic-size-md-document-clip-0">
+ <path d="M17 8v-8h-17v32h25v-24h-8zm-14 7h15v1h-15v-1zm0 8h17v1h-17v-1zm19 5h-19v-1h19v1zm0-8h-19v-1h19v1zm0-8h-19v-1h19v1z" />
+ </clipPath>
+ <clipPath id="iconic-size-sm-document-clip-0">
+ <path d="M8 0h-8v16h13v-11h-5v-5zm-6 4h4v1h-4v-1zm0 6h7v1h-7v-1zm9 4h-9v-1h9v1zm0-7v1h-9v-1h9z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-document-lg iconic-container iconic-lg" data-width="98" data-height="128" display="inline" transform="translate(15)">
+ <path clip-path="url(#iconic-size-lg-document-clip-0)" d="M96.5 128h-95c-.828 0-1.5-.672-1.5-1.5v-125c0-.828.672-1.5 1.5-1.5h95c.828 0 1.5.672 1.5 1.5v125c0 .828-.672 1.5-1.5 1.5z" class="iconic-document-page iconic-property-fill" />
+ <path class="iconic-document-flap iconic-property-fill" d="M98 24l-24-24v24z" />
+ </g>
+ <g class="iconic-document-md iconic-container iconic-md" data-width="25" data-height="32" display="none" transform="scale(4) translate(3)">
+ <path clip-path="url(#iconic-size-md-document-clip-0)" d="M24.5 32h-24c-.276 0-.5-.224-.5-.5v-31c0-.276.224-.5.5-.5h24c.276 0 .5.224.5.5v31c0 .276-.224.5-.5.5z" class="iconic-document-page iconic-property-fill" />
+ <path class="iconic-document-flap iconic-property-fill" d="M25 7l-7-7v7z" />
+ </g>
+ <g class="iconic-document-sm iconic-container iconic-sm" data-width="13" data-height="16" display="none" transform="scale(8) translate(1)">
+ <path clip-path="url(#iconic-size-sm-document-clip-0)" class="iconic-document-page iconic-property-fill" d="M0 0h13v16h-13z" />
+ <path class="iconic-document-flap iconic-property-fill" d="M13 4l-4-4v4z" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/envelope.svg b/afb-client/bower_components/foundation-apps/iconic/envelope.svg
new file mode 100755
index 0000000..4086e5a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/envelope.svg
@@ -0,0 +1,44 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="envelope" width="128" height="128" class="iconic iconic-envelope" viewBox="0 0 128 128">
+ <g><title>Envelope</title></g>
+ <g data-width="128" data-height="84" class="iconic-lg iconic-container" display="inline" transform="translate(0 22)">
+ <g class="iconic-envelope-closed">
+ <path d="M65.3 43.3l61.3-30.7c.7-.4 1.3-1.3 1.3-2.2v-9c0-.8-.7-1.5-1.5-1.5h-124.9c-.8.1-1.5.8-1.5 1.6v9c0 .8.6 1.8 1.3 2.2l61.3 30.7c.8.3 2 .3 2.7-.1z" class="iconic-envelope-closed-envelope-flap iconic-property-accent iconic-property-fill"/>
+ <path d="M62.7 51.3l-61.4-30.6c-.7-.4-1.3 0-1.3.8v61c0 .8.7 1.5 1.5 1.5h125c.8 0 1.5-.7 1.5-1.5v-61c0-.8-.6-1.2-1.3-.8l-61.4 30.6c-.7.4-1.9.4-2.6 0z" class="iconic-envelope-closed-envelope-body iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="128" data-height="116" class="iconic-lg iconic-container" display="inline" transform="translate(0 6)">
+ <g class="iconic-envelope-open" display="none">
+ <path d="M64 0l-64 32v84h128v-84l-64-32zm0 84l-56-28v-19.1l56-28 56 28v19.1l-56 28z" class="iconic-envelope-open-envelope iconic-property-fill"/>
+ <path class="iconic-envelope-open-letter iconic-property-accent iconic-property-fill" d="M64 79l52-26v-13h-104v13z"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="22" class="iconic-md iconic-container" display="none" transform="scale(4) translate(0 5)">
+ <g class="iconic-envelope-closed">
+ <path d="M16.4 10.8l15.1-7.6c.3-.1.5-.4.5-.7v-2c0-.3-.2-.5-.5-.5h-31c-.3 0-.5.2-.5.5v2c0 .3.2.6.4.7l15.1 7.6c.3.1.7.1.9 0z" class="iconic-envelope-closed-envelope-flap iconic-property-accent iconic-property-fill"/>
+ <path d="M15.6 13.8l-15.2-7.6c-.2-.1-.4 0-.4.3v15c0 .3.2.5.5.5h31c.3 0 .5-.2.5-.5v-15c0-.3-.2-.4-.4-.3l-15.1 7.6c-.3.1-.7.1-.9 0z" class="iconic-envelope-closed-envelope-body iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-envelope-open" display="none">
+ <path d="M16 0l-16 8v24h32v-24l-16-8zm0 24l-13-6.5v-7.6l13-6.5 13 6.5v7.6l-13 6.5z" class="iconic-envelope-open-envelope iconic-property-fill"/>
+ <path class="iconic-envelope-open-letter iconic-property-accent iconic-property-fill" d="M16 21.5l11-5.5v-4h-22v4z"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="12" class="iconic-sm iconic-container" display="none" transform="scale(8) translate(0 2)">
+ <g class="iconic-envelope-closed">
+ <path class="iconic-envelope-closed-envelope-flap iconic-property-accent iconic-property-fill" d="M8 6l8-4v-2h-16v2z"/>
+ <path class="iconic-envelope-closed-envelope-body iconic-property-fill" d="M8 8l-8-4v8h16v-8z"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <g class="iconic-envelope-open" display="none">
+ <path d="M8 0l-8 4v12h16v-12l-8-4zm0 12l-6-3v-3.8l6-3 6 3v3.8l-6 3z" class="iconic-envelope-open-envelope iconic-property-fill"/>
+ <path class="iconic-envelope-open-letter iconic-property-accent iconic-property-fill" d="M8 10.5l5-2.5v-2h-10v2z"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["envelope"]=iconicApis["envelope"]||function(t){var e=function(e){t.setAttribute("data-state",e);var i,r,a=t.querySelectorAll(".iconic-envelope-closed"),n=t.querySelectorAll(".iconic-envelope-open");i=r="none","open"===e?i="inline":r="inline";for(var o=0;o<a.length;o++)a[o].setAttribute("display",r),n[o].setAttribute("display",i)},i=function(){var i=t.getAttribute("data-state");i&&e(i)};return{update:i,setState:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/flag.svg b/afb-client/bower_components/foundation-apps/iconic/flag.svg
new file mode 100755
index 0000000..c1d62e6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/flag.svg
@@ -0,0 +1,24 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-flag" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Flag</title>
+ </g>
+ <g class="iconic-flag-lg iconic-container iconic-lg" data-width="98" data-height="128" display="inline" transform="translate(15)">
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" class="iconic-flag-mast iconic-property-stroke" d="M4 12v112" fill="none" />
+ <path d="M0 4c0-2.209 1.791-4 4-4s4 1.791 4 4v2h-8v-2z" class="iconic-flag-mast iconic-flag-mast-top iconic-property-fill" />
+ <path d="M42 13c0-.03.015-.056.017-.086-.002-.03-.017-.055-.017-.086 0-.324.175-.616.343-.828l1.314-2c.208-.287.343-.505.343-.828 0-.324-.131-.617-.343-.828-.212-.212-.505-.343-.828-.343h-32.828v52h32v-47z" class="iconic-flag-back iconic-property-accent iconic-property-fill"
+ />
+ <path d="M98 14h-54v51c0 .552.448 1 1 1h53l-14-26.11 14-25.89z" class="iconic-flag-front iconic-property-fill" />
+ </g>
+ <g class="iconic-flag-md iconic-container iconic-md" data-width="27" data-height="32" display="none" transform="scale(4) translate(2)">
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" class="iconic-flag-mast iconic-property-stroke" d="M1.5 3.5v27" fill="none" />
+ <path d="M0 1c0-.552.672-1 1.5-1s1.5.448 1.5 1h-3z" class="iconic-flag-mast iconic-flag-mast-top iconic-property-fill" />
+ <path d="M13 4.5c0-.044.014-.084.025-.125-.007-.042-.025-.081-.025-.125 0-.207.084-.395.22-.53l.561-.439c.136-.136.22-.323.22-.53s-.084-.395-.22-.53-.323-.22-.53-.22h-9.25v14h9v-11.5z" class="iconic-flag-back iconic-property-accent iconic-property-fill"
+ />
+ <path class="iconic-flag-front iconic-property-fill" d="M27 5h-13v14h13l-5-6.877z" />
+ </g>
+ <g class="iconic-flag-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" class="iconic-flag-mast iconic-property-stroke" d="M1 1v14" fill="none" />
+ <path d="M7 1.75c0-.138.08-.33.177-.427l.646-.646c.097-.097.177-.289.177-.427s-.112-.25-.25-.25h-4.75v8h4v-6.25z" class="iconic-flag-back iconic-property-accent iconic-property-fill" />
+ <path d="M16 2h-7.934c-.038.084-.066.174-.066.25v7.75h8l-4-3.938 4-4.062z" class="iconic-flag-front iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/home.svg b/afb-client/bower_components/foundation-apps/iconic/home.svg
new file mode 100755
index 0000000..eaff0e5
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/home.svg
@@ -0,0 +1,28 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-home" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Home</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-home-clip-0">
+ <path d="M64 16l-48 40 .25 62h37.75v-24h20v24h38v-62z" />
+ </clipPath>
+ <clipPath id="iconic-size-md-home-clip-0">
+ <path d="M16 5l-11 10v14h9v-6h4v6h9v-14z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-home-lg iconic-container iconic-lg" data-width="128" data-height="122" display="inline" transform="translate(0 3)">
+ <path clip-path="url(#iconic-size-lg-home-clip-0)" d="M16.006 57.5l.239 63c.003.828.677 1.5 1.506 1.5h92.75c.828 0 1.5-.672 1.5-1.5v-63c0-.828-.516-1.93-1.152-2.46l-45.695-38.079c-.636-.53-1.668-.53-2.305 0l-45.695 38.079c-.636.53-1.15 1.632-1.147 2.46z"
+ class="iconic-home-wall iconic-property-fill" />
+ <path d="M10.5 56h-9c-.828 0-.995-.442-.371-.988l61.742-54.024c.624-.545 1.634-.545 2.258 0l61.742 54.025c.624.545.457.988-.371.988h-9c-.828 0-2.013-.434-2.645-.969l-49.71-42.062c-.632-.535-1.658-.535-2.29 0l-49.71 42.062c-.632.535-1.817.969-2.645.969z"
+ class="iconic-home-roof iconic-property-fill" />
+ </g>
+ <g class="iconic-home-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <path clip-path="url(#iconic-size-md-home-clip-0)" d="M5.5 32h21c.276 0 .5-.224.5-.5v-16c0-.276-.166-.651-.37-.836l-10.26-9.327c-.204-.186-.536-.186-.74 0l-10.26 9.327c-.204.186-.37.56-.37.836v16c0 .276.224.5.5.5z" class="iconic-home-wall iconic-property-fill"
+ />
+ <path d="M.365 14.658l15.27-14.316c.202-.189.528-.189.73 0l15.271 14.316c.201.189.141.342-.135.342h-2c-.276 0-.664-.152-.867-.339l-12.265-11.322c-.203-.187-.532-.187-.735 0l-12.265 11.322c-.203.187-.591.339-.867.339h-2c-.276 0-.337-.153-.135-.342z"
+ class="iconic-home-roof iconic-property-fill" />
+ </g>
+ <g class="iconic-home-sm iconic-container iconic-sm" data-width="16" data-height="15" display="none" transform="scale(8)">
+ <path class="iconic-home-wall iconic-property-fill" d="M8 0l-8 7h2v8h5v-3h2v3h5v-8h2z" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/lock.svg b/afb-client/bower_components/foundation-apps/iconic/lock.svg
new file mode 100755
index 0000000..8af2303
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/lock.svg
@@ -0,0 +1,55 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="lock" width="128" height="128" class="iconic iconic-lock" viewBox="0 0 128 128">
+ <g><title>Lock</title></g>
+ <defs>
+ <clipPath id="iconic-size-lg-unlock-clip-0">
+ <path d="M18 0v66h58v-66h-58zm10 42c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ </clipPath>
+ </defs>
+ <g data-width="94" data-height="114" class="iconic-lg iconic-container" display="inline" transform="translate(17 7)">
+ <g class="iconic-lock-locked">
+ <path stroke="#000" stroke-width="8" stroke-miterlimit="10" d="M72 51v-22c0-13.8-11.2-25-25-25s-25 11.2-25 25v22" class="iconic-lock-locked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-locked-body iconic-lock-locked-body-main iconic-property-fill" d="M2 56h90v40h-90z"/>
+ <path class="iconic-lock-locked-body iconic-lock-locked-body-bottom iconic-property-fill" d="M0 98v16h94v-16h-56z"/>
+ <path class="iconic-lock-locked-body iconic-lock-locked-body-top iconic-property-fill" d="M0 48h94v6h-94z"/>
+ </g>
+ </g>
+ <g data-width="94" data-height="128" class="iconic-lg iconic-container" display="inline" transform="translate(17)">
+ <g class="iconic-lock-unlocked" display="none">
+ <path clip-path="url(#iconic-size-lg-unlock-clip-0)" stroke="#000" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M72 62.2v-33.2c0-13.8-11.2-25-25-25s-25 11.2-25 25v15" class="iconic-unlocked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-unlocked-body iconic-lock-unlocked-body-bottom iconic-property-fill" d="M0 112h94v16h-94z"/>
+ <path class="iconic-lock-unlocked-body iconic-lock-unlocked-body-main iconic-property-fill" d="M2 70h90v40h-90z"/>
+ <path class="iconic-lock-unlocked-body iconic-lock-unlocked-body-top iconic-property-fill" d="M0 62h94v6h-94z"/>
+ </g>
+ </g>
+ <g data-width="24" data-height="28" class="iconic-md iconic-container" display="none" transform="scale(4) translate(4 2)">
+ <g class="iconic-lock-locked">
+ <path stroke="#000" stroke-width="3" stroke-miterlimit="10" d="M5.5 14v-6c0-3.6 2.9-6.5 6.5-6.5s6.5 2.9 6.5 6.5v6" class="iconic-lock-locked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-locked-body iconic-lock-locked-body-main iconic-property-fill" d="M0 12h24v11h-24z"/>
+ <path class="iconic-lock-locked-body iconic-lock-locked-body-top iconic-property-fill" d="M0 24h24v4h-24z"/>
+ </g>
+ </g>
+ <g data-width="24" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4) translate(4)">
+ <g class="iconic-lock-unlocked" display="none">
+ <path stroke="#000" stroke-width="3" stroke-miterlimit="10" d="M5.5 11v-3c0-3.6 2.9-6.5 6.5-6.5s6.5 2.9 6.5 6.5v11" class="iconic-lock-unlocked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-unlocked-body iconic-lock-unlocked-body-main iconic-property-fill" d="M0 16h24v11h-24z"/>
+ <path class="iconic-lock-unlocked-body iconic-lock-unlocked-body-top iconic-property-fill" d="M0 28h24v4h-24z"/>
+ </g>
+ </g>
+ <g data-width="12" data-height="14" class="iconic-sm iconic-container" display="none" transform="scale(8) translate(2 1)">
+ <g class="iconic-lock-locked">
+ <path stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M9 8v-4c0-1.7-1.3-3-3-3s-3 1.3-3 3v2" class="iconic-lock-locked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-locked-body iconic-property-fill" d="M0 6h12v8h-12z"/>
+ </g>
+ </g>
+ <g data-width="12" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8) translate(2)">
+ <g class="iconic-lock-unlocked" display="none">
+ <path stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M9 8v-4c0-1.7-1.3-3-3-3s-3 1.3-3 3v1" class="iconic-lock-unlocked-loop iconic-property-accent iconic-property-stroke" fill="none"/>
+ <path class="iconic-lock-unlocked-body iconic-property-fill" d="M0 8h12v8h-12z"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["lock"]=iconicApis["lock"]||function(t){var e=function(e){t.setAttribute("data-state",e);var i,r,n=t.querySelectorAll(".iconic-lock-locked"),a=t.querySelectorAll(".iconic-lock-unlocked");i=r="none","unlocked"===e?r="inline":i="inline";for(var c=0;c<n.length;c++)n[c].setAttribute("display",i),a[c].setAttribute("display",r)},i=function(){var i=t.getAttribute("data-state");i&&e(i)};return{update:i,setState:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/magnifying-glass.svg b/afb-client/bower_components/foundation-apps/iconic/magnifying-glass.svg
new file mode 100755
index 0000000..fbc7c8c
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/magnifying-glass.svg
@@ -0,0 +1,26 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-magnifying-glass" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Magnifying Glass</title>
+ </g>
+ <defs>
+ <clipPath id="iconic-size-lg-magnifying-glass-clip-0">
+ <path d="M95.707 83.707l-6.707 6.707-1.414-1.414 6.707-6.707-4.293-4.293-12 12 38 38 12-12z" />
+ </clipPath>
+ </defs>
+ <g class="iconic-magnifying-glass-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
+ <path stroke="#000" stroke-width="8" class="iconic-magnifying-glass-handle iconic-magnifying-glass-handle-connector iconic-property-stroke" d="M85 85l-7.912-7.912" fill="none" />
+ <path d="M126.939 117.061l-9.879 9.879c-.586.586-1.536.586-2.121 0l-35.879-35.879c-.586-.586-.586-1.536 0-2.121l9.879-9.879c.586-.586 1.536-.586 2.121 0l35.879 35.879c.586.586.586 1.535 0 2.121z" clip-path="url(#iconic-size-lg-magnifying-glass-clip-0)"
+ class="iconic-magnifying-glass-handle iconic-property-fill" />
+ <circle stroke="#000" stroke-width="8" cx="46" cy="46" r="42" class="iconic-magnifying-glass-rim iconic-property-stroke" fill="none" />
+ <path fill="#fff" stroke="#000" stroke-width="2" stroke-linecap="round" d="M13 46c0-18.225 14.775-33 33-33" class="iconic-magnifying-glass-reflection iconic-property-accent iconic-property-stroke" />
+ </g>
+ <g class="iconic-magnifying-glass-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
+ <path fill="#fff" stroke="#000" stroke-width="3" class="iconic-magnifying-glass-handle iconic-magnifying-glass-handle-connector iconic-property-stroke" d="M19.5 19.582l9.438 9.438" />
+ <circle stroke="#000" stroke-width="3" cx="12" cy="12" r="10.5" class="iconic-magnifying-glass-rim iconic-property-stroke" fill="none" />
+ <path d="M23.646 20.354l-3.293 3.293c-.195.195-.195.512 0 .707l7.293 7.293c.195.195.512.195.707 0l3.293-3.293c.195-.195.195-.512 0-.707l-7.293-7.293c-.195-.195-.512-.195-.707 0z" class="iconic-magnifying-glass-handle iconic-property-fill" />
+ </g>
+ <g class="iconic-magnifying-glass-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path stroke="#000" stroke-width="3" stroke-linecap="round" class="iconic-magnifying-glass-handle iconic-property-stroke" d="M11 11l3.5 3.5" fill="none" />
+ <circle stroke="#000" stroke-width="2" cx="6.5" cy="6.5" r="5.5" class="iconic-magnifying-glass-rim iconic-property-stroke" fill="none" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/person.svg b/afb-client/bower_components/foundation-apps/iconic/person.svg
new file mode 100755
index 0000000..9657495
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/person.svg
@@ -0,0 +1,62 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="person" width="128" height="128" class="iconic iconic-person" viewBox="0 0 128 128">
+ <g><title>Person</title></g>
+ <g data-width="128" data-height="128" class="iconic-lg iconic-container" display="inline">
+ <g class="iconic-person-genderless">
+ <path d="M87.9 80c-.8 0-2 .4-2.7.9-6.1 4.6-13.3 7.1-21.2 7.1-7.5 0-14.5-2.5-20.5-7.1-.7-.5-1.8-.9-2.7-.9h-8.8c-17.7 0-32 14.3-32 32v14.5c0 .8.7 1.5 1.5 1.5h125c.8 0 1.5-.7 1.5-1.5v-14.5c0-17.7-14.3-32-32-32h-8.1z" class="iconic-person-body iconic-property-fill"/>
+ <path d="M96 35c0 22.1-10.1 45-32 45-20.1 0-32-22.9-32-45s14.3-35 32-35 32 12.9 32 35z" class="iconic-person-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="112" data-height="128" class="iconic-lg iconic-container" display="inline" transform="translate(8)">
+ <g class="iconic-person-female" display="none">
+ <path d="M78.7 80c-.7 0-1.7.5-2.3 1-6.3 5.8-13.4 9-20.4 9-7.3 0-14.4-3.4-20.5-9-.6-.6-1.6-1-2.3-1h-1.2c-8 0-32 16-32 40v6.5c0 .8.7 1.5 1.5 1.5h109c.8 0 1.5-.7 1.5-1.5v-6.5c0-24-24-40-32-40h-1.3z" class="iconic-person-female-body iconic-property-fill"/>
+ <path d="M104 64c-8 0-18-5.3-18-24 0-22.1-12.3-40-30-40s-30 17.9-30 40c0 18.7-10 24-18 24 0 0 11.5 4.3 24.9 1 5.9 10.1 14.8 17 23.1 17s17.3-7 23.2-17.2c13.2 3.5 24.8-.8 24.8-.8z" class="iconic-person-female-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="128" data-height="128" class="iconic-lg iconic-container" display="inline">
+ <g class="iconic-person-male" display="none">
+ <path d="M90.8 80c-.8 0-1.9.5-2.5 1.1-6.6 7.1-14.9 10.9-24.3 10.9s-17.8-3.8-24.3-10.9c-.6-.6-1.7-1.1-2.5-1.1h-5.2c-17.7 0-32 14.3-32 32v14.5c0 .8.7 1.5 1.5 1.5h125c.8 0 1.5-.7 1.5-1.5v-14.5c0-17.7-14.3-32-32-32h-5.2z" class="iconic-person-male-body iconic-property-fill"/>
+ <path d="M80 8c-.5-7.5-9.4-8-16-8-31.8 0-36.3 26-30 40 0 22.1 10 44 30 44 19.8 0 30-21.9 30-44 7.7-23.7-6.2-32-14-32z" class="iconic-person-male-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-person-genderless">
+ <path d="M23.6 20c-.2 0-.6.2-.8.3-1.8 1.7-4.2 2.7-6.8 2.7s-5-1-6.8-2.7c-.2-.1-.5-.3-.8-.3h-.4c-4.4 0-8 3.6-8 8v3.5c0 .3.2.5.5.5h31c.3 0 .5-.2.5-.5v-3.5c0-4.4-3.6-8-8-8h-.4z" class="iconic-person-body iconic-property-fill"/>
+ <path d="M24 9c0 5.5-2.6 11-8 11-5.5 0-8-5.5-8-11s3.6-9 8-9 8 3.5 8 9z" class="iconic-person-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="28" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4) translate(2)">
+ <g class="iconic-person-female" display="none">
+ <path d="M20.6 20.5c-2 2.1-4.3 3.5-6.6 3.5s-4.6-1.4-6.6-3.5c-.2-.2-.5-.3-.8-.2-2.5 1.2-6.6 4.7-6.6 9.7v1.5c0 .3.2.5.5.5h27c.3 0 .5-.2.5-.5v-1.5c0-5-4.1-8.5-6.6-9.6-.3-.2-.7-.1-.8.1z" class="iconic-person-female-body iconic-property-fill"/>
+ <path d="M26 17c-2 0-4-2.3-4-7 0-5.5-3.6-10-8-10s-8 4.5-8 10c0 4.7-2 7-4 7 0 0 2.9.7 6.3-.2 1.7 2.5 4 4.2 5.7 4.2 1.7 0 4.1-1.8 5.8-4.3 3.3 1 6.2.3 6.2.3z" class="iconic-person-female-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-person-male" display="none">
+ <path d="M23.9 20.4c-1.9 2.3-4.6 3.6-7.9 3.6s-6-1.3-7.9-3.6c-.2-.2-.5-.4-.8-.4-4.1.4-7.3 3.8-7.3 8v3.5c0 .3.2.5.5.5h31c.3 0 .5-.2.5-.5v-3.5c0-4.2-3.2-7.6-7.3-8-.3 0-.6.2-.8.4z" class="iconic-person-male-body iconic-property-fill"/>
+ <path d="M20 2c-.1-1.9-2.3-2-4-2-7.9 0-9.6 6.5-8 10 0 5.5 1.9 11 8 11 5.9 0 8-5.5 8-11 1.9-5.9-2.1-8-4-8z" class="iconic-person-male-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <g class="iconic-person-genderless">
+ <path d="M12.2 10c-1.1 1.2-2.6 2-4.2 2s-3.1-.8-4.2-2c-2.1.1-3.8 1.9-3.8 4v2h16v-2c0-2.1-1.7-3.9-3.8-4z" class="iconic-person-body iconic-property-fill"/>
+ <ellipse cx="8" cy="5" rx="4" ry="5" class="iconic-person-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <g class="iconic-person-female" display="none">
+ <path d="M11.8 10.2c-1.2 1.1-2.5 1.8-3.8 1.8s-2.6-.7-3.8-1.8c-1.5.5-4.2 2.3-4.2 4.8v1h16v-1c0-2.5-2.7-4.3-4.2-4.8z" class="iconic-person-female-body iconic-property-fill"/>
+ <path d="M14 8c-1 0-2-.7-2-3 0-2.8-1.8-5-4-5s-4 2.2-4 5c0 2.3-1 3-2 3 0 0 1.5.8 3.3.3.8 1 1.9 1.7 2.7 1.7.8 0 1.9-.7 2.8-1.7 1.7.5 3.2-.3 3.2-.3z" class="iconic-person-female-head iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)">
+ <g class="iconic-person-male" display="none">
+ <path d="M12.5 10c-1 1.3-2.6 2-4.5 2s-3.4-.7-4.5-2c-2 .3-3.5 2-3.5 4v2h16v-2c0-2-1.5-3.7-3.5-4z" class="iconic-person-male-body iconic-property-fill"/>
+ <path d="M10 1c-.1-.9-1.2-1-2-1-4 0-4.8 3.2-4 5 0 2.8 1 5 4 5s4-2.2 4-5c1-3-1-4-2-4z" class="iconic-person-male-head iconic-property-fill"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["person"]=iconicApis["person"]||function(t){var e=function(e){t.setAttribute("data-gender",e);var i,r,n,a=t.querySelectorAll(".iconic-person-genderless"),c=t.querySelectorAll(".iconic-person-female"),o=t.querySelectorAll(".iconic-person-male");switch(i=r=n="none",e){case"female":i="inline";break;case"male":n="inline";break;default:r="inline"}for(var s=0;s<a.length;s++)a[s].setAttribute("display",r),c[s].setAttribute("display",i),o[s].setAttribute("display",n)},i=function(){var i=t.getAttribute("data-gender");i&&e(i)};return{update:i,setGender:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/reload.svg b/afb-client/bower_components/foundation-apps/iconic/reload.svg
new file mode 100755
index 0000000..a817913
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/reload.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-reload" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Reload</title>
+ </g>
+ <g class="iconic-reload-lg iconic-container iconic-lg" data-width="127" data-height="127" display="inline">
+ <path stroke="#000" stroke-width="8" d="M123.956 63.96c0 22.534-13.073 43.601-33.199 53.691-20.763 10.41-46.377 7.568-64.436-6.972-17.721-14.268-25.908-37.951-20.841-60.125 5.023-21.982 22.571-39.743 44.522-44.953 20.127-4.777 41.747 1.298 56.38 15.931"
+ class="iconic-reload-line iconic-property-stroke" fill="none" />
+ <path d="M121.64 36.429l-5.369-24.937c-.174-.81-.791-.992-1.376-.406l-19.879 19.879c-.586.586-.403 1.198.407 1.368l25.064 5.255c.811.17 1.327-.349 1.152-1.159z" class="iconic-reload-arrowhead iconic-property-fill" />
+ </g>
+ <g class="iconic-reload-md iconic-container iconic-md" data-width="31" data-height="31" display="none" transform="scale(4)">
+ <path stroke="#000" stroke-width="3" d="M30.497 15.987c0 5.327-3.018 10.331-7.726 12.824-4.772 2.526-10.729 2.14-15.136-.976-4.384-3.1-6.727-8.494-6.005-13.815.711-5.238 4.356-9.781 9.308-11.625 5.265-1.96 11.343-.63 15.313 3.34" class="iconic-reload-line iconic-property-stroke"
+ fill="none" />
+ <path d="M29.502 9.916l-6.01-.859c-.273-.039-.337-.229-.141-.424l5.293-5.293c.195-.195.385-.132.424.141l.859 6.01c.039.273-.151.463-.424.424z" class="iconic-reload-arrowhead iconic-property-fill" />
+ </g>
+ <g class="iconic-reload-sm iconic-container iconic-sm" data-width="15" data-height="15" display="none" transform="scale(8)">
+ <path stroke="#000" stroke-width="2" d="M14.99 8c0 3.223-2.293 6.108-5.438 6.825-3.272.746-6.705-1.009-8.012-4.1-1.268-2.997-.24-6.568 2.413-8.444 2.748-1.943 6.609-1.609 8.987.77" class="iconic-reload-line iconic-property-stroke" fill="none" />
+ <path class="iconic-reload-arrowhead iconic-property-fill" d="M15.99 0v6h-6z" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/share-boxed.svg b/afb-client/bower_components/foundation-apps/iconic/share-boxed.svg
new file mode 100755
index 0000000..379bafc
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/share-boxed.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-share-boxed" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Share Boxed</title>
+ </g>
+ <g class="iconic-share-boxed-lg iconic-container iconic-lg" data-width="128" data-height="112" display="inline" transform="translate(0 8)">
+ <path stroke="#000" stroke-width="8" stroke-linecap="square" d="M108 56v49c0 1.657-1.343 3-3 3h-98c-1.657 0-3-1.343-3-3v-98c0-1.657 1.343-3 3-3h37" class="iconic-share-boxed-box iconic-property-accent iconic-property-stroke" fill="none" />
+ <path d="M128 26l-32-20v8h-2c-54 0-78 24.872-78 72 8.25-31.75 26-48 66-48 7.731 0 11.862 0 14 0v8l32-20z" class="iconic-share-boxed-arrow iconic-property-fill" />
+ </g>
+ <g class="iconic-share-boxed-md iconic-container iconic-md" data-width="32" data-height="29" display="none" transform="scale(4) translate(0 1)">
+ <path stroke="#000" stroke-width="3" stroke-linecap="square" d="M27.5 17.5v9c0 .552-.448 1-1 1h-24c-.552 0-1-.448-1-1v-24c0-.552.448-1 1-1h8" class="iconic-share-boxed-box iconic-property-accent iconic-property-stroke" fill="none" />
+ <path d="M32 7.333l-8-6.333v3c-13 0-18 6.218-18 18 2.063-7.938 8-12 16-12 .9 0 1.536 0 2 0v3l8-5.667z" class="iconic-share-boxed-arrow iconic-property-fill" />
+ </g>
+ <g class="iconic-share-boxed-sm iconic-container iconic-sm" data-width="16" data-height="14" display="none" transform="scale(8) translate(0 1)">
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" d="M13 11v1.5c0 .276-.224.5-.5.5h-11c-.276 0-.5-.224-.5-.5v-11c0-.276.224-.5.5-.5h3.5" class="iconic-share-boxed-box iconic-property-accent iconic-property-stroke" fill="none" />
+ <path d="M16 4l-4-4v2c-4.418 0-8 3.582-8 8 0-2.209 3-4 5-4 1.201 0 2.304 0 3 0v2l4-4z" class="iconic-share-boxed-arrow iconic-property-fill" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/star.svg b/afb-client/bower_components/foundation-apps/iconic/star.svg
new file mode 100755
index 0000000..df95657
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/star.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-star" width="128" height="128" viewBox="0 0 128 128">
+ <g class="iconic-metadata">
+ <title>Star</title>
+ </g>
+ <g class="iconic-star-lg iconic-container iconic-lg" data-width="128" data-height="122" display="inline" transform="translate(0 3)">
+ <path class="iconic-property-fill" d="M88.537 74.838l39.463-28.838h-48.918l-15.082-46-15.082 46h-48.918l39.463 28.838-15.463 47.162 40-29.231 40 29.231z" />
+ </g>
+ <g class="iconic-star-md iconic-container iconic-md" data-width="32" data-height="31" display="none" transform="scale(4)">
+ <path class="iconic-property-fill" d="M22.185 19.173l9.815-7.173h-12.129l-3.871-12-3.871 12h-12.129l9.815 7.173-3.815 11.827 10-7.308 10 7.308z" />
+ </g>
+ <g class="iconic-star-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
+ <path class="iconic-property-fill" d="M11 10l5-4h-6l-2-6-2 6h-6l5 4-2 6 5-4 5.004 4z" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/iconic/thumb.svg b/afb-client/bower_components/foundation-apps/iconic/thumb.svg
new file mode 100755
index 0000000..8e1a677
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/thumb.svg
@@ -0,0 +1,38 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="thumb" width="128" height="128" class="iconic iconic-thumb" viewBox="0 0 128 128">
+ <g><title>Thumb</title></g>
+ <g data-width="126" data-height="128" class="iconic-lg iconic-container" display="inline" transform="translate(1)">
+ <g class="iconic-thumbs-up">
+ <path d="M0 52l10 76h22v-76h-32zm26 72c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" class="iconic-thumbs-up-cuff iconic-property-accent iconic-property-fill"/>
+ <path d="M117 54h-27c-5 0-9-4.5-9-9s5-15 5-31v-5c0-5-4-9-9-9h-6c-1.7 0-3 1.3-3 3v11c0 12.1-11.6 27.2-19.3 34.7-3.3 3.4-7.7 5.3-12.7 5.3v68s8 4 20 4h43c3.7 0 6.9-2.3 8.3-5.5 0 0 15-42.1 18.1-54.5.4-1.4.6-2.5.6-3 0-5.1-4-9-9-9z" class="iconic-thumbs-up-hand iconic-property-fill"/>
+ </g>
+ <g class="iconic-thumbs-down" display="none">
+ <path d="M10 0l-10 76h32v-76h-22zm16 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" class="iconic-thumbs-down-cuff iconic-property-accent iconic-property-fill"/>
+ <path d="M125.4 62c-3.1-12.4-18.1-54.5-18.1-54.5-1.4-3.2-4.6-5.5-8.3-5.5h-43l-20 4v68c5 0 9.4 1.9 12.7 5.3 7.7 7.5 19.3 22.6 19.3 34.7v11c0 1.7 1.3 3 3 3h6c5 0 9-4 9-9v-5c0-16-5-26.5-5-31s4-9 9-9h27c5 0 9-3.9 9-9 0-.5-.2-1.6-.6-3z" class="iconic-thumbs-down-hand iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-thumbs-up">
+ <path d="M0 13l2 19h5v-19h-7zm5 18c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" class="iconic-thumbs-up-cuff iconic-property-accent iconic-property-fill"/>
+ <path d="M29.7 13h-7.2c-1.2 0-2.2-1.1-2.2-2.3s1.7-3.7 1.7-6.7v-1.5c0-1.4-1.1-2.5-2.5-2.5h-1.8c-.4 0-.7.3-.7.8v2.8c0 3-2.9 6.3-4.8 8.2-.9.7-2 1.2-3.2 1.2v17s2 1 5 1h11.2c.9 0 1.7-.6 2.1-1.4 0 0 3.8-10.5 4.5-13.6.1-.4.1-.6.1-.8.1-1.2-.9-2.2-2.2-2.2z" class="iconic-thumbs-up-hand iconic-property-fill"/>
+ </g>
+ <g class="iconic-thumbs-down" display="none">
+ <path d="M2 0l-2 19h7v-19h-5zm3 3c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" class="iconic-thumbs-down-cuff iconic-property-accent iconic-property-fill"/>
+ <path d="M31.9 16c-.8-3.1-4.5-13.6-4.5-13.6-.4-.8-1.2-1.4-2.1-1.4h-11.3l-5 1v17c1.2 0 2.3.5 3.2 1.3 1.9 1.9 4.8 5.1 4.8 8.2v2.8c0 .4.3.8.8.8h1.8c1.4 0 2.5-1.1 2.5-2.5v-1.5c0-3-1.7-5.6-1.7-6.7s1.4-2.4 2.6-2.4h6.8c1.2 0 2.2-1 2.2-2.2 0-.2 0-.4-.1-.8z" class="iconic-thumbs-down-hand iconic-property-fill"/>
+ </g>
+ </g>
+ <g data-width="14" data-height="14" class="iconic-sm iconic-container" display="none" transform="scale(8) translate(1 1)">
+ <g class="iconic-thumbs-up">
+ <path class="iconic-thumbs-up-cuff iconic-property-accent iconic-property-fill" d="M0 6h3v8h-3z"/>
+ <path d="M13 6h-3c-.6 0-1-.5-1-1s.8-3.2 1-3.7c.1-.5-.2-1.1-.7-1.3-.5-.1-1 .2-1.3.7-.3.5-2.2 4.3-2.6 4.7s-.8.6-1.4.6v8h7c.4 0 .8-.3.9-.6 0 0 2.1-5.8 2.1-6.4s-.4-1-1-1z" class="iconic-thumbs-up-hand iconic-property-fill"/>
+ </g>
+ <g class="iconic-thumbs-down" display="none">
+ <path class="iconic-thumbs-down-cuff iconic-property-accent iconic-property-fill" d="M0 0h3v8h-3z"/>
+ <path d="M11.9.6c-.1-.3-.5-.6-.9-.6h-7v8c.6 0 1 .2 1.4.6.4.4 2.3 4.2 2.6 4.7.3.5.8.8 1.3.7.5-.2.8-.7.7-1.3-.2-.5-1-3.2-1-3.7s.4-1 1-1h3c.6 0 1-.4 1-1l-2.1-6.4z" class="iconic-thumbs-down-hand iconic-property-fill"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["thumb"]=iconicApis["thumb"]||function(t){var e=function(e){t.setAttribute("data-state",e);var i,r,n=t.querySelectorAll(".iconic-thumbs-up"),a=t.querySelectorAll(".iconic-thumbs-down");i=r="none","down"===e?r="inline":i="inline";for(var c=0;c<n.length;c++)n[c].setAttribute("display",i),a[c].setAttribute("display",r)},i=function(){var i=t.getAttribute("data-state");i&&e(i)};return{update:i,setState:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/iconic/zoom.svg b/afb-client/bower_components/foundation-apps/iconic/zoom.svg
new file mode 100755
index 0000000..af1fbee
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/iconic/zoom.svg
@@ -0,0 +1,56 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" data-icon="zoom" width="128" height="128" class="iconic iconic-zoom" viewBox="0 0 128 128">
+ <g><title>Zoom</title></g>
+ <defs>
+ <clipPath id="iconic-size-lg-zoom-in-clip-0">
+ <path d="M95.7 83.7l-6.7 6.7-1.4-1.4 6.7-6.7-4.3-4.3-12 12 38 38 12-12z"/>
+ </clipPath>
+ <clipPath id="iconic-size-lg-zoom-out-clip-0">
+ <path d="M95.7 83.7l-6.7 6.7-1.4-1.4 6.7-6.7-4.3-4.3-12 12 38 38 12-12z"/>
+ </clipPath>
+ </defs>
+ <g data-width="128" data-height="128" class="iconic-lg iconic-container" display="inline">
+ <g class="iconic-zoom-in">
+ <path stroke="#000" stroke-width="8" stroke-miterlimit="10" class="iconic-zoom-in-handle iconic-zoom-in-handle-connector iconic-property-stroke" d="M85 85l-7.9-7.9" fill="none"/>
+ <path d="M126.9 117.1l-9.9 9.9c-.6.6-1.5.6-2.1 0l-35.8-35.9c-.6-.6-.6-1.5 0-2.1l9.9-9.9c.6-.6 1.5-.6 2.1 0l35.9 35.9c.5.5.5 1.5-.1 2.1z" clip-path="url(#iconic-size-lg-zoom-in-clip-0)" class="iconic-zoom-in-handle iconic-property-fill"/>
+ <circle stroke="#000" stroke-width="8" stroke-miterlimit="10" cx="46" cy="46" r="42" class="iconic-zoom-in-rim iconic-property-stroke" fill="none"/>
+ <path stroke="#000" stroke-width="4" stroke-linecap="square" stroke-miterlimit="10" class="iconic-zoom-in-plus iconic-property-accent iconic-property-stroke" d="M46 34v24m12-12h-24" fill="none"/>
+ </g>
+ <g class="iconic-zoom-out" display="none">
+ <path stroke="#000" stroke-width="8" stroke-miterlimit="10" class="iconic-zoom-out-handle iconic-zoom-out-handle-connector iconic-property-stroke" d="M85 85l-7.9-7.9" fill="none"/>
+ <path d="M126.9 117.1l-9.9 9.9c-.6.6-1.5.6-2.1 0l-35.8-35.9c-.6-.6-.6-1.5 0-2.1l9.9-9.9c.6-.6 1.5-.6 2.1 0l35.9 35.9c.5.5.5 1.5-.1 2.1z" clip-path="url(#iconic-size-lg-zoom-out-clip-0)" class="iconic-zoom-out-handle iconic-property-fill"/>
+ <circle stroke="#000" stroke-width="8" stroke-miterlimit="10" cx="46" cy="46" r="42" class="iconic-zoom-out-rim iconic-property-stroke" fill="none"/>
+ <path stroke="#000" stroke-width="4" stroke-linecap="square" stroke-miterlimit="10" class="iconic-zoom-out-minus iconic-property-accent iconic-property-stroke" d="M58 46h-24" fill="none"/>
+ </g>
+ </g>
+ <g data-width="32" data-height="32" class="iconic-md iconic-container" display="none" transform="scale(4)">
+ <g class="iconic-zoom-in">
+ <path fill="none" stroke="#000" stroke-width="3" stroke-miterlimit="10" class="iconic-zoom-in-handle iconic-zoom-in-handle-connector iconic-property-stroke" d="M19.5 19.6l9.4 9.4"/>
+ <circle stroke="#000" stroke-width="3" stroke-miterlimit="10" cx="12" cy="12" r="10.5" class="iconic-zoom-in-rim iconic-property-stroke" fill="none"/>
+ <path d="M23.6 20.4l-3.3 3.3c-.2.2-.2.5 0 .7l7.3 7.3c.2.2.5.2.7 0l3.3-3.3c.2-.2.2-.5 0-.7l-7.3-7.3c-.1-.2-.5-.2-.7 0z" class="iconic-zoom-in-handle iconic-property-fill"/>
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-zoom-in-plus iconic-property-accent iconic-property-stroke" d="M12 8v8m4-4h-8" fill="none"/>
+ </g>
+ <g class="iconic-zoom-out" display="none">
+ <path fill="none" stroke="#000" stroke-width="3" stroke-miterlimit="10" class="iconic-zoom-out-handle iconic-zoom-out-handle-connector iconic-property-stroke" d="M19.5 19.6l9.4 9.4"/>
+ <circle stroke="#000" stroke-width="3" stroke-miterlimit="10" cx="12" cy="12" r="10.5" class="iconic-zoom-out-rim iconic-property-stroke" fill="none"/>
+ <path d="M23.6 20.4l-3.3 3.3c-.2.2-.2.5 0 .7l7.3 7.3c.2.2.5.2.7 0l3.3-3.3c.2-.2.2-.5 0-.7l-7.3-7.3c-.1-.2-.5-.2-.7 0z" class="iconic-zoom-out-handle iconic-property-fill"/>
+ <path stroke="#000" stroke-width="2" stroke-linecap="square" stroke-miterlimit="10" class="iconic-zoom-out-minus iconic-property-accent iconic-property-stroke" d="M16 12h-8" fill="none"/>
+ </g>
+ </g>
+ <g data-width="16" data-height="16" class="iconic-sm iconic-container" display="none" transform="scale(8)" stroke="#000" stroke-miterlimit="10" fill="none">
+ <g class="iconic-zoom-in">
+ <path stroke-width="3" stroke-linecap="round" class="iconic-zoom-in-handle iconic-property-stroke" d="M11 11l3.5 3.5"/>
+ <circle stroke-width="2" cx="6.5" cy="6.5" r="5.5" class="iconic-zoom-in-rim iconic-property-stroke"/>
+ <path stroke-linecap="square" class="iconic-zoom-in-plus iconic-property-accent iconic-property-stroke" d="M6.5 4.5v4m2-2h-4"/>
+ </g>
+ <g class="iconic-zoom-out" display="none">
+ <path stroke-width="3" stroke-linecap="round" class="iconic-zoom-out-handle iconic-property-stroke" d="M11 11l3.5 3.5"/>
+ <circle stroke-width="2" cx="6.5" cy="6.5" r="5.5" class="iconic-zoom-out-rim iconic-property-stroke"/>
+ <path stroke-linecap="square" class="iconic-zoom-out-minus iconic-property-accent iconic-property-stroke" d="M8.5 6.5h-4"/>
+ </g>
+ </g>
+<script class="iconic-api" type="application/ecmascript">
+//<![CDATA[
+var iconicApis=window._Iconic?window._Iconic.smartIconApis:{};iconicApis["zoom"]=iconicApis["zoom"]||function(t){var e=function(e){t.setAttribute("data-state",e);var i,r,n=t.querySelectorAll(".iconic-zoom-in"),a=t.querySelectorAll(".iconic-zoom-out");i=r="none","out"===e?r="inline":i="inline";for(var c=0;c<n.length;c++)n[c].setAttribute("display",i),a[c].setAttribute("display",r)},i=function(){var i=t.getAttribute("data-state");i&&e(i)};return{update:i,setState:e}};
+//]]>
+</script>
+</svg>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/app.js b/afb-client/bower_components/foundation-apps/js/angular/app.js
new file mode 100644
index 0000000..7251eb1
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/app.js
@@ -0,0 +1,35 @@
+(function() {
+ 'use strict';
+
+ angular.module('application', [
+ 'ui.router',
+ 'ngAnimate',
+
+ //foundation
+ 'foundation',
+ 'foundation.dynamicRouting',
+ 'foundation.dynamicRouting.animations'
+ ])
+ .config(config)
+ .run(run)
+ ;
+
+ config.$inject = ['$urlRouterProvider', '$locationProvider'];
+
+ function config($urlProvider, $locationProvider) {
+ $urlProvider.otherwise('/');
+
+ $locationProvider.html5Mode({
+ enabled: false,
+ requireBase: false
+ });
+
+ $locationProvider.hashPrefix('!');
+ }
+
+
+ function run() {
+ FastClick.attach(document.body);
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html
new file mode 100644
index 0000000..2bc4892
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html
@@ -0,0 +1,4 @@
+<div class="accordion-item" ng-class="{'is-active': active}">
+ <div class="accordion-title" ng-click="activate()">{{ title }}</div>
+ <div class="accordion-content" ng-transclude></div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html
new file mode 100644
index 0000000..344586e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html
@@ -0,0 +1,2 @@
+<div class="accordion" ng-transclude>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js
new file mode 100644
index 0000000..2b2dac7
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js
@@ -0,0 +1,107 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.accordion', [])
+ .controller('ZfAccordionController', zfAccordionController)
+ .directive('zfAccordion', zfAccordion)
+ .directive('zfAccordionItem', zfAccordionItem)
+ ;
+
+ zfAccordionController.$inject = ['$scope'];
+
+ function zfAccordionController($scope) {
+ var controller = this;
+ var sections = controller.sections = $scope.sections = [];
+ var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false;
+ var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true
+ var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render
+
+ controller.select = function(selectSection) {
+ sections.forEach(function(section) {
+ //if multi open is allowed, toggle a tab
+ if(controller.multiOpen) {
+ if(section.scope === selectSection) {
+ section.scope.active = !section.scope.active;
+ }
+ } else {
+ //non multi open will close all tabs and open one
+ if(section.scope === selectSection) {
+ //if collapsible is allowed, a tab will toggle
+ section.scope.active = collapsible ? !section.scope.active : true;
+ } else {
+ section.scope.active = false;
+ }
+ }
+
+ });
+ };
+
+ controller.addSection = function addsection(sectionScope) {
+ sections.push({ scope: sectionScope });
+
+ if(sections.length === 1 && autoOpen === true) {
+ sections[0].active = true;
+ sections[0].scope.active = true;
+ }
+ };
+
+ controller.closeAll = function() {
+ sections.forEach(function(section) {
+ section.scope.active = false;
+ });
+ };
+ }
+
+ function zfAccordion() {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ replace: true,
+ templateUrl: 'components/accordion/accordion.html',
+ controller: 'ZfAccordionController',
+ scope: {
+ multiOpen: '@?',
+ collapsible: '@?',
+ autoOpen: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false;
+ scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false;
+ scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false;
+ }
+ }
+
+ //accordion item
+ function zfAccordionItem() {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/accordion/accordion-item.html',
+ transclude: true,
+ scope: {
+ title: '@'
+ },
+ require: '^zfAccordion',
+ replace: true,
+ controller: function() {},
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller, transclude) {
+ scope.active = false;
+ controller.addSection(scope);
+
+ scope.activate = function() {
+ controller.select(scope);
+ };
+
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html
new file mode 100644
index 0000000..6df405c
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html
@@ -0,0 +1,6 @@
+<div>
+ <a href="#"
+ class="button"
+ ng-if="title.length > 0">{{ title }}</a>
+ <div ng-transclude></div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html
new file mode 100644
index 0000000..cafb733
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html
@@ -0,0 +1,8 @@
+<div
+ class="action-sheet {{ position }}"
+ ng-class="{'is-active': active}"
+ >
+ <div
+ ng-transclude>
+ </div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html
new file mode 100644
index 0000000..0b1006c
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html
@@ -0,0 +1,3 @@
+<div class="action-sheet-container"
+ ng-transclude>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js
new file mode 100644
index 0000000..e38b67a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js
@@ -0,0 +1,226 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.actionsheet', ['foundation.core'])
+ .controller('ZfActionSheetController', zfActionSheetController)
+ .directive('zfActionSheet', zfActionSheet)
+ .directive('zfAsContent', zfAsContent)
+ .directive('zfAsButton', zfAsButton)
+ .service('FoundationActionSheet', FoundationActionSheet)
+ ;
+
+ FoundationActionSheet.$inject = ['FoundationApi'];
+
+ function FoundationActionSheet(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+ zfActionSheetController.$inject = ['$scope', 'FoundationApi'];
+
+ function zfActionSheetController($scope, foundationApi) {
+ var controller = this;
+ var content = controller.content = $scope.content;
+ var container = controller.container = $scope.container;
+ var body = angular.element(document.body);
+
+ controller.registerContent = function(scope) {
+ content = scope;
+ content.active = false;
+ };
+
+ controller.registerContainer = function(scope) {
+ container = scope;
+ container.active = false;
+ };
+
+ controller.toggle = toggle;
+ controller.hide = hide;
+
+ controller.registerListener = function() {
+ document.body.addEventListener('click', listenerLogic);
+ };
+
+ controller.deregisterListener = function() {
+ document.body.removeEventListener('click', listenerLogic);
+ }
+
+ function listenerLogic(e) {
+ var el = e.target;
+ var insideActionSheet = false;
+
+ do {
+ if(el.classList && el.classList.contains('action-sheet-container')) {
+ insideActionSheet = true;
+ break;
+ }
+
+ } while ((el = el.parentNode));
+
+ if(!insideActionSheet) {
+ // if the element has a toggle attribute, do nothing
+ if (e.target.attributes['zf-toggle'] || e.target.attributes['zf-hard-toggle']) {
+ return;
+ };
+ // if the element is outside the action sheet and is NOT a toggle element, hide
+ hide();
+ }
+ }
+
+ function hide() {
+ content.hide();
+ container.hide();
+
+ content.$apply();
+ container.$apply();
+ }
+
+ function toggle() {
+ content.toggle();
+ container.toggle();
+
+ content.$apply();
+ container.$apply();
+ }
+ }
+
+ zfActionSheet.$inject = ['FoundationApi'];
+
+ function zfActionSheet(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet.html',
+ controller: 'ZfActionSheetController',
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'actionsheet');
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ var id = attrs.id || foundationApi.generateUuid();
+ attrs.$set('id', id);
+
+ scope.active = false;
+
+ foundationApi.subscribe(id, function(msg) {
+ if (msg === 'toggle') {
+ controller.toggle();
+ }
+
+ if (msg === 'hide' || msg === 'close') {
+ controller.hide();
+ }
+
+ });
+
+ controller.registerContainer(scope);
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ return;
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ return;
+ };
+ }
+ }
+ }
+
+ zfAsContent.$inject = ['FoundationApi'];
+
+ function zfAsContent(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet-content.html',
+ require: '^zfActionSheet',
+ scope: {
+ position: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.active = false;
+ scope.position = scope.position || 'bottom';
+ controller.registerContent(scope);
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ if(scope.active) {
+ controller.registerListener();
+ } else {
+ controller.deregisterListener();
+ }
+
+ return;
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ controller.deregisterListener();
+ return;
+ };
+ }
+ }
+
+ zfAsButton.$inject = ['FoundationApi'];
+
+ function zfAsButton(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/actionsheet/actionsheet-button.html',
+ require: '^zfActionSheet',
+ scope: {
+ title: '@?'
+ },
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+
+ element.on('click', function(e) {
+ controller.toggle();
+ e.preventDefault();
+ });
+
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/common/common.js b/afb-client/bower_components/foundation-apps/js/angular/components/common/common.js
new file mode 100644
index 0000000..a818a6d
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/common/common.js
@@ -0,0 +1,171 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.common', ['foundation.core'])
+ .directive('zfClose', zfClose)
+ .directive('zfOpen', zfOpen)
+ .directive('zfToggle', zfToggle)
+ .directive('zfEscClose', zfEscClose)
+ .directive('zfSwipeClose', zfSwipeClose)
+ .directive('zfHardToggle', zfHardToggle)
+ ;
+
+ zfClose.$inject = ['FoundationApi'];
+
+ function zfClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ var targetId = '';
+ if (attrs.zfClose) {
+ targetId = attrs.zfClose;
+ } else {
+ var parentElement= false;
+ var tempElement = element.parent();
+ //find parent modal
+ while(parentElement === false) {
+ if(tempElement[0].nodeName == 'BODY') {
+ parentElement = '';
+ }
+
+ if(typeof tempElement.attr('zf-closable') !== 'undefined' && tempElement.attr('zf-closable') !== false) {
+ parentElement = tempElement;
+ }
+
+ tempElement = tempElement.parent();
+ }
+ targetId = parentElement.attr('id');
+ }
+
+ element.on('click', function(e) {
+ foundationApi.publish(targetId, 'close');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfOpen.$inject = ['FoundationApi'];
+
+ function zfOpen(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfOpen, 'open');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfToggle.$inject = ['FoundationApi'];
+
+ function zfToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfToggle, 'toggle');
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfEscClose.$inject = ['FoundationApi'];
+
+ function zfEscClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('keyup', function(e) {
+ if (e.keyCode === 27) {
+ foundationApi.closeActiveElements();
+ }
+ e.preventDefault();
+ });
+ }
+ }
+
+ zfSwipeClose.$inject = ['FoundationApi'];
+
+ function zfSwipeClose(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+ return directive;
+
+ function link($scope, element, attrs) {
+ var swipeDirection;
+ var hammerElem;
+ if (Hammer) {
+ hammerElem = new Hammer(element[0]);
+ // set the options for swipe (to make them a bit more forgiving in detection)
+ hammerElem.get('swipe').set({
+ direction: Hammer.DIRECTION_ALL,
+ threshold: 5, // this is how far the swipe has to travel
+ velocity: 0.5 // and this is how fast the swipe must travel
+ });
+ }
+ // detect what direction the directive is pointing
+ switch (attrs.zfSwipeClose) {
+ case 'right':
+ swipeDirection = 'swiperight';
+ break;
+ case 'left':
+ swipeDirection = 'swipeleft';
+ break;
+ case 'up':
+ swipeDirection = 'swipeup';
+ break;
+ case 'down':
+ swipeDirection = 'swipedown';
+ break;
+ default:
+ swipeDirection = 'swipe';
+ }
+ hammerElem.on(swipeDirection, function() {
+ foundationApi.publish(attrs.id, 'close');
+ });
+ }
+ }
+
+ zfHardToggle.$inject = ['FoundationApi'];
+
+ function zfHardToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ element.on('click', function(e) {
+ foundationApi.closeActiveElements({exclude: attrs.zfHardToggle});
+ foundationApi.publish(attrs.zfHardToggle, 'toggle');
+ e.preventDefault();
+ });
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js b/afb-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js
new file mode 100644
index 0000000..19cf192
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js
@@ -0,0 +1,186 @@
+(function () {
+ 'use strict';
+
+ angular.module('foundation.iconic', [])
+ .provider('Iconic', Iconic)
+ .directive('zfIconic', zfIconic)
+ ;
+
+ // iconic wrapper
+ function Iconic() {
+ // default path
+ var assetPath = 'assets/img/iconic/';
+
+ /**
+ * Sets the path used to locate the iconic SVG files
+ * @param {string} path - the base path used to locate the iconic SVG files
+ */
+ this.setAssetPath = function (path) {
+ assetPath = angular.isString(path) ? path : assetPath;
+ };
+
+ /**
+ * Service implementation
+ * @returns {{}}
+ */
+ this.$get = function () {
+ var iconicObject = new IconicJS();
+
+ var service = {
+ getAccess: getAccess,
+ getAssetPath: getAssetPath
+ };
+
+ return service;
+
+ /**
+ *
+ * @returns {Window.IconicJS}
+ */
+ function getAccess() {
+ return iconicObject;
+ }
+
+ /**
+ *
+ * @returns {string}
+ */
+ function getAssetPath() {
+ return assetPath;
+ }
+ };
+ }
+
+ zfIconic.$inject = ['Iconic', 'FoundationApi', '$compile'];
+
+ function zfIconic(iconic, foundationApi, $compile) {
+ var directive = {
+ restrict: 'A',
+ template: '<img ng-transclude>',
+ transclude: true,
+ replace: true,
+ scope: {
+ dynSrc: '=?',
+ dynIcon: '=?',
+ size: '@?',
+ icon: '@',
+ iconDir: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ var contents, assetPath;
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, element, attrs) {
+
+ if (scope.iconDir) {
+ // path set via attribute
+ assetPath = scope.iconDir;
+ } else {
+ // default path
+ assetPath = iconic.getAssetPath();
+ }
+ // make sure ends with /
+ if (assetPath.charAt(assetPath.length - 1) !== '/') {
+ assetPath += '/';
+ }
+
+ if (scope.dynSrc) {
+ attrs.$set('data-src', scope.dynSrc);
+ } else if (scope.dynIcon) {
+ attrs.$set('data-src', assetPath + scope.dynIcon + '.svg');
+ } else {
+ if (scope.icon) {
+ attrs.$set('data-src', assetPath + scope.icon + '.svg');
+ } else {
+ // To support expressions on data-src
+ attrs.$set('data-src', attrs.src);
+ }
+ }
+
+ // check if size already added as class
+ if (!element.hasClass('iconic-sm') && !element.hasClass('iconic-md') && !element.hasClass('iconic-lg')) {
+ var iconicClass;
+ switch (scope.size) {
+ case 'small':
+ iconicClass = 'iconic-sm';
+ break;
+ case 'medium':
+ iconicClass = 'iconic-md';
+ break;
+ case 'large':
+ iconicClass = 'iconic-lg';
+ break;
+ default:
+ iconicClass = 'iconic-fluid';
+ }
+ element.addClass(iconicClass);
+ }
+
+ // save contents of un-inject html, to use for dynamic re-injection
+ contents = element[0].outerHTML;
+ }
+
+ function postLink(scope, element, attrs) {
+ var svgElement, ico = iconic.getAccess();
+
+ injectSvg(element[0]);
+
+ foundationApi.subscribe('resize', function () {
+ // only run update on current element
+ ico.update(element[0]);
+ });
+
+ // handle dynamic updating of src
+ if (scope.dynSrc) {
+ scope.$watch('dynSrc', function (newVal, oldVal) {
+ if (newVal && newVal !== oldVal) {
+ reinjectSvg(scope.dynSrc);
+ }
+ });
+ }
+ // handle dynamic updating of icon
+ if (scope.dynIcon) {
+ scope.$watch('dynIcon', function (newVal, oldVal) {
+ if (newVal && newVal !== oldVal) {
+ reinjectSvg(assetPath + scope.dynIcon + '.svg');
+ }
+ });
+ }
+
+ function reinjectSvg(newSrc) {
+ if (svgElement) {
+ // set html
+ svgElement.empty();
+ svgElement.append(angular.element(contents));
+
+ // set new source
+ svgElement.attr('data-src', newSrc);
+
+ // reinject
+ injectSvg(svgElement[0]);
+ }
+ }
+
+ function injectSvg(element) {
+ ico.inject(element, {
+ each: function (injectedElem) {
+ // compile injected svg
+ var angElem = angular.element(injectedElem);
+ svgElement = $compile(angElem)(angElem.scope());
+ }
+ });
+ }
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js b/afb-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js
new file mode 100644
index 0000000..74ea897
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js
@@ -0,0 +1,94 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.interchange', ['foundation.core', 'foundation.mediaquery'])
+ .directive('zfInterchange', zfInterchange)
+ ;
+
+ zfInterchange.$inject = [ '$compile', '$http', '$templateCache', 'FoundationApi', 'FoundationMQ'];
+
+ function zfInterchange($compile, $http, $templateCache, foundationApi, foundationMQ) {
+
+ var directive = {
+ restrict: 'EA',
+ transclude: 'element',
+ scope: {
+ position: '@'
+ },
+ replace: true,
+ template: '<div></div>',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var childScope, current, scenarios, innerTemplates;
+
+ var globalQueries = foundationMQ.getMediaQueries();
+
+ //setup
+ foundationApi.subscribe('resize', function(msg) {
+ transclude(function(clone, newScope) {
+ if(!scenarios || !innerTemplates) {
+ collectInformation(clone);
+ }
+
+ var ruleMatches = foundationMQ.match(scenarios);
+ var scenario = ruleMatches.length === 0 ? null : scenarios[ruleMatches[0].ind];
+
+ //this could use some love
+ if(scenario && checkScenario(scenario)) {
+ var compiled;
+
+ if(childScope) {
+ childScope.$destroy();
+ childScope = null;
+ }
+
+ if(typeof scenario.templ !== 'undefined') {
+ childScope = newScope;
+
+ //temp container
+ var tmp = document.createElement('div');
+ tmp.appendChild(innerTemplates[scenario.templ][0]);
+
+ element.html(tmp.innerHTML);
+ $compile(element.contents())(childScope);
+ current = scenario;
+ } else {
+ var loader = templateLoader(scenario.src);
+ loader.success(function(html) {
+ childScope = newScope;
+ element.html(html);
+ }).then(function(){
+ $compile(element.contents())(childScope);
+ current = scenario;
+ });
+ }
+ }
+ });
+
+ });
+
+ //init
+ foundationApi.publish('resize', 'initial resize');
+
+ function templateLoader(templateUrl) {
+ return $http.get(templateUrl, {cache: $templateCache});
+ }
+
+ function collectInformation(el) {
+ var data = foundationMQ.collectScenariosFromElement(el);
+
+ scenarios = data.scenarios;
+ innerTemplates = data.templates;
+ }
+
+ function checkScenario(scenario) {
+ return !current || current !== scenario;
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.html b/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.html
new file mode 100644
index 0000000..83618db
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.html
@@ -0,0 +1,9 @@
+<div
+ class="modal-overlay"
+ ng-click="hideOverlay()">
+ <aside
+ class="modal"
+ ng-click="$event.stopPropagation();"
+ ng-transclude>
+ </aside>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.js b/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.js
new file mode 100644
index 0000000..415f21b
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/modal/modal.js
@@ -0,0 +1,291 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.modal', ['foundation.core'])
+ .directive('zfModal', modalDirective)
+ .factory('ModalFactory', ModalFactory)
+ ;
+
+ FoundationModal.$inject = ['FoundationApi', 'ModalFactory'];
+
+ function FoundationModal(foundationApi, ModalFactory) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+ service.newModal = newModal;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ //new modal has to be controlled via the new instance
+ function newModal(config) {
+ return new ModalFactory(config);
+ }
+ }
+
+ modalDirective.$inject = ['FoundationApi'];
+
+ function modalDirective(foundationApi) {
+
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/modal/modal.html',
+ transclude: true,
+ scope: true,
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'modal';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ }
+
+ function postLink(scope, element, attrs) {
+ var dialog = angular.element(element.children()[0]);
+
+ scope.active = scope.active || false;
+ scope.overlay = attrs.overlay === 'false' ? false : true;
+ scope.overlayClose = attrs.overlayClose === 'false' ? false : true;
+
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+
+ var overlayIn = 'fadeIn';
+ var overlayOut = 'fadeOut';
+
+ scope.hideOverlay = function() {
+ if(scope.overlayClose) {
+ scope.hide();
+ }
+ };
+
+ scope.hide = function() {
+ scope.active = false;
+ animate();
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ animate();
+ dialog.tabIndex = -1;
+ dialog[0].focus();
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ animate();
+ return;
+ };
+
+ init();
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'show' || msg === 'open') {
+ scope.show();
+ } else if (msg === 'close' || msg === 'hide') {
+ scope.hide();
+ } else if (msg === 'toggle') {
+ scope.toggle();
+ }
+
+ if (scope.$root && !scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ function animate() {
+ //animate both overlay and dialog
+ if(!scope.overlay) {
+ element.css('background', 'transparent');
+ }
+
+ foundationApi.animate(element, scope.active, overlayIn, overlayOut);
+ foundationApi.animate(dialog, scope.active, animationIn, animationOut);
+ }
+
+ function init() {
+ if(scope.active) {
+ scope.show();
+ }
+ }
+ }
+ }
+ }
+
+ ModalFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', '$q', 'FoundationApi'];
+
+ function ModalFactory($http, $templateCache, $rootScope, $compile, $timeout, $q, foundationApi) {
+ return modalFactory;
+
+ function modalFactory(config) {
+ var self = this, //for prototype functions
+ container = angular.element(config.container || document.body),
+ id = config.id || foundationApi.generateUuid(),
+ attached = false,
+ destroyed = false,
+ html,
+ element,
+ fetched,
+ scope,
+ contentScope
+ ;
+
+ var props = [
+ 'animationIn',
+ 'animationOut',
+ 'overlay',
+ 'overlayClose'
+ ];
+
+ if(config.templateUrl) {
+ //get template
+ fetched = $http.get(config.templateUrl, {
+ cache: $templateCache
+ }).then(function (response) {
+ html = response.data;
+ assembleDirective();
+ });
+
+ } else if(config.template) {
+ //use provided template
+ fetched = true;
+ html = config.template;
+ assembleDirective();
+ }
+
+ self.activate = activate;
+ self.deactivate = deactivate;
+ self.toggle = toggle;
+ self.destroy = destroy;
+
+
+ return {
+ activate: activate,
+ deactivate: deactivate,
+ toggle: toggle,
+ destroy: destroy
+ };
+
+ function checkStatus() {
+ if(destroyed) {
+ throw "Error: Modal was destroyed. Delete the object and create a new ModalFactory instance."
+ }
+ }
+
+ function activate() {
+ checkStatus();
+ $timeout(function() {
+ init(true);
+ foundationApi.publish(id, 'show');
+ }, 0, false);
+ }
+
+ function deactivate() {
+ checkStatus();
+ $timeout(function() {
+ init(false);
+ foundationApi.publish(id, 'hide');
+ }, 0, false);
+ }
+
+ function toggle() {
+ checkStatus();
+ $timeout(function() {
+ init(true);
+ foundationApi.publish(id, 'toggle');
+ }, 0, false);
+ }
+
+ function init(state) {
+ $q.when(fetched).then(function() {
+ if(!attached && html.length > 0) {
+ var modalEl = container.append(element);
+
+ scope.active = state;
+ $compile(element)(scope);
+
+ attached = true;
+ }
+ });
+ }
+
+ function assembleDirective() {
+ // check for duplicate elements to prevent factory from cloning modals
+ if (document.getElementById(id)) {
+ return;
+ }
+
+ html = '<zf-modal id="' + id + '">' + html + '</zf-modal>';
+
+ element = angular.element(html);
+
+ scope = $rootScope.$new();
+
+ // account for directive attributes
+ for(var i = 0; i < props.length; i++) {
+ var prop = props[i];
+
+ if(config[prop]) {
+ switch (prop) {
+ case 'animationIn':
+ element.attr('animation-in', config[prop]);
+ break;
+ case 'animationOut':
+ element.attr('animation-out', config[prop]);
+ break;
+ default:
+ element.attr(prop, config[prop]);
+ }
+ }
+ }
+ // access view scope variables
+ if (config.contentScope) {
+ contentScope = config.contentScope;
+ for (var prop in config.contentScope) {
+ if (config.contentScope.hasOwnProperty(prop)) {
+ scope[prop] = config.contentScope[prop];
+ }
+ }
+ }
+ }
+
+ function destroy() {
+ self.deactivate();
+ setTimeout(function() {
+ scope.$destroy();
+ element.remove();
+ destroyed = true;
+ }, 3000);
+ foundationApi.unsubscribe(id);
+ }
+
+ }
+
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html
new file mode 100644
index 0000000..9193026
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html
@@ -0,0 +1,9 @@
+<div class="notification-container {{position}}">
+ <zf-notification ng-repeat="notification in notifications"
+ title="notification.title"
+ image="notification.image"
+ notif-id = "notification.id"
+ color="notification.color"
+ autoclose="notification.autoclose"
+ >{{ notification.content }}</zf-notification>
+</div> \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html
new file mode 100644
index 0000000..f524eed
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html
@@ -0,0 +1,12 @@
+<div zf-swipe-close="swipe" class="static-notification {{ color }} {{ position }}">
+ <a href="#"
+ class="close-button"
+ ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>
+ <div class="notification-icon" ng-if="image">
+ <img ng-src="{{ image }}"/>
+ </div>
+ <div class="notification-content">
+ <h1>{{ title }}</h1>
+ <p ng-transclude></p>
+ </div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.html b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.html
new file mode 100644
index 0000000..a311f01
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.html
@@ -0,0 +1,12 @@
+<div zf-swipe-close="swipe" class="notification {{ color }}">
+ <a href="#"
+ class="close-button"
+ ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">&times;</a>
+ <div class="notification-icon" ng-if="image">
+ <img ng-src="{{ image }}"/>
+ </div>
+ <div class="notification-content">
+ <h1>{{ title }}</h1>
+ <p ng-transclude></p>
+ </div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.js b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.js
new file mode 100644
index 0000000..2c0e3bc
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/notification/notification.js
@@ -0,0 +1,417 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.notification', ['foundation.core'])
+ .controller('ZfNotificationController', ZfNotificationController)
+ .directive('zfNotificationSet', zfNotificationSet)
+ .directive('zfNotification', zfNotification)
+ .directive('zfNotificationStatic', zfNotificationStatic)
+ .directive('zfNotify', zfNotify)
+ .factory('NotificationFactory', NotificationFactory)
+ .service('FoundationNotification', FoundationNotification)
+ ;
+
+ FoundationNotification.$inject = ['FoundationApi', 'NotificationFactory'];
+
+ function FoundationNotification(foundationApi, NotificationFactory) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target) {
+ foundationApi.publish(target, 'toggle');
+ }
+
+ function createNotificationSet(config) {
+ return new NotificationFactory(config);
+ }
+ }
+
+
+ ZfNotificationController.$inject = ['$scope', 'FoundationApi'];
+
+ function ZfNotificationController($scope, foundationApi) {
+ var controller = this;
+ controller.notifications = $scope.notifications = $scope.notifications || [];
+
+ controller.addNotification = function(info) {
+ var id = foundationApi.generateUuid();
+ info.id = id;
+ $scope.notifications.push(info);
+ };
+
+ controller.removeNotification = function(id) {
+ $scope.notifications.forEach(function(notification) {
+ if(notification.id === id) {
+ var ind = $scope.notifications.indexOf(notification);
+ $scope.notifications.splice(ind, 1);
+ }
+ });
+ };
+
+ controller.clearAll = function() {
+ while($scope.notifications.length > 0) {
+ $scope.notifications.pop();
+ }
+ };
+ }
+
+ zfNotificationSet.$inject = ['FoundationApi'];
+
+ function zfNotificationSet(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification-set.html',
+ controller: 'ZfNotificationController',
+ replace: true,
+ scope: {
+ position: '@'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right';
+
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'clearall') {
+ controller.clearAll();
+ }
+ else {
+ controller.addNotification(msg);
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+ }
+ });
+ }
+ }
+
+ zfNotification.$inject = ['FoundationApi'];
+
+ function zfNotification(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification.html',
+ replace: true,
+ transclude: true,
+ require: '^zfNotificationSet',
+ controller: function() { },
+ scope: {
+ title: '=?',
+ content: '=?',
+ image: '=?',
+ notifId: '=',
+ color: '=?',
+ autoclose: '=?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'notification');
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ scope.active = false;
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+ var hammerElem;
+
+ //due to dynamic insertion of DOM, we need to wait for it to show up and get working!
+ setTimeout(function() {
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }, 50);
+
+ scope.hide = function() {
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ setTimeout(function() {
+ controller.removeNotification(scope.notifId);
+ }, 50);
+ };
+
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ }, parseInt(scope.autoclose));
+ };
+
+ // close on swipe
+ if (Hammer) {
+ hammerElem = new Hammer(element[0]);
+ // set the options for swipe (to make them a bit more forgiving in detection)
+ hammerElem.get('swipe').set({
+ direction: Hammer.DIRECTION_ALL,
+ threshold: 5, // this is how far the swipe has to travel
+ velocity: 0.5 // and this is how fast the swipe must travel
+ });
+ }
+
+ hammerElem.on('swipe', function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ });
+ }
+ }
+ }
+
+ zfNotificationStatic.$inject = ['FoundationApi'];
+
+ function zfNotificationStatic(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/notification/notification-static.html',
+ replace: true,
+ transclude: true,
+ scope: {
+ title: '@?',
+ content: '@?',
+ image: '@?',
+ color: '@?',
+ autoclose: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ var type = 'notification';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ }
+
+ function postLink(scope, element, attrs, controller) {
+ scope.position = attrs.position ? attrs.position.split(' ').join('-') : 'top-right';
+
+ var animationIn = attrs.animationIn || 'fadeIn';
+ var animationOut = attrs.animationOut || 'fadeOut';
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg == 'show' || msg == 'open') {
+ scope.show();
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.hide();
+ }
+ }, parseInt(scope.autoclose));
+ };
+ } else if (msg == 'close' || msg == 'hide') {
+ scope.hide();
+ } else if (msg == 'toggle') {
+ scope.toggle();
+ // close if autoclose
+ if (scope.autoclose) {
+ setTimeout(function() {
+ if (scope.active) {
+ scope.toggle();
+ }
+ }, parseInt(scope.autoclose));
+ };
+ }
+
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ scope.$apply();
+
+ return;
+ });
+
+ scope.hide = function() {
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ return;
+ };
+
+ }
+ }
+ }
+
+ zfNotify.$inject = ['FoundationApi'];
+
+ function zfNotify(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ scope: {
+ title: '@?',
+ content: '@?',
+ color: '@?',
+ image: '@?',
+ autoclose: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ element.on('click', function(e) {
+ foundationApi.publish(attrs.zfNotify, {
+ title: scope.title,
+ content: scope.content,
+ color: scope.color,
+ image: scope.image,
+ autoclose: scope.autoclose
+ });
+ e.preventDefault();
+ });
+ }
+ }
+
+ NotificationFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', 'FoundationApi'];
+
+ function NotificationFactory($http, $templateCache, $rootScope, $compile, $timeout, foundationApi) {
+ return notificationFactory;
+
+ function notificationFactory(config) {
+ var self = this, //for prototype functions
+ container = angular.element(config.container || document.body),
+ id = config.id || foundationApi.generateUuid(),
+ attached = false,
+ destroyed = false,
+ html,
+ element,
+ scope,
+ contentScope
+ ;
+
+ var props = [
+ 'position'
+ ];
+
+ assembleDirective();
+
+ self.addNotification = addNotification;
+ self.clearAll = clearAll;
+ self.destroy = destroy;
+
+ return {
+ addNotification: addNotification,
+ clearAll: clearAll,
+ destroy: destroy
+ };
+
+ function checkStatus() {
+ if(destroyed) {
+ throw "Error: Notification Set was destroyed. Delete the object and create a new NotificationFactory instance."
+ }
+ }
+
+ function addNotification(notification) {
+ checkStatus();
+ $timeout(function() {
+ foundationApi.publish(id, notification);
+ }, 0, false);
+ }
+
+ function clearAll() {
+ checkStatus();
+ $timeout(function() {
+ foundationApi.publish(id, 'clearall');
+ }, 0, false);
+ }
+
+ function init(state) {
+ if(!attached && html.length > 0) {
+ var modalEl = container.append(element);
+
+ scope.active = state;
+ $compile(element)(scope);
+
+ attached = true;
+ }
+ }
+
+ function assembleDirective() {
+ // check for duplicate element to prevent factory from cloning notification sets
+ if (document.getElementById(id)) {
+ return;
+ }
+ html = '<zf-notification-set id="' + id + '"></zf-notification-set>';
+
+ element = angular.element(html);
+
+ scope = $rootScope.$new();
+
+ for(var i = 0; i < props.length; i++) {
+ if(config[props[i]]) {
+ element.attr(props[i], config[props[i]]);
+ }
+ }
+
+ // access view scope variables
+ if (config.contentScope) {
+ contentScope = config.contentScope;
+ for (var prop in contentScope) {
+ if (contentScope.hasOwnProperty(prop)) {
+ scope[prop] = contentScope[prop];
+ }
+ }
+ }
+ init(true);
+ }
+
+ function destroy() {
+ self.clearAll();
+ setTimeout(function() {
+ scope.$destroy();
+ element.remove();
+ destroyed = true;
+ }, 3000);
+ foundationApi.unsubscribe(id);
+ }
+
+ }
+
+ }
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html b/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html
new file mode 100644
index 0000000..233cb02
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html
@@ -0,0 +1,5 @@
+<div
+ class="off-canvas {{ position }}"
+ ng-class="{'is-active': active}"
+ ng-transclude>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js b/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js
new file mode 100644
index 0000000..b1d6cff
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js
@@ -0,0 +1,102 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.offcanvas', ['foundation.core'])
+ .directive('zfOffcanvas', zfOffcanvas)
+ .service('FoundationOffcanvas', FoundationOffcanvas)
+ ;
+
+ FoundationOffcanvas.$inject = ['FoundationApi'];
+
+ function FoundationOffcanvas(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target) {
+ foundationApi.publish(target, 'toggle');
+ }
+ }
+
+ zfOffcanvas.$inject = ['FoundationApi'];
+
+ function zfOffcanvas(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/offcanvas/offcanvas.html',
+ transclude: true,
+ scope: {
+ position: '@'
+ },
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'offcanvas';
+
+ return {
+ pre: preLink,
+ post: postLink
+ }
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ document.body.classList.add('has-off-canvas');
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.position = scope.position || 'left';
+
+ scope.active = false;
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg === 'show' || msg === 'open') {
+ scope.show();
+ } else if (msg === 'close' || msg === 'hide') {
+ scope.hide();
+ } else if (msg === 'toggle') {
+ scope.toggle();
+ }
+
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ scope.hide = function() {
+ scope.active = false;
+ return;
+ };
+
+ scope.show = function() {
+ scope.active = true;
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ return;
+ };
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.html b/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.html
new file mode 100644
index 0000000..75a5b48
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.html
@@ -0,0 +1,6 @@
+<div
+ class="panel"
+ ng-class="positionClass"
+ ng-transclude
+ >
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.js b/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.js
new file mode 100644
index 0000000..396ca28
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/panel/panel.js
@@ -0,0 +1,144 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.panel', ['foundation.core'])
+ .directive('zfPanel', zfPanel)
+ .service('FoundationPanel', FoundationPanel)
+ ;
+
+ FoundationPanel.$inject = ['FoundationApi'];
+
+ function FoundationPanel(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+ zfPanel.$inject = ['FoundationApi', '$window'];
+
+ function zfPanel(foundationApi, $window) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/panel/panel.html',
+ transclude: true,
+ scope: {
+ position: '@?'
+ },
+ replace: true,
+ compile: compile
+ };
+
+ return directive;
+
+ function compile(tElement, tAttrs, transclude) {
+ var type = 'panel';
+
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs, controller) {
+ iAttrs.$set('zf-closable', type);
+ scope.position = scope.position || 'left';
+ scope.positionClass = 'panel-' + scope.position;
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.active = false;
+ var animationIn, animationOut;
+ var globalQueries = foundationApi.getSettings().mediaQueries;
+
+ //urgh, there must be a better way
+ if(scope.position === 'left') {
+ animationIn = attrs.animationIn || 'slideInRight';
+ animationOut = attrs.animationOut || 'slideOutLeft';
+ } else if (scope.position === 'right') {
+ animationIn = attrs.animationIn || 'slideInLeft';
+ animationOut = attrs.animationOut || 'slideOutRight';
+ } else if (scope.position === 'top') {
+ animationIn = attrs.animationIn || 'slideInDown';
+ animationOut = attrs.animationOut || 'slideOutUp';
+ } else if (scope.position === 'bottom') {
+ animationIn = attrs.animationIn || 'slideInUp';
+ animationOut = attrs.animationOut || 'slideOutBottom';
+ }
+
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ var panelPosition = $window.getComputedStyle(element[0]).getPropertyValue("position");
+
+ // patch to prevent panel animation on larger screen devices
+ if (panelPosition !== 'absolute') {
+ return;
+ }
+
+ if(msg == 'show' || msg == 'open') {
+ scope.show();
+ } else if (msg == 'close' || msg == 'hide') {
+ scope.hide();
+ } else if (msg == 'toggle') {
+ scope.toggle();
+ }
+
+ if (!scope.$root.$$phase) {
+ scope.$apply();
+ }
+
+ return;
+ });
+
+ scope.hide = function() {
+ if(scope.active){
+ scope.active = false;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+
+ return;
+ };
+
+ scope.show = function() {
+ if(!scope.active){
+ scope.active = true;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+
+ return;
+ };
+
+ scope.toggle = function() {
+ scope.active = !scope.active;
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+
+ return;
+ };
+
+ element.on('click', function(e) {
+ //check sizing
+ var srcEl = e.srcElement;
+
+ if(!matchMedia(globalQueries.medium).matches && srcEl.href && srcEl.href.length > 0) {
+ //hide element if it can't match at least medium
+ scope.hide();
+ foundationApi.animate(element, scope.active, animationIn, animationOut);
+ }
+ });
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.html b/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.html
new file mode 100644
index 0000000..50abed7
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.html
@@ -0,0 +1,2 @@
+<div class="popup" ng-class="{'is-active': active }" ng-transclude>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.js b/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.js
new file mode 100644
index 0000000..f51b1c6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/popup/popup.js
@@ -0,0 +1,160 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.popup', ['foundation.core'])
+ .directive('zfPopup', zfPopup)
+ .directive('zfPopupToggle', zfPopupToggle)
+ .service('FoundationPopup', FoundationPopup)
+ ;
+
+ FoundationPopup.$inject = ['FoundationApi'];
+
+ function FoundationPopup(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ //target should be element ID
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+
+ function toggle(target, popupTarget) {
+ foundationApi.publish(target, ['toggle', popupTarget]);
+ }
+ }
+
+ zfPopup.$inject = ['FoundationApi'];
+
+ function zfPopup(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ templateUrl: 'components/popup/popup.html',
+ scope: {
+ pinTo: '@?',
+ pinAt: '@?',
+ target: '@?'
+ },
+ compile: compile
+ };
+
+ return directive;
+
+ function compile() {
+ return {
+ pre: preLink,
+ post: postLink
+ };
+
+ function preLink(scope, iElement, iAttrs) {
+ iAttrs.$set('zf-closable', 'popup');
+ }
+
+ function postLink(scope, element, attrs) {
+ scope.active = false;
+ scope.target = scope.target || false;
+
+ var attachment = scope.pinTo || 'top center';
+ var targetAttachment = scope.pinAt || 'bottom center';
+ var tetherInit = false;
+ var tether = {};
+
+ //setup
+ foundationApi.subscribe(attrs.id, function(msg) {
+ if(msg[0] === 'show' || msg[0] === 'open') {
+ scope.show(msg[1]);
+ } else if (msg[0] === 'close' || msg[0] === 'hide') {
+ scope.hide();
+ } else if (msg[0] === 'toggle') {
+ scope.toggle(msg[1]);
+ }
+
+ scope.$apply();
+
+ return;
+ });
+
+
+ scope.hide = function() {
+ scope.active = false;
+ tetherElement();
+ tether.disable();
+ return;
+ };
+
+ scope.show = function(newTarget) {
+ scope.active = true;
+ tetherElement(newTarget);
+ tether.enable();
+
+ return;
+ };
+
+ scope.toggle = function(newTarget) {
+ scope.active = !scope.active;
+ tetherElement(newTarget);
+
+ if(scope.active) {
+ tether.enable();
+ } else {
+ tether.disable();
+ }
+
+ return;
+ };
+
+ function tetherElement(target) {
+ if(tetherInit) {
+ return;
+ }
+
+ scope.target = scope.target ? document.getElementById(scope.target) : document.getElementById(target);
+
+ tether = new Tether({
+ element: element[0],
+ target: scope.target,
+ attachment: attachment,
+ targetAttachment: targetAttachment,
+ enable: false
+ });
+
+ tetherInit = true;
+ }
+
+ }
+ }
+ }
+
+ zfPopupToggle.$inject = ['FoundationApi'];
+
+ function zfPopupToggle(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs) {
+ var target = attrs.zfPopupToggle;
+ var id = attrs.id || foundationApi.generateUuid();
+ attrs.$set('id', id);
+
+ element.on('click', function(e) {
+ foundationApi.publish(target, ['toggle', id]);
+ e.preventDefault();
+ });
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html
new file mode 100644
index 0000000..6ae46e7
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html
@@ -0,0 +1,8 @@
+<div class="tab-contents">
+ <div zf-tab-individual
+ class="tab-content"
+ ng-class="{'is-active': tab.active}"
+ ng-repeat="tab in tabs"
+ tab="tab">
+ </div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html
new file mode 100644
index 0000000..082bf86
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html
@@ -0,0 +1,3 @@
+<div class="tab-item"
+ ng-class="{'is-active': active}"
+ ng-click="makeActive()">{{ title }}</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html
new file mode 100644
index 0000000..b8a66f5
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html
@@ -0,0 +1,8 @@
+<div>
+ <div class="tabs" ng-transclude>
+ </div>
+ <div zf-tab-content
+ target="{{ id }}"
+ ng-if="showTabContent">
+ </div>
+</div>
diff --git a/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js
new file mode 100644
index 0000000..3818a2a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js
@@ -0,0 +1,311 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.tabs', ['foundation.core'])
+ .controller('ZfTabsController', ZfTabsController)
+ .directive('zfTabs', zfTabs)
+ .directive('zfTabContent', zfTabContent)
+ .directive('zfTab', zfTab)
+ .directive('zfTabIndividual', zfTabIndividual)
+ .directive('zfTabHref', zfTabHref)
+ .directive('zfTabCustom', zfTabCustom)
+ .directive('zfTabContentCustom', zfTabContentCustom)
+ .service('FoundationTabs', FoundationTabs)
+ ;
+
+ FoundationTabs.$inject = ['FoundationApi'];
+
+ function FoundationTabs(foundationApi) {
+ var service = {};
+
+ service.activate = activate;
+
+ return service;
+
+ //target should be element ID
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ }
+
+ ZfTabsController.$inject = ['$scope', 'FoundationApi'];
+
+ function ZfTabsController($scope, foundationApi) {
+ var controller = this;
+ var tabs = controller.tabs = $scope.tabs = [];
+ var id = '';
+
+ controller.select = function(selectTab) {
+ tabs.forEach(function(tab) {
+ tab.active = false;
+ tab.scope.active = false;
+
+ if(tab.scope === selectTab) {
+ foundationApi.publish(id, ['activate', tab]);
+
+ tab.active = true;
+ tab.scope.active = true;
+ }
+ });
+
+ };
+
+ controller.addTab = function addTab(tabScope) {
+ tabs.push({ scope: tabScope, active: false, parentContent: controller.id });
+
+ if(tabs.length === 1) {
+ tabs[0].active = true;
+ tabScope.active = true;
+ }
+ };
+
+ controller.getId = function() {
+ return id;
+ };
+
+ controller.setId = function(newId) {
+ id = newId;
+ };
+ }
+
+ zfTabs.$inject = ['FoundationApi'];
+
+ function zfTabs(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ replace: true,
+ templateUrl: 'components/tabs/tabs.html',
+ controller: 'ZfTabsController',
+ scope: {
+ displaced: '@?'
+ },
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller) {
+ scope.id = attrs.id || foundationApi.generateUuid();
+ scope.showTabContent = scope.displaced !== 'true';
+ attrs.$set('id', scope.id);
+ controller.setId(scope.id);
+
+ //update tabs in case tab-content doesn't have them
+ var updateTabs = function() {
+ foundationApi.publish(scope.id + '-tabs', scope.tabs);
+ };
+
+ foundationApi.subscribe(scope.id + '-get-tabs', function() {
+ updateTabs();
+ });
+ }
+ }
+
+ zfTabContent.$inject = ['FoundationApi'];
+
+ function zfTabContent(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ transclude: 'true',
+ replace: true,
+ scope: {
+ tabs: '=?',
+ target: '@'
+ },
+ templateUrl: 'components/tabs/tab-content.html',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl) {
+ scope.tabs = scope.tabs || [];
+ var id = scope.target;
+
+ foundationApi.subscribe(id, function(msg) {
+ if(msg[0] === 'activate') {
+ var tabId = msg[1];
+ scope.tabs.forEach(function (tab) {
+ tab.scope.active = false;
+ tab.active = false;
+
+ if(tab.scope.id === id) {
+ tab.scope.active = true;
+ tab.active = true;
+ }
+ });
+ }
+ });
+
+ //if tabs empty, request tabs
+ if(scope.tabs.length === 0) {
+ foundationApi.subscribe(id + '-tabs', function(tabs) {
+ scope.tabs = tabs;
+ });
+
+ foundationApi.publish(id + '-get-tabs', '');
+ }
+ }
+ }
+
+ zfTab.$inject = ['FoundationApi'];
+
+ function zfTab(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ templateUrl: 'components/tabs/tab.html',
+ transclude: true,
+ scope: {
+ title: '@'
+ },
+ require: '^zfTabs',
+ replace: true,
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, controller, transclude) {
+ scope.id = attrs.id || foundationApi.generateUuid();
+ scope.active = false;
+ scope.transcludeFn = transclude;
+ controller.addTab(scope);
+
+ foundationApi.subscribe(scope.id, function(msg) {
+ if(msg === 'show' || msg === 'open' || msg === 'activate') {
+ scope.makeActive();
+ }
+ });
+
+ scope.makeActive = function() {
+ controller.select(scope);
+ };
+ }
+ }
+
+ zfTabIndividual.$inject = ['FoundationApi'];
+
+ function zfTabIndividual(foundationApi) {
+ var directive = {
+ restrict: 'EA',
+ transclude: 'true',
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var tab = scope.$eval(attrs.tab);
+ var id = tab.scope.id;
+
+ tab.scope.transcludeFn(tab.scope, function(tabContent) {
+ element.append(tabContent);
+ });
+
+ foundationApi.subscribe(tab.scope.id, function(msg) {
+ foundationApi.publish(tab.parentContent, ['activate', tab.scope.id]);
+ scope.$apply();
+ });
+
+ }
+ }
+
+ //custom tabs
+
+ zfTabHref.$inject = ['FoundationApi'];
+
+ function zfTabHref(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ replace: false,
+ link: link
+ }
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl) {
+ var target = attrs.zfTabHref;
+
+ foundationApi.subscribe(target, function(msg) {
+ if(msg === 'activate' || msg === 'show' || msg === 'open') {
+ makeActive();
+ }
+ });
+
+
+ element.on('click', function(e) {
+ foundationApi.publish(target, 'activate');
+ makeActive();
+ e.preventDefault();
+ });
+
+ function makeActive() {
+ element.parent().children().removeClass('is-active');
+ element.addClass('is-active');
+ }
+ }
+ }
+
+ zfTabCustom.$inject = ['FoundationApi'];
+
+ function zfTabCustom(foundationApi) {
+ var directive = {
+ restrict: 'A',
+ replace: false,
+ link: link
+ };
+
+ return directive;
+
+ function link(scope, element, attrs, ctrl, transclude) {
+ var children = element.children();
+ angular.element(children[0]).addClass('is-active');
+ }
+ }
+
+ zfTabContentCustom.$inject = ['FoundationApi'];
+
+ function zfTabContentCustom(foundationApi) {
+ return {
+ restrict: 'A',
+ link: link
+ };
+
+ function link(scope, element, attrs) {
+ var tabs = [];
+ var children = element.children();
+
+ angular.forEach(children, function(node) {
+ if(node.id) {
+ var tabId = node.id;
+ tabs.push(tabId);
+ foundationApi.subscribe(tabId, function(msg) {
+ if(msg === 'activate' || msg === 'show' || msg === 'open') {
+ activateTabs(tabId);
+ }
+ });
+
+ if(tabs.length === 1) {
+ var el = angular.element(node);
+ el.addClass('is-active');
+ }
+ }
+ });
+
+ function activateTabs(tabId) {
+ var tabNodes = element.children();
+ angular.forEach(tabNodes, function(node) {
+ var el = angular.element(node);
+ el.removeClass('is-active');
+ if(el.attr('id') === tabId) {
+ el.addClass('is-active');
+ }
+
+ });
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/foundation.js b/afb-client/bower_components/foundation-apps/js/angular/foundation.js
new file mode 100644
index 0000000..71ac6e3
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/foundation.js
@@ -0,0 +1,22 @@
+(function() {
+ 'use strict';
+
+ // imports all components and dependencies under a single namespace
+
+ angular.module('foundation', [
+ 'foundation.core',
+ 'foundation.mediaquery',
+ 'foundation.accordion',
+ 'foundation.actionsheet',
+ 'foundation.common',
+ 'foundation.iconic',
+ 'foundation.interchange',
+ 'foundation.modal',
+ 'foundation.notification',
+ 'foundation.offcanvas',
+ 'foundation.panel',
+ 'foundation.popup',
+ 'foundation.tabs'
+ ]);
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.animation.js b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.animation.js
new file mode 100644
index 0000000..535798a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.animation.js
@@ -0,0 +1,129 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.core.animation', [])
+ .service('FoundationAnimation', FoundationAnimation)
+ ;
+
+ function FoundationAnimation() {
+ var animations = [];
+ var service = {};
+
+ var initClasses = ['ng-enter', 'ng-leave'];
+ var activeClasses = ['ng-enter-active', 'ng-leave-active'];
+ var activeGenericClass = 'is-active';
+ var events = [
+ 'webkitAnimationEnd', 'mozAnimationEnd',
+ 'MSAnimationEnd', 'oanimationend',
+ 'animationend', 'webkitTransitionEnd',
+ 'otransitionend', 'transitionend'
+ ];
+
+ service.animate = animate;
+ service.toggleAnimation = toggleAnimation;
+
+ return service;
+
+ function toggleAnimation(element, futureState) {
+ if(futureState) {
+ element.addClass(activeGenericClass);
+ } else {
+ element.removeClass(activeGenericClass);
+ }
+ }
+
+ function animate(element, futureState, animationIn, animationOut) {
+ var timedOut = true;
+ var self = this;
+ self.cancelAnimation = cancelAnimation;
+
+ var animationClass = futureState ? animationIn: animationOut;
+ var activation = futureState;
+ var initClass = activation ? initClasses[0] : initClasses[1];
+ var activeClass = activation ? activeClasses[0] : activeClasses[1];
+ //stop animation
+ registerElement(element);
+ reset();
+ element.addClass(animationClass);
+ element.addClass(initClass);
+
+ element.addClass(activeGenericClass);
+
+ //force a "tick"
+ reflow();
+
+ //activate
+ element[0].style.transitionDuration = '';
+ element.addClass(activeClass);
+
+ element.one(events.join(' '), function() {
+ finishAnimation();
+ });
+
+ setTimeout(function() {
+ if(timedOut) {
+ finishAnimation();
+ }
+ }, 3000);
+
+ function finishAnimation() {
+ deregisterElement(element);
+ reset(); //reset all classes
+ element[0].style.transitionDuration = '';
+ element.removeClass(!activation ? activeGenericClass : ''); //if not active, remove active class
+ reflow();
+ timedOut = false;
+ }
+
+
+ function cancelAnimation(element) {
+ deregisterElement(element);
+ angular.element(element).off(events.join(' ')); //kill all animation event handlers
+ timedOut = false;
+ }
+
+ function registerElement(el) {
+ var elObj = {
+ el: el,
+ animation: self
+ };
+
+ //kill in progress animations
+ var inProgress = animations.filter(function(obj) {
+ return obj.el === el;
+ });
+ if(inProgress.length > 0) {
+ var target = inProgress[0].el[0];
+
+ inProgress[0].animation.cancelAnimation(target);
+ }
+
+ animations.push(elObj);
+ }
+
+ function deregisterElement(el) {
+ var index;
+ var currentAnimation = animations.filter(function(obj, ind) {
+ if(obj.el === el) {
+ index = ind;
+ }
+ });
+
+ if(index >= 0) {
+ animations.splice(index, 1);
+ }
+
+ }
+
+ function reflow() {
+ return element[0].offsetWidth;
+ }
+
+ function reset() {
+ element[0].style.transitionDuration = 0;
+ element.removeClass(initClasses.join(' ') + ' ' + activeClasses.join(' ') + ' ' + animationIn + ' ' + animationOut);
+ }
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.js b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.js
new file mode 100644
index 0000000..6aeb9da
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.core.js
@@ -0,0 +1,163 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.core', [
+ 'foundation.core.animation'
+ ])
+ .service('FoundationApi', FoundationApi)
+ .service('FoundationAdapter', FoundationAdapter)
+ .factory('Utils', Utils)
+ ;
+
+ FoundationApi.$inject = ['FoundationAnimation'];
+
+ function FoundationApi(FoundationAnimation) {
+ var listeners = {};
+ var settings = {};
+ var uniqueIds = [];
+ var service = {};
+
+ service.subscribe = subscribe;
+ service.unsubscribe = unsubscribe;
+ service.publish = publish;
+ service.getSettings = getSettings;
+ service.modifySettings = modifySettings;
+ service.generateUuid = generateUuid;
+ service.toggleAnimate = toggleAnimate;
+ service.closeActiveElements = closeActiveElements;
+ service.animate = animate;
+
+ return service;
+
+ function subscribe(name, callback) {
+ if (!listeners[name]) {
+ listeners[name] = [];
+ }
+
+ listeners[name].push(callback);
+ return true;
+ }
+
+ function unsubscribe(name, callback) {
+ if (listeners[name] !== undefined) {
+ delete listeners[name];
+ }
+ if (typeof callback == 'function') {
+ callback.call(this);
+ }
+ }
+
+ function publish(name, msg) {
+ if (!listeners[name]) {
+ listeners[name] = [];
+ }
+
+ listeners[name].forEach(function(cb) {
+ cb(msg);
+ });
+
+ return;
+ }
+
+ function getSettings() {
+ return settings;
+ }
+
+ function modifySettings(tree) {
+ settings = angular.extend(settings, tree);
+ return settings;
+ }
+
+ function generateUuid() {
+ var uuid = '';
+
+ //little trick to produce semi-random IDs
+ do {
+ uuid += 'zf-uuid-';
+ for (var i=0; i<15; i++) {
+ uuid += Math.floor(Math.random()*16).toString(16);
+ }
+ } while(!uniqueIds.indexOf(uuid));
+
+ uniqueIds.push(uuid);
+ return uuid;
+ }
+
+ function toggleAnimate(element, futureState) {
+ FoundationAnimation.toggleAnimate(element, futureState);
+ }
+
+ function closeActiveElements(options) {
+ var self = this;
+ options = options || {};
+ var activeElements = document.querySelectorAll('.is-active[zf-closable]');
+ // action sheets are nested zf-closable elements, so we have to target the parent
+ var nestedActiveElements = document.querySelectorAll('[zf-closable] > .is-active')
+
+ if (activeElements.length) {
+ angular.forEach(activeElements, function(el) {
+ if (options.exclude !== el.id) {
+ self.publish(el.id, 'close');
+ }
+ });
+ }
+ if (nestedActiveElements.length) {
+ angular.forEach(nestedActiveElements, function(el) {
+ var parentId = el.parentNode.id;
+ if (options.exclude !== parentId) {
+ self.publish(parentId, 'close');
+ }
+ })
+ }
+ }
+
+ function animate(element, futureState, animationIn, animationOut) {
+ FoundationAnimation.animate(element, futureState, animationIn, animationOut);
+ }
+ }
+
+ FoundationAdapter.$inject = ['FoundationApi'];
+
+ function FoundationAdapter(foundationApi) {
+
+ var service = {};
+
+ service.activate = activate;
+ service.deactivate = deactivate;
+
+ return service;
+
+ function activate(target) {
+ foundationApi.publish(target, 'show');
+ }
+
+ function deactivate(target) {
+ foundationApi.publish(target, 'hide');
+ }
+ }
+
+
+ function Utils() {
+ var utils = {};
+
+ utils.throttle = throttleUtil;
+
+ return utils;
+
+ function throttleUtil(func, delay) {
+ var timer = null;
+
+ return function () {
+ var context = this, args = arguments;
+
+ if (timer === null) {
+ timer = setTimeout(function () {
+ func.apply(context, args);
+ timer = null;
+ }, delay);
+ }
+ };
+ }
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.animations.js b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.animations.js
new file mode 100644
index 0000000..ba79c52
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.animations.js
@@ -0,0 +1,125 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.dynamicRouting.animations', ['foundation.dynamicRouting'])
+ .directive('uiView', uiView)
+ ;
+
+ uiView.$inject = ['$rootScope', '$state'];
+
+ function uiView($rootScope, $state) {
+ var directive = {
+ restrict : 'ECA',
+ priority : -400,
+ link : link
+ };
+
+ return directive;
+
+ function link(scope, element) {
+ var animation = {};
+ var animationEnded = false;
+ var presetHeight;
+
+ var cleanup = [
+ $rootScope.$on('$stateChangeStart', onStateChangeStart),
+ $rootScope.$on('$stateChangeError', onStateChangeError),
+ scope.$on('$stateChangeSuccess', onStateChangeSuccess),
+ scope.$on('$viewContentAnimationEnded', onViewContentAnimationEnded)
+ ];
+
+ var destroyed = scope.$on('$destroy', function onDestroy() {
+ angular.forEach(cleanup, function (cb) {
+ if (angular.isFunction(cb)) {
+ cb();
+ }
+ });
+
+ destroyed();
+ });
+
+ function onStateChangeStart(event, toState, toParams, fromState, fromParams) {
+
+ if (fromState.animation) {
+ if (!fromState.animation.leave && !toState.animation.leave) {
+ return;
+ }
+ else {
+ animationRouter(event, toState, fromState);
+ }
+ }
+ }
+
+ function animationRouter(event, toState, fromState) {
+ if (!animationEnded) {
+ resetParent();
+ prepareParent();
+
+ element.removeClass(fromState.animation.leave);
+ }
+ else {
+ prepareParent();
+
+ element.addClass(fromState.animation.leave);
+ }
+
+ }
+
+ function onStateChangeError() {
+ if(animation.leave) {
+ element.removeClass(animation.leave);
+ }
+
+ resetParent(); //reset parent if state change fails
+ }
+
+ function onStateChangeSuccess() {
+ resetParent();
+ if ($state.includes(getState()) && animation.enter) {
+ element.addClass(animation.enter);
+ }
+ }
+
+ function onViewContentAnimationEnded(event) {
+ if (event.targetScope === scope && animation.enter) {
+ element.removeClass(animation.enter);
+ }
+
+ animationEnded = true;
+
+ }
+
+ function getState() {
+ var view = element.data('$uiView');
+ var state = view && view.state && view.state.self;
+
+ if (state) {
+ angular.extend(animation, state.animation);
+ }
+
+ return state;
+ }
+
+ function resetParent() {
+ element.parent().removeClass('position-absolute');
+ if(presetHeight !== true) {
+ element.parent()[0].style.height = null;
+ }
+ }
+
+ function prepareParent() {
+ var parentHeight = parseInt(element.parent()[0].style.height);
+ var elHeight = parseInt(window.getComputedStyle(element[0], null).getPropertyValue('height'));
+ var tempHeight = parentHeight > 0 ? parentHeight : elHeight > 0 ? elHeight : '';
+
+ if(parentHeight > 0) {
+ presetHeight = true;
+ }
+
+ element.parent()[0].style.height = tempHeight + 'px';
+ element.parent().addClass('position-absolute');
+ }
+ }
+ }
+
+})(); \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.js b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.js
new file mode 100644
index 0000000..27e3767
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.dynamicRouting.js
@@ -0,0 +1,156 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.dynamicRouting', ['ui.router'])
+ .provider('$FoundationState', FoundationState)
+ .controller('DefaultController', DefaultController)
+ .config(DynamicRoutingConfig)
+ .run(DynamicRoutingRun)
+ ;
+
+ FoundationState.$inject = ['$stateProvider'];
+
+ function FoundationState($stateProvider) {
+ var complexViews = {};
+
+ this.registerDynamicRoutes = function(routes) {
+ var dynamicRoutes = routes || foundationRoutes;
+
+ angular.forEach(dynamicRoutes, function(page) {
+ if (page.hasComposed) {
+ if (!angular.isDefined(complexViews[page.parent])) {
+ complexViews[page.parent] = { children: {} };
+ }
+
+ if (page.controller) {
+ page.controller = getController(page);
+ }
+
+ complexViews[page.parent].children[page.name] = page;
+
+ } else if (page.composed) {
+ if(!angular.isDefined(complexViews[page.name])) {
+ complexViews[page.name] = { children: {} };
+ }
+
+ if (page.controller) {
+ page.controller = getController(page);
+ }
+
+ angular.extend(complexViews[page.name], page);
+ } else {
+ var state = {
+ url: page.url,
+ templateUrl: page.path,
+ abstract: page.abstract || false,
+ parent: page.parent || '',
+ controller: getController(page),
+ data: getData(page),
+ animation: buildAnimations(page),
+ };
+
+ $stateProvider.state(page.name, state);
+ }
+ });
+
+ angular.forEach(complexViews, function(page) {
+ var state = {
+ url: page.url,
+ parent: page.parent || '',
+ abstract: page.abstract || false,
+ data: getData(page),
+ animation: buildAnimations(page),
+ views: {
+ '': buildState(page.path, page)
+ }
+ };
+
+ angular.forEach(page.children, function(sub) {
+ state.views[sub.name + '@' + page.name] = buildState(sub.path, page);
+ });
+
+ $stateProvider.state(page.name, state);
+ });
+ };
+
+ this.$get = angular.noop;
+
+ function getData(page) {
+ var data = { vars: {} };
+ if (page.data) {
+ if (typeof page.data.vars === "object") {
+ data.vars = page.data.vars;
+ }
+ delete page.data.vars;
+ angular.extend(data, page.data);
+ }
+ delete page.data;
+ angular.extend(data.vars, page);
+ return data;
+ }
+
+ function buildState(path, state) {
+ return {
+ templateUrl: path,
+ controller: getController(state),
+ };
+ }
+
+ function getController(state) {
+ var ctrl = state.controller || 'DefaultController';
+
+ if (!/\w\s+as\s+\w/.test(ctrl)) {
+ ctrl += ' as PageCtrl';
+ }
+
+ return ctrl;
+ }
+
+ function buildAnimations(state) {
+ var animations = {};
+
+ if (state.animationIn) {
+ animations.enter = state.animationIn;
+ }
+
+ if (state.animationOut) {
+ animations.leave = state.animationOut;
+ }
+
+ return animations;
+ }
+ }
+
+ DefaultController.$inject = ['$scope', '$stateParams', '$state'];
+
+ function DefaultController($scope, $stateParams, $state) {
+ var params = {};
+ angular.forEach($stateParams, function(value, key) {
+ params[key] = value;
+ });
+
+ $scope.params = params;
+ $scope.current = $state.current.name;
+
+ if($state.current.views) {
+ $scope.vars = $state.current.data.vars;
+ $scope.composed = $state.current.data.vars.children;
+ } else {
+ $scope.vars = $state.current.data.vars;
+ }
+ }
+
+ DynamicRoutingConfig.$inject = ['$FoundationStateProvider'];
+
+ function DynamicRoutingConfig(FoundationStateProvider) {
+ FoundationStateProvider.registerDynamicRoutes(foundationRoutes);
+ }
+
+ DynamicRoutingRun.$inject = ['$rootScope', '$state', '$stateParams'];
+
+ function DynamicRoutingRun($rootScope, $state, $stateParams) {
+ $rootScope.$state = $state;
+ $rootScope.$stateParams = $stateParams;
+ }
+
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/services/foundation.mediaquery.js b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.mediaquery.js
new file mode 100644
index 0000000..12715f6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/services/foundation.mediaquery.js
@@ -0,0 +1,198 @@
+(function() {
+ 'use strict';
+
+ angular.module('foundation.mediaquery', ['foundation.core'])
+ .run(mqInitRun)
+ .factory('FoundationMQInit', FoundationMQInit)
+ .factory('mqHelpers', mqHelpers)
+ .service('FoundationMQ', FoundationMQ)
+ ;
+
+ mqInitRun.$inject = ['FoundationMQInit'];
+
+ function mqInitRun(mqInit) {
+ mqInit.init();
+ }
+
+ FoundationMQInit.$inject = ['mqHelpers', 'FoundationApi', 'Utils'];
+
+ function FoundationMQInit(helpers, foundationApi, u){
+ var factory = {};
+ var namedQueries = {
+ 'default' : 'only screen',
+ landscape : 'only screen and (orientation: landscape)',
+ portrait : 'only screen and (orientation: portrait)',
+ retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
+ 'only screen and (min--moz-device-pixel-ratio: 2),' +
+ 'only screen and (-o-min-device-pixel-ratio: 2/1),' +
+ 'only screen and (min-device-pixel-ratio: 2),' +
+ 'only screen and (min-resolution: 192dpi),' +
+ 'only screen and (min-resolution: 2dppx)'
+ };
+
+ factory.init = init;
+
+ return factory;
+
+ function init() {
+ var mediaQueries;
+ var extractedMedia;
+ var mediaObject;
+
+ helpers.headerHelper(['foundation-mq']);
+ extractedMedia = helpers.getStyle('.foundation-mq', 'font-family');
+
+ mediaQueries = helpers.parseStyleToObject((extractedMedia));
+
+ for(var key in mediaQueries) {
+ mediaQueries[key] = 'only screen and (min-width: ' + mediaQueries[key].replace('rem', 'em') + ')';
+ }
+
+
+ foundationApi.modifySettings({
+ mediaQueries: angular.extend(mediaQueries, namedQueries)
+ });
+
+ window.addEventListener('resize', u.throttle(function() {
+ foundationApi.publish('resize', 'window resized');
+ }, 50));
+
+ }
+ }
+
+
+ function mqHelpers() {
+ var factory = {};
+
+ factory.headerHelper = headerHelper;
+ factory.getStyle = getStyle;
+ factory.parseStyleToObject = parseStyleToObject;
+
+ return factory;
+
+ function headerHelper(classArray) {
+ var i = classArray.length;
+ var head = angular.element(document.querySelectorAll('head'));
+
+ while(i--) {
+ head.append('<meta class="' + classArray[i] + '" />');
+ }
+
+ return;
+ }
+
+ function getStyle(selector, styleName) {
+ var elem = document.querySelectorAll(selector)[0];
+ var style = window.getComputedStyle(elem, null);
+
+ return style.getPropertyValue('font-family');
+ }
+
+ // https://github.com/sindresorhus/query-string
+ function parseStyleToObject(str) {
+ var styleObject = {};
+
+ if (typeof str !== 'string') {
+ return styleObject;
+ }
+
+ str = str.trim().slice(1, -1); // browsers re-quote string style values
+
+ if (!str) {
+ return styleObject;
+ }
+
+ styleObject = str.split('&').reduce(function(ret, param) {
+ var parts = param.replace(/\+/g, ' ').split('=');
+ var key = parts[0];
+ var val = parts[1];
+ key = decodeURIComponent(key);
+
+ // missing `=` should be `null`:
+ // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
+ val = val === undefined ? null : decodeURIComponent(val);
+
+ if (!ret.hasOwnProperty(key)) {
+ ret[key] = val;
+ } else if (Array.isArray(ret[key])) {
+ ret[key].push(val);
+ } else {
+ ret[key] = [ret[key], val];
+ }
+ return ret;
+ }, {});
+
+ return styleObject;
+ }
+ }
+
+ FoundationMQ.$inject = ['FoundationApi'];
+
+ function FoundationMQ(foundationApi) {
+ var service = [];
+
+ service.getMediaQueries = getMediaQueries;
+ service.match = match;
+ service.collectScenariosFromElement = collectScenariosFromElement;
+
+ return service;
+
+ function getMediaQueries() {
+ return foundationApi.getSettings().mediaQueries;
+ }
+
+ function match(scenarios) {
+ var count = scenarios.length;
+ var queries = service.getMediaQueries();
+ var matches = [];
+
+ if (count > 0) {
+ while (count--) {
+ var mq;
+ var rule = scenarios[count].media;
+
+ if (queries[rule]) {
+ mq = matchMedia(queries[rule]);
+ } else {
+ mq = matchMedia(rule);
+ }
+
+ if (mq.matches) {
+ matches.push({ ind: count});
+ }
+ }
+ }
+
+ return matches;
+ }
+
+ // Collects a scenario object and templates from element
+ function collectScenariosFromElement(parentElement) {
+ var scenarios = [];
+ var templates = [];
+
+ var elements = parentElement.children();
+ var i = 0;
+
+ angular.forEach(elements, function(el) {
+ var elem = angular.element(el);
+
+
+ //if no source or no html, capture element itself
+ if (!elem.attr('src') || !elem.attr('src').match(/.html$/)) {
+ templates[i] = elem;
+ scenarios[i] = { media: elem.attr('media'), templ: i };
+ } else {
+ scenarios[i] = { media: elem.attr('media'), src: elem.attr('src') };
+ }
+
+ i++;
+ });
+
+ return {
+ scenarios: scenarios,
+ templates: templates
+ };
+ }
+ }
+})();
diff --git a/afb-client/bower_components/foundation-apps/js/angular/vendor/markdown.js b/afb-client/bower_components/foundation-apps/js/angular/vendor/markdown.js
new file mode 100644
index 0000000..d0dd9d6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/vendor/markdown.js
@@ -0,0 +1,10 @@
+angular.module('markdown', [])
+ .directive('markdown', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs, controller) {
+ element.html(marked(element.html()));
+ }
+ };
+
+});
diff --git a/afb-client/bower_components/foundation-apps/js/angular/vendor/svgDirs.js b/afb-client/bower_components/foundation-apps/js/angular/vendor/svgDirs.js
new file mode 100755
index 0000000..c07c883
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/angular/vendor/svgDirs.js
@@ -0,0 +1,101 @@
+'use strict';
+
+(function(){
+ var svgDirectives = {};
+
+ angular.forEach([
+ 'clipPath',
+ 'colorProfile',
+ 'src',
+ 'cursor',
+ 'fill',
+ 'filter',
+ 'marker',
+ 'markerStart',
+ 'markerMid',
+ 'markerEnd',
+ 'mask',
+ 'stroke'
+ ],
+ function(attr) {
+ svgDirectives[attr] = [
+ '$rootScope',
+ '$location',
+ '$interpolate',
+ '$sniffer',
+ 'urlResolve',
+ 'computeSVGAttrValue',
+ 'svgAttrExpressions',
+ function(
+ $rootScope,
+ $location,
+ $interpolate,
+ $sniffer,
+ urlResolve,
+ computeSVGAttrValue,
+ svgAttrExpressions) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ var initialUrl;
+
+ //Only apply to svg elements to avoid unnecessary observing
+ //Check that is in html5Mode and that history is supported
+ if ((!svgAttrExpressions.SVG_ELEMENT.test(element[0] &&
+ element[0].toString())) ||
+ !$location.$$html5 ||
+ !$sniffer.history) return;
+
+ //Assumes no expressions, since svg is unforgiving of xml violations
+ initialUrl = attrs[attr];
+ attrs.$observe(attr, updateValue);
+ $rootScope.$on('$locationChangeSuccess', updateValue);
+
+ function updateValue () {
+ var newVal = computeSVGAttrValue(initialUrl);
+ //Prevent recursive updating
+ if (newVal && attrs[attr] !== newVal) attrs.$set(attr, newVal);
+ }
+ }
+ };
+ }];
+ });
+
+ angular.module('ngSVGAttributes', []).
+ factory('urlResolve', [function() {
+ //Duplicate of urlResolve & urlParsingNode in angular core
+ var urlParsingNode = document.createElement('a');
+ return function urlResolve(url) {
+ urlParsingNode.setAttribute('href', url);
+ return urlParsingNode;
+ };
+ }]).
+ value('svgAttrExpressions', {
+ FUNC_URI: /^url\((.*)\)$/,
+ SVG_ELEMENT: /SVG[a-zA-Z]*Element/,
+ HASH_PART: /#.*/
+ }).
+ factory('computeSVGAttrValue', [
+ '$location', '$sniffer', 'svgAttrExpressions', 'urlResolve',
+ function($location, $sniffer, svgAttrExpressions, urlResolve) {
+ return function computeSVGAttrValue(url) {
+ var match, fullUrl;
+ if (match = svgAttrExpressions.FUNC_URI.exec(url)) {
+ //hash in html5Mode, forces to be relative to current url instead of base
+ if (match[1].indexOf('#') === 0) {
+ fullUrl = $location.absUrl().
+ replace(svgAttrExpressions.HASH_PART, '') +
+ match[1];
+ }
+ //Presumably links to external SVG document
+ else {
+ fullUrl = urlResolve(match[1]);
+ }
+ }
+ return fullUrl ? 'url(' + fullUrl + ')' : null;
+ };
+ }
+ ]
+ ).
+ directive(svgDirectives);
+}());
diff --git a/afb-client/bower_components/foundation-apps/js/vendor/iconic.min.js b/afb-client/bower_components/foundation-apps/js/vendor/iconic.min.js
new file mode 100755
index 0000000..a18ac59
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/js/vendor/iconic.min.js
@@ -0,0 +1,6 @@
+/*!
+ * iconic.js v0.4.0 - The Iconic JavaScript library
+ * Copyright (c) 2014 Waybury - http://useiconic.com
+ */
+
+!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.IconicJS=a():"undefined"!=typeof global?global.IconicJS=a():"undefined"!=typeof self&&(self.IconicJS=a())}(function(){var a;return function b(a,c,d){function e(g,h){if(!c[g]){if(!a[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};a[g][0].call(j.exports,function(b){var c=a[g][1][b];return e(c?c:b)},j,j.exports,b,a,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){var c=(a("./modules/polyfills"),a("./modules/svg-injector")),d=a("./modules/extend"),e=a("./modules/responsive"),f=a("./modules/position"),g=a("./modules/container"),h=a("./modules/log"),i={},j=window.iconicSmartIconApis={},k=("file:"===window.location.protocol,0),l=function(a,b,e){b=d({},i,b||{});var f={evalScripts:b.evalScripts,pngFallback:b.pngFallback};f.each=function(a){if(a)if("string"==typeof a)h.debug(a);else if(a instanceof SVGSVGElement){var c=a.getAttribute("data-icon");if(c&&j[c]){var d=j[c](a);for(var e in d)a[e]=d[e]}/iconic-bg-/.test(a.getAttribute("class"))&&g.addBackground(a),m(a),k++,b&&b.each&&"function"==typeof b.each&&b.each(a)}},"string"==typeof a&&(a=document.querySelectorAll(a)),c(a,f,e)},m=function(a){var b=[];a?"string"==typeof a?b=document.querySelectorAll(a):void 0!==a.length?b=a:"object"==typeof a&&b.push(a):b=document.querySelectorAll("svg.iconic"),Array.prototype.forEach.call(b,function(a){a instanceof SVGSVGElement&&(a.update&&a.update(),e.refresh(a),f.refresh(a))})},n=function(){i.debug&&console.time&&console.time("autoInjectSelector - "+i.autoInjectSelector);var a=k;l(i.autoInjectSelector,{},function(){if(i.debug&&console.timeEnd&&console.timeEnd("autoInjectSelector - "+i.autoInjectSelector),h.debug("AutoInjected: "+(k-a)),e.refreshAll(),i.autoInjectDone&&"function"==typeof i.autoInjectDone){var b=k-a;i.autoInjectDone(b)}})},o=function(a){a&&""!==a&&"complete"!==document.readyState?document.addEventListener("DOMContentLoaded",n):document.removeEventListener("DOMContentLoaded",n)},p=function(a){return a=a||{},d(i,a),o(i.autoInjectSelector),h.enableDebug(i.debug),window._Iconic?window._Iconic:{inject:l,update:m,smartIconApis:j,svgInjectedCount:k}};b.exports=p,window._Iconic=new p({autoInjectSelector:"img.iconic",evalScripts:"once",pngFallback:!1,each:null,autoInjectDone:null,debug:!1})},{"./modules/container":2,"./modules/extend":3,"./modules/log":4,"./modules/polyfills":5,"./modules/position":6,"./modules/responsive":7,"./modules/svg-injector":8}],2:[function(a,b){var c=function(a){var b=a.getAttribute("class").split(" "),c=-1!==b.indexOf("iconic-fluid"),d=[],e=["iconic-bg"];Array.prototype.forEach.call(b,function(a){switch(a){case"iconic-sm":case"iconic-md":case"iconic-lg":d.push(a),c||e.push(a.replace(/-/,"-bg-"));break;case"iconic-fluid":d.push(a),e.push(a.replace(/-/,"-bg-"));break;case"iconic-bg-circle":case"iconic-bg-rounded-rect":case"iconic-bg-badge":e.push(a);break;default:d.push(a)}}),a.setAttribute("class",d.join(" "));var f=a.parentNode,g=Array.prototype.indexOf.call(f.childNodes,a),h=document.createElement("span");h.setAttribute("class",e.join(" ")),h.appendChild(a),f.insertBefore(h,f.childNodes[g])};b.exports={addBackground:c}},{}],3:[function(a,b){b.exports=function(a){return Array.prototype.forEach.call(Array.prototype.slice.call(arguments,1),function(b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}),a}},{}],4:[function(a,b){var c=!1,d=function(a){console&&console.log&&console.log(a)},e=function(a){d("Iconic INFO: "+a)},f=function(a){d("Iconic WARNING: "+a)},g=function(a){c&&d("Iconic DEBUG: "+a)},h=function(a){c=a};b.exports={info:e,warn:f,debug:g,enableDebug:h}},{}],5:[function(){Array.prototype.forEach||(Array.prototype.forEach=function(a,b){"use strict";if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)}),function(){if(Event.prototype.preventDefault||(Event.prototype.preventDefault=function(){this.returnValue=!1}),Event.prototype.stopPropagation||(Event.prototype.stopPropagation=function(){this.cancelBubble=!0}),!Element.prototype.addEventListener){var a=[],b=function(b,c){var d=this,e=function(a){a.target=a.srcElement,a.currentTarget=d,c.handleEvent?c.handleEvent(a):c.call(d,a)};if("DOMContentLoaded"==b){var f=function(a){"complete"==document.readyState&&e(a)};if(document.attachEvent("onreadystatechange",f),a.push({object:this,type:b,listener:c,wrapper:f}),"complete"==document.readyState){var g=new Event;g.srcElement=window,f(g)}}else this.attachEvent("on"+b,e),a.push({object:this,type:b,listener:c,wrapper:e})},c=function(b,c){for(var d=0;d<a.length;){var e=a[d];if(e.object==this&&e.type==b&&e.listener==c){"DOMContentLoaded"==b?this.detachEvent("onreadystatechange",e.wrapper):this.detachEvent("on"+b,e.wrapper);break}++d}};Element.prototype.addEventListener=b,Element.prototype.removeEventListener=c,HTMLDocument&&(HTMLDocument.prototype.addEventListener=b,HTMLDocument.prototype.removeEventListener=c),Window&&(Window.prototype.addEventListener=b,Window.prototype.removeEventListener=c)}}()},{}],6:[function(a,b){var c=function(a){var b=a.getAttribute("data-position");if(b&&""!==b){var c,d,e,f,g,h,i,j=a.getAttribute("width"),k=a.getAttribute("height"),l=b.split("-"),m=a.querySelectorAll("g.iconic-container");Array.prototype.forEach.call(m,function(a){if(c=a.getAttribute("data-width"),d=a.getAttribute("data-height"),c!==j||d!==k){if(e=a.getAttribute("transform"),f=1,e){var b=e.match(/scale\((\d)/);f=b&&b[1]?b[1]:1}g=Math.floor((j/f-c)/2),h=Math.floor((k/f-d)/2),Array.prototype.forEach.call(l,function(a){switch(a){case"top":h=0;break;case"bottom":h=k/f-d;break;case"left":g=0;break;case"right":g=j/f-c;break;case"center":break;default:console&&console.log&&console.log("Unknown position: "+a)}}),i=0===h?g:g+" "+h,i="translate("+i+")",e?/translate/.test(e)?e=e.replace(/translate\(.*?\)/,i):e+=" "+i:e=i,a.setAttribute("transform",e)}})}};b.exports={refresh:c}},{}],7:[function(a,b){var c=/(iconic-sm\b|iconic-md\b|iconic-lg\b)/,d=function(a,b){var c="undefined"!=typeof window.getComputedStyle&&window.getComputedStyle(a,null).getPropertyValue(b);return!c&&a.currentStyle&&(c=a.currentStyle[b.replace(/([a-z])\-([a-z])/,function(a,b,c){return b+c.toUpperCase()})]||a.currentStyle[b]),c},e=function(a){var b=a.style.display;a.style.display="block";var c=parseFloat(d(a,"width").slice(0,-2)),e=parseFloat(d(a,"height").slice(0,-2));return a.style.display=b,{width:c,height:e}},f=function(){var a="/* Iconic Responsive Support Styles */\n.iconic-property-fill, .iconic-property-text {stroke: none !important;}\n.iconic-property-stroke {fill: none !important;}\nsvg.iconic.iconic-fluid {height:100% !important;width:100% !important;}\nsvg.iconic.iconic-sm:not(.iconic-size-md):not(.iconic-size-lg), svg.iconic.iconic-size-sm{width:16px;height:16px;}\nsvg.iconic.iconic-md:not(.iconic-size-sm):not(.iconic-size-lg), svg.iconic.iconic-size-md{width:32px;height:32px;}\nsvg.iconic.iconic-lg:not(.iconic-size-sm):not(.iconic-size-md), svg.iconic.iconic-size-lg{width:128px;height:128px;}\nsvg.iconic-sm > g.iconic-md, svg.iconic-sm > g.iconic-lg, svg.iconic-md > g.iconic-sm, svg.iconic-md > g.iconic-lg, svg.iconic-lg > g.iconic-sm, svg.iconic-lg > g.iconic-md {display: none;}\nsvg.iconic.iconic-icon-sm > g.iconic-lg, svg.iconic.iconic-icon-md > g.iconic-lg {display:none;}\nsvg.iconic-sm:not(.iconic-icon-md):not(.iconic-icon-lg) > g.iconic-sm, svg.iconic-md.iconic-icon-sm > g.iconic-sm, svg.iconic-lg.iconic-icon-sm > g.iconic-sm {display:inline;}\nsvg.iconic-md:not(.iconic-icon-sm):not(.iconic-icon-lg) > g.iconic-md, svg.iconic-sm.iconic-icon-md > g.iconic-md, svg.iconic-lg.iconic-icon-md > g.iconic-md {display:inline;}\nsvg.iconic-lg:not(.iconic-icon-sm):not(.iconic-icon-md) > g.iconic-lg, svg.iconic-sm.iconic-icon-lg > g.iconic-lg, svg.iconic-md.iconic-icon-lg > g.iconic-lg {display:inline;}";navigator&&navigator.userAgent&&/MSIE 10\.0/.test(navigator.userAgent)&&(a+="svg.iconic{zoom:1.0001;}");var b=document.createElement("style");b.id="iconic-responsive-css",b.type="text/css",b.styleSheet?b.styleSheet.cssText=a:b.appendChild(document.createTextNode(a)),(document.head||document.getElementsByTagName("head")[0]).appendChild(b)},g=function(a){if(/iconic-fluid/.test(a.getAttribute("class"))){var b,d=e(a),f=a.viewBox.baseVal.width/a.viewBox.baseVal.height;b=1===f?Math.min(d.width,d.height):1>f?d.width:d.height;var g;g=32>b?"iconic-sm":b>=32&&128>b?"iconic-md":"iconic-lg";var h=a.getAttribute("class"),i=c.test(h)?h.replace(c,g):h+" "+g;a.setAttribute("class",i)}},h=function(){var a=document.querySelectorAll(".injected-svg.iconic-fluid");Array.prototype.forEach.call(a,function(a){g(a)})};document.addEventListener("DOMContentLoaded",function(){f()}),window.addEventListener("resize",function(){h()}),b.exports={refresh:g,refreshAll:h}},{}],8:[function(b,c,d){!function(b,e){"use strict";function f(a){a=a.split(" ");for(var b={},c=a.length,d=[];c--;)b.hasOwnProperty(a[c])||(b[a[c]]=1,d.unshift(a[c]));return d.join(" ")}var g="file:"===b.location.protocol,h=e.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),i=Array.prototype.forEach||function(a,b){if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)},j={},k=0,l=[],m=[],n={},o=function(a){return a.cloneNode(!0)},p=function(a,b){m[a]=m[a]||[],m[a].push(b)},q=function(a){for(var b=0,c=m[a].length;c>b;b++)!function(b){setTimeout(function(){m[a][b](o(j[a]))},0)}(b)},r=function(a,c){if(void 0!==j[a])j[a]instanceof SVGSVGElement?c(o(j[a])):p(a,c);else{if(!b.XMLHttpRequest)return c("Browser does not support XMLHttpRequest"),!1;j[a]={},p(a,c);var d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState){if(404===d.status||null===d.responseXML)return c("Unable to load SVG file: "+a),g&&c("Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver."),c(),!1;if(!(200===d.status||g&&0===d.status))return c("There was a problem injecting the SVG: "+d.status+" "+d.statusText),!1;if(d.responseXML instanceof Document)j[a]=d.responseXML.documentElement;else if(DOMParser&&DOMParser instanceof Function){var b;try{var e=new DOMParser;b=e.parseFromString(d.responseText,"text/xml")}catch(f){b=void 0}if(!b||b.getElementsByTagName("parsererror").length)return c("Unable to parse SVG file: "+a),!1;j[a]=b.documentElement}q(a)}},d.open("GET",a),d.overrideMimeType&&d.overrideMimeType("text/xml"),d.send()}},s=function(a,c,d,e){var g=a.getAttribute("data-src")||a.getAttribute("src");if(!/svg$/i.test(g))return e("Attempted to inject a file with a non-svg extension: "+g),void 0;if(!h){var j=a.getAttribute("data-fallback")||a.getAttribute("data-png");return j?(a.setAttribute("src",j),e(null)):d?(a.setAttribute("src",d+"/"+g.split("/").pop().replace(".svg",".png")),e(null)):e("This browser does not support SVG and no PNG fallback was defined."),void 0}-1===l.indexOf(a)&&(l.push(a),a.setAttribute("src",""),r(g,function(d){if("undefined"==typeof d||"string"==typeof d)return e(d),!1;var h=a.getAttribute("id");h&&d.setAttribute("id",h);var j=a.getAttribute("title");j&&d.setAttribute("title",j);var m=[].concat(d.getAttribute("class")||[],"injected-svg",a.getAttribute("class")||[]).join(" ");d.setAttribute("class",f(m));var o=a.getAttribute("style");o&&d.setAttribute("style",o);var p=[].filter.call(a.attributes,function(a){return/^data-\w[\w\-]*$/.test(a.name)});i.call(p,function(a){a.name&&a.value&&d.setAttribute(a.name,a.value)});for(var q,r=d.querySelectorAll("defs clipPath[id]"),s=0,t=r.length;t>s;s++){q=r[s].id+"-"+k;for(var u=d.querySelectorAll('[clip-path*="'+r[s].id+'"]'),v=0,w=u.length;w>v;v++)u[v].setAttribute("clip-path","url(#"+q+")");r[s].id=q}d.removeAttribute("xmlns:a");for(var x,y,z=d.querySelectorAll("script"),A=[],B=0,C=z.length;C>B;B++)y=z[B].getAttribute("type"),y&&"application/ecmascript"!==y&&"application/javascript"!==y||(x=z[B].innerText||z[B].textContent,A.push(x),d.removeChild(z[B]));if(A.length>0&&("always"===c||"once"===c&&!n[g])){for(var D=0,E=A.length;E>D;D++)new Function(A[D])(b);n[g]=!0}a.parentNode.replaceChild(d,a),delete l[l.indexOf(a)],a=null,k++,e(d)}))},t=function(a,b,c){b=b||{};var d=b.evalScripts||"always",e=b.pngFallback||!1,f=b.each;if(void 0!==a.length){var g=0;i.call(a,function(b){s(b,d,e,function(b){f&&"function"==typeof f&&f(b),c&&a.length===++g&&c(g)})})}else a?s(a,d,e,function(b){f&&"function"==typeof f&&f(b),c&&c(1),a=null}):c&&c(0)};"object"==typeof c&&"object"==typeof c.exports?c.exports=d=t:"function"==typeof a&&a.amd?a(function(){return t}):"object"==typeof b&&(b.SVGInjector=t)}(window,document)},{}]},{},[1])(1)}); \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/scss/_global.scss b/afb-client/bower_components/foundation-apps/scss/_global.scss
new file mode 100755
index 0000000..e4cffc6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/_global.scss
@@ -0,0 +1,131 @@
+/*
+ GLOBAL
+ ------
+
+ Global styles and settings for Foundation for Apps are stored here. This file must always
+ be imported, no matter what.
+
+ Includes:
+ -
+*/
+
+/// @Foundation.settings
+// Global Styles
+// This sets 1rem to be 16px
+$rem-base: 16px;
+
+// The default font-size is set to 100% of the browser style sheet (usually 16px)
+// for compatibility with browser-based text zoom or user-set defaults.
+
+// Since the typical default browser font-size is 16px, that makes the calculation for grid size.
+// If you want your base font-size to be different and not have it affect the grid breakpoints,
+// set $rem-base to $base-font-size and make sure $base-font-size is a px value.
+$base-font-size: 100% !default;
+
+// $base-line-height is 24px while $base-font-size is 16px
+$base-line-height: 1.5 !default;
+
+// Text selector helpers
+$headers: "h1,h2,h3,h4,h5,h6";
+
+// We use these to define default font weights
+$font-weight-normal: normal !default;
+$font-weight-bold: bold !default;
+
+// We use these to control various global styles
+$body-background: #fff !default;
+$body-font-color: #222 !default;
+$body-font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif !default;
+$body-font-weight: $font-weight-normal !default;
+$body-font-style: normal !default;
+$body-antialiased: true;
+
+// Application Colors
+$primary-color: #00558b !default;
+$secondary-color: #f1f1f1 !default;
+$alert-color: #F04124 !default;
+$info-color: #A0D3E8 !default;
+$success-color: #43AC6A !default;
+$warning-color: #F08A24 !default;
+$dark-color: #232323 !default;
+$gray: #dfdfdf !default;
+$gray-dark: darken($gray, 8) !default;
+$gray-light: lighten($gray, 8) !default;
+
+// We use these to make sure border radius matches unless we want it different.
+$global-radius: 4px !default;
+$global-rounded: 1000px !default;
+
+// We use this for default spacing
+$global-padding: 1rem !default;
+$global-spacing: rem-calc(15) !default;
+///
+
+// For internal use: a color map
+$foundation-colors: (
+ primary: $primary-color,
+ success: $success-color,
+ warning: $warning-color,
+ alert: $alert-color,
+ dark: $dark-color,
+);
+
+@include exports(global) {
+ // Make extra sure we're using the whole window
+ html, body {
+ height: 100%;
+ font-size: $base-font-size;
+ }
+ // Set box-sizing globally to handle padding and border widths
+ html {
+ box-sizing: border-box;
+ }
+ *, *:before, *:after {
+ box-sizing: inherit;
+ }
+
+ // Default body styles
+ body {
+ background: $body-background;
+ color: $body-font-color;
+ padding: 0;
+ margin: 0;
+ font-family: $body-font-family;
+ font-weight: $body-font-weight;
+ font-style: $body-font-style;
+ line-height: 1;
+ position: relative;
+
+ @if $body-antialiased {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ }
+
+ img {
+ // Grid Defaults to get images and embeds to work properly
+ max-width: 100%;
+ height: auto;
+ -ms-interpolation-mode: bicubic;
+
+ // Get rid of gap under images by making them display: inline-block; by default
+ display: inline-block;
+ vertical-align: middle;
+ }
+
+ // Give all anchors and interactive directives the hover cusor
+ a, [ui-sref], [zf-open], [zf-close], [zf-toggle] {
+ cursor: pointer;
+ }
+
+ #map_canvas,
+ .map_canvas {
+ img,
+ embed,
+ object { max-width: none !important; }
+ }
+
+ .padding {
+ padding: $global-padding;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/_settings.scss b/afb-client/bower_components/foundation-apps/scss/_settings.scss
new file mode 100644
index 0000000..7374cbc
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/_settings.scss
@@ -0,0 +1,614 @@
+// FOUNDATION FOR APPS SETTINGS
+// ----------------------------
+//
+// Table of Contents:
+//
+// 1. CSS Exports
+// 2. Global Styles
+// 3. Breakpoints
+// 4. Typography
+// 5. Grid
+// 6. Button
+// 7. Accordion
+// 8. Action Sheet
+// 9. Block List
+// 10. Button Group
+// 11. Card
+// 12. Extras
+// 13. Forms
+// 14. Iconic
+// 15. Label
+// 16. Menu Bar
+// 17. Modal
+// 18. Motion UI
+// 19. Notification
+// 20. Off-canvas
+// 21. Panel
+// 22. Popup
+// 23. Switch
+// 24. Tabs
+// 25. Title Bar
+
+@import "helpers/functions";
+
+// 1. CSS Exports
+// - - - - - - - - - - - - - - -
+
+// Change any value in this map from "true" to "false" to disable that component's CSS class output. You'll still be able to use the component's mixins, but none of our pre-written classes will be in your CSS.
+
+// $include-css: (
+// accordion: true,
+// action-sheet: true,
+// block-list: true,
+// button: true,
+// button-group: true,
+// card: true,
+// coloring: true,
+// extras: true,
+// forms: true,
+// grid: true,
+// iconic: true,
+// label: true,
+// badge: true,
+// list: true,
+// menu-bar: true,
+// modal: true,
+// motion: true,
+// notification: true,
+// off-canvas: true,
+// panel: true,
+// popup: true,
+// switch: true,
+// tabs: true,
+// title-bar: true,
+// typography: true,
+// utilities: true,
+// );
+
+// 2. Global Styles
+// - - - - - - - - - - - - - - -
+
+// This sets 1rem to be 16px
+// $rem-base: 16px;
+
+// The default font-size is set to 100% of the browser style sheet (usually 16px)
+// for compatibility with browser-based text zoom or user-set defaults.
+
+// Since the typical default browser font-size is 16px, that makes the calculation for grid size.
+// If you want your base font-size to be different and not have it affect the grid breakpoints,
+// set $rem-base to $base-font-size and make sure $base-font-size is a px value.
+// $base-font-size: 100%;
+
+// $base-line-height is 24px while $base-font-size is 16px
+// $base-line-height: 1.5;
+
+// Text selector helpers
+// $headers: "h1,h2,h3,h4,h5,h6";
+
+// We use these to define default font weights
+// $font-weight-normal: normal;
+// $font-weight-bold: bold;
+
+// We use these to control various global styles
+// $body-background: #fff;
+// $body-font-color: #222;
+// $body-font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+// $body-font-weight: $font-weight-normal;
+// $body-font-style: normal;
+// $body-antialiased: true;
+
+// Application Colors
+// $primary-color: #00558b;
+// $secondary-color: #f1f1f1;
+// $alert-color: #F04124;
+// $info-color: #A0D3E8;
+// $success-color: #43AC6A;
+// $warning-color: #F08A24;
+// $dark-color: #232323;
+// $gray: #dfdfdf;
+// $gray-dark: darken($gray, 8);
+// $gray-light: lighten($gray, 8);
+
+// We use these to make sure border radius matches unless we want it different.
+// $global-radius: 4px;
+// $global-rounded: 1000px;
+
+// We use this for default spacing
+// $global-padding: 1rem;
+// $global-spacing: rem-calc(15);
+
+// 3. Breakpoints
+// - - - - - - - - - - - - - - -
+
+// These are our named breakpoints. You can use them in our breakpoint function like this: @include breakpoint(medium) { // Medium and larger styles }
+// $breakpoints: (
+// small: rem-calc(0),
+// medium: rem-calc(640),
+// large: rem-calc(1200),
+// xlarge: rem-calc(1440),
+// xxlarge: rem-calc(1920),
+// );
+
+// All of the names in this list will be output as classes in your CSS, like small-12, medium-6, and so on.
+// $breakpoint-classes: (small medium large);
+
+// 4. Typography
+// - - - - - - - - - - - - - - -
+
+// We use these to control header font styles
+// $header-font-family: $body-font-family;
+// $header-font-weight: $font-weight-normal;
+// $header-font-style: $font-weight-normal;
+// $header-font-color: #222;
+// $header-line-height: 1.4;
+// $header-top-margin: .2rem;
+// $header-bottom-margin: .5rem;
+// $header-text-rendering: optimizeLegibility;
+
+// We use these to control header font sizes
+// $h1-font-size: rem-calc(44);
+// $h2-font-size: rem-calc(37);
+// $h3-font-size: rem-calc(27);
+// $h4-font-size: rem-calc(23);
+// $h5-font-size: rem-calc(18);
+// $h6-font-size: 1rem;
+
+// We use these to control header size reduction on small screens
+// $h1-font-reduction: rem-calc(10);
+// $h2-font-reduction: rem-calc(10);
+// $h3-font-reduction: rem-calc(5);
+// $h4-font-reduction: rem-calc(5);
+// $h5-font-reduction: 0;
+// $h6-font-reduction: 0;
+
+// These control how subheaders are styled.
+// $subheader-line-height: 1.4;
+// $subheader-font-color: scale-color($header-font-color, $lightness: 35%);
+// $subheader-font-weight: $font-weight-normal;
+// $subheader-top-margin: .2rem;
+// $subheader-bottom-margin: .5rem;
+
+// A general <small> styling
+// $small-font-size: 60%;
+// $small-font-color: scale-color($header-font-color, $lightness: 35%);
+
+// We use these to style paragraphs
+// $paragraph-font-family: inherit;
+// $paragraph-font-weight: $font-weight-normal;
+// $paragraph-font-size: 1rem;
+// $paragraph-line-height: 1.6;
+// $paragraph-margin-bottom: rem-calc(20);
+// $paragraph-aside-font-size: rem-calc(14);
+// $paragraph-aside-line-height: 1.35;
+// $paragraph-aside-font-style: italic;
+// $paragraph-text-rendering: optimizeLegibility;
+
+// We use these to style <code> tags
+// $code-color: grayscale($primary-color);
+// $code-font-family: Consolas, 'Liberation Mono', Courier, monospace;
+// $code-font-weight: $font-weight-normal;
+// $code-background-color: scale-color($secondary-color, $lightness: 70%);
+// $code-border-size: 1px;
+// $code-border-style: solid;
+// $code-border-color: scale-color($code-background-color, $lightness: -10%);
+// $code-padding: rem-calc(2) rem-calc(5) rem-calc(1);
+
+// We use these to style anchors
+// $anchor-text-decoration: none;
+// $anchor-text-decoration-hover: none;
+// $anchor-font-color: $primary-color;
+// $anchor-font-color-hover: scale-color($anchor-font-color, $lightness: -14%);
+
+// We use these to style the <hr> element
+// $hr-border-width: 1px;
+// $hr-border-style: solid;
+// $hr-border-color: #ddd;
+// $hr-margin: rem-calc(20);
+
+// We use these to style lists
+// $list-font-family: $paragraph-font-family;
+// $list-font-size: $paragraph-font-size;
+// $list-line-height: $paragraph-line-height;
+// $list-margin-bottom: $paragraph-margin-bottom;
+// $list-style-position: outside;
+// $list-side-margin: 1.1rem;
+// $list-ordered-side-margin: 1.4rem;
+// $list-side-margin-no-bullet: 0;
+// $list-nested-margin: rem-calc(20);
+// $definition-list-header-weight: $font-weight-bold;
+// $definition-list-header-margin-bottom: .3rem;
+// $definition-list-margin-bottom: rem-calc(12);
+
+// We use these to style blockquotes
+// $blockquote-font-color: scale-color($header-font-color, $lightness: 35%);
+// $blockquote-padding: rem-calc(9 20 0 19);
+// $blockquote-border: 1px solid #ddd;
+// $blockquote-cite-font-size: rem-calc(13);
+// $blockquote-cite-font-color: scale-color($header-font-color, $lightness: 23%);
+// $blockquote-cite-link-color: $blockquote-cite-font-color;
+
+// Acronym styles
+// $acronym-underline: 1px dotted #ddd;
+
+// 5. Grid
+// - - - - - - - - - - - - - - -
+
+// $container-width: rem-calc(900);
+// $block-padding: $global-padding;
+// $total-columns: 12;
+// $block-grid-max-size: 6;
+
+// 6. Button
+// - - - - - - - - - - - - - - -
+
+// $button-padding: 0.85em 1em;
+// $button-margin: 0 $global-padding $global-padding 0;
+// $button-style: solid;
+// $button-background: $primary-color;
+// $button-background-hover: scale-color($button-background, $lightness: -15%);
+// $button-color: auto;
+// $button-radius: 0;
+// $button-sizes: (
+// tiny: 0.7,
+// small: 0.8,
+// medium: 1,
+// large: 1.3,
+// );
+// $button-font-size: 0.9rem;
+// $button-opacity-disabled: 0.5;
+// $button-tag-selector: false;
+
+// 7. Accordion
+// - - - - - - - - - - - - - - -
+
+// $accordion-border: 1px solid $gray-dark;
+
+// $accordion-title-background: $gray-light;
+// $accordion-title-background-hover: smartscale($accordion-title-background, 5%);
+// $accordion-title-background-active: smartscale($accordion-title-background, 3%);
+// $accordion-title-color: isitlight($accordion-title-background);
+// $accordion-title-color-active: isitlight($accordion-title-background);
+
+// $accordion-title-padding: $global-padding;
+// $accordion-content-padding: $global-padding;
+
+// 8. Action Sheet
+// - - - - - - - - - - - - - - -
+
+// $actionsheet-background: white;
+// $actionsheet-border-color: #ccc;
+// $actionsheet-animate: transform opacity;
+// $actionsheet-animation-speed: 0.25s;
+// $actionsheet-width: 300px;
+// $actionsheet-radius: 4px;
+// $actionsheet-shadow: 0 -3px 10px rgba(black, 0.25);
+// $actionsheet-padding: $global-padding;
+// $actionsheet-tail-size: 10px;
+
+// $actionsheet-popup-shadow: 0 0 10px rgba(black, 0.25);
+
+// $actionsheet-link-color: #000;
+// $actionsheet-link-background-hover: smartscale($actionsheet-background);
+
+// 9. Block List
+// - - - - - - - - - - - - - - -
+
+// $blocklist-background: #fff;
+// $blocklist-fullbleed: true;
+// $blocklist-fontsize: 1rem;
+
+// $blocklist-item-padding: 0.8rem 1rem;
+// $blocklist-item-color: isitlight($blocklist-background, #000, #fff);
+// $blocklist-item-background-hover: smartscale($blocklist-background, 4.5%);
+// $blocklist-item-color-disabled: #999;
+// $blocklist-item-border: 1px solid smartscale($blocklist-background, 18.5%);
+
+// $blocklist-item-label-color: scale-color($blocklist-item-color, $lightness: 60%);
+// $blocklist-item-icon-size: 0.8;
+
+// $blocklist-header-fontsize: 0.8em;
+// $blocklist-header-color: smartscale($blocklist-item-color, 40%);
+// $blocklist-header-uppercase: true;
+
+// $blocklist-check-icons: true;
+
+// 10. Button Group
+// - - - - - - - - - - - - - - -
+
+// $btngroup-background: $primary-color;
+// $btngroup-color: #fff;
+// $btngroup-radius: $button-radius;
+
+// 11. Card
+// - - - - - - - - - - - - - - -
+
+// $card-background: #fff;
+// $card-color: isitlight($card-background);
+// $card-border: 1px solid smartscale($card-background, 7%);
+// $card-radius: $global-radius;
+// $card-shadow: 0 1px 2px rgba(#000, 0.2);
+// $card-padding: $global-padding;
+// $card-margin: 0.5rem;
+
+// $card-divider-background: smartscale($card-background, 7%);
+
+// 12. Extras
+// - - - - - - - - - - - - - - -
+
+// $closebutton-position: (top right);
+// $closebutton-size: 2em;
+// $closebutton-lineheight: 0.5;
+// $closebutton-color: #999;
+// $closebutton-color-hover: #333;
+
+// $thumbnail-padding: 0.5rem;
+// $thumbnail-shadow: 0 3px 15px rgba(black, 0.25);
+
+// 13. Forms
+// - - - - - - - - - - - - - - -
+
+// Basic form variables
+// $form-fontsize: 1rem;
+// $form-padding: 0.5rem;
+
+// Text fields
+// $input-color: #000;
+// $input-color-hover: $input-color;
+// $input-color-focus: $input-color;
+// $input-background: #fff;
+// $input-background-hover: $input-background;
+// $input-background-focus: $input-background;
+// $input-background-disabled: smartscale($input-background);
+// $input-border: 1px solid #ccc;
+// $input-border-hover: 1px solid #bbb;
+// $input-border-focus: 1px solid #999;
+// $input-cursor-disabled: not-allowed;
+
+// Select menus
+// $select-color: #000;
+// $select-background: #fafafa;
+// $select-background-hover: smartscale($select-background, 4%);
+// $select-arrow: true;
+// $select-arrow-color: $select-color;
+
+// Labels
+// $form-label-fontsize: 0.9rem;
+// $form-label-margin: 0.5rem;
+// $form-label-color: #333;
+
+// Inline labels
+// $inlinelabel-color: #333;
+// $inlinelabel-background: #eee;
+// $inlinelabel-border: $input-border;
+
+// Range slider
+// $slider-background: #ddd;
+// $slider-height: 1rem;
+// $slider-radius: 0px;
+// $slider-thumb-height: 1.5rem;
+// $slider-thumb-color: $primary-color;
+// $slider-thumb-radius: 0px;
+
+// Progress and meter
+// $meter-height: 1.5rem;
+// $meter-background: #ccc;
+// $meter-fill: $primary-color;
+// $meter-fill-high: $success-color;
+// $meter-fill-medium: #e7cf00;
+// $meter-fill-low: $alert-color;
+// $meter-radius: 0;
+
+// 14. Iconic
+// - - - - - - - - - - - - - - -
+
+// $iconic-primary-fill: $primary-color;
+// $iconic-primary-stroke: $primary-color;
+// $iconic-accent-fill: $iconic-primary-fill;
+// $iconic-accent-stroke: $iconic-accent-fill;
+
+// 15. Label
+// - - - - - - - - - - - - - - -
+
+// $label-fontsize: 0.8rem;
+// $label-padding: ($global-padding / 3) ($global-padding / 2);
+// $label-radius: 0;
+// $label-background: $primary-color;
+// $label-color: isitlight($primary-color);
+
+// $badge-fontsize: 0.8em;
+// $badge-diameter: 1.5rem;
+// $badge-background: $primary-color;
+// $badge-color: #fff;
+
+// 16. Menu Bar
+// - - - - - - - - - - - - - - -
+
+// $menubar-fontsize: 1rem;
+// $menubar-background: #fff;
+// $menubar-background-hover: smartscale($menubar-background, 7%);
+// $menubar-background-active: $menubar-background-hover;
+// $menubar-color: isitlight($menubar-background);
+// $menubar-color-hover: $menubar-color;
+// $menubar-color-active: $menubar-color-hover;
+
+// $menubar-item-padding: $global-padding;
+// $menubar-icon-size: 25px;
+// $menubar-icon-spacing: $menubar-item-padding;
+
+// 17. Modal
+// - - - - - - - - - - - - - - -
+
+// $modal-background: #fff;
+// $modal-border: 0;
+// $modal-radius: 0px;
+// $modal-shadow: none;
+// $modal-zindex: 1000;
+// $modal-sizes: (
+// tiny: 300px,
+// small: 500px,
+// medium: 600px,
+// large: 800px,
+// );
+
+// $modal-overlay-class: 'modal-overlay';
+// $modal-overlay-background: rgba(#333, 0.7);
+
+// 18. Motion UI
+// - - - - - - - - - - - - - - -
+
+// Classes to use when triggering in/out animations
+// $motion-class: (
+// in: "ng-enter",
+// out: "ng-leave",
+// );
+// $motion-class-active: (
+// in: "ng-enter-active",
+// out: "ng-leave-active",
+// );
+// $motion-class-stagger: (
+// in: "ng-enter-stagger",
+// out: "ng-leave-stagger",
+// );
+// $motion-class-showhide: (
+// in: "ng-hide-remove",
+// out: "ng-hide-add",
+// );
+// $motion-class-showhide-active: (
+// in: "ng-hide-remove-active",
+// out: "ng-hide-add-active",
+// );
+
+// Set if movement-based transitions should also fade the element in and out
+// $motion-slide-and-fade: false;
+// $motion-hinge-and-fade: true;
+// $motion-scale-and-fade: true;
+// $motion-spin-and-fade: true;
+
+// Default speed for transitions and animations
+// $motion-duration-default: 500ms;
+
+// Slow and fast modifiders
+// $motion-duration-slow: 750ms;
+// $motion-duration-fast: 250ms;
+// $motion-stagger-duration-default: 150ms;
+// $motion-stagger-duration-short: 50ms;
+// $motion-stagger-duration-long: 300ms;
+
+// Default timing function for transitions and animations
+// $motion-timing-default: ease;
+
+// Built-in and custom easing functions
+// Every item in this map becomes a CSS class
+// $motion-timings: (
+// linear: linear,
+// ease: ease,
+// easeIn: ease-in,
+// easeOut: ease-out,
+// easeInOut: ease-in-out,
+// bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245),
+// bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845),
+// bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245),
+// );
+
+// Default delay for all transitions and animations
+// $motion-delay-default: 0;
+// Short and long delay modifiers
+// $motion-delay-short: 300ms;
+// $motion-delay-long: 700ms;
+
+// 19. Notification
+// - - - - - - - - - - - - - - -
+
+// $notification-default-position: right top;
+// $notification-width: rem-calc(400);
+// $notification-offset: $global-padding;
+
+// $notification-background: $primary-color;
+// $notification-color: white;
+// $notification-padding: $global-padding;
+// $notification-radius: 4px;
+
+// $notification-icon-size: 60px;
+// $notification-icon-margin: $global-padding;
+// $notification-icon-align: top;
+
+
+// 20. Off-canvas
+// - - - - - - - - - - - - - - -
+
+// $offcanvas-size-horizontal: 250px;
+// $offcanvas-size-vertical: 250px;
+
+// $offcanvas-background: #fff;
+// $offcanvas-color: isitlight($offcanvas-background);
+// $offcanvas-padding: 0;
+// $offcanvas-shadow: 3px 0 10px rgba(black, 0.25);
+// $offcanvas-animation-speed: 0.25s;
+
+// $offcanvas-frame-selector: '.grid-frame';
+
+// 21. Panel
+// - - - - - - - - - - - - - - -
+
+// $panel-size-horizontal: 300px;
+// $panel-size-vertical: 300px;
+// $panel-padding: 0;
+
+// $panel-background: #fff;
+// $panel-shadow: 3px 0 10px rgba(black, 0.25);
+
+// DEPRECATED: these variables will be removed in a future version.
+// $panel-animation-speed: 0.25s;
+
+// 22. Popup
+// - - - - - - - - - - - - - - -
+
+// $popup-width: rem-calc(300);
+// $popup-background: #fff;
+// $popup-border: 0;
+// $popup-radius: 0;
+// $popup-shadow: 0 0 10px rgba(#000, 0.25);
+
+// 23. Switch
+// - - - - - - - - - - - - - - -
+
+// $switch-width: rem-calc(50);
+// $switch-height: rem-calc(32);
+// $switch-background: #ccc;
+// $switch-background-active: $primary-color;
+// $switch-border: 0;
+// $switch-radius: 9999px;
+// $switch-animation-speed: 0.15s;
+
+// $switch-paddle-color: white;
+// $switch-paddle-offset: 4px;
+
+// 24. Tabs
+// - - - - - - - - - - - - - - -
+
+// $tabstrip-background: transparent;
+
+// $tab-title-background: $gray-light;
+// $tab-title-background-hover: smartscale($tab-title-background, 5%);
+// $tab-title-background-active: smartscale($tab-title-background, 3%);
+// $tab-title-color: isitlight($tab-title-background);
+// $tab-title-color-active: $tab-title-color;
+
+// $tab-title-padding: $global-padding;
+// $tab-content-padding: $global-padding;
+
+// 25. Title Bar
+// - - - - - - - - - - - - - - -
+
+// $titlebar-center-width: 50%;
+// $titlebar-side-width: (100% - $titlebar-center-width) / 2;
+// $titlebar-background: #eee;
+// $titlebar-color: #000;
+// $titlebar-border: 1px solid #ccc;
+// $titlebar-padding: $global-padding;
+// $titlebar-item-classes: (
+// center: 'center',
+// left: 'left',
+// right: 'right',
+// title: 'title',
+// );
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_accordion.scss b/afb-client/bower_components/foundation-apps/scss/components/_accordion.scss
new file mode 100644
index 0000000..d330f47
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_accordion.scss
@@ -0,0 +1,72 @@
+/*
+ ACCORDION
+ ---------
+
+ The trusy accordion allows you to create a series of vertical tabs.
+*/
+
+/// @Foundation.settings
+// Accordion
+$accordion-border: 1px solid $gray-dark !default;
+
+$accordion-title-background: $gray-light !default;
+$accordion-title-background-hover: smartscale($accordion-title-background, 5%) !default;
+$accordion-title-background-active: smartscale($accordion-title-background, 3%) !default;
+$accordion-title-color: isitlight($accordion-title-background) !default;
+$accordion-title-color-active: isitlight($accordion-title-background) !default;
+
+$accordion-title-padding: $global-padding !default;
+$accordion-content-padding: $global-padding !default;
+///
+
+@mixin accordion-title(
+ $background: $accordion-title-background,
+ $background-hover: $accordion-title-background-hover,
+ $background-active: $accordion-title-background-active,
+ $color: $accordion-title-color,
+ $color-active: $accordion-title-color-active,
+ $padding: $accordion-title-padding
+) {
+ padding: $padding;
+ background: $background;
+ color: $color;
+ line-height: 1;
+ cursor: pointer;
+
+ &:hover {
+ background: $background-hover;
+ }
+
+ .is-active > & {
+ background: $background-active;
+ color: $color-active;
+ }
+}
+
+@mixin accordion-content(
+ $padding: $accordion-content-padding
+) {
+ padding: $padding;
+
+ display: none;
+ .is-active > & {
+ display: block;
+ }
+}
+
+@include exports(accordion) {
+ .accordion {
+ @if hasvalue($accordion-border) {
+ border: $accordion-border;
+ }
+ }
+ .accordion-item {
+
+ }
+ .accordion-title {
+ @include accordion-title;
+ }
+ .accordion-content {
+ @include accordion-content;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_action-sheet.scss b/afb-client/bower_components/foundation-apps/scss/components/_action-sheet.scss
new file mode 100644
index 0000000..28b945c
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_action-sheet.scss
@@ -0,0 +1,265 @@
+/*
+ ACTION SHEET
+ ------------
+
+ A dropdown menu that sticks to the bottom of the screen on small devices, and becomes a dropdown menu on larger devices.
+*/
+
+/// @Foundation.settings
+// Action Sheet
+$actionsheet-background: white !default;
+$actionsheet-border-color: #ccc !default;
+$actionsheet-animate: transform opacity !default;
+$actionsheet-animation-speed: 0.25s !default;
+$actionsheet-width: 300px !default;
+$actionsheet-radius: 4px !default;
+$actionsheet-shadow: 0 -3px 10px rgba(black, 0.25) !default;
+$actionsheet-padding: $global-padding !default;
+$actionsheet-tail-size: 10px !default;
+
+$actionsheet-popup-shadow: 0 0 10px rgba(black, 0.25) !default;
+
+$actionsheet-link-color: #000 !default;
+$actionsheet-link-background-hover: smartscale($actionsheet-background) !default;
+///
+
+/*
+ Styles for the list inside an action sheet.
+ Don't include this mixin if you want to build custom controls inside the sheet.
+*/
+@mixin action-sheet-menu(
+ $padding: $actionsheet-padding,
+ $color: $actionsheet-link-color,
+ $border-color: $actionsheet-border-color,
+ $background-hover: $actionsheet-link-background-hover
+) {
+ // Menu container
+ ul {
+ margin: -($padding);
+ margin-top: 0;
+ list-style-type: none;
+ user-select: none;
+
+ // If the menu has no content above it
+ &:first-child {
+ margin-top: -$padding;
+
+ li:first-child {
+ border-top: 0;
+ }
+ }
+
+ // Menu links
+ a {
+ display: block;
+ padding: $padding * 0.8;
+ line-height: 1;
+ color: $color;
+ border-top: 1px solid $border-color;
+
+ &:hover {
+ color: $color;
+ background: $background-hover;
+ }
+ }
+
+ .alert > a {
+ color: $alert-color;
+ }
+ .disabled > a {
+ pointer-events: none;
+ color: #999;
+ }
+ }
+}
+
+/*
+ Styles for the action sheet container. Action sheets pin to the top or bottom of the screen.
+*/
+@mixin action-sheet(
+ $position: bottom,
+ $shadow: $actionsheet-shadow,
+ $animate: $actionsheet-animate,
+ $animation-speed: $actionsheet-animation-speed,
+ $padding: $actionsheet-padding,
+ $background: $actionsheet-background
+) {
+ position: fixed;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ padding: $padding;
+ background: $background;
+ text-align: center;
+ transition-property: $animate;
+ transition-duration: $animation-speed;
+ transition-timing-function: ease-out;
+
+ @if hasvalue($shadow) {
+ box-shadow: $shadow;
+ }
+
+ // Positions
+ @if $position == bottom {
+ bottom: 0;
+ transform: translateY(100%);
+
+ &.is-active {
+ transform: translateY(0%);
+ }
+ }
+ // These two don't quite work as planned yet
+ @else if $position == top {
+ top: 0;
+ transform: translateY(-100%);
+
+ &.is-active {
+ transform: translateY(0%);
+ }
+ }
+}
+
+@mixin popup-menu(
+ $position: bottom,
+ $background: $actionsheet-background,
+ $width: $actionsheet-width,
+ $radius: $actionsheet-radius,
+ $shadow: $actionsheet-popup-shadow,
+ $tail-size: $actionsheet-tail-size
+) {
+ /*
+ Core styles
+ */
+ position: absolute;
+ left: 50%;
+ width: $width;
+ border-radius: $radius;
+ opacity: 0;
+ pointer-events: none;
+
+ /*
+ Menu shadow
+ */
+ @if hasvalue($shadow) {
+ box-shadow: $shadow;
+ }
+
+ /*
+ Active state
+ */
+ &.is-active {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ /*
+ Menu tail
+ */
+ &::before, &::after {
+ content: '';
+ position: absolute;
+ left: 50%;
+ display: block;
+ width: 0px;
+ height: 0px;
+ border-left: $tail-size solid transparent;
+ border-right: $tail-size solid transparent;
+ margin-left: -($tail-size);
+ }
+
+ /*
+ Positioning
+ */
+ @if $position == bottom {
+ top: auto;
+ bottom: 0;
+ transform: translateX(-50%) translateY(110%);
+ &.is-active {
+ transform: translateX(-50%) translateY(100%);
+ }
+
+ &::before, &::after {
+ top: -($tail-size);
+ bottom: auto;
+ border-top: 0;
+ border-bottom: $tail-size solid $background;
+ }
+ &::before {
+ top: -($tail-size + 2);
+ border-bottom-color: rgba(black, 0.15);
+ }
+
+ }
+ @else if $position == top {
+ top: 0;
+ bottom: auto;
+ transform: translateX(-50%) translateY(-120%);
+ &.is-active {
+ transform: translateX(-50%) translateY(-110%);
+ }
+
+ &::before, &::after {
+ top: auto;
+ bottom: -($tail-size);
+ border-top: $tail-size solid $background;
+ border-bottom: 0;
+ }
+ &::before {
+ bottom: -($tail-size + 2);
+ border-top-color: rgba(black, 0.15);
+ }
+ }
+}
+
+@include exports(action-sheet) {
+ .action-sheet-container {
+ position: relative;
+ display: inline-block;
+
+ .button {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ }
+ .action-sheet {
+ @include action-sheet;
+ @include action-sheet-menu;
+
+ @include breakpoint(medium) {
+ @include popup-menu;
+
+ &.top {
+ @include popup-menu(top);
+ }
+ }
+
+ &.primary {
+ background: $primary-color;
+ color: isitlight($primary-color);
+ border: 0;
+ &::before { display: none; }
+ &::before, &::after { border-top-color: $primary-color; }
+ &.top::before, &.top::after { border-bottom-color: $primary-color; }
+
+ @include action-sheet-menu(
+ $color: isitlight($primary-color),
+ $border-color: smartscale($primary-color, 10%),
+ $background-hover: smartscale($primary-color)
+ );
+ }
+ &.dark {
+ background: $dark-color;
+ color: isitlight($dark-color);
+ border: 0;
+ &::before { display: none; }
+ &::before, &::after { border-top-color: $dark-color; }
+ &.top::before, &.top::after { border-bottom-color: $dark-color; }
+
+ @include action-sheet-menu(
+ $color: isitlight($dark-color),
+ $border-color: smartscale($dark-color, 10%),
+ $background-hover: smartscale($dark-color)
+ );
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_block-list.scss b/afb-client/bower_components/foundation-apps/scss/components/_block-list.scss
new file mode 100644
index 0000000..5b1cbe4
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_block-list.scss
@@ -0,0 +1,350 @@
+/*
+ BLOCK LIST
+ ----------
+
+ A generic list component that can accomodate a variety of styles and controls.
+
+ Features:
+ - Icons
+ - Labels
+ - Chevrons
+ - Text fields
+ - Dropdown menus
+ - Checkbox/radio inputs
+*/
+
+/// @Foundation.settings
+// Block List
+$blocklist-background: #fff !default;
+$blocklist-fullbleed: true !default;
+$blocklist-fontsize: 1rem !default;
+
+$blocklist-item-padding: 0.8rem 1rem !default;
+$blocklist-item-color: isitlight($blocklist-background, #000, #fff) !default;
+$blocklist-item-background-hover: smartscale($blocklist-background, 4.5%) !default;
+$blocklist-item-color-disabled: #999 !default;
+$blocklist-item-border: 1px solid smartscale($blocklist-background, 18.5%) !default;
+
+$blocklist-item-label-color: scale-color($blocklist-item-color, $lightness: 60%) !default;
+$blocklist-item-icon-size: 0.8 !default;
+
+$blocklist-header-fontsize: 0.8em !default;
+$blocklist-header-color: smartscale($blocklist-item-color, 40%) !default;
+$blocklist-header-uppercase: true;
+
+$blocklist-check-icons: true !default;
+///
+
+/*
+ Adds styles for a block list container.
+
+ $font-size: global font size for the list.
+ $full-bleed: when "true", the margins of the list invert to line it up with the edge of a padded element.
+*/
+%block-list-container {
+ margin-bottom: 1rem;
+ line-height: 1;
+ user-select: none;
+
+ &, ul {
+ list-style-type: none;
+ }
+ ul {
+ margin-left: 0;
+ }
+}
+@mixin block-list-container(
+ $font-size: $blocklist-fontsize,
+ $full-bleed: $blocklist-fullbleed
+) {
+ @extend %block-list-container;
+ font-size: $font-size;
+
+ @if $full-bleed {
+ margin-left: -$global-padding;
+ margin-right: -$global-padding;
+ }
+}
+
+/*
+ Styles block list headers on the selector you include this mixin in (normally a <header>).
+
+ $color - color of the header.
+ $font-size - font size of the header.
+ $offset - left margin to add to the header, to line it up with the list items.
+*/
+@mixin block-list-header(
+ $color: $blocklist-header-color,
+ $font-size: $blocklist-header-fontsize,
+ $uppercase: $blocklist-header-uppercase,
+ $offset: get-side($blocklist-item-padding, left)
+) {
+ margin-top: 1em;
+ color: $color;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ margin-left: $offset;
+ font-size: $font-size;
+ cursor: default;
+ @if $uppercase { text-transform: uppercase; }
+}
+
+/*
+ Styles block list items on the selector you include this mixin in (normally an <li>).
+
+ $color - color of items.
+ $color-hover - color of items on hover.
+ $background - background of items.
+ $background-hover - background of items on hover.
+ $border - border between items.
+ $padding - padding on items.
+*/
+@mixin block-list-item(
+ $color: $blocklist-item-color,
+ $color-hover: $blocklist-item-color,
+ $color-disabled: $blocklist-item-color-disabled,
+ $background: transparent,
+ $background-hover: $blocklist-item-background-hover,
+ $border: $blocklist-item-border,
+ $padding: $blocklist-item-padding
+) {
+ position: relative;
+
+ @if hasvalue($border) {
+ border-bottom: $border;
+ &:first-child {
+ border-top: $border;
+ }
+ }
+
+ // Inner elements share the same basic styles
+ > a, > span, > label {
+ display: block;
+ padding: $padding;
+ padding-left: get-side($padding, left);
+ color: $color;
+ line-height: 1;
+ }
+ > span {
+ cursor: default;
+ }
+ > a, > label {
+ cursor: pointer;
+
+ &:hover {
+ color: $color-hover;
+ }
+ }
+ > a, > label, select {
+ &:hover {
+ background: $background-hover;
+ }
+ }
+
+ // Coloring classes
+ &.caution > a {
+ &, &:hover { color: $alert-color; }
+ }
+ &.disabled > a {
+ cursor: default;
+ &, &:hover { color: $color-disabled; }
+ &:hover { background: transparent; }
+ }
+}
+
+/*
+ Adds label styles to the class you include this mixin in.
+
+ $color - color of the label.
+ $left-class - extra class to flip the orientation of the label.
+ $left-padding - left padding to use for left-hand labels.
+*/
+@mixin block-list-label(
+ $color: $blocklist-item-label-color,
+ $left-class: 'left',
+ $left-padding: get-side($blocklist-item-padding, top)
+) {
+ display: inline-block;
+ float: right;
+ padding: 0;
+ color: $color;
+ pointer-events: none;
+
+ &.#{$left-class} {
+ margin-left: $left-padding;
+ float: none;
+ }
+}
+
+/*
+ Adds support for chevrons, which appear on the right-hand side of the item.
+
+ $color - color of the chevron.
+ $padding - include the global padding of block list items here.
+*/
+@mixin block-list-chevron(
+ $color: $blocklist-header-color,
+ $padding: $blocklist-item-padding,
+ $label-class: 'block-list-label'
+) {
+ // Chevrons are a pseudo-element
+ &::after {
+ content: '\203A';
+ display: block;
+ position: absolute;
+ right: get-side($padding, right);
+ top: 50%;
+ transform: translateY(-50%);
+ font-weight: bold;
+ color: $color;
+ font-size: 2em;
+ }
+
+ // Labels next to links move over to make room for the chevron
+ // TODO: this selector needs to be customiable, but adding a setting just for it might be weird
+ .#{$label-class} {
+ padding-right: get-side($padding, right) * 1.5;
+ }
+}
+
+/*
+ Adds icon styles. Call this mixin on a block list container.
+
+ $size - size of the icon as a percentage (decimal) of the list item's height.
+ $item-selector - overrides the 'li' selector used for list items.
+*/
+@mixin block-list-icons(
+ $size: $blocklist-item-icon-size,
+ $item-selector: 'li'
+) {
+ // PH - need a better solution
+ $item-height:
+ $blocklist-fontsize
+ + get-side($blocklist-item-padding, top)
+ + get-side($blocklist-item-padding, top);
+
+ $icon-height: $item-height * $blocklist-item-icon-size;
+ $icon-offset: ($item-height - $icon-height) / 2;
+
+ #{$item-selector} {
+ > a, > span, > label {
+ padding-left: (get-side($blocklist-item-padding, left) * 2) + $blocklist-item-icon-size;
+ }
+ img, .iconic {
+ position: absolute;
+ top: $icon-offset;
+ left: $icon-offset;
+ width: $icon-height;
+ height: $icon-height;
+ border-radius: 8px;
+ pointer-events: none;
+ }
+ }
+}
+
+/*
+ Adds support for text fields, select menus, and checkbox/radio groups in block lists.
+
+ $color - color of select menu arrow.
+ $background-hover - color of select menu when hovered over.
+ $padding - include the global padding of block list items here.
+ $dropdown-class - class to use for list items that contain a dropdown.
+ $switch-class - class to use for switches inside list items.
+*/
+@mixin block-list-inputs(
+ $color: $blocklist-item-color,
+ $background: $blocklist-background,
+ $background-hover: $blocklist-item-background-hover,
+ $padding: $blocklist-item-padding,
+ $icons: $blocklist-check-icons,
+ $dropdown-class: 'with-dropdown',
+ $switch-class: 'switch'
+) {
+ // Text fields
+ #{$text-input-selectors} {
+ margin: 0;
+ border: 0;
+ line-height: 1;
+ height: auto;
+ padding: $padding;
+ color: inherit;
+
+ &:hover, &:focus {
+ border: 0;
+ }
+ }
+
+ // Multiple select
+ li > input[type="checkbox"], li > input[type="radio"] {
+ position: absolute;
+ left: -9999px;
+
+ & + label {
+ display: block;
+ font-size: $blocklist-fontsize;
+ margin: 0;
+ }
+
+ @if $icons == true {
+ &:checked + label {
+ &::before {
+ @include image-checkmark($color);
+ content: '';
+ background-size: 100% 100%;
+ width: 1.5em;
+ height: 1.5em;
+ color: $primary-color;
+ float: right;
+ pointer-events: none;
+ margin-top: -0.25em;
+ }
+ }
+ }
+ }
+
+ // Dropdowns
+ .#{$dropdown-class} {
+ color: inherit;
+
+ select {
+ // Reset pesky <select> styles
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ outline: 0;
+ background: 0;
+ border: 0;
+ height: auto;
+ padding: $padding;
+ margin: 0;
+ font-size: 1em; // Same size as its parent
+ line-height: 1;
+ color: inherit;
+ background-color: transparent;
+ }
+ }
+
+ // Switches
+ .#{$switch-class} {
+ position: absolute;
+ top: 50%;
+ right: get-side($padding, right);
+ transform: translateY(-50%);
+ }
+}
+
+@include exports(block-list) {
+ .block-list {
+ @include block-list-container;
+ @include block-list-inputs;
+
+ &.with-icons { @include block-list-icons; }
+ header { @include block-list-header; }
+
+ li {
+ @include block-list-item;
+
+ &.with-chevron { @include block-list-chevron; }
+ .block-list-label { @include block-list-label; }
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_button-group.scss b/afb-client/bower_components/foundation-apps/scss/components/_button-group.scss
new file mode 100644
index 0000000..8505c84
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_button-group.scss
@@ -0,0 +1,197 @@
+/// @Foundation.settings
+// Button Group
+$btngroup-background: $primary-color !default;
+$btngroup-color: #fff !default;
+$btngroup-radius: $button-radius !default;
+///
+
+$child-selectors: '> a, > label, > button';
+
+%button-group {
+ margin: 0;
+ margin-bottom: 1rem;
+ list-style-type: none;
+ display: inline-flex;
+ border-radius: $btngroup-radius;
+ overflow: hidden;
+ font-size: $button-font-size;
+
+ > li {
+ flex: 0 0 auto;
+
+ // Links become buttons
+ #{$child-selectors} {
+ @extend %button;
+ border-radius: 0;
+ font-size: inherit;
+ display: block;
+ margin: 0;
+ }
+ > input + label {
+ margin-left: 0;
+ }
+ // Add borders between items
+ &:not(:last-child) {
+ #{$child-selectors} {
+ border-right: 1px solid scale-color($btngroup-background, $lightness: -25%);
+ }
+ }
+ }
+
+ @if using(iconic) {
+ .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; // The icons are oddly misaligned
+ }
+ }
+}
+
+%button-group-segmented {
+ border: 1px solid $primary-color;
+ transition-property: background color;
+
+ > li {
+ // Hide the radio button
+ > input[type="radio"] {
+ position: absolute;
+ left: -9999px;
+ }
+ // This is the button
+ #{$child-selectors} {
+ margin-right: 0;
+ background: transparent;
+ }
+ }
+}
+
+@mixin button-group-size($size: medium, $expand: false) {
+ $size: $button-font-size * map-get($button-sizes, $size);
+ font-size: $size;
+
+ @if $expand {
+ @include button-group-expand;
+ }
+}
+@mixin button-group-expand($stretch: true) {
+ display: if($stretch, flex, inline-flex);
+
+ > li {
+ flex: if($stretch, 1, 0 0 auto);
+
+ #{$child-selectors} {
+ @if $stretch { @include button-expand; }
+ }
+ }
+}
+@mixin button-group-style(
+ $segmented: false,
+ $background: $primary-color,
+ $color: auto
+) {
+
+ @if not($segmented) {
+ > li {
+ #{$child-selectors} {
+ @include button-style($background, auto, $color);
+ border-color: scale-color($background, $lightness: -15%);
+ }
+ &.is-active {
+ #{$child-selectors} {
+ background: scale-color($background, $lightness: -15%);
+ }
+ }
+ }
+ }
+ @else {
+ @extend %button-group-segmented;
+ $hover-color: rgba($background, 0.25);
+ border-color: $background;
+
+ > li {
+ // This is the button
+ #{$child-selectors} {
+ border-color: $background;
+ color: $background;
+
+ // This is the button being hovered on
+ &:hover {
+ background: $hover-color;
+ color: $background;
+ }
+
+ @if using(iconic) {
+ .iconic { @include color-icon($background); }
+ }
+ }
+
+ // This is the button when it's active
+ &.is-active > a,
+ > input:checked + label {
+ &, &:hover {
+ background: $background;
+ color: isitlight($background);
+ }
+
+ @if using(iconic) {
+ .iconic { @include color-icon(isitlight($background)); }
+ }
+ }
+ }
+ }
+}
+
+@mixin button-group(
+ $segmented: false,
+ $expand: false,
+ $background: $primary-color,
+ $color: #fff
+) {
+ @extend %button-group;
+ @include button-group-expand($expand);
+ @include button-group-style($segmented, $background, $color);
+ border-radius: $btngroup-radius;
+}
+
+@include exports(button-group) {
+ .button-group {
+ @include button-group;
+
+ // Colors
+ &.secondary { @include button-group-style(false, $secondary-color); }
+ &.success { @include button-group-style(false, $success-color); }
+ &.warning { @include button-group-style(false, $warning-color); }
+ &.alert { @include button-group-style(false, $alert-color); }
+
+ // Individual colors
+ > li {
+ &.secondary { #{$child-selectors} { @include button-style($secondary-color, auto, $btngroup: true); } }
+ &.success { #{$child-selectors} { @include button-style($success-color, auto, $btngroup: true); } }
+ &.warning { #{$child-selectors} { @include button-style($warning-color, auto, $btngroup: true); } }
+ &.alert { #{$child-selectors} { @include button-style($alert-color, auto, $btngroup: true); } }
+ }
+
+ // Segmented
+ &.segmented { @include button-group-style(true);
+ &.secondary { @include button-group-style(true, $secondary-color); }
+ &.success { @include button-group-style(true, $success-color); }
+ &.warning { @include button-group-style(true, $warning-color); }
+ &.alert { @include button-group-style(true, $alert-color); }
+ }
+
+ // Sizing
+ &.tiny { @include button-group-size(tiny); }
+ &.small { @include button-group-size(small); }
+ &.large { @include button-group-size(large); }
+ &.expand { @include button-group-expand; }
+
+ // Disabled
+ li.disabled {
+ #{$child-selectors} {
+ @include button-disabled;
+ }
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_button.scss b/afb-client/bower_components/foundation-apps/scss/components/_button.scss
new file mode 100644
index 0000000..6e22b19
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_button.scss
@@ -0,0 +1,205 @@
+/// @Foundation.settings
+// Button
+$button-padding: 0.85em 1em !default;
+$button-margin: 0 $global-padding $global-padding 0 !default;
+$button-style: solid !default;
+$button-background: $primary-color !default;
+$button-background-hover: scale-color($button-background, $lightness: -15%) !default;
+$button-color: auto !default;
+$button-radius: 0 !default;
+$button-sizes: (
+ tiny: 0.7,
+ small: 0.8,
+ medium: 1,
+ large: 1.3,
+) !default;
+$button-font-size: 0.9rem !default;
+$button-opacity-disabled: 0.5 !default;
+$button-tag-selector: false !default;
+///
+
+%button {
+ display: inline-block;
+ border: 0;
+ text-align: center;
+ line-height: 1;
+ cursor: pointer;
+ -webkit-appearance: none;
+ -webkit-font-smoothing: antialiased;
+ transition: background 0.25s ease-out;
+ vertical-align: middle;
+
+ padding: $button-padding;
+ margin: $button-margin;
+ font-size: $button-font-size;
+ border-radius: $button-radius;
+
+ // Dropdown arrow
+ // TODO: Change to class and mixin because now the toggle is 'fa-open' which is too generic
+ // &[data-popup-toggle] {
+ // position: relative;
+ // padding-right: 2em; // Placeholder
+
+ // &::after {
+ // @include css-triangle(6px, black, top);
+ // position: absolute;
+ // right: 0.7em;
+ // top: 50%;
+ // margin-top: -3px;
+ // }
+ // }
+}
+
+@mixin button-size($size: medium, $expand: false) {
+ $size: $button-font-size * map-get($button-sizes, $size);
+ font-size: $size;
+
+ @if $expand {
+ @include button-expand;
+ }
+
+ @if using(iconic) {
+ .iconic {
+ width: 1em;
+ height: 1em;
+ vertical-align: middle;
+ margin-right: 0.25em;
+ margin-top: -2px; // The icons are oddly misaligned
+ }
+ }
+}
+
+@mixin button-expand($expand: true) {
+ @if $expand {
+ display: block;
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ }
+ @else {
+ display: inline-block;
+ width: auto;
+ margin: $button-margin;
+ }
+}
+
+@mixin button-style(
+ $background: $button-background,
+ $background-hover: $button-background-hover,
+ $color: $button-color,
+ $style: $button-style,
+ $radius: $button-radius,
+ $btngroup: false
+){
+ @if $style == hollow {
+ border: 1px solid $background;
+ background: transparent;
+ color: $background;
+
+ &:hover, &:focus {
+ border-color: scale-color($background, $lightness: 25%);
+ background: transparent;
+ color: scale-color($background, $lightness: 25%);
+ }
+ }
+ // Solid is the default
+ @else {
+ @if $color == auto {
+ $color: isitlight($background);
+ }
+
+ background: $background;
+ color: $color;
+
+ &:hover, &:focus {
+ @if $background-hover == auto {
+ background: scale-color($background, $lightness: -15%);
+ }
+ @else {
+ background: $background-hover;
+ }
+ color: $color;
+ }
+ }
+
+ @if $btngroup {
+ border-color: $background;
+ &:hover, &:focus {
+ border-color: scale-color($background, $lightness: -25%);
+ }
+ }
+
+ @if using(iconic) {
+ @if $style == hollow {
+ .iconic {
+ @include color-icon($background);
+ }
+ &:hover .iconic {
+ @include color-icon(scale-color($background, $lightness: 25%));
+ }
+ }
+ @else {
+ .iconic {
+ @include color-icon($color);
+ }
+ }
+ }
+}
+
+@mixin button-disabled() {
+ opacity: $button-opacity-disabled;
+ cursor: default;
+ pointer-events: none;
+}
+
+@mixin button(
+ $size: medium,
+ $expand: false,
+ $background: $button-background,
+ $background-hover: $button-background-hover,
+ $color: $button-color,
+ $style: $button-style,
+ $radius: $button-radius
+) {
+ @extend %button;
+ @include button-size($size);
+ @include button-expand($expand);
+ @include button-style($background, $background-hover, $color, $style);
+}
+
+@include exports(button) {
+ .button {
+ @include button;
+
+ &.tiny { @include button-size(tiny); }
+ &.small { @include button-size(small); }
+ &.large { @include button-size(large); }
+ &.expand { @include button-expand; }
+
+ &.secondary { @include button-style($secondary-color, auto) }
+ &.success { @include button-style($success-color, auto) }
+ &.warning { @include button-style($warning-color, auto) }
+ &.alert { @include button-style($alert-color, auto) }
+ &.info { @include button-style($info-color, auto) }
+ &.dark { @include button-style($dark-color, auto) }
+
+ @if $button-style != hollow {
+ &.hollow { @include button-style($style: hollow);
+ &.secondary { @include button-style($secondary-color, $style: hollow); }
+ &.success { @include button-style($success-color, $style: hollow); }
+ &.warning { @include button-style($warning-color, $style: hollow); }
+ &.alert { @include button-style($alert-color, $style: hollow); }
+ &.info { @include button-style($info-color, $style: hollow); }
+ &.dark { @include button-style($dark-color, $style: hollow); }
+ }
+ }
+
+ &.disabled { @include button-disabled; }
+ }
+
+ @if $button-tag-selector {
+ button {
+ @extend .button;
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_card.scss b/afb-client/bower_components/foundation-apps/scss/components/_card.scss
new file mode 100644
index 0000000..680a755
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_card.scss
@@ -0,0 +1,93 @@
+/*
+ Cards
+
+ Structure:
+
+ titles
+ lists
+*/
+
+/// @Foundation.settings
+// Card
+$card-background: #fff !default;
+$card-color: isitlight($card-background) !default;
+$card-border: 1px solid smartscale($card-background, 7%) !default;
+$card-radius: $global-radius !default;
+$card-shadow: 0 1px 2px rgba(#000, 0.2) !default;
+$card-padding: $global-padding !default;
+$card-margin: 0.5rem !default;
+
+$card-divider-background: smartscale($card-background, 7%) !default;
+///
+
+@mixin card-container(
+ $background: $card-background,
+ $color: $card-color,
+ $border: $card-border,
+ $radius: $card-radius,
+ $shadow: $card-shadow,
+ $padding: $card-padding,
+ $margin: $card-margin
+) {
+ border: $border;
+ margin-bottom: $margin;
+ background: $background;
+ color: $color;
+ border-radius: $radius;
+ box-shadow: $shadow;
+ overflow: hidden;
+
+ h1, h2, h3, h4, h5, h6 {
+ color: inherit;
+ }
+
+ ul {
+ margin-bottom: 0;
+ }
+
+ img {
+ width: 100%;
+ }
+}
+
+@mixin card-divider(
+ $background: $card-divider-background,
+ $padding: $card-padding
+) {
+ background: $background;
+ padding: $padding;
+}
+
+@mixin card-section(
+ $padding: $card-padding
+) {
+ padding: $padding;
+}
+
+@include exports(card) {
+ .card {
+ @include card-container;
+
+ @each $color in map-keys($foundation-colors) {
+ &.#{$color} {
+ $color-value: map-get($foundation-colors, $color);
+ @include card-container(
+ $background: $color-value,
+ $color: isitlight($color-value),
+ $border: 0
+ );
+ .card-divider {
+ @include card-divider(
+ $background: smartscale($color-value, 7%)
+ );
+ }
+ }
+ }
+ }
+ .card-divider {
+ @include card-divider;
+ }
+ .card-section {
+ @include card-section;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_extras.scss b/afb-client/bower_components/foundation-apps/scss/components/_extras.scss
new file mode 100644
index 0000000..1e2443a
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_extras.scss
@@ -0,0 +1,54 @@
+/*
+ Odds and ends.
+*/
+
+/// @Foundation.settings
+// Extras
+$closebutton-position: (top right) !default;
+$closebutton-size: 2em !default;
+$closebutton-lineheight: 0.5 !default;
+$closebutton-color: #999 !default;
+$closebutton-color-hover: #333 !default;
+
+$thumbnail-padding: 0.5rem !default;
+$thumbnail-shadow: 0 3px 15px rgba(black, 0.25) !default;
+///
+
+// A basic close button. They pin to the corner of the thing they're inside.
+%close-button {
+ $x: nth($closebutton-position, 1);
+ $y: nth($closebutton-position, 2);
+
+ position: absolute;
+ color: $closebutton-color;
+ #{$x}: $global-padding;
+ #{$y}: $global-padding;
+ font-size: $closebutton-size;
+ line-height: $closebutton-lineheight;
+ cursor: pointer;
+
+ &:hover {
+ color: $closebutton-color-hover;
+ }
+}
+
+// Make your images fancy-like.
+%thumbnail {
+ padding: $thumbnail-padding;
+ box-shadow: $thumbnail-shadow;
+}
+
+@include exports(extras) {
+ .close-button {
+ @extend %close-button;
+ }
+ .thumbnail {
+ @extend %thumbnail;
+ }
+ ul.thumbnails > li {
+ margin-bottom: 1rem;
+
+ a { display: block; }
+ img { @extend %thumbnail; }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_forms.scss b/afb-client/bower_components/foundation-apps/scss/components/_forms.scss
new file mode 100755
index 0000000..7d0376b
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_forms.scss
@@ -0,0 +1,458 @@
+/*
+ FORMS
+ -----
+
+ Our form styles include basic resets for text fields, select menus, and so on, along with some of our own custom components.
+
+ Includes:
+ - Text fields
+ - Text areas
+ - Select menus
+ - Checkboxes and radio buttons
+ - Range slider
+ - Progress bars and meters
+*/
+
+/// @Foundation.settings
+// Forms
+// Basic form variables
+$form-fontsize: 1rem !default;
+$form-padding: 0.5rem !default;
+
+// Text fields
+$input-color: #000 !default;
+$input-color-hover: $input-color !default;
+$input-color-focus: $input-color !default;
+$input-background: #fff !default;
+$input-background-hover: $input-background !default;
+$input-background-focus: $input-background !default;
+$input-background-disabled: smartscale($input-background) !default;
+$input-border: 1px solid #ccc !default;
+$input-border-hover: 1px solid #bbb !default;
+$input-border-focus: 1px solid #999 !default;
+$input-cursor-disabled: not-allowed !default;
+
+// Select menus
+$select-color: #000 !default;
+$select-background: #fafafa !default;
+$select-background-hover: smartscale($select-background, 4%) !default;
+$select-arrow: true !default;
+$select-arrow-color: $select-color !default;
+
+// Labels
+$form-label-fontsize: 0.9rem !default;
+$form-label-margin: 0.5rem !default;
+$form-label-color: #333 !default;
+
+// Inline labels
+$inlinelabel-color: #333 !default;
+$inlinelabel-background: #eee !default;
+$inlinelabel-border: $input-border !default;
+
+// Range slider
+$slider-background: #ddd !default;
+$slider-height: 1rem !default;
+$slider-radius: 0px !default;
+$slider-thumb-height: 1.5rem !default;
+$slider-thumb-color: $primary-color !default;
+$slider-thumb-radius: 0px !default;
+
+// Progress and meter
+$meter-height: 1.5rem !default;
+$meter-background: #ccc !default;
+$meter-fill: $primary-color !default;
+$meter-fill-high: $success-color !default;
+$meter-fill-medium: #e7cf00 !default;
+$meter-fill-low: $alert-color !default;
+$meter-radius: 0 !default;
+///
+
+// Disable OS-level styles
+@mixin no-appearance {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+}
+
+// Text fields
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+#{$text-input-selectors} {
+ $top-padding: get-side($form-padding, top);
+ $bottom-padding: get-side($form-padding, bottom);
+ $height: ($form-fontsize * 1.4) + $top-padding + $bottom-padding;
+
+ @include no-appearance;
+ display: block;
+ width: 100%;
+ height: $height;
+ padding: $form-padding;
+ margin: 0 0 $global-padding 0;
+ border: $input-border;
+ border-radius: 0;
+ background: $input-background;
+ color: $input-color;
+ font-size: $form-fontsize;
+ -webkit-font-smoothing: antialiased;
+ vertical-align: middle;
+
+ &:hover {
+ border: $input-border-hover;
+ background: $input-background-hover;
+ color: $input-color-hover;
+ }
+ &:focus {
+ outline: 0;
+ border: $input-border-focus;
+ background: $input-background-focus;
+ color: $input-color-focus;
+ }
+
+ label > & {
+ margin-top: $form-label-margin;
+ }
+}
+
+// Override the content-box declaration set by Normalize
+input[type="search"] {
+ box-sizing: border-box;
+}
+
+// Disabled state
+input {
+ &.disabled,
+ &[disabled],
+ &[readonly],
+ fieldset[disabled] & {
+ cursor: $input-cursor-disabled;
+
+ &, &:hover {
+ background-color: $input-background-disabled;
+ }
+ }
+}
+
+// Labels
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+label {
+ display: block;
+ font-size: $form-label-fontsize;
+ margin-bottom: $form-label-margin;
+ color: $form-label-color;
+
+ > input, > textarea {
+ margin-top: $form-label-margin;
+ }
+}
+
+// Checkbox/radio buttons
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+input[type="checkbox"], input[type="radio"] {
+ width: 1rem;
+ height: 1rem;
+
+ // Input inside of a label
+ label > & {
+ margin-right: $form-padding * 0.5;
+ }
+
+ // Input next to a label
+ & + label {
+ display: inline-block;
+ margin-left: $form-padding;
+ margin-right: $form-padding * 2;
+ margin-bottom: 0;
+ vertical-align: baseline;
+ }
+}
+
+// Inline labels
+// Inline labels allow you to prefix or postfix special labels to inputs
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+.inline-label {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: stretch;
+ margin-bottom: $global-padding;
+
+ // Imitates the top margin on normal inputs
+ label > & {
+ margin-top: $form-label-margin;
+ }
+
+ // Inputs stretch all the way out
+ > input, > select {
+ flex: 1;
+ margin: 0;
+ }
+
+ // Inline labels and buttons shrink
+ > .form-label {
+ flex: 0 0 auto;
+ background: $inlinelabel-background;
+ color: $inlinelabel-color;
+ border: $inlinelabel-border;
+ padding: 0 $form-padding;
+ display: flex;
+ align-items: center;
+
+ &:first-child { border-right: 0; }
+ &:last-child { border-left: 0; }
+ }
+ // Buttons also shrink
+ > a,
+ > button,
+ > input[type="button"],
+ > input[type="submit"] {
+ flex: 0 0 auto;
+ display: flex;
+ align-items: center;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin: 0;
+ border-radius: 0;
+ }
+}
+
+// Text areas
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+textarea {
+ height: auto;
+ width: 100%;
+ min-height: 50px;
+}
+
+// Select menus
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+select {
+ $top-padding: get-side($form-padding, top);
+ $bottom-padding: get-side($form-padding, bottom);
+ $height: ($form-fontsize * 1.4) + $top-padding + $bottom-padding;
+ $color: isitlight($select-background);
+
+ @include no-appearance;
+ display: block;
+ width: 100%;
+ height: $height;
+ padding: $form-padding;
+ margin: 0 0 $global-padding 0;
+ font-size: $form-fontsize;
+ color: $select-color;
+ border-radius: 0;
+ border: $input-border;
+
+ @if $select-arrow {
+ background: $select-background url(image-triangle($select-arrow-color)) right 10px center no-repeat;
+ background-size: 8px 8px;
+ padding-right: rem-calc(18px) + $form-padding;
+ }
+ @else {
+ background-color: $select-background
+ }
+
+ &:hover {
+ background-color: $select-background-hover;
+ }
+
+ &:focus {
+ outline: 0;
+ }
+
+ // Remove the dropdown arrow added in IE10/11
+ &::-ms-expand {
+ display: none;
+ }
+}
+
+// Range slider
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+input[type="range"] {
+ $margin: ($slider-thumb-height - $slider-height) / 2;
+
+ @include no-appearance;
+ display: block;
+ width: 100%;
+ height: auto;
+ cursor: pointer;
+ margin-top: $margin;
+ margin-bottom: $margin;
+ border: 0;
+ line-height: 1;
+
+ @if hasvalue($slider-radius) {
+ border-radius: $slider-radius;
+ }
+
+ &:focus {
+ outline: 0;
+ }
+
+ // Chrome/Safari
+ &::-webkit-slider-runnable-track {
+ height: $slider-height;
+ background: $slider-background;
+ }
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ background: $slider-thumb-color;
+ width: $slider-thumb-height;
+ height: $slider-thumb-height;
+ margin-top: -$margin;
+ @if hasvalue($slider-thumb-radius) {
+ border-radius: $slider-thumb-radius;
+ }
+ }
+ // Firefox
+ &::-moz-range-track {
+ -moz-appearance: none;
+ height: $slider-height;
+ background: #ccc;
+ }
+ &::-moz-range-thumb {
+ -moz-appearance: none;
+ background: $slider-thumb-color;
+ width: $slider-thumb-height;
+ height: $slider-thumb-height;
+ margin-top: -$margin;
+ @if hasvalue($slider-thumb-radius) {
+ border-radius: $slider-thumb-radius;
+ }
+ }
+ // Internet Explorer
+ &::-ms-track {
+ height: $slider-height;
+ background: $slider-background;
+ color: transparent;
+ border: 0;
+ overflow: visible;
+ border-top: $margin solid $body-background;
+ border-bottom: $margin solid $body-background;
+ }
+ &::-ms-thumb {
+ background: $slider-thumb-color;
+ width: $slider-thumb-height;
+ height: $slider-thumb-height;
+ border: 0;
+ @if hasvalue($slider-thumb-radius) {
+ border-radius: $slider-thumb-radius;
+ }
+ }
+ &::-ms-fill-lower, &::-ms-fill-upper {
+ background: $slider-background;
+ }
+}
+output {
+ line-height: $slider-thumb-height;
+ vertical-align: middle;
+ margin-left: 0.5em;
+}
+
+// Number inputs
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+input[type="number"] {
+ &::-webkit-inner-spin-button {
+
+ }
+ &::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ background: $primary-color;
+ }
+}
+
+// Progress and meter
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+progress, meter {
+ @include no-appearance;
+ display: block;
+ width: 100%;
+ height: $meter-height;
+ margin-bottom: 1rem;
+
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+
+ // For Firefox
+ background: $meter-background;
+ border: 0;
+}
+
+progress {
+ &::-webkit-progress-bar {
+ background: $meter-background;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-webkit-progress-value {
+ background: $meter-fill;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-moz-progress-bar {
+ background: $meter-fill;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+
+ @each $name, $color in (high: $meter-fill-high, medium: $meter-fill-medium, low: $meter-fill-low) {
+ &.#{$name} {
+ &::-webkit-progress-value {
+ background: $color;
+ }
+ &::-moz-progress-bar {
+ background: $color;
+ }
+ }
+ }
+}
+meter {
+ // Chrome/Safari
+ &::-webkit-meter-bar {
+ background: $meter-background;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-webkit-meter-inner-element {
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-webkit-meter-optimum-value {
+ background: $meter-fill-high;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-webkit-meter-suboptimum-value {
+ background: $meter-fill-medium;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &::-webkit-meter-even-less-good-value {
+ background: $meter-fill-low;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+
+ // Firefox
+ background: $meter-background;
+ &::-moz-meter-bar {
+ background: $primary-color;
+ @if hasvalue($meter-radius) {
+ border-radius: $meter-radius;
+ }
+ }
+ &:-moz-meter-optimum::-moz-meter-bar {
+ background: $meter-fill-high;
+ }
+ &:-moz-meter-sub-optimum::-moz-meter-bar {
+ background: $meter-fill-medium;
+ }
+ &:-moz-meter-sub-sub-optimum::-moz-meter-bar {
+ background: $meter-fill-low;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_grid.scss b/afb-client/bower_components/foundation-apps/scss/components/_grid.scss
new file mode 100644
index 0000000..4a00fd6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_grid.scss
@@ -0,0 +1,420 @@
+@import "panel";
+
+/*
+ THE GRID
+ --------
+
+ Foundation's magical, flexbox-powered grid.
+
+ Features:
+ - Horizontal or vertical grids
+ - Auto-sizing or percentage width grid blocks
+ - Independently-scrollable blocks
+ - Column alignment
+ - Source ordering
+ - Offsets
+*/
+
+/// @Foundation.settings
+// Grid
+$container-width: rem-calc(900) !default;
+$block-padding: $global-padding !default;
+$total-columns: 12 !default;
+$block-grid-max-size: 6 !default;
+///
+
+/*
+ Define the size of a grid block. Blocks are flex items. By default, they stretch to fill all available space, based on the size of sibling blocks. This is the "expand" behavior.
+
+ If set to "shrink", the block will contract and only fill as much space as it needs for its content.
+
+ If set to a number, the block will be given a percentage width, based on the total number of columns (12 by default). Percentage widths don't work if a block is inside a vertical grid.
+
+ @group grid
+
+ @param {number|string} $size - Sizing behavior of the block. Should be expand, shrink, or a number.
+
+ @output The flex-basis, flex-grow, and flex-shrink properties.
+*/
+@mixin grid-size($size: expand) {
+ @if (type-of($size) == 'number') {
+ $pct: percentage($size / $total-columns);
+ flex: 0 0 $pct;
+ // max-width prevents columns from wrapping early in IE10/11
+ max-width: $pct;
+ }
+ @else if ($size == shrink) {
+ flex: 0 0 auto;
+ }
+ @else if ($size == expand) {
+ flex: 1 1 auto;
+ }
+}
+/*
+ Set the orientation of blocks within this block. The grid is re-oriented by changing the flex direction of the block.
+
+ @group grid
+
+ @param {string} $orientation - Direction of the grid, either horizontal or vertical.
+
+ @output A flex-flow property to match the direction given.
+*/
+@mixin grid-orient($orientation: horizontal) {
+ @if ($orientation == vertical) {
+ flex-flow: column nowrap;
+ align-items: stretch;
+ }
+ @else {
+ flex-flow: row wrap;
+ }
+}
+/*
+ Stretch a grid's child blocks across its cross-axis, making every column appear to have the same height.
+
+ @group grid
+
+ @param {bool} $stretch - Stretch blocks if true, or align blocks to top if false.
+
+ @output Sets align-items to "stretch" if $stretch is true, or "flex-start" (the default value) if false.
+*/
+@mixin grid-wrap($wrap: true) {
+ @if $wrap {
+ flex-wrap: wrap;
+ align-items: flex-start;
+ }
+ @else {
+ flex-wrap: nowrap;
+ align-items: stretch;
+ }
+}
+/*
+ Set the alignment of blocks within a grid.
+
+ left: Items align to the left.
+ right: Items align to the right.
+ center: Items align to the center.
+ justify: Items are spaced equally apart so they occupy the space of the entire grid.
+ spaced: Items are given equal space to their left and right.
+
+ @group grid
+
+ @param {string} $align - Alignment to use.
+
+ @output An appropriate justify-content value.
+*/
+@mixin grid-align($align: left) {
+ $options: (
+ left: flex-start,
+ right: flex-end,
+ center: center,
+ justify: space-between,
+ spaced: space-around,
+ );
+ justify-content: map-get($options, $align);
+}
+/*
+ Set the source order of a block. Items with lower numbers appear first. If multiple items have the same number, the one in the HTML first will appear first.
+
+ @group grid
+
+ @param {number} $order - Position in source order.
+
+ @output An order property.
+*/
+@mixin grid-order($order: 0) {
+ order: $order;
+}
+/*
+ Collapse a content block by removing the padding.
+
+ @group grid
+
+ @param {bool} $collapse - Collapses the block if true.
+
+ @output A padding value.
+
+ @todo No way to reverse collapse using this mixin. Solution:
+ - If true, add padding: 0;
+ - If false, add padding: 1rem;
+ - If null, add nothing, to cut down on CSS output
+ - Make null the default value
+*/
+@mixin grid-collapse($collapse: true) {
+ @if ($collapse) {
+ padding: 0;
+ }
+}
+/*
+ Constrain the size of a block to the size of the average grid row, and center-align it. This imitates the behavior of ordinary Foundation rows.
+
+ @group grid
+
+ @param {bool} $container - Adds container styles if true.
+
+ @output A maximum width and the good old margin: 0 auto for center alignment.
+*/
+@mixin grid-container($width: $container-width, $align: center) {
+ $margins: (
+ left: 0 auto 0 0,
+ right: 0 0 0 auto,
+ center: 0 auto,
+ );
+ max-width: $width;
+ margin: map-get($margins, $align);
+}
+/*
+ Add negative margins to a block, equal to the padding of a content block. This aligns the edges of a block nested inside a content block.
+
+ @group grid
+
+ @param {bool} $nest - Adds negative margins if true.
+
+ @output Negative margin values.
+*/
+@mixin grid-nest($nest: true) {
+ @if ($nest) {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+}
+/*
+ Offset a block by adding a left margin.
+
+ @group grid
+
+ @param {number | bool} $offset - If false, nothing is output. If a number, offsets the column by the specified number of columns.
+
+ @output A left margin based on the number of columns specified, and the global number of columns.
+*/
+@mixin grid-offset($offset: false) {
+ @if ($offset != false) {
+ margin-left: percentage($offset / $total-columns);
+ }
+}
+
+/*
+ Resets styles set by panels. Use this when a panel transforms into a block on larger screens.
+
+ @group grid
+
+ @output Resets to transform, position, and a few visual styles.
+*/
+@mixin grid-panel-reset() {
+ transform: none;
+ position: relative;
+ width: auto;
+ height: auto;
+ z-index: auto;
+ box-shadow: none;
+ background: transparent;
+ top: auto;
+ right: auto;
+ bottom: auto;
+ left: auto;
+}
+
+/*
+ Frames are containers that stretch to the full dimmensions of the browser window.
+*/
+@mixin grid-frame($size: expand, $orientation: horizontal, $wrap: false, $align: left, $order: 0) {
+ display: flex;
+ height: 100vh;
+ position: relative;
+ overflow: hidden;
+ backface-visibility: hidden;
+
+ @include grid-size($size);
+ @include grid-orient($orientation);
+ @include grid-wrap($wrap);
+ @include grid-align($align);
+ @include grid-order($order);
+}
+
+/*
+ Groups are collections of content items. They're the "rows" of Foundation for Apps.
+*/
+@mixin grid-block($size: expand, $orientation: horizontal, $wrap: false, $align: left, $order: 0) {
+ @include grid-frame($size, $orientation, $wrap, $align, $order);
+
+ // Reset the height used by frames
+ height: auto;
+
+ // Blocks will scroll by default if their content overflows
+ @if ($orientation == vertical) {
+ overflow-x: auto;
+ }
+ @else {
+ overflow-y: auto;
+ }
+
+ // Add scrolling with inertia
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+}
+
+/*
+ Blocks are containers for actual content. They're the "columns" of Foundation for Apps.
+*/
+@mixin grid-content($size: expand, $offset: null, $order: null) {
+ // Content blocks are not flex items and have padding
+ display: block;
+ padding: 0 $block-padding;
+
+ // Add scrolling with inertia
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+
+ @include grid-size($size);
+ @if $offset != null { @include grid-offset($offset); }
+ @if $order != null { @include grid-order($order); }
+}
+
+@mixin grid-layout($up) {
+ flex-flow: row wrap;
+ overflow: visible;
+ list-style-type: none;
+
+ > li, > div, > section {
+ padding: 0 1rem 1rem;
+ flex: 0 0 percentage(1 / $up);
+ }
+}
+
+// CSS Output
+// - - - - - - - - - - - - - - - - - - - -
+
+// Shared styles for frames and blocks (parent elements)
+%block-core {
+ // Change the direction children flow
+ &.vertical { @include grid-orient(vertical); }
+ @each $size in $breakpoint-classes {
+ @include breakpoint($size) {
+ &.#{$size}-vertical { @include grid-orient(vertical); }
+ &.#{$size}-horizontal { @include grid-orient(horizontal); }
+ }
+ }
+
+ // Align the children of a grid block
+ &.align-right { @include grid-align(right); }
+ &.align-center { @include grid-align(center); }
+ &.align-justify { @include grid-align(justify); }
+ &.align-spaced { @include grid-align(spaced); }
+
+ // Allow child elements to wrap
+ &.wrap { @include grid-wrap(true); }
+}
+
+// Shared styles for blocks and content blocks (child elements)
+%child-core {
+ // Shrink a flex item so it only takes up the space it needs
+ &.shrink { @include grid-size(shrink); }
+
+ // Prevent an element from scrolling
+ &.noscroll { overflow: hidden; }
+}
+
+@include exports(grid) {
+ // The core grid elements:
+ // - Frame
+ // - Block
+ // - Content block
+ // - Container
+ .grid-frame {
+ @extend %block-core;
+ @include grid-frame;
+ }
+ .grid-block {
+ @extend %block-core;
+ @extend %child-core;
+ @include grid-block;
+ }
+ .grid-content {
+ @extend %child-core;
+ @include grid-content;
+
+ &.collapse {
+ padding: 0;
+ }
+
+ // Grids inside content blocks should wrap by default, so they mimic traditional float grids
+ .grid-block {
+ margin-left: -($block-padding);
+ margin-right: -($block-padding);
+ flex-wrap: wrap;
+ overflow: visible;
+
+ // Reverse the above wrapping behavior
+ &.nowrap {
+ @include grid-wrap(false);
+ }
+
+ .grid-content {
+ overflow: visible;
+ }
+ }
+ }
+ .grid-container {
+ @include grid-container;
+
+ &.contain-left { @include grid-container($align: left); }
+ &.contain-right { @include grid-container($align: right); }
+ }
+
+ // Breakpoint classes for blocks
+ @each $size in $breakpoint-classes {
+ .#{$size}-grid-block {
+ @extend %block-core;
+ @extend %child-core;
+
+ @include breakpoint($size) {
+ @include grid-block;
+
+ // Override panel styles
+ &.panel { @include grid-panel-reset; }
+ }
+ }
+ .#{$size}-grid-content {
+ @extend %child-core;
+
+ @include breakpoint($size) {
+ @include grid-content;
+
+ // Override panel styles
+ &.panel { @include grid-panel-reset; }
+ }
+ }
+ }
+
+ // Sizing and ordering classes
+ @for $i from 1 through $total-columns {
+ // Source ordering
+ .order-#{$i} { @include grid-order($i); }
+ }
+ @each $size in $breakpoint-classes {
+ @for $i from 1 through $total-columns {
+ @include breakpoint($size) {
+ // Block sizing
+ .#{$size}-#{$i} {
+ @include grid-size($i);
+ }
+ // Source ordering
+ .#{$size}-order-#{$i} {
+ @include grid-order($i);
+ }
+ // Offsets
+ .#{$size}-offset-#{$i} {
+ @include grid-offset($i);
+ }
+ // Parent sizing (block grids)
+ .#{$size}-up-#{$i} {
+ @include grid-layout($i);
+ }
+ }
+ }
+ }
+
+ .grid-content .modal .grid-block {
+ flex-wrap: nowrap;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_iconic.scss b/afb-client/bower_components/foundation-apps/scss/components/_iconic.scss
new file mode 100644
index 0000000..77d0bd3
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_iconic.scss
@@ -0,0 +1,95 @@
+// ICONIC
+// ------
+//
+// A sample of 24 flexible, easily schemable icons from the folks at Iconic.
+//
+// Features:
+// - 24 icons
+// - Built-in coloring and sizing classes
+// - Coloring mixin
+// - Angular support
+
+/// @Foundation.settings
+// Iconic
+$iconic-primary-fill: $primary-color !default;
+$iconic-primary-stroke: $primary-color !default;
+$iconic-accent-fill: $iconic-primary-fill !default;
+$iconic-accent-stroke: $iconic-accent-fill !default;
+///
+
+// Colors the fill, and optionally stroke, accent fill, and accent stroke of an Iconic icon.
+@mixin color-icon(
+ $fill,
+ $stroke: null,
+ $fillAccent: null,
+ $strokeAccent: null
+) {
+ * {
+ fill: $fill;
+
+ // Use the fill color if no stroke is provided
+ @if hasvalue($stroke) {
+ stroke: $stroke;
+ }
+ @else {
+ stroke: $fill;
+ }
+
+ &.iconic-property-accent {
+ // Use the fill color if no accent is provided
+ @if hasvalue($fillAccent) {
+ fill: $fillAccent;
+ }
+ @else {
+ fill: $fill;
+ }
+
+ // Use the normal stroke color if no accent is provided
+ @if hasvalue($strokeAccent) {
+ stroke: $strokeAccent;
+ }
+ @else {
+ // ...or use the fill if no normal stroke is provided
+ @if hasvalue($stroke) {
+ stroke: $stroke;
+ }
+ @else {
+ stroke: $fill;
+ }
+ }
+ }
+ }
+}
+
+@include exports(iconic) {
+ .iconic {
+ width: 1rem;
+ height: 1rem;
+ vertical-align: middle;
+
+ a > & {
+ @include color-icon($primary-color);
+ margin-top: -2px;
+ margin-right: 0.25rem;
+ }
+ }
+
+ .iconic * {
+ fill: $iconic-primary-fill;
+ stroke: $iconic-primary-stroke;
+
+ &.iconic-property-accent {
+ fill: $iconic-accent-fill;
+ stroke: $iconic-accent-stroke;
+ }
+ }
+
+ @each $color in map-keys($foundation-colors) {
+ .iconic-color-#{$color} {
+ @include color-icon(map-get($foundation-colors, $color));
+ }
+ }
+ .iconic-color-secondary {
+ @include color-icon($secondary-color);
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_label.scss b/afb-client/bower_components/foundation-apps/scss/components/_label.scss
new file mode 100644
index 0000000..129757e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_label.scss
@@ -0,0 +1,134 @@
+/*
+ Label
+*/
+
+/// @Foundation.settings
+// Label
+$label-fontsize: 0.8rem !default;
+$label-padding: ($global-padding / 3) ($global-padding / 2) !default;
+$label-radius: 0 !default;
+$label-background: $primary-color !default;
+$label-color: isitlight($primary-color) !default;
+
+$badge-fontsize: 0.8em !default;
+$badge-diameter: 1.5rem !default;
+$badge-background: $primary-color !default;
+$badge-color: #fff !default;
+///
+
+%label {
+ line-height: 1;
+ white-space: nowrap;
+ display: inline-block;
+ cursor: default;
+}
+
+@mixin label-layout(
+ $fontsize: $label-fontsize,
+ $padding: $label-padding
+) {
+ font-size: $fontsize;
+ padding: $padding;
+}
+
+@mixin label-style(
+ $background: $label-background,
+ $color: $label-color,
+ $radius: $label-radius
+) {
+ background: $background;
+ border-radius: $radius;
+
+ @if $color == auto {
+ color: isitlight($background);
+ }
+ @else {
+ color: $color;
+ }
+}
+
+@mixin label(
+ $background: $label-background,
+ $color: $label-color,
+ $radius: $label-radius,
+ $fontsize: $label-fontsize,
+ $padding: $label-padding
+) {
+ @extend %label;
+ @include label-layout($fontsize, $padding);
+ @include label-style($background, $color, $radius);
+}
+
+@include exports(label) {
+ .label {
+ @include label;
+
+ @each $color in map-keys($foundation-colors) {
+ &.#{$color} {
+ $color-value: map-get($foundation-colors, $color);
+ @include label-style($color-value, auto);
+ }
+ }
+ }
+}
+
+/*
+ Badge
+*/
+
+%badge {
+ align-items: center;
+ justify-content: center;
+ display: inline-flex;
+ border-radius: 1000px;
+}
+
+@mixin badge-layout(
+ $fontsize: $badge-fontsize,
+ $diameter: $badge-diameter
+) {
+ font-size: $fontsize;
+ width: $diameter;
+ height: $diameter;
+}
+
+@mixin badge-style(
+ $background: $badge-background,
+ $color: $badge-font-color
+) {
+ background: $background;
+
+ @if $color == auto {
+ color: isitlight($background);
+ }
+ @else {
+ color: $color;
+ }
+}
+
+@mixin badge(
+ $background: $badge-background,
+ $color: $badge-color,
+ $diameter: $badge-diameter,
+ $fontsize: $badge-fontsize
+) {
+ @extend %badge;
+ @include badge-layout($fontsize, $diameter);
+ @include badge-style($background, $color);
+}
+
+@include exports(badge) {
+ .badge {
+ @include badge;
+
+ &.secondary {
+ @include badge-style($secondary-color, auto);
+ }
+ @each $color in map-keys($foundation-colors) {
+ &.#{$color} {
+ $color-value: map-get($foundation-colors, $color);
+ @include badge-style($color-value, auto);
+ }
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_list.scss b/afb-client/bower_components/foundation-apps/scss/components/_list.scss
new file mode 100755
index 0000000..a303dcb
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_list.scss
@@ -0,0 +1,19 @@
+@mixin inline-list($alignment){
+ list-style-type: none;
+ text-align: $alignment;
+ li, dt, dd {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ }
+}
+
+@include exports(list) {
+ .inline-list {
+ @include inline-list(left);
+ li {
+ margin-right: 1rem;
+ margin-left: 0;
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_menu-bar.scss b/afb-client/bower_components/foundation-apps/scss/components/_menu-bar.scss
new file mode 100644
index 0000000..7e2f99d
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_menu-bar.scss
@@ -0,0 +1,363 @@
+/*
+ MENU BAR
+ --------
+
+ A generic, flexible menu component.
+
+ Features:
+ - Orient horizontally and vertically
+ - Change orientation at certain breakpoints
+ - Items with icons above, below, or to the left or right
+ - Text labels for vertical menus and badges for horizontal menus
+*/
+
+/// @Foundation.settings
+// Menu Bar
+$menubar-fontsize: 1rem !default;
+$menubar-background: #fff !default;
+$menubar-background-hover: smartscale($menubar-background, 7%) !default;
+$menubar-background-active: $menubar-background-hover;
+$menubar-color: isitlight($menubar-background) !default;
+$menubar-color-hover: $menubar-color !default;
+$menubar-color-active: $menubar-color-hover;
+
+$menubar-item-padding: $global-padding !default;
+$menubar-icon-size: 25px !default;
+$menubar-icon-spacing: $menubar-item-padding !default;
+///
+
+// Menu bar container
+%menu-bar {
+ display: flex;
+ align-items: stretch;
+ margin: 0;
+ list-style-type: none;
+
+ // Menu item
+ > li {
+ // This flex setting makes each item an equal width
+ flex: 1 0 auto;
+ align-items: center;
+
+ // Link inside menu item
+ > a {
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: center;
+ padding: $menubar-item-padding;
+ font-size: $menubar-fontsize;
+ line-height: 1;
+ }
+ }
+}
+
+@mixin menu-bar-layout (
+ $orientation: horizontal,
+ $stretch: true
+) {
+ /*
+ Orientation
+ */
+ @if $orientation == horizontal {
+ overflow-x: hidden;
+ flex-flow: row nowrap;
+ > li > a {
+ flex-flow: column nowrap;
+ }
+ }
+ @else {
+ flex-flow: column nowrap;
+ > li > a {
+ flex-flow: row nowrap;
+ }
+ }
+
+ /*
+ Stretch
+ */
+ > li {
+ @if $stretch == false {
+ flex: 0 0 auto;
+ }
+ }
+}
+
+@mixin menu-bar-style(
+ $background: $menubar-background,
+ $background-hover: $menubar-background-hover,
+ $background-active: $menubar-background-active,
+ $color: $menubar-color,
+ $color-hover: $menubar-color-hover,
+ $color-active: $menubar-color-active,
+ $autocolor: false
+) {
+ // Autocoloring
+ @if ($autocolor) {
+ $background-hover: smartscale($background, 7%);
+ $background-active: $background-hover;
+
+ $color: isitlight($background);
+ $color-hover: $color;
+ $color-active: $color;
+ }
+
+ // Container
+ background: $background;
+
+ // Items
+ > li > a {
+ color: $color;
+
+ &:hover {
+ background: $background-hover;
+ color: $color-hover;
+ }
+ }
+ .is-active > a {
+ background: $background-active;
+ color: $color-active
+ }
+
+ // Iconic
+ @if using(iconic) {
+ .iconic { @include color-icon($color); }
+ }
+}
+
+@mixin menu-bar-icons(
+ $position: left,
+ $size: $menubar-icon-size
+) {
+ > li {
+ // Sizing
+ > img, > .iconic {
+ margin: 0;
+ @if $menubar-icon-size != false {
+ width: $menubar-icon-size;
+ height: $menubar-icon-size;
+ }
+ }
+
+ // Position
+ @if $position == left {
+ > a {
+ flex-flow: row nowrap;
+ align-items: center;
+ > img, > .iconic { margin: 0 $menubar-icon-spacing 0 0; }
+ }
+ }
+ @if $position == top {
+ > a {
+ flex-flow: column nowrap;
+ > img, > .iconic { margin: 0 0 $menubar-icon-spacing 0; }
+ }
+ }
+ @if $position == right {
+ > a {
+ flex-flow: row-reverse nowrap;
+ > img, > .iconic { margin: 0 0 0 $menubar-icon-spacing; }
+ }
+ }
+ @if $position == bottom {
+ > a {
+ flex-flow: column-reverse nowrap;
+ > img, > .iconic { margin: $menubar-icon-spacing 0 0 0; }
+ }
+ }
+ }
+}
+
+@mixin menu-bar-labels(
+ $x: right,
+ $y: center,
+ $offset: $menubar-item-padding,
+ $size: 1.2rem,
+ $background: red,
+ $color: auto,
+ $selector: '.menu-bar-label'
+) {
+ > li {
+ position: relative;
+
+ > a {
+ @if $x == left or $x == right {
+ padding-#{$x}: $size + $offset * 2;
+ }
+ }
+ }
+
+ #{$selector} {
+ display: block;
+ font-size: $size * 0.75;
+ width: $size;
+ height: $size;
+ line-height: $size;
+ text-align: center;
+ border-radius: 1000px;
+ background: $background;
+ color: if($color == auto, isitlight($background), $color);
+ position: absolute;
+ pointer-events: none;
+
+ @if $x == left or $x == right {
+ #{$x}: $offset;
+ }
+
+ @if $y == top or $y == bottom {
+ #{$y}: $offset;
+ }
+ @else {
+ top: 50%;
+ transform: translateY(-50%);
+ }
+ }
+}
+
+/*
+ Set the alignment of menu items (li) within a menu-bar
+
+ left: Items align to the left.
+ right: Items align to the right.
+ center: Items align to the center.
+ justify: Items are spaced equally apart so they occupy the space of the entire grid.
+ spaced: Items are given equal space to their left and right.
+
+ @group menu-bar
+
+ @param {string} $align - Alignment to use.
+
+ @output An appropriate justify-content value.
+*/
+@mixin menu-bar-align($align: left) {
+ $options: (
+ left: flex-start,
+ right: flex-end,
+ center: center,
+ justify: space-between,
+ spaced: space-around,
+ );
+ justify-content: map-get($options, $align);
+}
+
+/*
+ CSS output
+*/
+@include exports(menu-bar) {
+ .menu-bar {
+ @extend %menu-bar;
+ @include menu-bar-style;
+
+ // Positioning
+ &, &.horizontal { @include menu-bar-layout(horizontal); }
+ &.vertical { @include menu-bar-layout(vertical); }
+
+ // Condensed bar
+ &.condense {
+ > li { flex: 0 0 auto; }
+ }
+
+ // Align Menu Items
+ &.align-right { @include menu-bar-align(right); }
+ &.align-center { @include menu-bar-align(center); }
+ &.align-justify { @include menu-bar-align(justify); }
+ &.align-spaced { @include menu-bar-align(spaced); }
+
+ @each $size in $breakpoint-classes {
+ @include breakpoint($size) {
+ &.#{$size}-condense { li { flex: 0 0 auto; } }
+ &.#{$size}-expand { li { flex: 1 0 auto; } }
+
+ // Responsive Alignment
+ &.#{$size}-align-left { @include menu-bar-align(left); }
+ &.#{$size}-align-right { @include menu-bar-align(right); }
+ &.#{$size}-align-center { @include menu-bar-align(center); }
+ &.#{$size}-align-justify { @include menu-bar-align(justify); }
+ &.#{$size}-align-spaced { @include menu-bar-align(spaced); }
+ }
+ }
+
+ // Responsive positioning
+ @each $size in $breakpoint-classes {
+ @include breakpoint($size) {
+ &.#{$size}-horizontal {
+ @include menu-bar-layout(horizontal);
+ }
+ &.#{$size}-vertical {
+ @include menu-bar-layout(vertical);
+ }
+ }
+ }
+
+ // Icon positioning
+ &, &.icon-top { @include menu-bar-icons(top); }
+ &.icon-right { @include menu-bar-icons(right); }
+ &.icon-bottom { @include menu-bar-icons(bottom); }
+ &.icon-left { @include menu-bar-icons(left); }
+ @each $size in $breakpoint-classes {
+ @each $pos in (top, right, bottom, left) {
+ @include breakpoint($size) {
+ &.#{$size}-icon-#{$pos} { @include menu-bar-icons($pos); }
+ }
+ }
+ }
+
+ // Labels
+ &.label-side { @include menu-bar-labels(right, center); }
+ &.label-corner { @include menu-bar-labels(right, top); }
+
+ // Coloring
+ &.primary {
+ @include menu-bar-style($primary-color, $autocolor: true);
+ }
+ &.dark {
+ @include menu-bar-style($dark-color, $autocolor: true);
+ }
+
+ // Title
+ > li.title {
+ padding: $menubar-item-padding;
+ cursor: default;
+ font-weight: bold;
+ }
+ }
+
+ // Menu groups
+ .menu-group {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+
+ @include breakpoint(medium) {
+ flex-wrap: nowrap;
+ }
+
+ > .menu-group-left, > .menu-group-right {
+ flex: 1 1 100%;
+
+ @include breakpoint(medium) {
+ flex: 0 0 auto;
+ }
+ }
+
+ // Menu bar is condensed
+ .menu-bar {
+ > li { flex: 0 0 auto; }
+ margin: 0;
+ }
+
+ // Coloring class cascades down to the menu bar
+ &.primary {
+ background-color: $primary-color;
+ .menu-bar {
+ @include menu-bar-style($primary-color, $autocolor: true);
+ }
+ }
+ &.dark {
+ background-color: $dark-color;
+ .menu-bar {
+ @include menu-bar-style($dark-color, $autocolor: true);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_modal.scss b/afb-client/bower_components/foundation-apps/scss/components/_modal.scss
new file mode 100644
index 0000000..0899a71
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_modal.scss
@@ -0,0 +1,126 @@
+/*
+ MODAL
+ -----
+
+ The humble modal hides off-canvas until summoned with an fa-open directive. Modals appear over an overlay that darkens the rest of the page, and have a maxmimum width. You can construct a grid inside a modal, or attach panels to it.
+
+ Note that the modal overlay is hardcoded into the CSS, because whether or not you build your modal semantically, the overlay is always required and will always look the same.
+*/
+
+/// @Foundation.settings
+// Modal
+$modal-background: #fff !default;
+$modal-border: 0 !default;
+$modal-radius: 0px !default;
+$modal-shadow: none !default;
+$modal-zindex: 1000 !default;
+$modal-sizes: (
+ tiny: 300px,
+ small: 500px,
+ medium: 600px,
+ large: 800px,
+) !default;
+
+$modal-overlay-class: 'modal-overlay' !default;
+$modal-overlay-background: rgba(#333, 0.7) !default;
+///
+
+%modal {
+ position: relative;
+ z-index: $modal-zindex + 1;
+ background: $modal-background;
+ flex: 0 0 auto;
+ width: 100%;
+ height: 100vh;
+ max-height: 100%;
+ overflow: hidden;
+ padding: $global-padding;
+
+ @include breakpoint(medium) {
+ height: auto;
+ max-width: map-get($modal-sizes, medium);
+ }
+
+ .grid-content, .grid-block {
+ margin: 0;
+ }
+
+ .close-button, [fa-close] {
+ z-index: $modal-zindex + 1;
+ }
+}
+
+@mixin modal-dialog() {
+ height: auto;
+}
+@mixin modal-layout(
+ $width: map-get($modal-sizes, medium),
+ $dialog: false
+) {
+ max-width: $width;
+}
+@mixin modal-style(
+ $border: $modal-border,
+ $radius: $modal-radius,
+ $shadow: $modal-shadow
+) {
+ @if $border != 0 {
+ border: $border;
+ }
+ @if $radius != 0 {
+ border-radius: $radius;
+ }
+ @if $shadow != none {
+ box-shadow: $shadow;
+ }
+}
+
+@mixin modal(
+ $width: map-get($modal-sizes, medium),
+ $border: $modal-border,
+ $radius: $modal-radius,
+ $shadow: $modal-shadow
+) {
+ @extend %modal;
+ @include modal-layout($width);
+ @include modal-style($border, $radius, $shadow);
+}
+
+@include exports(modal) {
+ .modal {
+ @include modal;
+
+ @each $size in map-keys($modal-sizes) {
+ $width: map-get($modal-sizes, $size);
+ @if $size != medium {
+ .#{$size} > & { @include modal-layout($width); }
+ }
+ }
+
+ .dialog > & {
+ @include modal-dialog;
+ }
+ .collapse > & {
+ padding: 0;
+ }
+ }
+
+ .#{$modal-overlay-class} {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $modal-zindex;
+ display: none;
+ background-color: $modal-overlay-background;
+
+ // Horizontally and vertically center the modal
+ align-items: center;
+ justify-content: center;
+
+ &.is-active {
+ display: flex;
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_motion.scss b/afb-client/bower_components/foundation-apps/scss/components/_motion.scss
new file mode 100644
index 0000000..88bd3a0
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_motion.scss
@@ -0,0 +1,524 @@
+// FOUNDATION MOTION UI
+// Table of Contents
+//
+// 0. Variables
+// 1. Base Transitions
+// a. Slide
+// b. Fade
+// c. Hinge
+// d. Scale
+// e. Spin
+// 2. Base Animations
+// a. Shake
+// b. Spinners
+// c. Wiggle
+// 3. HTML Attributes
+
+// 0. Variables
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+/// @Foundation.settings
+// Motion UI
+// Classes to use when triggering in/out animations
+$motion-class: (
+ in: "ng-enter",
+ out: "ng-leave",
+) !default;
+$motion-class-active: (
+ in: "ng-enter-active",
+ out: "ng-leave-active",
+) !default;
+$motion-class-stagger: (
+ in: "ng-enter-stagger",
+ out: "ng-leave-stagger",
+) !default;
+$motion-class-showhide: (
+ in: "ng-hide-remove",
+ out: "ng-hide-add",
+);
+$motion-class-showhide-active: (
+ in: "ng-hide-remove-active",
+ out: "ng-hide-add-active",
+);
+
+// Set if movement-based transitions should also fade the element in and out
+$motion-slide-and-fade: false !default;
+$motion-hinge-and-fade: true !default;
+$motion-scale-and-fade: true !default;
+$motion-spin-and-fade: true !default;
+
+// Default speed for transitions and animations
+$motion-duration-default: 500ms !default;
+
+// Slow and fast modifiders
+$motion-duration-slow: 750ms !default;
+$motion-duration-fast: 250ms !default;
+$motion-stagger-duration-default: 150ms !default;
+$motion-stagger-duration-short: 50ms !default;
+$motion-stagger-duration-long: 300ms !default;
+
+// Default timing function for transitions and animations
+$motion-timing-default: ease !default;
+
+// Built-in and custom easing functions
+// Every item in this map becomes a CSS class
+$motion-timings: (
+ linear: linear,
+ ease: ease,
+ easeIn: ease-in,
+ easeOut: ease-out,
+ easeInOut: ease-in-out,
+ bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245),
+ bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845),
+ bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245),
+) !default;
+
+// Default delay for all transitions and animations
+$motion-delay-default: 0 !default;
+// Short and long delay modifiers
+$motion-delay-short: 300ms !default;
+$motion-delay-long: 700ms !default;
+///
+
+// Looks for a timing function in the list of presets
+// If none are found, returns the value as-is.
+@function get-timing($timing) {
+ @if map-has-key($motion-timings, $timing) {
+ @return map-get($motion-timings, $timing);
+ }
+ @else {
+ @return $timing;
+ }
+}
+
+// Applies transition settings common to all mixins
+@mixin transition-basics(
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+ transition-duration: $duration;
+ transition-timing-function: get-timing($timing);
+ transition-delay: $delay;
+}
+
+// Wraps content in an enter/leave class, chained to the parent selector
+// Define the initial state of a transition here
+@mixin transition-start($dir) {
+ $sel1: map-get($motion-class, $dir);
+ $sel2: map-get($motion-class-showhide, $dir);
+
+ &.#{$sel1},
+ &.#{$sel2} {
+ @content;
+ }
+}
+
+// Wraps content in an enter/leave active class, chained to the matching
+// enter/leave class, chained to the parent selector
+// Define the end state of a transition here
+@mixin transition-end($dir) {
+ $sel1: map-get($motion-class, $dir);
+ $sel1A: map-get($motion-class-active, $dir);
+
+ $sel2: map-get($motion-class-showhide, $dir);
+ $sel2A: map-get($motion-class-showhide-active, $dir);
+
+ &.#{$sel1}.#{$sel1A},
+ &.#{$sel2}.#{$sel2A} {
+ @content;
+ }
+}
+
+@mixin stagger($delay-amount) {
+ transition-delay: $delay-amount;
+ // this is to avoid accidental CSS inheritance
+ transition-duration:0;
+}
+
+
+// 1. Base Transitions
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+// SLIDE
+@mixin slide (
+ $dir: in,
+ $from: left,
+ $fade: $motion-slide-and-fade,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+ $slideDirections: (
+ top: translateY(-100%),
+ right: translateX(100%),
+ bottom: translateY(100%),
+ left: translateX(-100%),
+ );
+ $start: '';
+ $end: '';
+
+ @if $dir == in {
+ $start: map-get($slideDirections, $from);
+ $end: translateX(0) translateY(0);
+ }
+ @else {
+ $start: translateX(0) translateY(0);
+ $end: map-get($slideDirections, $from);
+ }
+
+ // CSS Output
+ @include transition-start($dir) {
+ @include transition-basics($duration, $timing, $delay);
+ transition-property: transform, opacity;
+ backface-visibility: hidden;
+ transform: $start;
+
+ @if $fade { opacity: if($dir == in, 0, 1); }
+ }
+ @include transition-end($dir) {
+ transform: $end;
+
+ @if $fade { opacity: if($dir == in, 1, 0); }
+ }
+}
+
+// FADE
+@mixin fade(
+ $dir: in,
+ $from: 0,
+ $to: 1,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+ @include transition-start($dir) {
+ @include transition-basics($duration, $timing, $delay);
+ transition-property: opacity;
+ opacity: $from;
+ }
+ @include transition-end($dir) {
+ opacity: $to;
+ }
+}
+
+// HINGE
+@mixin hinge (
+ $dir: in,
+ $from: left,
+ $axis: edge,
+ $perspective: 2000px,
+ $turn-origin: from-back,
+ $fade: $motion-hinge-and-fade,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+
+ // Rotation directions when hinging from back vs. front
+ $rotationAmount: 90deg;
+ $rotationsBack: (
+ top: rotateX($rotationAmount * -1),
+ right: rotateY($rotationAmount * -1),
+ bottom: rotateX($rotationAmount),
+ left: rotateY($rotationAmount),
+ );
+ $rotationsFrom: (
+ top: rotateX($rotationAmount),
+ right: rotateY($rotationAmount),
+ bottom: rotateX($rotationAmount * -1),
+ left: rotateY($rotationAmount * -1),
+ );
+
+ // Rotation origin
+ $rotation: '';
+ @if $turn-origin == from-front {
+ $rotation: map-get($rotationsFrom, $from);
+ }
+ @else if $turn-origin == from-back {
+ $rotation: map-get($rotationsBack, $from);
+ }
+ @else {
+ @warn "`$turn-origin` must be either `from-back` or `from-front`";
+ }
+
+ // Start and end state
+ $start: '';
+ $end: '';
+ @if $dir == in {
+ $start: perspective($perspective) $rotation;
+ $end: rotate(0deg);
+ }
+ @else {
+ $start: rotate(0deg);
+ $end: perspective($perspective) $rotation;
+ }
+
+ // Turn axis
+ $origin: '';
+ @if $axis == edge {
+ $origin: $from;
+ }
+ @else {
+ $origin: center;
+ }
+
+ @include transition-start($dir) {
+ @include transition-basics($duration, $timing, $delay);
+ transition-property: transform, opacity;
+ transform: $start;
+ transform-origin: $origin;
+ @if $fade { opacity: if($dir == in, 0, 1); }
+ }
+ @include transition-end($dir) {
+ transform: $end;
+ @if $fade { opacity: if($dir == in, 1, 0); }
+ }
+}
+
+// SCALE
+@mixin scale(
+ $dir: in,
+ $from: 1.5,
+ $to: 1,
+ $fade: $motion-scale-and-fade,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+ @include transition-start($dir) {
+ @include transition-basics($duration, $timing, $delay);
+ transition-property: transform, property;
+ transform: scale($from);
+ @if $fade { opacity: if($dir == in, 0, 1) }
+ }
+ @include transition-end($dir) {
+ transform: scale($to);
+ @if $fade { opacity: if($dir == in, 1, 0) }
+ }
+}
+
+// SPIN
+@mixin spin(
+ $dir: in,
+ $amount: 0.75turn,
+ $ccw: false,
+ $fade: $motion-spin-and-fade,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default
+) {
+ $amount: turn-to-deg($amount);
+ $start: 0;
+ $end: 0;
+
+ @if $dir == in {
+ $start: if($ccw, $amount, $amount * -1);
+ $end: 0;
+ }
+ @else {
+ $start: 0;
+ $end: if($ccw, $amount * -1, $amount);
+ }
+
+ @include transition-start($dir) {
+ transition-property: transform, opacity;
+ transform: rotate($start);
+ @if $fade { opacity: if($dir == in, 0, 1); }
+ }
+ @include transition-end($dir) {
+ transform: rotate($end);
+ @if $fade { opacity: if($dir == in, 1, 0); }
+ }
+}
+
+
+// 2. Base Animations
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+// SHAKE
+@keyframes shake {
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
+ transform: translateX(7%);
+ }
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
+ transform: translateX(-7%);
+ }
+ 100% { transform: translateX(0); }
+}
+
+// SPINNERS
+@keyframes spin-cw {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+@keyframes spin-ccw {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(-360deg); }
+}
+
+// WIGGLE
+@keyframes wiggle {
+ 40%, 50%, 60% {
+ transform: rotate(7deg);
+ }
+ 35%, 45%, 55%, 65% {
+ transform: rotate(-7deg);
+ }
+ 0%, 30%, 70%, 100% { transform: rotate(0); }
+}
+
+@mixin animation(
+ $animation,
+ $duration: $motion-duration-default,
+ $timing: $motion-timing-default,
+ $delay: $motion-delay-default,
+ $iterations: null
+) {
+
+ animation-name: $animation;
+ animation-duration: $duration;
+ animation-timing-function: $timing;
+
+ backface-visibility: hidden;
+ transform: translate3d(0,0,0);
+
+ @if $delay != null {
+ animation-delay: $delay;
+ }
+ @if $iterations != null {
+ animation-iteration-count: $iterations;
+ }
+
+ @if $animation == null {
+ @warn "Please include an animation name";
+ }
+}
+
+// 3. HTML Exports
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+@include exports(motion) {
+ /*
+ Transitions
+ */
+
+ // Slide
+ .slideInDown { @include slide($from: top); }
+ .slideInLeft { @include slide($from: right); }
+ .slideInUp { @include slide($from: bottom); }
+ .slideInRight { @include slide($from: left); }
+ .slideOutBottom { @include slide($dir: out, $from: bottom); }
+ .slideOutRight { @include slide($dir: out, $from: right); }
+ .slideOutUp { @include slide($dir: out, $from: top); }
+ .slideOutLeft { @include slide($dir: out, $from: left); }
+
+ // Fade
+ .fadeIn { @include fade(in, 0, 1); }
+ .fadeOut { @include fade(out, 1, 0); }
+
+ // Hinge
+ .hingeInFromTop { @include hinge($dir: in, $from: top); }
+ .hingeInFromRight { @include hinge($dir: in, $from: right); }
+ .hingeInFromBottom { @include hinge($dir: in, $from: bottom); }
+ .hingeInFromLeft { @include hinge($dir: in, $from: left); }
+ .hingeInFromMiddleX { @include hinge($dir: in, $from: top, $axis: center); }
+ .hingeInFromMiddleY { @include hinge($dir: in, $from: right, $axis: center); }
+ .hingeOutFromTop { @include hinge($dir: out, $from: top); }
+ .hingeOutFromRight { @include hinge($dir: out, $from: right); }
+ .hingeOutFromBottom { @include hinge($dir: out, $from: bottom); }
+ .hingeOutFromLeft { @include hinge($dir: out, $from: left); }
+ .hingeOutFromMiddleX { @include hinge($dir: out, $from: top, $axis: center); }
+ .hingeOutFromMiddleY { @include hinge($dir: out, $from: right, $axis: center); }
+
+ // Scale
+ .zoomIn { @include scale(in, 1.5, 1); }
+ .zoomOut { @include scale(out, 0.5, 1); }
+
+ // Spin
+ .spinIn { @include spin(in, 0.75turn); }
+ .spinOut { @include spin(out, 0.75turn); }
+ .spinInCCW { @include spin(in, 0.75turn, true); }
+ .spinOutCCW { @include spin(out, 0.75turn, true); }
+
+ /*
+ Transition modifiers
+ */
+
+ // Duration
+ .slow { transition-duration: $motion-duration-slow !important; }
+ .fast { transition-duration: $motion-duration-fast !important; }
+
+ // Easing
+ @each $easing in map-keys($motion-timings) {
+ .#{$easing} {
+ transition-timing-function: map-get($motion-timings, $easing) !important;
+ }
+ }
+
+ // Delay
+ .delay { transition-delay: $motion-delay-short !important; }
+ .long-delay { transition-delay: $motion-delay-long !important; }
+
+ /*
+ Animations
+ */
+
+ .shake { @include animation(shake); }
+ .spin-cw { @include animation(spin-cw); }
+ .spin-ccw { @include animation(spin-ccw); }
+ .wiggle { @include animation(wiggle); }
+
+ /*
+ Animation modifiers
+ */
+
+ .shake,
+ .spin-cw,
+ .spin-ccw,
+ .wiggle {
+ // Repeat
+ &.infinite { animation-iteration-count: infinite; }
+
+ // Easing
+ @each $timing in map-keys($motion-timings) {
+ &.#{$timing} {
+ animation-timing-function: map-get($motion-timings, $timing) !important;
+ }
+ }
+
+ // Duration
+ &.slow { animation-duration: $motion-duration-slow !important; }
+ &.fast { animation-duration: $motion-duration-fast !important; }
+
+ // Delay
+ &.delay { animation-delay: $motion-delay-short !important; }
+ &.long-delay { animation-delay: $motion-delay-long !important; }
+ }
+ .stagger { @include stagger($motion-stagger-duration-default); }
+ .stort-stagger { @include stagger($motion-stagger-duration-default); }
+ .long-stagger { @include stagger($motion-stagger-duration-default); }
+}
+
+// View animation classes
+// - - - - - - - - - - - - - - - - - - - -
+
+// Applied to the immediate parent of the animating views
+.position-absolute {
+ overflow: hidden;
+ position: relative;
+}
+
+// Applied to the animating views
+.ui-animation {
+ &.ng-enter-active, &.ng-leave-active {
+ position: absolute !important;
+ backface-visibility: hidden;
+ -webkit-transform-style: preserve-3d;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_notification.scss b/afb-client/bower_components/foundation-apps/scss/components/_notification.scss
new file mode 100644
index 0000000..0386510
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_notification.scss
@@ -0,0 +1,207 @@
+/*
+ NOTIFICATION
+ ------------
+
+ An alert that pins to the corner of the screen when triggered by JavaScript. It can be set to disappear after a certain period of time, or to stay put until the user clicks on it. A custom action can be asigned to a notification as well.
+
+ Optionally, the notifications directive can also tap into the browser's native notification support, if it exists.
+*/
+
+/// @Foundation.settings
+// Notification
+$notification-default-position: right top !default;
+$notification-width: rem-calc(400) !default;
+$notification-offset: $global-padding !default;
+
+$notification-background: $primary-color !default;
+$notification-color: white !default;
+$notification-padding: $global-padding !default;
+$notification-radius: 4px !default;
+
+$notification-icon-size: 60px !default;
+$notification-icon-margin: $global-padding !default;
+$notification-icon-align: top !default;
+
+///
+
+%notification {
+ z-index: 1000;
+ display: flex;
+ position: relative;
+ margin-top: .5rem;
+ margin-bottom: .5rem;
+ display: none;
+
+ h1 {
+ font-size: 1.25em;
+ margin: 0;
+ }
+ p {
+ margin: 0;
+ }
+
+ // Placeholder animation
+ // transition: opacity 1s ease-out;
+
+ &.is-active {
+ display: flex;
+ }
+
+ .close-button {
+ color: white;
+ }
+}
+
+%notification-container {
+ z-index: 3000;
+ position: fixed;
+
+ display: flex;
+ flex-direction: column;
+}
+
+@mixin notification-layout(
+ $x: nth($notification-default-position, 1),
+ $y: nth($notification-default-position, 2),
+ $size: $notification-width,
+ $offset: $notification-offset
+) {
+ width: $size;
+
+ @if $x == right {
+ right: $offset;
+ }
+ @else if $x == left {
+ left: $offset;
+ }
+ @else if $x == middle {
+ left: 50%;
+ margin-left: -($size / 2);
+ }
+
+ @if $y == top {
+ top: $offset;
+ }
+ @else if $y == bottom {
+ top: auto;
+ bottom: $offset;
+ }
+
+ // On small screens, notifications are full width but maintain their vertical orientation
+ @include breakpoint(small only) {
+ width: auto;
+ left: $offset;
+ right: $offset;
+ margin-left: 0;
+ }
+}
+@mixin notification-style(
+ $background: $notification-background,
+ $color: $notification-color,
+ $padding: $notification-padding,
+ $radius: $notification-radius
+) {
+ background: $background;
+ padding: $padding;
+ border-radius: $radius;
+
+ &, h1, h2, h3, h4, h5, h6 {
+ color: $color;
+ }
+}
+
+@mixin notification(
+ $background: $notification-background,
+ $color: $notification-color,
+ $padding: $notification-padding,
+ $radius: $notification-radius
+) {
+ @extend %notification;
+ @include notification-style($background, $color, $padding, $radius);
+}
+
+@mixin notification-container(
+ $x: nth($notification-default-position, 1),
+ $y: nth($notification-default-position, 2),
+ $size: $notification-width,
+ $offset: $notification-offset
+) {
+ @extend %notification-container;
+ @include notification-layout($x, $y, $size, $offset);
+}
+
+@mixin notification-icon(
+ $size: $notification-icon-size,
+ $margin: $notification-icon-margin,
+ $align: $notification-icon-align
+) {
+ $alignments: (
+ top: flex-start,
+ middle: middle,
+ bottom: flex-end,
+ );
+ flex: 0 0 $size;
+ margin-right: $global-padding;
+ align-self: map-get($alignments, $align);
+
+ img {
+ width: 100%;
+ height: auto;
+ }
+}
+
+/*
+ CSS Output
+*/
+
+@include exports(notification) {
+ .notification {
+ @include notification;
+
+ &.success { @include notification-style($success-color) }
+ &.warning { @include notification-style($warning-color) }
+ &.alert { @include notification-style($alert-color) }
+ &.dark { @include notification-style($dark-color, #fff) }
+
+
+ }
+
+ .static-notification {
+ @include notification;
+
+ position: fixed !important;
+
+ &.top-right { @include notification-layout(right, top); }
+ &.top-left { @include notification-layout(left, top); }
+ &.top-middle { @include notification-layout(middle, top); }
+
+ &.bottom-right { @include notification-layout(right, bottom); }
+ &.bottom-left { @include notification-layout(left, bottom); }
+ &.bottom-middle { @include notification-layout(middle, bottom); }
+
+ &.success { @include notification-style($success-color) }
+ &.warning { @include notification-style($warning-color) }
+ &.alert { @include notification-style($alert-color) }
+ &.dark { @include notification-style($dark-color, #fff) }
+ }
+
+ .notification-container {
+ @include notification-container;
+
+ &.top-right { @include notification-layout(right, top); }
+ &.top-left { @include notification-layout(left, top); }
+ &.top-middle { @include notification-layout(middle, top); }
+
+ &.bottom-right { @include notification-layout(right, bottom); }
+ &.bottom-left { @include notification-layout(left, bottom); }
+ &.bottom-middle { @include notification-layout(middle, bottom); }
+ }
+
+ .notification-icon {
+ @include notification-icon;
+ }
+ .notification-content {
+ flex: 1;
+ }
+
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_off-canvas.scss b/afb-client/bower_components/foundation-apps/scss/components/_off-canvas.scss
new file mode 100644
index 0000000..d93e74c
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_off-canvas.scss
@@ -0,0 +1,169 @@
+/*
+ Off-canvas menu
+ ---------------
+
+ A generic container that stays fixed to the left, top, right, or bottom of the screen, and is summoned when needed. When an off-canvas panel is open, the app frame shifts over to reveal the menu.
+*/
+
+/// @Foundation.settings
+// Off-canvas
+$offcanvas-size-horizontal: 250px !default;
+$offcanvas-size-vertical: 250px !default;
+
+$offcanvas-background: #fff !default;
+$offcanvas-color: isitlight($offcanvas-background) !default;
+$offcanvas-padding: 0 !default;
+$offcanvas-shadow: 3px 0 10px rgba(black, 0.25) !default;
+$offcanvas-animation-speed: 0.25s !default;
+
+$offcanvas-frame-selector: '.grid-frame' !default;
+///
+
+%off-canvas {
+ position: fixed;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+ transition: transform $offcanvas-animation-speed ease-out;
+ z-index: 2;
+
+ // Active state
+ &.is-active {
+ transform: translate(0,0) !important;
+ }
+
+ // Frame styles
+ & ~ #{$offcanvas-frame-selector} {
+ transform: translate(0,0,0);
+ transition: transform 0.25s ease-out;
+ backface-visibility: hidden;
+ background: white;
+ }
+}
+@mixin off-canvas-detached {
+ z-index: 0;
+ box-shadow: none;
+
+ &, &.is-active {
+ transform: none;
+ }
+
+ & ~ #{$offcanvas-frame-selector} {
+ z-index: 1;
+ box-shadow: 0 0 15px rgba(0,0,0,0.5);
+ }
+}
+
+@mixin off-canvas-layout(
+ $position: left,
+ $size: default,
+ $shadow: $offcanvas-shadow
+) {
+ /*
+ Get shadow values for later use
+ */
+ $shadow-length: '';
+ $shadow-size: '';
+ $shadow-color: '';
+ @if hasvalue($shadow) {
+ $shadow-length: get-shadow-value($shadow, x);
+ $shadow-size: get-shadow-value($shadow, size);
+ $shadow-color: get-shadow-value($shadow, color);
+ }
+
+ /*
+ Sizing
+ */
+ @if $position == left or $position == right {
+ @if $size == default {
+ $size: $offcanvas-size-horizontal;
+ }
+ width: $size;
+ height: 100%;
+ }
+ @else {
+ @if $size == default {
+ $size: $offcanvas-size-vertical;
+ }
+ height: $size;
+ width: 100%;
+ }
+
+ /*
+ Positioning
+ */
+ @if $position == left {
+ top: 0;
+ left: 0;
+ @if hasvalue($shadow) { box-shadow: inset (-$shadow-length) 0 $shadow-size $shadow-color; }
+ transform: translateX(-100%);
+ &.is-active {
+ & ~ #{$offcanvas-frame-selector} { transform: translateX($size) !important; }
+ }
+ }
+ @else if $position == right {
+ left: auto;
+ top: 0;
+ right: 0;
+ @if hasvalue($shadow) { box-shadow: inset $shadow-length 0 $shadow-size $shadow-color; }
+ transform: translateX(100%);
+ &.is-active {
+ & ~ #{$offcanvas-frame-selector} { transform: translateX(-$size) !important; }
+ }
+ }
+ @else if $position == top {
+ top: 0;
+ left: 0;
+ transform: translateY(-100%);
+ @if hasvalue($shadow) { box-shadow: inset 0 (-$shadow-length) $shadow-size $shadow-color; }
+ &.is-active {
+ & ~ #{$offcanvas-frame-selector} { transform: translateY($size) !important; }
+ }
+ }
+ @else if $position == bottom {
+ top: auto;
+ bottom: 0;
+ left: 0;
+ transform: translateY(100%);
+ @if hasvalue($shadow) { box-shadow: inset 0 $shadow-length $shadow-size $shadow-color; }
+ &.is-active {
+ & ~ #{$offcanvas-frame-selector} { transform: translateY(-$size) !important; }
+ }
+ }
+}
+
+@mixin off-canvas-style(
+ $background: $offcanvas-background,
+ $color: $offcanvas-color,
+ $padding: $offcanvas-padding
+) {
+ background: $background;
+
+ @if $color == auto {
+ color: isitlight($background, #000, #fff);
+ }
+ @else {
+ color: $color;
+ }
+
+ @if hasvalue($padding) {
+ padding: $padding;
+ }
+}
+
+@include exports(off-canvas) {
+ .off-canvas {
+ @extend %off-canvas;
+ @include off-canvas-layout;
+ @include off-canvas-style;
+
+ &.top { @include off-canvas-layout(top); }
+ &.right { @include off-canvas-layout(right); }
+ &.bottom { @include off-canvas-layout(bottom); }
+ &.left { @include off-canvas-layout(left); }
+
+ &.detached { @include off-canvas-detached; }
+
+ &.primary { @include off-canvas-style($primary-color, auto); }
+ &.dark { @include off-canvas-style($dark-color, auto); }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_panel.scss b/afb-client/bower_components/foundation-apps/scss/components/_panel.scss
new file mode 100644
index 0000000..5855419
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_panel.scss
@@ -0,0 +1,134 @@
+/*
+ PANEL
+ -----
+
+ The friendly panel is an all-purpose container for hiding content off-screen.
+
+ Features:
+ - Position at top, right, bottom, or left
+ - Anchor to grid block or window
+ - Define max width or height
+ - Transform into grid block depending on screen size
+*/
+
+/// @Foundation.settings
+// Panel
+$panel-size-horizontal: 300px !default;
+$panel-size-vertical: 300px !default;
+$panel-padding: 0 !default;
+
+$panel-background: #fff !default;
+$panel-shadow: 3px 0 10px rgba(black, 0.25) !default;
+
+// DEPRECATED: these variables will be removed in a future version.
+$panel-animation-speed: 0.25s !default;
+///
+
+%panel-base {
+ display: block;
+ position: absolute;
+ z-index: 100;
+ overflow-y: auto;
+ display: none;
+
+ &.is-active {
+ display: block;
+ }
+}
+
+@mixin panel-layout(
+ $position: left,
+ $size: default,
+ $shadow: $panel-shadow
+) {
+ @if $size == default {
+ @if $position == left or $position == right {
+ $size: $panel-size-horizontal;
+ }
+ @if $position == top or $position == bottom {
+ $size: $panel-size-vertical;
+ }
+ }
+
+ /*
+ Direction
+ */
+ @if $position == top {
+ top: 0;
+ left: 0;
+ width: 100%;
+ }
+ @else if $position == right {
+ top: 0;
+ right: 0;
+ height: 100%;
+ }
+ @else if $position == bottom {
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ }
+ @else if $position == left {
+ top: 0;
+ left: 0;
+ height: 100%;
+ }
+
+ /*
+ Sizing
+ */
+ // Horizontal panels are always all the way tall and have a set width
+ @if $position == left or $position == right {
+ @if unit($size) == '%' {
+ width: $size;
+ }
+ @else {
+ width: 100%;
+ @include breakpoint($size) {
+ width: $size;
+ }
+ }
+ }
+ // (For now) vertical panels don't change size
+ @if $position == top or $position == bottom {
+ height: $size;
+ }
+
+ /*
+ Shadows
+ */
+ $shadow-distance: get-shadow-value($shadow, x);
+ $shadow-size: get-shadow-value($shadow, size);
+ $shadow-color: get-shadow-value($shadow, color);
+ &.is-active {
+ @if $position == left { box-shadow: $shadow-distance 0 $shadow-size $shadow-color; }
+ @else if $position == right { box-shadow: (-$shadow-distance) 0 $shadow-size $shadow-color; }
+ @else if $position == top { box-shadow: 0 $shadow-distance $shadow-size $shadow-color; }
+ @else if $position == bottom { box-shadow: 2px (-$shadow-distance) $shadow-size $shadow-color; }
+ }
+}
+
+@mixin panel-style(
+ $padding: $panel-padding,
+ $background: $panel-background
+) {
+ /*
+ Basic styles
+ */
+ padding: $padding;
+ background: $background;
+}
+
+@include exports(panel) {
+ .panel {
+ @extend %panel-base;
+ @include panel-style;
+ }
+
+ .panel-top { @include panel-layout(top); }
+ .panel-right { @include panel-layout(right); }
+ .panel-bottom { @include panel-layout(bottom); }
+ .panel-left { @include panel-layout(left); }
+
+ .panel-fixed { position: fixed; }
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_popup.scss b/afb-client/bower_components/foundation-apps/scss/components/_popup.scss
new file mode 100644
index 0000000..03403d6
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_popup.scss
@@ -0,0 +1,68 @@
+/*
+ POPUP
+ -----
+
+ A floating container that can anchor to any other on-screen element, and contain any content, including grid blocks or panels.
+*/
+
+/// @Foundation.settings
+// Popup
+$popup-width: rem-calc(300) !default;
+$popup-background: #fff !default;
+$popup-border: 0 !default;
+$popup-radius: 0 !default;
+$popup-shadow: 0 0 10px rgba(#000, 0.25) !default;
+///
+
+%popup {
+ position: absolute;
+ z-index: 1000;
+ opacity: 0;
+ overflow: hidden;
+ transition: opacity 0.25s ease-out;
+ pointer-events: none;
+
+ &.tether-enabled {
+ opacity: 1;
+ pointer-events: auto;
+ }
+}
+
+@mixin popup-layout(
+ $width: $popup-width
+) {
+ width: $popup-width;
+}
+@mixin popup-style(
+ $background: $popup-background,
+ $color: #000,
+ $radius: $popup-radius,
+ $shadow: $popup-shadow,
+ $border: $popup-border
+) {
+ background: $background;
+ border-radius: $radius;
+ box-shadow: $shadow;
+ border: $border;
+}
+
+@mixin popup(
+ $width: $popup-width,
+ $background: $popup-background,
+ $radius: $popup-radius,
+ $shadow: $popup-shadow,
+ $border: $popup-border
+) {
+ @extend %popup;
+ @include popup-layout($width);
+ @include popup-style($background, isitlight($background), $radius, $shadow, $border);
+}
+
+@include exports(popup) {
+ .popup {
+ @include popup;
+
+ &.dark { @include popup-style($dark-color, #fff); }
+ &.primary { @include popup-style($primary-color, isitlight($primary-color)); }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_switch.scss b/afb-client/bower_components/foundation-apps/scss/components/_switch.scss
new file mode 100644
index 0000000..7710ad4
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_switch.scss
@@ -0,0 +1,130 @@
+/*
+ SWITCH
+ ------
+*/
+
+/// @Foundation.settings
+// Switch
+$switch-width: rem-calc(50) !default;
+$switch-height: rem-calc(32) !default;
+$switch-background: #ccc !default;
+$switch-background-active: $primary-color !default;
+$switch-border: 0 !default;
+$switch-radius: 9999px !default;
+$switch-animation-speed: 0.15s !default;
+
+$switch-paddle-color: white !default;
+$switch-paddle-offset: 4px !default;
+///
+
+%switch {
+ position: relative;
+ overflow: hidden;
+ display: inline-block;
+
+ > input {
+ position: absolute;
+ left: -9999px;
+ outline: none;
+ }
+
+ > label {
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ display: block;
+ width: 100%;
+ height: 100%;
+ cursor: pointer;
+ margin: 0;
+
+ // Paddle
+ &::after {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+ }
+}
+
+/*
+ Defines the dimmensions of the switch.
+
+ $width - width of the switch.
+ $height - height of the switch.
+*/
+@mixin switch-layout(
+ $width: $switch-width,
+ $height: $switch-height
+) {
+ width: $width;
+ height: $height;
+
+ > label {
+ &::after {
+ width: $height;
+ height: $height;
+ }
+ }
+ input:checked + label {
+ &::after {
+ left: $width - $height;
+ }
+ }
+}
+
+@mixin switch-style(
+ $background: $switch-background,
+ $background-active: $switch-background-active,
+ $border: $switch-border,
+ $radius: $switch-radius,
+ $paddle-color: $switch-paddle-color,
+ $paddle-offset: $switch-paddle-offset,
+ $animation-speed: $switch-animation-speed
+) {
+ @if hasvalue($border) {
+ border: $border;
+ }
+ border-radius: $radius;
+
+ > label {
+ background: $background;
+
+ &::after {
+ background: $paddle-color;
+ border-radius: $radius;
+ transition: left $animation-speed ease-out;
+
+ @if hasvalue($paddle-offset) {
+ border: $paddle-offset solid $background
+ }
+ }
+ }
+
+ input:checked + label {
+ background: $background-active;
+ margin: 0;
+
+ &::after {
+ @if hasvalue($paddle-offset) {
+ border-color: $background-active;
+ }
+ }
+ }
+}
+
+@mixin switch() {
+ @extend %switch;
+ @include switch-layout;
+ @include switch-style;
+}
+
+@include exports(switch) {
+ .switch {
+ @include switch;
+
+ &.small { @include switch-layout(rem-calc(40), rem-calc(26)); }
+ &.large { @include switch-layout(rem-calc(60), rem-calc(38)); }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_tabs.scss b/afb-client/bower_components/foundation-apps/scss/components/_tabs.scss
new file mode 100644
index 0000000..7e4293e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_tabs.scss
@@ -0,0 +1,100 @@
+/*
+ TABS
+ ----
+*/
+
+/// @Foundation.settings
+// Tabs
+$tabstrip-background: transparent !default;
+
+$tab-title-background: $gray-light !default;
+$tab-title-background-hover: smartscale($tab-title-background, 5%) !default;
+$tab-title-background-active: smartscale($tab-title-background, 3%) !default;
+$tab-title-color: isitlight($tab-title-background) !default;
+$tab-title-color-active: $tab-title-color !default;
+
+$tab-title-padding: $global-padding !default;
+$tab-content-padding: $global-padding !default;
+///
+
+@mixin tabstrip(
+ $orientation: horizontal,
+ $background: $tabstrip-background
+) {
+ /*
+ Container styles
+ */
+ display: flex;
+ background: $background;
+
+ @if $orientation == vertical {
+ flex-flow: column nowrap;
+ }
+ @else {
+ flex-flow: row wrap;
+ }
+}
+
+@mixin tabstrip-item(
+ $background: $tab-title-background,
+ $background-hover: $tab-title-background-hover,
+ $background-active: $tab-title-background-active,
+ $color: $tab-title-color,
+ $color-active: $tab-title-color-active,
+ $padding: $tab-title-padding
+) {
+ background: $background;
+ padding: $padding;
+ line-height: 1;
+ margin: 0;
+ flex: 0 1 auto;
+ cursor: pointer;
+ color: $color;
+
+ &.is-active {
+ background: $background-active;
+ color: $color-active;
+
+ &:hover {
+ background: $background-hover;
+ }
+ }
+ &:hover {
+ background: $background-hover;
+ }
+}
+
+@mixin tab-content(
+ $padding: $tab-content-padding
+) {
+ padding: $padding;
+}
+
+@mixin tab-content-item {
+ display: none;
+ &.is-active {
+ display: block;
+ }
+}
+
+@include exports(tabs) {
+ .tabs {
+ @include tabstrip(horizontal);
+
+ &.vertical {
+ @include tabstrip(vertical);
+ }
+
+ .tab-item {
+ @include tabstrip-item;
+ }
+ }
+
+ .tab-contents {
+ @include tab-content;
+
+ .tab-content {
+ @include tab-content-item;
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_title-bar.scss b/afb-client/bower_components/foundation-apps/scss/components/_title-bar.scss
new file mode 100644
index 0000000..e73bb4e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_title-bar.scss
@@ -0,0 +1,135 @@
+/*
+ TITLE BAR
+ ---------
+
+ A navigational component which can display the current screen the user is on, along with additional controls or menu items.
+
+ The title bar includes classes to create center, left, and right sections, which can be used in any combination. However, in the markup, the sections must come in this order:
+ - Center
+ - Left
+ - Right
+*/
+
+/// @Foundation.settings
+// Title Bar
+$titlebar-center-width: 50% !default;
+$titlebar-side-width: (100% - $titlebar-center-width) / 2 !default;
+$titlebar-background: #eee !default;
+$titlebar-color: #000 !default;
+$titlebar-border: 1px solid #ccc !default;
+$titlebar-padding: $global-padding !default;
+$titlebar-item-classes: (
+ center: 'center',
+ left: 'left',
+ right: 'right',
+ title: 'title',
+) !default;
+///
+
+%title-bar {
+ $center: map-get($titlebar-item-classes, center);
+ $left: map-get($titlebar-item-classes, left);
+ $right: map-get($titlebar-item-classes, right);
+ $title: map-get($titlebar-item-classes, title);
+
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ justify-content: flex-start;
+ overflow: visible;
+
+ // Denotes the title of the bar
+ .#{$title} {
+ font-weight: bold;
+ }
+
+ // Denotes left, right, and center sections of the bar
+ .#{$left}, .#{$center}, .#{$right} {
+ display: block;
+ white-space: nowrap;
+ overflow: visible;
+
+ // If only one section is in use, stretch it all the way out
+ &:first-child:last-child {
+ flex: 1;
+ margin: 0;
+ }
+ }
+
+ // Left always comes first, then center, then right
+ // The left and right sections have the same width
+ .#{$left} {
+ order: 1;
+ flex: 0 0 $titlebar-side-width;
+ }
+ .#{$center} {
+ order: 2;
+ flex: 0 0 $titlebar-center-width;
+ text-align: center;
+ }
+ .#{$right} {
+ order: 3;
+ flex: 0 0 $titlebar-side-width;
+ text-align: right;
+ }
+
+ // If only left and right are in use, stretch them both out equally
+ .#{$left}:first-child {
+ flex: 1 1 auto;
+ }
+ .#{$left}:first-child + .#{$right}:last-child {
+ flex: 1 1 auto;
+ }
+
+ // If only center and right are in use, shift the center section into the right position
+ .#{$center}:first-child:not(:last-child) {
+ margin-left: $titlebar-side-width;
+ }
+ // If only center and left are in use, override the above style
+ .#{$center} + .#{$left} {
+ margin-right: -($titlebar-side-width);
+ }
+}
+
+@mixin title-bar-style(
+ $background: $titlebar-background,
+ $color: $titlebar-color,
+ $border: $titlebar-border,
+ $padding: $titlebar-padding
+) {
+ background: $background;
+ color: $color;
+ padding: $padding;
+ border-bottom: $border;
+}
+
+@mixin title-bar(
+ $background: $titlebar-background,
+ $color: $titlebar-color,
+ $border: $titlebar-border,
+ $padding: $titlebar-padding
+) {
+ @extend %title-bar;
+ @include title-bar-style($background, $color, $border, $padding);
+}
+
+@include exports(title-bar) {
+ .title-bar {
+ @include title-bar;
+
+ &.primary {
+ @include title-bar-style($primary-color, isitlight($primary-color));
+ a, a:hover { color: isitlight($primary-color); }
+ @if using(iconic) { .iconic { @include color-icon(isitlight($primary-color)); } }
+ }
+ &.dark {
+ @include title-bar-style($dark-color, #fff);
+ a, a:hover { color: #fff; }
+ @if using(iconic) { .iconic { @include color-icon(#fff); } }
+ }
+ }
+ .title-bar-bottom {
+ border-bottom: 0;
+ border-top: $titlebar-border;
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_typography.scss b/afb-client/bower_components/foundation-apps/scss/components/_typography.scss
new file mode 100755
index 0000000..8e64a89
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_typography.scss
@@ -0,0 +1,345 @@
+/*
+ TYPOGRAPHY
+ ----------
+
+ Includes typographic resets for many common elements, and a few helper classes.
+ - Headers
+ - Subheaders
+ - Lead paragraphs
+ - Ordered/unordered lists
+ - Code samples
+ - Anchors
+ - Dividers
+ - Blockquotes
+ - Acronyms
+*/
+
+/// @Foundation.settings
+// Typography
+// We use these to control header font styles
+$header-font-family: $body-font-family !default;
+$header-font-weight: $font-weight-normal !default;
+$header-font-style: $font-weight-normal !default;
+$header-font-color: #222 !default;
+$header-line-height: 1.4 !default;
+$header-top-margin: .2rem !default;
+$header-bottom-margin: .5rem !default;
+$header-text-rendering: optimizeLegibility !default;
+
+// We use these to control header font sizes
+$h1-font-size: rem-calc(44) !default;
+$h2-font-size: rem-calc(37) !default;
+$h3-font-size: rem-calc(27) !default;
+$h4-font-size: rem-calc(23) !default;
+$h5-font-size: rem-calc(18) !default;
+$h6-font-size: 1rem !default;
+
+// We use these to control header size reduction on small screens
+$h1-font-reduction: rem-calc(10) !default;
+$h2-font-reduction: rem-calc(10) !default;
+$h3-font-reduction: rem-calc(5) !default;
+$h4-font-reduction: rem-calc(5) !default;
+$h5-font-reduction: 0 !default;
+$h6-font-reduction: 0 !default;
+
+// These control how subheaders are styled.
+$subheader-line-height: 1.4 !default;
+$subheader-font-color: scale-color($header-font-color, $lightness: 35%) !default;
+$subheader-font-weight: $font-weight-normal !default;
+$subheader-top-margin: .2rem !default;
+$subheader-bottom-margin: .5rem !default;
+
+// A general <small> styling
+$small-font-size: 60% !default;
+$small-font-color: scale-color($header-font-color, $lightness: 35%) !default;
+
+// We use these to style paragraphs
+$paragraph-font-family: inherit !default;
+$paragraph-font-weight: $font-weight-normal !default;
+$paragraph-font-size: 1rem !default;
+$paragraph-line-height: 1.6 !default;
+$paragraph-margin-bottom: rem-calc(20) !default;
+$paragraph-aside-font-size: rem-calc(14) !default;
+$paragraph-aside-line-height: 1.35 !default;
+$paragraph-aside-font-style: italic !default;
+$paragraph-text-rendering: optimizeLegibility !default;
+
+// We use these to style <code> tags
+$code-color: grayscale($primary-color) !default;
+$code-font-family: Consolas, 'Liberation Mono', Courier, monospace !default;
+$code-font-weight: $font-weight-normal !default;
+$code-background-color: scale-color($secondary-color, $lightness: 70%) !default;
+$code-border-size: 1px !default;
+$code-border-style: solid !default;
+$code-border-color: scale-color($code-background-color, $lightness: -10%) !default;
+$code-padding: rem-calc(2) rem-calc(5) rem-calc(1) !default;
+
+// We use these to style anchors
+$anchor-text-decoration: none !default;
+$anchor-text-decoration-hover: none !default;
+$anchor-font-color: $primary-color !default;
+$anchor-font-color-hover: scale-color($anchor-font-color, $lightness: -14%) !default;
+
+// We use these to style the <hr> element
+$hr-border-width: 1px !default;
+$hr-border-style: solid !default;
+$hr-border-color: #ddd !default;
+$hr-margin: rem-calc(20) !default;
+
+// We use these to style lists
+$list-font-family: $paragraph-font-family !default;
+$list-font-size: $paragraph-font-size !default;
+$list-line-height: $paragraph-line-height !default;
+$list-margin-bottom: $paragraph-margin-bottom !default;
+$list-style-position: outside !default;
+$list-side-margin: 1.1rem !default;
+$list-ordered-side-margin: 1.4rem !default;
+$list-side-margin-no-bullet: 0 !default;
+$list-nested-margin: rem-calc(20) !default;
+$definition-list-header-weight: $font-weight-bold !default;
+$definition-list-header-margin-bottom: .3rem !default;
+$definition-list-margin-bottom: rem-calc(12) !default;
+
+// We use these to style blockquotes
+$blockquote-font-color: scale-color($header-font-color, $lightness: 35%) !default;
+$blockquote-padding: rem-calc(9 20 0 19) !default;
+$blockquote-border: 1px solid #ddd !default;
+$blockquote-cite-font-size: rem-calc(13) !default;
+$blockquote-cite-font-color: scale-color($header-font-color, $lightness: 23%) !default;
+$blockquote-cite-link-color: $blockquote-cite-font-color !default;
+
+// Acronym styles
+$acronym-underline: 1px dotted #ddd !default;
+///
+
+@mixin lead {
+ font-size: $paragraph-font-size + rem-calc(3.5);
+ line-height: 1.6;
+}
+
+@mixin subheader {
+ line-height: $subheader-line-height;
+ color: $subheader-font-color;
+ font-weight: $subheader-font-weight;
+ margin-top: $subheader-top-margin;
+ margin-bottom: $subheader-bottom-margin;
+}
+
+@include exports(typography) {
+ /* Typography resets */
+ div,
+ dl,
+ dt,
+ dd,
+ ul,
+ ol,
+ li,
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ pre,
+ form,
+ p,
+ blockquote,
+ th,
+ td {
+ margin:0;
+ padding:0;
+ }
+
+ /* Default Link Styles */
+ a {
+ color: $anchor-font-color;
+ text-decoration: $anchor-text-decoration;
+ line-height: inherit;
+
+ &[ui-sref] {
+ cursor: pointer;
+ }
+
+ &:hover,
+ &:focus {
+ color: $anchor-font-color-hover;
+ @if $anchor-text-decoration-hover != $anchor-text-decoration {
+ text-decoration: $anchor-text-decoration-hover;
+ }
+ }
+
+ img { border:none; }
+ }
+
+ /* Default paragraph styles */
+ p {
+ font-family: $paragraph-font-family;
+ font-weight: $paragraph-font-weight;
+ font-size: $paragraph-font-size;
+ line-height: $paragraph-line-height;
+ margin-bottom: $paragraph-margin-bottom;
+ text-rendering: $paragraph-text-rendering;
+
+ &.lead { @include lead; }
+
+ & aside {
+ font-size: $paragraph-aside-font-size;
+ line-height: $paragraph-aside-line-height;
+ font-style: $paragraph-aside-font-style;
+ }
+ }
+
+ /* Default header styles */
+ h1, h2, h3, h4, h5, h6 {
+ font-family: $header-font-family;
+ font-weight: $header-font-weight;
+ font-style: $header-font-style;
+ color: $header-font-color;
+ text-rendering: $header-text-rendering;
+ margin-top: $header-top-margin;
+ margin-bottom: $header-bottom-margin;
+ line-height: $header-line-height;
+
+ small {
+ font-size: $small-font-size;
+ color: $small-font-color;
+ line-height: 0;
+ }
+ }
+
+ h1 { font-size: $h1-font-size - $h1-font-reduction; }
+ h2 { font-size: $h2-font-size - $h2-font-reduction; }
+ h3 { font-size: $h3-font-size - $h3-font-reduction; }
+ h4 { font-size: $h4-font-size - $h4-font-reduction; }
+ h5 { font-size: $h5-font-size - $h5-font-reduction; }
+ h6 { font-size: $h6-font-size - $h6-font-reduction; }
+
+ .subheader { @include subheader; }
+
+ hr {
+ border: $hr-border-style $hr-border-color;
+ border-width: $hr-border-width 0 0;
+ clear: both;
+ margin: $hr-margin 0 ($hr-margin - rem-calc($hr-border-width));
+ height: 0;
+ }
+
+ /* Helpful Typography Defaults */
+ em,
+ i {
+ font-style: italic;
+ line-height: inherit;
+ }
+
+ strong,
+ b {
+ font-weight: $font-weight-bold;
+ line-height: inherit;
+ }
+
+ small {
+ font-size: $small-font-size;
+ color: $small-font-color;
+ line-height: inherit;
+ }
+
+ code {
+ font-family: $code-font-family;
+ font-weight: $code-font-weight;
+ color: $code-color;
+ background-color: $code-background-color;
+ border-width: $code-border-size;
+ border-style: $code-border-style;
+ border-color: $code-border-color;
+ padding: $code-padding;
+ }
+
+ /* Lists */
+ ul,
+ ol,
+ dl {
+ font-size: $list-font-size;
+ line-height: $list-line-height;
+ margin-bottom: $list-margin-bottom;
+ list-style-position: $list-style-position;
+ font-family: $list-font-family;
+ }
+
+ /* Lists */
+ ul, ol {
+ margin-left: $list-side-margin;
+ li {
+ ul,
+ ol {
+ margin-left: $list-nested-margin;
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ /* Lists without bullets */
+ ul.no-bullet {
+ &, li ul, li ol {
+ list-style-type: none;
+ }
+ margin-left: $list-side-margin-no-bullet;
+ }
+
+ /* Definition Lists */
+ dl {
+ dt {
+ margin-bottom: $definition-list-header-margin-bottom;
+ font-weight: $definition-list-header-weight;
+ }
+ dd { margin-bottom: $definition-list-margin-bottom; }
+ }
+
+ /* Abbreviations */
+ abbr,
+ acronym {
+ text-transform: uppercase;
+ font-size: 90%;
+ color: $body-font-color;
+ border-bottom: $acronym-underline;
+ cursor: help;
+ }
+ abbr {
+ text-transform: none;
+ }
+
+ /* Blockquotes */
+ blockquote {
+ margin: 0 0 $paragraph-margin-bottom;
+ padding: $blockquote-padding;
+ border-left: $blockquote-border;
+
+ cite {
+ display: block;
+ font-size: $blockquote-cite-font-size;
+ color: $blockquote-cite-font-color;
+ &:before {
+ content: "\2014 \0020";
+ }
+
+ a,
+ a:visited {
+ color: $blockquote-cite-link-color;
+ }
+ }
+ }
+ blockquote,
+ blockquote p {
+ line-height: $paragraph-line-height;
+ color: $blockquote-font-color;
+ }
+
+ @include breakpoint(medium) {
+ h1,h2,h3,h4,h5,h6 { line-height: $header-line-height; }
+ h1 { font-size: $h1-font-size; }
+ h2 { font-size: $h2-font-size; }
+ h3 { font-size: $h3-font-size; }
+ h4 { font-size: $h4-font-size; }
+ h5 { font-size: $h5-font-size; }
+ h6 { font-size: $h6-font-size; }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/components/_utilities.scss b/afb-client/bower_components/foundation-apps/scss/components/_utilities.scss
new file mode 100755
index 0000000..dabe22f
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/components/_utilities.scss
@@ -0,0 +1,160 @@
+/*
+ UTILITIES
+ ---------
+
+ Responsive helper classes to assist you in quickly doing basic formatting and layout.
+
+ Features:
+ - Vertical alignment
+ - Visibility
+ - Text alignment
+ - Floating
+*/
+
+$block-selector: '[class*="grid-block"]';
+
+@mixin show-for($size, $prop: block) {
+ &:not(.ng-hide) {
+ display: none !important;
+ @include breakpoint($size) {
+ display: $prop !important;
+ }
+ }
+}
+
+@mixin show-for-only($size, $prop: block) {
+ &:not(.ng-hide) {
+ display: none !important;
+ @include breakpoint($size only) {
+ display: $prop !important;
+ }
+ }
+}
+
+@mixin hide-for($size, $prop: block) {
+ &:not(.ng-hide) {
+ display: $prop !important;
+ @include breakpoint($size) {
+ display: none !important;
+ }
+ }
+}
+
+@mixin hide-for-only($size, $prop: block) {
+ &:not(.ng-hide) {
+ display: $prop !important;
+ @include breakpoint($size only) {
+ display: none !important;
+ }
+ }
+}
+
+@include exports(utilities) {
+ // Vertical alignment
+ .v-align {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ $align-values: (
+ 'top': flex-start,
+ 'center': center,
+ 'bottom': flex-end,
+ );
+
+ @each $orient in (top, center, bottom) {
+ .align-#{$orient} {
+ align-self: map-get($align-values, $orient);
+ }
+ }
+
+ @each $size in $breakpoint-classes {
+ @each $orient in (top, center, bottom) {
+ @include breakpoint($size) {
+ .#{$size}-align-#{$orient} {
+ align-self: map-get($align-values, $orient);
+ }
+ }
+ }
+ }
+ }
+
+ // Visibility
+ .hide { display: none !important; }
+
+ .invisible { visibility: hidden; }
+
+ @each $size in $breakpoint-classes {
+ .hide-for-#{$size} {
+ @include hide-for($size);
+ &#{$block-selector} { @include hide-for($size, flex); }
+ }
+
+ .show-for-#{$size} {
+ @include show-for($size);
+ &#{$block-selector} { @include show-for($size, flex); }
+ }
+
+ .hide-for-#{$size}-only {
+ @include hide-for-only($size);
+ &#{$block-selector} { @include hide-for-only($size, flex); }
+ }
+
+ .show-for-#{$size}-only {
+ @include show-for-only($size);
+ &#{$block-selector} { @include show-for-only($size, flex); }
+ }
+ }
+
+ @each $orientation in (portrait, landscape) {
+ .hide-for-#{$orientation} {
+ @include breakpoint($orientation) {
+ display: none !important;
+ &#{$block-selector} { display: flex !important; }
+ }
+ }
+
+ .show-for-#{$orientation} {
+ display: none !important;
+
+ @include breakpoint($orientation) {
+ display: block !important;
+ &#{$block-selector} { display: flex !important; }
+ }
+ }
+ }
+
+ /*
+ Text alignment
+ */
+ @each $align in (left, right, center, justify) {
+ .text-#{$align} {
+ text-align: $align;
+ }
+
+ @each $size in $breakpoint-classes {
+ @include breakpoint($size) {
+ .#{$size}-text-#{$align} {
+ text-align: $align;
+ }
+ }
+
+ @include breakpoint($size only) {
+ .#{$size}-only-text-#{$align} {
+ text-align: $align;
+ }
+ }
+ }
+ }
+
+ /*
+ Floating
+ */
+ .clearfix { @include clearfix; }
+
+ @each $float in (left, right, none) {
+ .float-#{$float} {
+ float: #{$float};
+ }
+ }
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/foundation.scss b/afb-client/bower_components/foundation-apps/scss/foundation.scss
new file mode 100755
index 0000000..42ff302
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/foundation.scss
@@ -0,0 +1,50 @@
+// Foundation for Apps
+// by ZURB
+// foundation.zurb.com
+// Licensed under MIT Open Source
+
+$foundation-version: '1.1.0';
+
+// Make sure the charset is set appropriately
+@charset "UTF-8";
+
+// Libraries (let's make Normalize an external dependency eventually)
+@import
+ "vendor/normalize";
+
+// Helpers
+@import
+ "helpers/functions",
+ "helpers/mixins",
+ "helpers/breakpoints",
+ "helpers/images";
+
+// Global styles
+@import
+ "global";
+
+// Components
+@import
+ "components/iconic",
+ "components/action-sheet",
+ "components/block-list",
+ "components/button",
+ "components/button-group",
+ "components/card",
+ "components/extras",
+ "components/forms",
+ "components/grid",
+ "components/title-bar",
+ "components/label",
+ "components/list",
+ "components/menu-bar",
+ "components/modal",
+ "components/motion",
+ "components/notification",
+ "components/off-canvas",
+ "components/popup",
+ "components/switch",
+ "components/tabs",
+ "components/accordion",
+ "components/typography",
+ "components/utilities";
diff --git a/afb-client/bower_components/foundation-apps/scss/helpers/_breakpoints.scss b/afb-client/bower_components/foundation-apps/scss/helpers/_breakpoints.scss
new file mode 100644
index 0000000..36300d7
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/helpers/_breakpoints.scss
@@ -0,0 +1,154 @@
+// Foundation for Apps
+//
+// BREAKPOINTS
+// -----------
+// Foundation for Apps has three core breakpoints: small (> 0), medium (>= 640), and large (>= 1024).
+// There are two additional breakpoints, xlarge, and xxlarge, which (by default) do not output as sizing classes.
+// Access named breakpoints using the mixin breakpoint($size), where $size is a breakpoint value.
+// You can also pass an em, rem, or pixel value into this mixin to generate an em-based media query.
+// Create new named breakpoints using the $breakpoints map. Change which named breakpoints get their own classes by modifying the $breakpoint-classes map.
+// NOTE: If you change the $breakpoints map, know that all values must be ordered by width, smallest width first. So 0 is always your first value.
+
+// 1. Variables
+// - - - - - - - - - - - - - - -
+
+/// @Foundation.settings
+// Breakpoints
+// These are our named breakpoints. You can use them in our breakpoint function like this: @include breakpoint(medium) { // Medium and larger styles }
+$breakpoints: (
+ small: rem-calc(0),
+ medium: rem-calc(640),
+ large: rem-calc(1200),
+ xlarge: rem-calc(1440),
+ xxlarge: rem-calc(1920),
+) !default;
+
+// All of the names in this list will be output as classes in your CSS, like small-12, medium-6, and so on.
+$breakpoint-classes: (small medium large) !default;
+///
+
+// 2. Mixins
+// - - - - - - - - - - - - - - -
+
+/// Wraps a media query around the content you put inside the mixin. This mixin accepts a number of values:
+/// - If a string is passed, the mixin will look for it in the $breakpoints map, and use a media query there.
+/// - If a pixel value is passed, it will be converted to an em value using $rem-base.
+/// - If a rem value is passed, the unit will be changed to em.
+/// - If an em value is passed, the value will be used as-is.
+///
+/// @param {mixed} $val - Breakpoint name or px/em/rem value to process.
+///
+/// @output If the breakpoint is "0px and larger", outputs the content. Otherwise, outputs the content wrapped in a media query.
+@mixin breakpoint($val: small) {
+ // Size or keyword
+ $bp: nth($val, 1);
+ // Value for max-width media queries
+ $bpMax: 0;
+ // Direction of media query (up, down, or only)
+ $dir: if(length($val) > 1, nth($val, 2), up);
+ // Eventual output
+ $str: 'only screen';
+ // Is it a named media query?
+ $named: false;
+
+ // Orientation media queries have a unique syntax
+ @if $bp == 'landscape' or $bp == 'portrait' {
+ $str: $str + ' and (orientation: #{$bp})';
+ }
+
+ @else {
+ // Try to pull a named breakpoint out of the $breakpoints map
+ @if type-of($bp) == 'string' {
+ @if map-has-key($breakpoints, $bp) {
+ @if $dir == 'only' {
+ $next-bp: map-next($breakpoints, $bp);
+ @if $next-bp == null {
+ $bpMax: null;
+ }
+ @else {
+ $bpMax: $next-bp - (1/16);
+ }
+ }
+ $bp: map-get($breakpoints, $bp);
+ $named: true;
+ }
+ @else {
+ $bp: 0;
+ }
+ }
+
+ // Pixel and unitless values are converted to rems
+ @if unit($bp) == 'px' or unit($bp) == '' {
+ $bp: rem-calc($bp);
+ }
+ // Finally, the rem value is turned into an em value
+ $bp: strip-unit($bp) * 1em;
+
+ // Skip media query creation if the input is "0 up" or "0 down"
+ @if $bp > 0 or $dir == 'only' {
+ // And lo, a media query was born
+ @if $dir == 'only' {
+ @if $named == true {
+ $str: $str + ' and (min-width: #{$bp})';
+ @if $bpMax != null {
+ $str: $str + ' and (max-width: #{$bpMax})';
+ }
+ }
+ @else {
+ @debug 'ERROR: Only named media queries can have an "only" range.';
+ }
+ }
+ @else if $dir == 'down' {
+ $max: $bp - (1/16);
+ $str: $str + ' and (max-width: #{$max})';
+ }
+ @else {
+ $str: $str + ' and (min-width: #{$bp})';
+ }
+ }
+ }
+
+ // Output
+ @if $bp == 0em and $dir != 'only' {
+ @content;
+ }
+ @else {
+ @media #{$str} {
+ @content;
+ }
+ }
+}
+
+/// Prefixes selector $class with breakpoint keywords, allowing you to create a batch of breakpoint classes with one chunk of code. If you want to skip a breakpoint (like small, because mobile first and all that), add values to the $omit parameter.
+///
+/// @param {string} $class - Class to prefix with the breakpoint name and a hyphen.
+/// @param {list} $omit - Named breakpoints to skip. No class will be added with breakpoints in this list.
+@mixin each-breakpoint($class, $omit: ()) {
+ // Iterate through breakpoint classes
+ @each $size in $breakpoint-classes {
+ // Only do something if the breakpoint is not in $omit
+ @if index($omit, $size) == null {
+ $val: map-get($breakpoints, $size);
+ // Prefix $class with $size and a hyphen
+ .#{$size + '-' + $class} {
+ @include breakpoint($size) {
+ @content;
+ }
+ }
+ }
+ }
+}
+
+// 3. CSS Output
+// - - - - - - - - - - - - - - -
+
+// Meta styles are included in all builds, as they are a dependancy of the Javascript.
+// Used to provide media query values for javascript components.
+// Forward slash placed around everything to convince PhantomJS to read the value.
+
+meta.foundation-version {
+ font-family: "#{$foundation-version}";
+}
+meta.foundation-mq {
+ font-family: "#{map-serialize($breakpoints)}";
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/helpers/_functions.scss b/afb-client/bower_components/foundation-apps/scss/helpers/_functions.scss
new file mode 100755
index 0000000..cb2ab37
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/helpers/_functions.scss
@@ -0,0 +1,343 @@
+// Foundation for Apps ALPHA
+// by ZURB
+// foundation.zurb.com
+// Licensed under MIT Open Source
+
+$include-css: () !default;
+$modules: () !default;
+$rem-base: 16px !default;
+
+/// Checks if a module is in use.
+@function using($name) {
+ // Import from global scope
+ $include-css: $include-css !global;
+ $module-key: map-get($include-css, $name);
+
+ @if $module-key == true or $module-key == null {
+ @return true;
+ }
+ @else {
+ @return false;
+ }
+}
+
+/// Checks if a module's CSS has already been exported.
+@function imported($name) {
+ // Import from global scope
+ $modules: $modules !global;
+ // Check if the module is already on the imported list
+ @if type-of(index($modules, $name)) == 'number' {
+ @return true;
+ }
+ @else {
+ @return false;
+ }
+}
+
+/// Outputs the chunk of content passed if component $name hasn't yet been output.
+/// This prevents code duplication by keeping track of which components have already been output.
+///
+/// @param {string} $name - Name of component to output
+///
+/// @output The content passed, if the component has not yet been exported.
+@mixin exports($name) {
+ // Check if the module has already been imported
+ @if not(imported($name)) {
+ // Check if the module should be used
+ @if using($name) {
+ $modules: append($modules, $name) !global;
+ @content;
+ }
+ }
+}
+
+/// Map Serialize
+/// Converts a Sass map to a URL-encoded string, like this: `key1=value1&key2=value2`. We use this function to encode the media queries in the `$breakpoints` variable, so it can be transferred to our JavaScript for use there.
+///
+/// @param {map} $map - Map to convert.
+///
+/// @return A string with a map converted to a string.
+@function map-serialize($map) {
+ $str: '';
+ @each $key, $value in $map {
+ $str: $str + $key + '=' + $value + '&';
+ }
+ $str: str-slice($str, 1, -2);
+
+ @return $str;
+}
+
+/// Map Next
+/// Find the next key in a map.
+///
+/// @param {map} $map - Map to traverse.
+/// @param {mixed} $key - Key to use as a starting point.
+///
+/// @return The value for the key after `$key` if `$key` was found. If `$key` was not found, or `$key` was the last value in the map, returns null.
+@function map-next($map, $key) {
+ // Store the values of the map as a list, so we can access them with nth
+ $values: map-values($map);
+
+ // Ghetto for loop
+ $i: 1;
+ $found: false;
+ @each $val in map-keys($map) {
+ @if $found == false {
+ @if ($key == $val) {
+ $found: true;
+ }
+ $i: $i + 1;
+ }
+ }
+
+ // If the key doesn't exist, or it's the last key in the map, return null
+ @if $i > length($map) {
+ @return null;
+ }
+ // Otherwise return the value
+ @else {
+ @return nth($values, $i);
+ }
+}
+
+/// Is It Light?
+/// Checks the lightness of $color, and if it passes the $threshold of lightness, it returns the `$yes` color. Otherwise, it returns the `$no` color. Use this function to dynamically output a foreground color based on a given background color.
+///
+/// @param {color} $color - Color to check the lightness of.
+/// @param {color} $yes - Color to return if $color is light.
+/// @param {color} $no - Color to return if $color is dark.
+/// @param {percentage} $threshold - Threshold of lightness to check against.
+///
+/// @return The $yes color or $no color.
+@function isitlight($color, $yes: #000, $no: #fff, $threshold: 60%) {
+ @if (lightness($color) > $threshold) {
+ @return $yes;
+ }
+ @else {
+ @return $no;
+ }
+}
+
+/// Smart Scale
+/// Scales a color to be lighter if it's light, or darker if it's dark. Use this function to "fade" a color appropriate to its lightness.
+///
+/// @param {color} $color - Color to scale.
+/// @param {percentage} $scale - Amount to scale up or down.
+/// @param {percentage} $threshold - Threshold of lightness to check against.
+///
+/// @return A scaled color.
+@function smartscale($color, $scale: 5%, $threshold: 60%) {
+ @if lightness($color) > $threshold {
+ $scale: -$scale;
+ }
+ @return scale-color($color, $lightness: $scale);
+}
+
+/// Has Value
+/// Returns true if a value is not 0, null, or none. Use this function to check for values like `border: 0` or `box-shadow: none`.
+///
+/// @param $val - Value to check.
+///
+/// @return True if `$val` is not 0, null, or none.
+@function hasvalue($val) {
+ @if $val == null or $val == none {
+ @return false;
+ }
+ @if type-of($val) == 'number' and strip-unit($val) == 0 {
+ @return false;
+ }
+ @return true;
+}
+
+/// Get Side
+/// Determine a top/right/bottom/right value on a padding, margin, etc. property, no matter how many values were passed in. Use this function if you need to know the specific side of a value, but don't know if the value is using shorthand.
+///
+/// @param {list|number} $val - Value to analyze. Should be a shorthand sizing property, e.g. "1em 2em 1em"
+/// @param {keyword} $side - Side to return. Should be top, right, bottom, or left.
+///
+/// @return A single value based on `$val` and `$side`.
+@function get-side($val, $side) {
+ $length: length($val);
+
+ @if $length == 1 {
+ @return $val;
+ }
+ @if $length == 2 {
+ @return map-get((
+ top: nth($val, 1),
+ bottom: nth($val, 1),
+ left: nth($val, 2),
+ right: nth($val, 2),
+ ), $side);
+ }
+ @if $length == 3 {
+ @return map-get((
+ top: nth($val, 1),
+ left: nth($val, 2),
+ right: nth($val, 2),
+ bottom: nth($val, 3),
+ ), $side);
+ }
+ @if $length == 4 {
+ @return map-get((
+ top: nth($val, 1),
+ right: nth($val, 2),
+ bottom: nth($val, 3),
+ left: nth($val, 4),
+ ), $side);
+ }
+}
+
+/// Get Border Value
+/// Given border $val, find a specific element of the border, which is $elem. The possible values for $elem are width, style, and color.
+///
+/// @param {list} $val - Border value to find a value in.
+/// @param {keyword} $elem - Border component to extract.
+///
+/// @param If the value exists, returns the value. If the value is not in the border definition, the function will return a 0px width, solid style, or black border.
+ @function get-border-value($val, $elem) {
+ // Find the width, style, or color and return it
+ @each $v in $val {
+ $type: type-of($v);
+ @if $elem == width and $type == 'number' {
+ @return $v;
+ }
+ @if $elem == style and $type == 'string' {
+ @return $v;
+ }
+ @if $elem == color and $type == 'color' {
+ @return $v;
+ }
+ }
+
+ // Defaults
+ $defaults: (
+ width: 0,
+ style: solid,
+ color: black,
+ );
+ @return map-get($defaults, $elem);
+ }
+
+/// Get Shadow Value
+/// Given shadow value $val, find a specific element of the shadow, which is $elem. The possible values for $elem are x, y, size, spread, color, and inset.
+///
+/// @param {list} $val - Shadow value to find a value in.
+/// @param {keyword} $elem - Shadow component to extract.
+///
+/// @return If the value exists, returns the value. If the value is not set, returns false. If `$elem` is "inset", returns true, otherwise false.
+@function get-shadow-value($val, $elem) {
+ // Return "none" if there's no shadow
+ @if $val == none {
+ @return none;
+ }
+
+ // Inset and color are always at the beginning and end
+ @if $elem == inset {
+ @return nth($val, 1) == inset;
+ }
+ @if $elem == color {
+ @if type-of(nth($val, -1)) == color {
+ @return nth($val, -1);
+ }
+ @else {
+ @return black;
+ }
+ }
+
+ // The rest of the values are located perilously in the middle
+ $values: ();
+ @each $v in $val {
+ @if type-of($v) == 'number' {
+ $values: append($values, $v);
+ }
+ }
+ @if $elem == x {
+ @if length($values) >= 1 {
+ @return nth($values, 1);
+ }
+ @else {
+ @return 0;
+ }
+ }
+ @else if $elem == y {
+ @if length($values) >= 2 {
+ @return nth($values, 2);
+ }
+ @else {
+ @return 0;
+ }
+ }
+ @else if $elem == size {
+ @if length($values) >= 3 {
+ @return nth($values, 3);
+ }
+ @else {
+ @return 0;
+ }
+ }
+ @else if $elem == spread {
+ @if length($values) >= 4 {
+ @return nth($values, 4);
+ }
+ @else {
+ @return 0;
+ }
+ }
+ @else {
+ @return false;
+ }
+}
+
+/// Strip Unit
+/// Removes the unit (e.g. px, em, rem) from a value, returning the number only.
+///
+/// @param {number} $num - Number to strip unit from.
+///
+/// @return The same number, sans unit.
+@function strip-unit($num) {
+ @return $num / ($num * 0 + 1);
+}
+
+/// Turn to Degrees
+/// Converts a turn unit to the equivalent unit in degrees. 1turn is equal to 360 degrees. Not all browsers support turn, so this function allows us to use turns while outputting a value that all browsers understand.
+///
+/// @param {number} $value - Turn value to convert.
+///
+/// @return The same value, but in degrees.
+@function turn-to-deg($value) {
+ @return strip-unit($value) * 360deg;
+}
+
+/// Convert to Rem
+/// Converts a pixel value to matching rem value. *Any* value passed, regardless of unit, is assumed to be a pixel value. By default, the base pixel value used to calculate the rem value is taken from the `$rem-base` variable.
+///
+/// @param {number} $value - Pixel value to convert.
+///
+/// @return A number in rems, calculated based on the given value and the base pixel value.
+@function convert-to-rem($value, $base-value: $rem-base) {
+ $value: strip-unit($value) / strip-unit($base-value) * 1rem;
+ @if ($value == 0rem) { $value: 0; } // Turn 0rem into 0
+ @return $value;
+}
+
+/// Rem Calculator
+/// Converts one or more pixel values into matching rem values. This function works a lot like `convert-to-rem`, except it can convert more than one value at once, which is useful when setting multiple values on a `margin` or `padding` property.
+///
+/// @param {number|list} $values - One or more values to convert. Be sure to separate them with spaces and not commas. If you need to convert a comma-separated list, wrap the list in parentheses.
+///
+/// @return A list of converted values.
+@function rem-calc($values, $base-value: null) {
+ @if $base-value == null {
+ $base-value: $rem-base;
+ }
+ $max: length($values);
+
+ @if $max == 1 { @return convert-to-rem(nth($values, 1), $base-value); }
+
+ $remValues: ();
+ @for $i from 1 through $max {
+ $remValues: append($remValues, convert-to-rem(nth($values, $i), $base-value));
+ }
+ @return $remValues;
+}
diff --git a/afb-client/bower_components/foundation-apps/scss/helpers/_images.scss b/afb-client/bower_components/foundation-apps/scss/helpers/_images.scss
new file mode 100644
index 0000000..c91052e
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/helpers/_images.scss
@@ -0,0 +1,19 @@
+@function image-triangle($color: #000) {
+ $color: rgb(red($color), green($color), blue($color));
+ @return 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="24" viewBox="0 0 32 24"><polygon points="0,0 32,0 16,24" style="fill: #{$color}"></polygon></svg>';
+}
+
+@mixin image-checkmark($color: #000) {
+ $color: rgb(red($color), green($color), blue($color));
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="32" viewBox="0 0 32 32"><path fill="#{$color}" d="M16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zm6.906 8.875l2.219 2.031-12.063 13.281-6.188-6.188 2.125-2.125 3.938 3.938 9.969-10.938z"/></svg>');
+
+ // IE10 fallback, since it doesn't support SVG data URLs
+ @media screen and (min-width:0\0) {
+ @if lightness($color) < 60% {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUeNrMl0FugzAQRY3TRZeoFyhVL0BOkGTXJezaHZwguUnECaCrdFd6gqQnCN11Uyk5QekNOlONJWMVGMCgfGlkEIY3HnsG2xFM3d96PjQB2AJsWdPtAPYOln+dTwXnuw4DHEGzBvNFN6EDCTiS9XIAwB40acNoucKoxODIie0AwAOCu8KOSnIiNx/MakK+A7sW9oTferxx3fP3T1nURoBG/irGVahHwjHm/Ggx7E3TMVdrQmoP0gngghhpZQ3QvG/EdPLUelARWI8Aycjq9Md0qMIdbcNhjmOKLoY7quk3l1Rebeqg4AwFkmq7LWGOh1pmNY0etZAWSq0OX8HoS4JvWuCopbSY26EGR/CW86K0BF+pwkLwlPuyHJhOCl5oe4ZtF++vOqST+GdOYwO+71pN2VNAjmQGPCe42weuHDg0PI8olUwnYrXTGQJH9gxq8l1LKvrQx4O6/YY32Kp/ugb3ey7gZ4xAzuhYiYTxB/UHZFAuaREVXZ2g6yFlvEC2yoKEmbsRZYNgVLk2JeaOaG+xLHN+WCszDWMqLGOrJFa1DlApjSdwoHJGqGzLIb0+cas0wh5Bh780ngswx8GJD7h8sHg2wLA/mfDLPZpdxOF0quP5rwADAAFIzSRvu1m5AAAAAElFTkSuQmCC');
+ }
+ @else {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT9JREFUeNrMV4sRgyAMDU7gCI6AE7QjMILdoCO4Cd2g3aB2Ah2hG7Qb0ODRO2r98Anqu8txKvISII/AwBFKKY6NQDugHSe6NWgPtBtjrAMKIHGF1ip/6H+qGOIC7a7ioccofMkF2kvRQY8lfKY8FSqXyFPjZyaYvebYtGg5pMUbrcQseeqHzPogVyAHwyHXXPfZ/cCMA3rqOXGkF9NObbwOl6HsFS5BdNKaXTnTj2dGXinRYGQnx74CiNTOlt/cMfpeJSEh+dnlJyCU2iIkq4CInIemtIsDcmYth+Tc9xCDyHQSMeReDow4UVnv89Dj2yUNx5wYkreB+6dPw9pH2QbOxJBr1D5SLEccuEZmEP8O1Po64aByi8IVehxLAvL/8oz4TFjefHspyTYvSvdVlu/iYrKLq9mal1O29fX8I8AANpIQzC0hTdEAAAAASUVORK5CYII=');
+ }
+ }
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-apps/scss/helpers/_mixins.scss b/afb-client/bower_components/foundation-apps/scss/helpers/_mixins.scss
new file mode 100644
index 0000000..403fe61
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/helpers/_mixins.scss
@@ -0,0 +1,123 @@
+// Foundation for Apps
+//
+// Mixins
+// ------
+// The framework comes with a number of mixins that help you easily create common small components,
+// like triangles and menu icons.
+
+/// CSS Triangle
+/// Creates a CSS triangle, which can be used for dropdown arrows, popup tails, and more. Use this mixin inside a `&::before` or `&::after` selector, to attach the triangle to an existing element.
+///
+/// @param {number} $triangle-size - Width of the triangle.
+/// @param {color} $triangle-color - Color of the triangle.
+/// @param {keyword} $triangle-direction - Direction the triangle points. Can be `top`, `right`, `bottom`, or `left`.
+@mixin css-triangle($triangle-size, $triangle-color, $triangle-direction) {
+ content: "";
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset $triangle-size;
+ @if ($triangle-direction == top) {
+ border-color: $triangle-color transparent transparent transparent;
+ border-top-style: solid;
+ }
+ @if ($triangle-direction == bottom) {
+ border-color: transparent transparent $triangle-color transparent;
+ border-bottom-style: solid;
+ }
+ @if ($triangle-direction == left) {
+ border-color: transparent transparent transparent $triangle-color;
+ border-left-style: solid;
+ }
+ @if ($triangle-direction == right) {
+ border-color: transparent $triangle-color transparent transparent;
+ border-right-style: solid;
+ }
+}
+
+// @mixins
+//
+/// Hamburger
+/// Creates a three-line menu icon, affectionately referred to as the "hamburger icon".
+///
+/// @param {number} $width - Width of the icon, in rem units.
+/// @param {number|boolean} $left - Left offset of the icon. Set to `false` to center the icon horizontally.
+/// @param {number|boolean} $top - Top offset of the icon. Set to `false` to center the icon vertically.
+/// @param {number} $thickness - Height of each line in the icon.
+/// @param {number} $gap - Amount of space between each line.
+/// @param {color} $color - Color of the lines.
+/// @param {color} $hover-color - Color of the lines on hover.
+@mixin hamburger($width, $left, $top, $thickness, $gap, $color, $hover-color, $offcanvas) {
+ span::after {
+ content: "";
+ position: absolute;
+ display: block;
+ height: 0;
+
+ @if $offcanvas {
+ @if $top {
+ top: $top;
+ }
+ @else {
+ top: 50%;
+ margin-top: -$width/2;
+ }
+ @if $left {
+ left: $left;
+ }
+ @else {
+ left: ($tabbar-menu-icon-width - $width)/2;
+ }
+ }
+ @else {
+ top: 50%;
+ margin-top: -$width/2;
+ #{$opposite-direction}: $topbar-link-padding;
+ }
+
+ box-shadow:
+ 0 0px 0 $thickness $color,
+ 0 $gap + $thickness 0 $thickness $color,
+ 0 (2 * $gap + 2*$thickness) 0 $thickness $color;
+ width: $width;
+ }
+ span:hover:after {
+ box-shadow:
+ 0 0px 0 $thickness $hover-color,
+ 0 $gap + $thickness 0 $thickness $hover-color,
+ 0 (2 * $gap + 2*$thickness) 0 $thickness $hover-color;
+ }
+}
+
+/// Clearfix
+/// Uses the micro clearfix hack popularized by Nicolas Gallagher. Include this mixin on a container if its children are all floated, to give the container a proper height.
+///
+/// @see http://nicolasgallagher.com/micro-clearfix-hack/
+@mixin clearfix {
+ &:before, &:after { content: " "; display: table; }
+ &:after { clear: both; }
+}
+
+/// Invisible Element
+/// Makes an element visually hidden, but accessible.
+///
+/// @see http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
+@mixin element-invisible {
+ position: absolute !important;
+ height: 1px;
+ width: 1px;
+ overflow: hidden;
+ clip: rect(1px, 1px, 1px, 1px);
+}
+
+/// Invisible Element Off
+/// Reverses the CSS output by the `element-invisible()` mixin.
+@mixin element-invisible-off {
+ position: static !important;
+ height: auto;
+ width: auto;
+ overflow: visible;
+ clip: auto;
+}
+
+$text-input-selectors: 'input[type="text"], input[type="password"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="week"], input[type="email"], input[type="number"], input[type="search"], input[type="tel"], input[type="time"], input[type="url"], input[type="color"], textarea';
diff --git a/afb-client/bower_components/foundation-apps/scss/vendor/_normalize.scss b/afb-client/bower_components/foundation-apps/scss/vendor/_normalize.scss
new file mode 100644
index 0000000..ae8bc83
--- /dev/null
+++ b/afb-client/bower_components/foundation-apps/scss/vendor/_normalize.scss
@@ -0,0 +1,425 @@
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-icon-fonts/.bower.json b/afb-client/bower_components/foundation-icon-fonts/.bower.json
new file mode 100644
index 0000000..917fa26
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/.bower.json
@@ -0,0 +1,17 @@
+{
+ "name": "foundation-icon-fonts",
+ "main": [
+ "foundation-icons.css"
+ ],
+ "ignore": [],
+ "homepage": "https://github.com/zurb/foundation-icon-fonts",
+ "_release": "afed003521",
+ "_resolution": {
+ "type": "branch",
+ "branch": "master",
+ "commit": "afed003521ff971bc614de68bba2676e16ce39f4"
+ },
+ "_source": "git://github.com/zurb/foundation-icon-fonts.git",
+ "_target": "*",
+ "_originalSource": "foundation-icon-fonts"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-icon-fonts/.fontcustom-data b/afb-client/bower_components/foundation-icon-fonts/.fontcustom-data
new file mode 100644
index 0000000..8753d7b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/.fontcustom-data
@@ -0,0 +1,298 @@
+{
+ "fonts": [
+ "fontcustom_10588e4d0af9f9cd5471c9540658204b.ttf",
+ "fontcustom_10588e4d0af9f9cd5471c9540658204b.woff",
+ "fontcustom_10588e4d0af9f9cd5471c9540658204b.eot",
+ "fontcustom_10588e4d0af9f9cd5471c9540658204b.svg"
+ ],
+ "templates": [
+ "fontcustom.css",
+ "fontcustom-preview.html"
+ ],
+ "file_name": "fontcustom_10588e4d0af9f9cd5471c9540658204b",
+ "glyphs": [
+ "fi-address-book",
+ "fi-alert",
+ "fi-align-center",
+ "fi-align-justify",
+ "fi-align-left",
+ "fi-align-right",
+ "fi-anchor",
+ "fi-annotate",
+ "fi-archive",
+ "fi-arrow-down",
+ "fi-arrow-left",
+ "fi-arrow-right",
+ "fi-arrow-up",
+ "fi-arrows-compress",
+ "fi-arrows-expand",
+ "fi-arrows-in",
+ "fi-arrows-out",
+ "fi-asl",
+ "fi-asterisk",
+ "fi-at-sign",
+ "fi-background-color",
+ "fi-battery-empty",
+ "fi-battery-full",
+ "fi-battery-half",
+ "fi-bitcoin-circle",
+ "fi-bitcoin",
+ "fi-blind",
+ "fi-bluetooth",
+ "fi-bold",
+ "fi-book-bookmark",
+ "fi-book",
+ "fi-bookmark",
+ "fi-braille",
+ "fi-burst-new",
+ "fi-burst-sale",
+ "fi-burst",
+ "fi-calendar",
+ "fi-camera",
+ "fi-check",
+ "fi-checkbox",
+ "fi-clipboard-notes",
+ "fi-clipboard-pencil",
+ "fi-clipboard",
+ "fi-clock",
+ "fi-closed-caption",
+ "fi-cloud",
+ "fi-comment-minus",
+ "fi-comment-quotes",
+ "fi-comment-video",
+ "fi-comment",
+ "fi-comments",
+ "fi-compass",
+ "fi-contrast",
+ "fi-credit-card",
+ "fi-crop",
+ "fi-crown",
+ "fi-css3",
+ "fi-database",
+ "fi-die-five",
+ "fi-die-four",
+ "fi-die-one",
+ "fi-die-six",
+ "fi-die-three",
+ "fi-die-two",
+ "fi-dislike",
+ "fi-dollar-bill",
+ "fi-dollar",
+ "fi-download",
+ "fi-eject",
+ "fi-elevator",
+ "fi-euro",
+ "fi-eye",
+ "fi-fast-forward",
+ "fi-female-symbol",
+ "fi-female",
+ "fi-filter",
+ "fi-first-aid",
+ "fi-flag",
+ "fi-folder-add",
+ "fi-folder-lock",
+ "fi-folder",
+ "fi-foot",
+ "fi-foundation",
+ "fi-graph-bar",
+ "fi-graph-horizontal",
+ "fi-graph-pie",
+ "fi-graph-trend",
+ "fi-guide-dog",
+ "fi-hearing-aid",
+ "fi-heart",
+ "fi-home",
+ "fi-html5",
+ "fi-indent-less",
+ "fi-indent-more",
+ "fi-info",
+ "fi-italic",
+ "fi-key",
+ "fi-laptop",
+ "fi-layout",
+ "fi-lightbulb",
+ "fi-like",
+ "fi-link",
+ "fi-list-bullet",
+ "fi-list-number",
+ "fi-list-thumbnails",
+ "fi-list",
+ "fi-lock",
+ "fi-loop",
+ "fi-magnifying-glass",
+ "fi-mail",
+ "fi-male-female",
+ "fi-male-symbol",
+ "fi-male",
+ "fi-map",
+ "fi-marker",
+ "fi-megaphone",
+ "fi-microphone",
+ "fi-minus-circle",
+ "fi-minus",
+ "fi-mobile-signal",
+ "fi-mobile",
+ "fi-monitor",
+ "fi-mountains",
+ "fi-music",
+ "fi-next",
+ "fi-no-dogs",
+ "fi-no-smoking",
+ "fi-page-add",
+ "fi-page-copy",
+ "fi-page-csv",
+ "fi-page-delete",
+ "fi-page-doc",
+ "fi-page-edit",
+ "fi-page-export-csv",
+ "fi-page-export-doc",
+ "fi-page-export-pdf",
+ "fi-page-export",
+ "fi-page-filled",
+ "fi-page-multiple",
+ "fi-page-pdf",
+ "fi-page-remove",
+ "fi-page-search",
+ "fi-page",
+ "fi-paint-bucket",
+ "fi-paperclip",
+ "fi-pause",
+ "fi-paw",
+ "fi-paypal",
+ "fi-pencil",
+ "fi-photo",
+ "fi-play-circle",
+ "fi-play-video",
+ "fi-play",
+ "fi-plus",
+ "fi-pound",
+ "fi-power",
+ "fi-previous",
+ "fi-price-tag",
+ "fi-pricetag-multiple",
+ "fi-print",
+ "fi-prohibited",
+ "fi-projection-screen",
+ "fi-puzzle",
+ "fi-quote",
+ "fi-record",
+ "fi-refresh",
+ "fi-results-demographics",
+ "fi-results",
+ "fi-rewind-ten",
+ "fi-rewind",
+ "fi-rss",
+ "fi-safety-cone",
+ "fi-save",
+ "fi-share",
+ "fi-sheriff-badge",
+ "fi-shield",
+ "fi-shopping-bag",
+ "fi-shopping-cart",
+ "fi-shuffle",
+ "fi-skull",
+ "fi-social-500px",
+ "fi-social-adobe",
+ "fi-social-amazon",
+ "fi-social-android",
+ "fi-social-apple",
+ "fi-social-behance",
+ "fi-social-bing",
+ "fi-social-blogger",
+ "fi-social-delicious",
+ "fi-social-designer-news",
+ "fi-social-deviant-art",
+ "fi-social-digg",
+ "fi-social-dribbble",
+ "fi-social-drive",
+ "fi-social-dropbox",
+ "fi-social-evernote",
+ "fi-social-facebook",
+ "fi-social-flickr",
+ "fi-social-forrst",
+ "fi-social-foursquare",
+ "fi-social-game-center",
+ "fi-social-github",
+ "fi-social-google-plus",
+ "fi-social-hacker-news",
+ "fi-social-hi5",
+ "fi-social-instagram",
+ "fi-social-joomla",
+ "fi-social-lastfm",
+ "fi-social-linkedin",
+ "fi-social-medium",
+ "fi-social-myspace",
+ "fi-social-orkut",
+ "fi-social-path",
+ "fi-social-picasa",
+ "fi-social-pinterest",
+ "fi-social-rdio",
+ "fi-social-reddit",
+ "fi-social-skillshare",
+ "fi-social-skype",
+ "fi-social-smashing-mag",
+ "fi-social-snapchat",
+ "fi-social-spotify",
+ "fi-social-squidoo",
+ "fi-social-stack-overflow",
+ "fi-social-steam",
+ "fi-social-stumbleupon",
+ "fi-social-treehouse",
+ "fi-social-tumblr",
+ "fi-social-twitter",
+ "fi-social-vimeo",
+ "fi-social-windows",
+ "fi-social-xbox-20",
+ "fi-social-yahoo",
+ "fi-social-yelp",
+ "fi-social-youtube",
+ "fi-social-zerply",
+ "fi-social-zurb",
+ "fi-sound",
+ "fi-star",
+ "fi-stop",
+ "fi-strikethrough",
+ "fi-subscript",
+ "fi-superscript",
+ "fi-tablet-landscape",
+ "fi-tablet-portrait",
+ "fi-target-two",
+ "fi-target",
+ "fi-telephone-accessible",
+ "fi-telephone",
+ "fi-text-color",
+ "fi-thumbnails",
+ "fi-ticket",
+ "fi-torso-business",
+ "fi-torso-female",
+ "fi-torso",
+ "fi-torsos-all-female",
+ "fi-torsos-all",
+ "fi-torsos-female-male",
+ "fi-torsos-male-female",
+ "fi-torsos",
+ "fi-trash",
+ "fi-trees",
+ "fi-trophy",
+ "fi-underline",
+ "fi-universal-access",
+ "fi-unlink",
+ "fi-unlock",
+ "fi-upload-cloud",
+ "fi-upload",
+ "fi-usb",
+ "fi-video",
+ "fi-volume-none",
+ "fi-volume-strike",
+ "fi-volume",
+ "fi-web",
+ "fi-wheelchair",
+ "fi-widget",
+ "fi-wrench",
+ "fi-x-circle",
+ "fi-x",
+ "fi-yen",
+ "fi-zoom-in",
+ "fi-zoom-out"
+ ]
+} \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-icon-fonts/.gitignore b/afb-client/bower_components/foundation-icon-fonts/.gitignore
new file mode 100644
index 0000000..ccc9fd9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/.gitignore
@@ -0,0 +1 @@
+*.DS_Store \ No newline at end of file
diff --git a/afb-client/bower_components/foundation-icon-fonts/README.md b/afb-client/bower_components/foundation-icon-fonts/README.md
new file mode 100644
index 0000000..65874f8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/README.md
@@ -0,0 +1,5 @@
+# Quickstart
+
+```
+bower install foundation-icon-fonts
+```
diff --git a/afb-client/bower_components/foundation-icon-fonts/_foundation-icons.scss b/afb-client/bower_components/foundation-icon-fonts/_foundation-icons.scss
new file mode 100644
index 0000000..edb4b99
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/_foundation-icons.scss
@@ -0,0 +1,596 @@
+/*
+ * Foundation Icons v 3.0
+ * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3
+ * MIT License
+ */
+
+ $fi-path: "." !default;
+
+@font-face {
+ font-family: "foundation-icons";
+ src: url("#{$fi-path}/foundation-icons.eot");
+ src: url("#{$fi-path}/foundation-icons.eot?#iefix") format("embedded-opentype"),
+ url("#{$fi-path}/foundation-icons.woff") format("woff"),
+ url("#{$fi-path}/foundation-icons.ttf") format("truetype"),
+ url("#{$fi-path}/foundation-icons.svg#fontcustom") format("svg");
+ font-weight: normal;
+ font-style: normal;
+}
+
+.fi-address-book:before,
+.fi-alert:before,
+.fi-align-center:before,
+.fi-align-justify:before,
+.fi-align-left:before,
+.fi-align-right:before,
+.fi-anchor:before,
+.fi-annotate:before,
+.fi-archive:before,
+.fi-arrow-down:before,
+.fi-arrow-left:before,
+.fi-arrow-right:before,
+.fi-arrow-up:before,
+.fi-arrows-compress:before,
+.fi-arrows-expand:before,
+.fi-arrows-in:before,
+.fi-arrows-out:before,
+.fi-asl:before,
+.fi-asterisk:before,
+.fi-at-sign:before,
+.fi-background-color:before,
+.fi-battery-empty:before,
+.fi-battery-full:before,
+.fi-battery-half:before,
+.fi-bitcoin-circle:before,
+.fi-bitcoin:before,
+.fi-blind:before,
+.fi-bluetooth:before,
+.fi-bold:before,
+.fi-book-bookmark:before,
+.fi-book:before,
+.fi-bookmark:before,
+.fi-braille:before,
+.fi-burst-new:before,
+.fi-burst-sale:before,
+.fi-burst:before,
+.fi-calendar:before,
+.fi-camera:before,
+.fi-check:before,
+.fi-checkbox:before,
+.fi-clipboard-notes:before,
+.fi-clipboard-pencil:before,
+.fi-clipboard:before,
+.fi-clock:before,
+.fi-closed-caption:before,
+.fi-cloud:before,
+.fi-comment-minus:before,
+.fi-comment-quotes:before,
+.fi-comment-video:before,
+.fi-comment:before,
+.fi-comments:before,
+.fi-compass:before,
+.fi-contrast:before,
+.fi-credit-card:before,
+.fi-crop:before,
+.fi-crown:before,
+.fi-css3:before,
+.fi-database:before,
+.fi-die-five:before,
+.fi-die-four:before,
+.fi-die-one:before,
+.fi-die-six:before,
+.fi-die-three:before,
+.fi-die-two:before,
+.fi-dislike:before,
+.fi-dollar-bill:before,
+.fi-dollar:before,
+.fi-download:before,
+.fi-eject:before,
+.fi-elevator:before,
+.fi-euro:before,
+.fi-eye:before,
+.fi-fast-forward:before,
+.fi-female-symbol:before,
+.fi-female:before,
+.fi-filter:before,
+.fi-first-aid:before,
+.fi-flag:before,
+.fi-folder-add:before,
+.fi-folder-lock:before,
+.fi-folder:before,
+.fi-foot:before,
+.fi-foundation:before,
+.fi-graph-bar:before,
+.fi-graph-horizontal:before,
+.fi-graph-pie:before,
+.fi-graph-trend:before,
+.fi-guide-dog:before,
+.fi-hearing-aid:before,
+.fi-heart:before,
+.fi-home:before,
+.fi-html5:before,
+.fi-indent-less:before,
+.fi-indent-more:before,
+.fi-info:before,
+.fi-italic:before,
+.fi-key:before,
+.fi-laptop:before,
+.fi-layout:before,
+.fi-lightbulb:before,
+.fi-like:before,
+.fi-link:before,
+.fi-list-bullet:before,
+.fi-list-number:before,
+.fi-list-thumbnails:before,
+.fi-list:before,
+.fi-lock:before,
+.fi-loop:before,
+.fi-magnifying-glass:before,
+.fi-mail:before,
+.fi-male-female:before,
+.fi-male-symbol:before,
+.fi-male:before,
+.fi-map:before,
+.fi-marker:before,
+.fi-megaphone:before,
+.fi-microphone:before,
+.fi-minus-circle:before,
+.fi-minus:before,
+.fi-mobile-signal:before,
+.fi-mobile:before,
+.fi-monitor:before,
+.fi-mountains:before,
+.fi-music:before,
+.fi-next:before,
+.fi-no-dogs:before,
+.fi-no-smoking:before,
+.fi-page-add:before,
+.fi-page-copy:before,
+.fi-page-csv:before,
+.fi-page-delete:before,
+.fi-page-doc:before,
+.fi-page-edit:before,
+.fi-page-export-csv:before,
+.fi-page-export-doc:before,
+.fi-page-export-pdf:before,
+.fi-page-export:before,
+.fi-page-filled:before,
+.fi-page-multiple:before,
+.fi-page-pdf:before,
+.fi-page-remove:before,
+.fi-page-search:before,
+.fi-page:before,
+.fi-paint-bucket:before,
+.fi-paperclip:before,
+.fi-pause:before,
+.fi-paw:before,
+.fi-paypal:before,
+.fi-pencil:before,
+.fi-photo:before,
+.fi-play-circle:before,
+.fi-play-video:before,
+.fi-play:before,
+.fi-plus:before,
+.fi-pound:before,
+.fi-power:before,
+.fi-previous:before,
+.fi-price-tag:before,
+.fi-pricetag-multiple:before,
+.fi-print:before,
+.fi-prohibited:before,
+.fi-projection-screen:before,
+.fi-puzzle:before,
+.fi-quote:before,
+.fi-record:before,
+.fi-refresh:before,
+.fi-results-demographics:before,
+.fi-results:before,
+.fi-rewind-ten:before,
+.fi-rewind:before,
+.fi-rss:before,
+.fi-safety-cone:before,
+.fi-save:before,
+.fi-share:before,
+.fi-sheriff-badge:before,
+.fi-shield:before,
+.fi-shopping-bag:before,
+.fi-shopping-cart:before,
+.fi-shuffle:before,
+.fi-skull:before,
+.fi-social-500px:before,
+.fi-social-adobe:before,
+.fi-social-amazon:before,
+.fi-social-android:before,
+.fi-social-apple:before,
+.fi-social-behance:before,
+.fi-social-bing:before,
+.fi-social-blogger:before,
+.fi-social-delicious:before,
+.fi-social-designer-news:before,
+.fi-social-deviant-art:before,
+.fi-social-digg:before,
+.fi-social-dribbble:before,
+.fi-social-drive:before,
+.fi-social-dropbox:before,
+.fi-social-evernote:before,
+.fi-social-facebook:before,
+.fi-social-flickr:before,
+.fi-social-forrst:before,
+.fi-social-foursquare:before,
+.fi-social-game-center:before,
+.fi-social-github:before,
+.fi-social-google-plus:before,
+.fi-social-hacker-news:before,
+.fi-social-hi5:before,
+.fi-social-instagram:before,
+.fi-social-joomla:before,
+.fi-social-lastfm:before,
+.fi-social-linkedin:before,
+.fi-social-medium:before,
+.fi-social-myspace:before,
+.fi-social-orkut:before,
+.fi-social-path:before,
+.fi-social-picasa:before,
+.fi-social-pinterest:before,
+.fi-social-rdio:before,
+.fi-social-reddit:before,
+.fi-social-skillshare:before,
+.fi-social-skype:before,
+.fi-social-smashing-mag:before,
+.fi-social-snapchat:before,
+.fi-social-spotify:before,
+.fi-social-squidoo:before,
+.fi-social-stack-overflow:before,
+.fi-social-steam:before,
+.fi-social-stumbleupon:before,
+.fi-social-treehouse:before,
+.fi-social-tumblr:before,
+.fi-social-twitter:before,
+.fi-social-vimeo:before,
+.fi-social-windows:before,
+.fi-social-xbox:before,
+.fi-social-yahoo:before,
+.fi-social-yelp:before,
+.fi-social-youtube:before,
+.fi-social-zerply:before,
+.fi-social-zurb:before,
+.fi-sound:before,
+.fi-star:before,
+.fi-stop:before,
+.fi-strikethrough:before,
+.fi-subscript:before,
+.fi-superscript:before,
+.fi-tablet-landscape:before,
+.fi-tablet-portrait:before,
+.fi-target-two:before,
+.fi-target:before,
+.fi-telephone-accessible:before,
+.fi-telephone:before,
+.fi-text-color:before,
+.fi-thumbnails:before,
+.fi-ticket:before,
+.fi-torso-business:before,
+.fi-torso-female:before,
+.fi-torso:before,
+.fi-torsos-all-female:before,
+.fi-torsos-all:before,
+.fi-torsos-female-male:before,
+.fi-torsos-male-female:before,
+.fi-torsos:before,
+.fi-trash:before,
+.fi-trees:before,
+.fi-trophy:before,
+.fi-underline:before,
+.fi-universal-access:before,
+.fi-unlink:before,
+.fi-unlock:before,
+.fi-upload-cloud:before,
+.fi-upload:before,
+.fi-usb:before,
+.fi-video:before,
+.fi-volume-none:before,
+.fi-volume-strike:before,
+.fi-volume:before,
+.fi-web:before,
+.fi-wheelchair:before,
+.fi-widget:before,
+.fi-wrench:before,
+.fi-x-circle:before,
+.fi-x:before,
+.fi-yen:before,
+.fi-zoom-in:before,
+.fi-zoom-out:before {
+ font-family: "foundation-icons";
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ display: inline-block;
+ text-decoration: inherit;
+}
+
+.fi-address-book:before { content: "\f100"; }
+.fi-alert:before { content: "\f101"; }
+.fi-align-center:before { content: "\f102"; }
+.fi-align-justify:before { content: "\f103"; }
+.fi-align-left:before { content: "\f104"; }
+.fi-align-right:before { content: "\f105"; }
+.fi-anchor:before { content: "\f106"; }
+.fi-annotate:before { content: "\f107"; }
+.fi-archive:before { content: "\f108"; }
+.fi-arrow-down:before { content: "\f109"; }
+.fi-arrow-left:before { content: "\f10a"; }
+.fi-arrow-right:before { content: "\f10b"; }
+.fi-arrow-up:before { content: "\f10c"; }
+.fi-arrows-compress:before { content: "\f10d"; }
+.fi-arrows-expand:before { content: "\f10e"; }
+.fi-arrows-in:before { content: "\f10f"; }
+.fi-arrows-out:before { content: "\f110"; }
+.fi-asl:before { content: "\f111"; }
+.fi-asterisk:before { content: "\f112"; }
+.fi-at-sign:before { content: "\f113"; }
+.fi-background-color:before { content: "\f114"; }
+.fi-battery-empty:before { content: "\f115"; }
+.fi-battery-full:before { content: "\f116"; }
+.fi-battery-half:before { content: "\f117"; }
+.fi-bitcoin-circle:before { content: "\f118"; }
+.fi-bitcoin:before { content: "\f119"; }
+.fi-blind:before { content: "\f11a"; }
+.fi-bluetooth:before { content: "\f11b"; }
+.fi-bold:before { content: "\f11c"; }
+.fi-book-bookmark:before { content: "\f11d"; }
+.fi-book:before { content: "\f11e"; }
+.fi-bookmark:before { content: "\f11f"; }
+.fi-braille:before { content: "\f120"; }
+.fi-burst-new:before { content: "\f121"; }
+.fi-burst-sale:before { content: "\f122"; }
+.fi-burst:before { content: "\f123"; }
+.fi-calendar:before { content: "\f124"; }
+.fi-camera:before { content: "\f125"; }
+.fi-check:before { content: "\f126"; }
+.fi-checkbox:before { content: "\f127"; }
+.fi-clipboard-notes:before { content: "\f128"; }
+.fi-clipboard-pencil:before { content: "\f129"; }
+.fi-clipboard:before { content: "\f12a"; }
+.fi-clock:before { content: "\f12b"; }
+.fi-closed-caption:before { content: "\f12c"; }
+.fi-cloud:before { content: "\f12d"; }
+.fi-comment-minus:before { content: "\f12e"; }
+.fi-comment-quotes:before { content: "\f12f"; }
+.fi-comment-video:before { content: "\f130"; }
+.fi-comment:before { content: "\f131"; }
+.fi-comments:before { content: "\f132"; }
+.fi-compass:before { content: "\f133"; }
+.fi-contrast:before { content: "\f134"; }
+.fi-credit-card:before { content: "\f135"; }
+.fi-crop:before { content: "\f136"; }
+.fi-crown:before { content: "\f137"; }
+.fi-css3:before { content: "\f138"; }
+.fi-database:before { content: "\f139"; }
+.fi-die-five:before { content: "\f13a"; }
+.fi-die-four:before { content: "\f13b"; }
+.fi-die-one:before { content: "\f13c"; }
+.fi-die-six:before { content: "\f13d"; }
+.fi-die-three:before { content: "\f13e"; }
+.fi-die-two:before { content: "\f13f"; }
+.fi-dislike:before { content: "\f140"; }
+.fi-dollar-bill:before { content: "\f141"; }
+.fi-dollar:before { content: "\f142"; }
+.fi-download:before { content: "\f143"; }
+.fi-eject:before { content: "\f144"; }
+.fi-elevator:before { content: "\f145"; }
+.fi-euro:before { content: "\f146"; }
+.fi-eye:before { content: "\f147"; }
+.fi-fast-forward:before { content: "\f148"; }
+.fi-female-symbol:before { content: "\f149"; }
+.fi-female:before { content: "\f14a"; }
+.fi-filter:before { content: "\f14b"; }
+.fi-first-aid:before { content: "\f14c"; }
+.fi-flag:before { content: "\f14d"; }
+.fi-folder-add:before { content: "\f14e"; }
+.fi-folder-lock:before { content: "\f14f"; }
+.fi-folder:before { content: "\f150"; }
+.fi-foot:before { content: "\f151"; }
+.fi-foundation:before { content: "\f152"; }
+.fi-graph-bar:before { content: "\f153"; }
+.fi-graph-horizontal:before { content: "\f154"; }
+.fi-graph-pie:before { content: "\f155"; }
+.fi-graph-trend:before { content: "\f156"; }
+.fi-guide-dog:before { content: "\f157"; }
+.fi-hearing-aid:before { content: "\f158"; }
+.fi-heart:before { content: "\f159"; }
+.fi-home:before { content: "\f15a"; }
+.fi-html5:before { content: "\f15b"; }
+.fi-indent-less:before { content: "\f15c"; }
+.fi-indent-more:before { content: "\f15d"; }
+.fi-info:before { content: "\f15e"; }
+.fi-italic:before { content: "\f15f"; }
+.fi-key:before { content: "\f160"; }
+.fi-laptop:before { content: "\f161"; }
+.fi-layout:before { content: "\f162"; }
+.fi-lightbulb:before { content: "\f163"; }
+.fi-like:before { content: "\f164"; }
+.fi-link:before { content: "\f165"; }
+.fi-list-bullet:before { content: "\f166"; }
+.fi-list-number:before { content: "\f167"; }
+.fi-list-thumbnails:before { content: "\f168"; }
+.fi-list:before { content: "\f169"; }
+.fi-lock:before { content: "\f16a"; }
+.fi-loop:before { content: "\f16b"; }
+.fi-magnifying-glass:before { content: "\f16c"; }
+.fi-mail:before { content: "\f16d"; }
+.fi-male-female:before { content: "\f16e"; }
+.fi-male-symbol:before { content: "\f16f"; }
+.fi-male:before { content: "\f170"; }
+.fi-map:before { content: "\f171"; }
+.fi-marker:before { content: "\f172"; }
+.fi-megaphone:before { content: "\f173"; }
+.fi-microphone:before { content: "\f174"; }
+.fi-minus-circle:before { content: "\f175"; }
+.fi-minus:before { content: "\f176"; }
+.fi-mobile-signal:before { content: "\f177"; }
+.fi-mobile:before { content: "\f178"; }
+.fi-monitor:before { content: "\f179"; }
+.fi-mountains:before { content: "\f17a"; }
+.fi-music:before { content: "\f17b"; }
+.fi-next:before { content: "\f17c"; }
+.fi-no-dogs:before { content: "\f17d"; }
+.fi-no-smoking:before { content: "\f17e"; }
+.fi-page-add:before { content: "\f17f"; }
+.fi-page-copy:before { content: "\f180"; }
+.fi-page-csv:before { content: "\f181"; }
+.fi-page-delete:before { content: "\f182"; }
+.fi-page-doc:before { content: "\f183"; }
+.fi-page-edit:before { content: "\f184"; }
+.fi-page-export-csv:before { content: "\f185"; }
+.fi-page-export-doc:before { content: "\f186"; }
+.fi-page-export-pdf:before { content: "\f187"; }
+.fi-page-export:before { content: "\f188"; }
+.fi-page-filled:before { content: "\f189"; }
+.fi-page-multiple:before { content: "\f18a"; }
+.fi-page-pdf:before { content: "\f18b"; }
+.fi-page-remove:before { content: "\f18c"; }
+.fi-page-search:before { content: "\f18d"; }
+.fi-page:before { content: "\f18e"; }
+.fi-paint-bucket:before { content: "\f18f"; }
+.fi-paperclip:before { content: "\f190"; }
+.fi-pause:before { content: "\f191"; }
+.fi-paw:before { content: "\f192"; }
+.fi-paypal:before { content: "\f193"; }
+.fi-pencil:before { content: "\f194"; }
+.fi-photo:before { content: "\f195"; }
+.fi-play-circle:before { content: "\f196"; }
+.fi-play-video:before { content: "\f197"; }
+.fi-play:before { content: "\f198"; }
+.fi-plus:before { content: "\f199"; }
+.fi-pound:before { content: "\f19a"; }
+.fi-power:before { content: "\f19b"; }
+.fi-previous:before { content: "\f19c"; }
+.fi-price-tag:before { content: "\f19d"; }
+.fi-pricetag-multiple:before { content: "\f19e"; }
+.fi-print:before { content: "\f19f"; }
+.fi-prohibited:before { content: "\f1a0"; }
+.fi-projection-screen:before { content: "\f1a1"; }
+.fi-puzzle:before { content: "\f1a2"; }
+.fi-quote:before { content: "\f1a3"; }
+.fi-record:before { content: "\f1a4"; }
+.fi-refresh:before { content: "\f1a5"; }
+.fi-results-demographics:before { content: "\f1a6"; }
+.fi-results:before { content: "\f1a7"; }
+.fi-rewind-ten:before { content: "\f1a8"; }
+.fi-rewind:before { content: "\f1a9"; }
+.fi-rss:before { content: "\f1aa"; }
+.fi-safety-cone:before { content: "\f1ab"; }
+.fi-save:before { content: "\f1ac"; }
+.fi-share:before { content: "\f1ad"; }
+.fi-sheriff-badge:before { content: "\f1ae"; }
+.fi-shield:before { content: "\f1af"; }
+.fi-shopping-bag:before { content: "\f1b0"; }
+.fi-shopping-cart:before { content: "\f1b1"; }
+.fi-shuffle:before { content: "\f1b2"; }
+.fi-skull:before { content: "\f1b3"; }
+.fi-social-500px:before { content: "\f1b4"; }
+.fi-social-adobe:before { content: "\f1b5"; }
+.fi-social-amazon:before { content: "\f1b6"; }
+.fi-social-android:before { content: "\f1b7"; }
+.fi-social-apple:before { content: "\f1b8"; }
+.fi-social-behance:before { content: "\f1b9"; }
+.fi-social-bing:before { content: "\f1ba"; }
+.fi-social-blogger:before { content: "\f1bb"; }
+.fi-social-delicious:before { content: "\f1bc"; }
+.fi-social-designer-news:before { content: "\f1bd"; }
+.fi-social-deviant-art:before { content: "\f1be"; }
+.fi-social-digg:before { content: "\f1bf"; }
+.fi-social-dribbble:before { content: "\f1c0"; }
+.fi-social-drive:before { content: "\f1c1"; }
+.fi-social-dropbox:before { content: "\f1c2"; }
+.fi-social-evernote:before { content: "\f1c3"; }
+.fi-social-facebook:before { content: "\f1c4"; }
+.fi-social-flickr:before { content: "\f1c5"; }
+.fi-social-forrst:before { content: "\f1c6"; }
+.fi-social-foursquare:before { content: "\f1c7"; }
+.fi-social-game-center:before { content: "\f1c8"; }
+.fi-social-github:before { content: "\f1c9"; }
+.fi-social-google-plus:before { content: "\f1ca"; }
+.fi-social-hacker-news:before { content: "\f1cb"; }
+.fi-social-hi5:before { content: "\f1cc"; }
+.fi-social-instagram:before { content: "\f1cd"; }
+.fi-social-joomla:before { content: "\f1ce"; }
+.fi-social-lastfm:before { content: "\f1cf"; }
+.fi-social-linkedin:before { content: "\f1d0"; }
+.fi-social-medium:before { content: "\f1d1"; }
+.fi-social-myspace:before { content: "\f1d2"; }
+.fi-social-orkut:before { content: "\f1d3"; }
+.fi-social-path:before { content: "\f1d4"; }
+.fi-social-picasa:before { content: "\f1d5"; }
+.fi-social-pinterest:before { content: "\f1d6"; }
+.fi-social-rdio:before { content: "\f1d7"; }
+.fi-social-reddit:before { content: "\f1d8"; }
+.fi-social-skillshare:before { content: "\f1d9"; }
+.fi-social-skype:before { content: "\f1da"; }
+.fi-social-smashing-mag:before { content: "\f1db"; }
+.fi-social-snapchat:before { content: "\f1dc"; }
+.fi-social-spotify:before { content: "\f1dd"; }
+.fi-social-squidoo:before { content: "\f1de"; }
+.fi-social-stack-overflow:before { content: "\f1df"; }
+.fi-social-steam:before { content: "\f1e0"; }
+.fi-social-stumbleupon:before { content: "\f1e1"; }
+.fi-social-treehouse:before { content: "\f1e2"; }
+.fi-social-tumblr:before { content: "\f1e3"; }
+.fi-social-twitter:before { content: "\f1e4"; }
+.fi-social-vimeo:before { content: "\f1e5"; }
+.fi-social-windows:before { content: "\f1e6"; }
+.fi-social-xbox:before { content: "\f1e7"; }
+.fi-social-yahoo:before { content: "\f1e8"; }
+.fi-social-yelp:before { content: "\f1e9"; }
+.fi-social-youtube:before { content: "\f1ea"; }
+.fi-social-zerply:before { content: "\f1eb"; }
+.fi-social-zurb:before { content: "\f1ec"; }
+.fi-sound:before { content: "\f1ed"; }
+.fi-star:before { content: "\f1ee"; }
+.fi-stop:before { content: "\f1ef"; }
+.fi-strikethrough:before { content: "\f1f0"; }
+.fi-subscript:before { content: "\f1f1"; }
+.fi-superscript:before { content: "\f1f2"; }
+.fi-tablet-landscape:before { content: "\f1f3"; }
+.fi-tablet-portrait:before { content: "\f1f4"; }
+.fi-target-two:before { content: "\f1f5"; }
+.fi-target:before { content: "\f1f6"; }
+.fi-telephone-accessible:before { content: "\f1f7"; }
+.fi-telephone:before { content: "\f1f8"; }
+.fi-text-color:before { content: "\f1f9"; }
+.fi-thumbnails:before { content: "\f1fa"; }
+.fi-ticket:before { content: "\f1fb"; }
+.fi-torso-business:before { content: "\f1fc"; }
+.fi-torso-female:before { content: "\f1fd"; }
+.fi-torso:before { content: "\f1fe"; }
+.fi-torsos-all-female:before { content: "\f1ff"; }
+.fi-torsos-all:before { content: "\f200"; }
+.fi-torsos-female-male:before { content: "\f201"; }
+.fi-torsos-male-female:before { content: "\f202"; }
+.fi-torsos:before { content: "\f203"; }
+.fi-trash:before { content: "\f204"; }
+.fi-trees:before { content: "\f205"; }
+.fi-trophy:before { content: "\f206"; }
+.fi-underline:before { content: "\f207"; }
+.fi-universal-access:before { content: "\f208"; }
+.fi-unlink:before { content: "\f209"; }
+.fi-unlock:before { content: "\f20a"; }
+.fi-upload-cloud:before { content: "\f20b"; }
+.fi-upload:before { content: "\f20c"; }
+.fi-usb:before { content: "\f20d"; }
+.fi-video:before { content: "\f20e"; }
+.fi-volume-none:before { content: "\f20f"; }
+.fi-volume-strike:before { content: "\f210"; }
+.fi-volume:before { content: "\f211"; }
+.fi-web:before { content: "\f212"; }
+.fi-wheelchair:before { content: "\f213"; }
+.fi-widget:before { content: "\f214"; }
+.fi-wrench:before { content: "\f215"; }
+.fi-x-circle:before { content: "\f216"; }
+.fi-x:before { content: "\f217"; }
+.fi-yen:before { content: "\f218"; }
+.fi-zoom-in:before { content: "\f219"; }
+.fi-zoom-out:before { content: "\f21a"; }
diff --git a/afb-client/bower_components/foundation-icon-fonts/bower.json b/afb-client/bower_components/foundation-icon-fonts/bower.json
new file mode 100644
index 0000000..0731087
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/bower.json
@@ -0,0 +1,6 @@
+{
+ "name": "foundation-icon-fonts",
+ "version": "3.0.0",
+ "main": ["foundation-icons.css"],
+ "ignore": []
+}
diff --git a/afb-client/bower_components/foundation-icon-fonts/foundation-icons.css b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.css
new file mode 100644
index 0000000..d866a73
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.css
@@ -0,0 +1,594 @@
+/*
+ * Foundation Icons v 3.0
+ * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3
+ * MIT License
+ */
+
+@font-face {
+ font-family: "foundation-icons";
+ src: url("foundation-icons.eot");
+ src: url("foundation-icons.eot?#iefix") format("embedded-opentype"),
+ url("foundation-icons.woff") format("woff"),
+ url("foundation-icons.ttf") format("truetype"),
+ url("foundation-icons.svg#fontcustom") format("svg");
+ font-weight: normal;
+ font-style: normal;
+}
+
+.fi-address-book:before,
+.fi-alert:before,
+.fi-align-center:before,
+.fi-align-justify:before,
+.fi-align-left:before,
+.fi-align-right:before,
+.fi-anchor:before,
+.fi-annotate:before,
+.fi-archive:before,
+.fi-arrow-down:before,
+.fi-arrow-left:before,
+.fi-arrow-right:before,
+.fi-arrow-up:before,
+.fi-arrows-compress:before,
+.fi-arrows-expand:before,
+.fi-arrows-in:before,
+.fi-arrows-out:before,
+.fi-asl:before,
+.fi-asterisk:before,
+.fi-at-sign:before,
+.fi-background-color:before,
+.fi-battery-empty:before,
+.fi-battery-full:before,
+.fi-battery-half:before,
+.fi-bitcoin-circle:before,
+.fi-bitcoin:before,
+.fi-blind:before,
+.fi-bluetooth:before,
+.fi-bold:before,
+.fi-book-bookmark:before,
+.fi-book:before,
+.fi-bookmark:before,
+.fi-braille:before,
+.fi-burst-new:before,
+.fi-burst-sale:before,
+.fi-burst:before,
+.fi-calendar:before,
+.fi-camera:before,
+.fi-check:before,
+.fi-checkbox:before,
+.fi-clipboard-notes:before,
+.fi-clipboard-pencil:before,
+.fi-clipboard:before,
+.fi-clock:before,
+.fi-closed-caption:before,
+.fi-cloud:before,
+.fi-comment-minus:before,
+.fi-comment-quotes:before,
+.fi-comment-video:before,
+.fi-comment:before,
+.fi-comments:before,
+.fi-compass:before,
+.fi-contrast:before,
+.fi-credit-card:before,
+.fi-crop:before,
+.fi-crown:before,
+.fi-css3:before,
+.fi-database:before,
+.fi-die-five:before,
+.fi-die-four:before,
+.fi-die-one:before,
+.fi-die-six:before,
+.fi-die-three:before,
+.fi-die-two:before,
+.fi-dislike:before,
+.fi-dollar-bill:before,
+.fi-dollar:before,
+.fi-download:before,
+.fi-eject:before,
+.fi-elevator:before,
+.fi-euro:before,
+.fi-eye:before,
+.fi-fast-forward:before,
+.fi-female-symbol:before,
+.fi-female:before,
+.fi-filter:before,
+.fi-first-aid:before,
+.fi-flag:before,
+.fi-folder-add:before,
+.fi-folder-lock:before,
+.fi-folder:before,
+.fi-foot:before,
+.fi-foundation:before,
+.fi-graph-bar:before,
+.fi-graph-horizontal:before,
+.fi-graph-pie:before,
+.fi-graph-trend:before,
+.fi-guide-dog:before,
+.fi-hearing-aid:before,
+.fi-heart:before,
+.fi-home:before,
+.fi-html5:before,
+.fi-indent-less:before,
+.fi-indent-more:before,
+.fi-info:before,
+.fi-italic:before,
+.fi-key:before,
+.fi-laptop:before,
+.fi-layout:before,
+.fi-lightbulb:before,
+.fi-like:before,
+.fi-link:before,
+.fi-list-bullet:before,
+.fi-list-number:before,
+.fi-list-thumbnails:before,
+.fi-list:before,
+.fi-lock:before,
+.fi-loop:before,
+.fi-magnifying-glass:before,
+.fi-mail:before,
+.fi-male-female:before,
+.fi-male-symbol:before,
+.fi-male:before,
+.fi-map:before,
+.fi-marker:before,
+.fi-megaphone:before,
+.fi-microphone:before,
+.fi-minus-circle:before,
+.fi-minus:before,
+.fi-mobile-signal:before,
+.fi-mobile:before,
+.fi-monitor:before,
+.fi-mountains:before,
+.fi-music:before,
+.fi-next:before,
+.fi-no-dogs:before,
+.fi-no-smoking:before,
+.fi-page-add:before,
+.fi-page-copy:before,
+.fi-page-csv:before,
+.fi-page-delete:before,
+.fi-page-doc:before,
+.fi-page-edit:before,
+.fi-page-export-csv:before,
+.fi-page-export-doc:before,
+.fi-page-export-pdf:before,
+.fi-page-export:before,
+.fi-page-filled:before,
+.fi-page-multiple:before,
+.fi-page-pdf:before,
+.fi-page-remove:before,
+.fi-page-search:before,
+.fi-page:before,
+.fi-paint-bucket:before,
+.fi-paperclip:before,
+.fi-pause:before,
+.fi-paw:before,
+.fi-paypal:before,
+.fi-pencil:before,
+.fi-photo:before,
+.fi-play-circle:before,
+.fi-play-video:before,
+.fi-play:before,
+.fi-plus:before,
+.fi-pound:before,
+.fi-power:before,
+.fi-previous:before,
+.fi-price-tag:before,
+.fi-pricetag-multiple:before,
+.fi-print:before,
+.fi-prohibited:before,
+.fi-projection-screen:before,
+.fi-puzzle:before,
+.fi-quote:before,
+.fi-record:before,
+.fi-refresh:before,
+.fi-results-demographics:before,
+.fi-results:before,
+.fi-rewind-ten:before,
+.fi-rewind:before,
+.fi-rss:before,
+.fi-safety-cone:before,
+.fi-save:before,
+.fi-share:before,
+.fi-sheriff-badge:before,
+.fi-shield:before,
+.fi-shopping-bag:before,
+.fi-shopping-cart:before,
+.fi-shuffle:before,
+.fi-skull:before,
+.fi-social-500px:before,
+.fi-social-adobe:before,
+.fi-social-amazon:before,
+.fi-social-android:before,
+.fi-social-apple:before,
+.fi-social-behance:before,
+.fi-social-bing:before,
+.fi-social-blogger:before,
+.fi-social-delicious:before,
+.fi-social-designer-news:before,
+.fi-social-deviant-art:before,
+.fi-social-digg:before,
+.fi-social-dribbble:before,
+.fi-social-drive:before,
+.fi-social-dropbox:before,
+.fi-social-evernote:before,
+.fi-social-facebook:before,
+.fi-social-flickr:before,
+.fi-social-forrst:before,
+.fi-social-foursquare:before,
+.fi-social-game-center:before,
+.fi-social-github:before,
+.fi-social-google-plus:before,
+.fi-social-hacker-news:before,
+.fi-social-hi5:before,
+.fi-social-instagram:before,
+.fi-social-joomla:before,
+.fi-social-lastfm:before,
+.fi-social-linkedin:before,
+.fi-social-medium:before,
+.fi-social-myspace:before,
+.fi-social-orkut:before,
+.fi-social-path:before,
+.fi-social-picasa:before,
+.fi-social-pinterest:before,
+.fi-social-rdio:before,
+.fi-social-reddit:before,
+.fi-social-skillshare:before,
+.fi-social-skype:before,
+.fi-social-smashing-mag:before,
+.fi-social-snapchat:before,
+.fi-social-spotify:before,
+.fi-social-squidoo:before,
+.fi-social-stack-overflow:before,
+.fi-social-steam:before,
+.fi-social-stumbleupon:before,
+.fi-social-treehouse:before,
+.fi-social-tumblr:before,
+.fi-social-twitter:before,
+.fi-social-vimeo:before,
+.fi-social-windows:before,
+.fi-social-xbox:before,
+.fi-social-yahoo:before,
+.fi-social-yelp:before,
+.fi-social-youtube:before,
+.fi-social-zerply:before,
+.fi-social-zurb:before,
+.fi-sound:before,
+.fi-star:before,
+.fi-stop:before,
+.fi-strikethrough:before,
+.fi-subscript:before,
+.fi-superscript:before,
+.fi-tablet-landscape:before,
+.fi-tablet-portrait:before,
+.fi-target-two:before,
+.fi-target:before,
+.fi-telephone-accessible:before,
+.fi-telephone:before,
+.fi-text-color:before,
+.fi-thumbnails:before,
+.fi-ticket:before,
+.fi-torso-business:before,
+.fi-torso-female:before,
+.fi-torso:before,
+.fi-torsos-all-female:before,
+.fi-torsos-all:before,
+.fi-torsos-female-male:before,
+.fi-torsos-male-female:before,
+.fi-torsos:before,
+.fi-trash:before,
+.fi-trees:before,
+.fi-trophy:before,
+.fi-underline:before,
+.fi-universal-access:before,
+.fi-unlink:before,
+.fi-unlock:before,
+.fi-upload-cloud:before,
+.fi-upload:before,
+.fi-usb:before,
+.fi-video:before,
+.fi-volume-none:before,
+.fi-volume-strike:before,
+.fi-volume:before,
+.fi-web:before,
+.fi-wheelchair:before,
+.fi-widget:before,
+.fi-wrench:before,
+.fi-x-circle:before,
+.fi-x:before,
+.fi-yen:before,
+.fi-zoom-in:before,
+.fi-zoom-out:before {
+ font-family: "foundation-icons";
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ display: inline-block;
+ text-decoration: inherit;
+}
+
+.fi-address-book:before { content: "\f100"; }
+.fi-alert:before { content: "\f101"; }
+.fi-align-center:before { content: "\f102"; }
+.fi-align-justify:before { content: "\f103"; }
+.fi-align-left:before { content: "\f104"; }
+.fi-align-right:before { content: "\f105"; }
+.fi-anchor:before { content: "\f106"; }
+.fi-annotate:before { content: "\f107"; }
+.fi-archive:before { content: "\f108"; }
+.fi-arrow-down:before { content: "\f109"; }
+.fi-arrow-left:before { content: "\f10a"; }
+.fi-arrow-right:before { content: "\f10b"; }
+.fi-arrow-up:before { content: "\f10c"; }
+.fi-arrows-compress:before { content: "\f10d"; }
+.fi-arrows-expand:before { content: "\f10e"; }
+.fi-arrows-in:before { content: "\f10f"; }
+.fi-arrows-out:before { content: "\f110"; }
+.fi-asl:before { content: "\f111"; }
+.fi-asterisk:before { content: "\f112"; }
+.fi-at-sign:before { content: "\f113"; }
+.fi-background-color:before { content: "\f114"; }
+.fi-battery-empty:before { content: "\f115"; }
+.fi-battery-full:before { content: "\f116"; }
+.fi-battery-half:before { content: "\f117"; }
+.fi-bitcoin-circle:before { content: "\f118"; }
+.fi-bitcoin:before { content: "\f119"; }
+.fi-blind:before { content: "\f11a"; }
+.fi-bluetooth:before { content: "\f11b"; }
+.fi-bold:before { content: "\f11c"; }
+.fi-book-bookmark:before { content: "\f11d"; }
+.fi-book:before { content: "\f11e"; }
+.fi-bookmark:before { content: "\f11f"; }
+.fi-braille:before { content: "\f120"; }
+.fi-burst-new:before { content: "\f121"; }
+.fi-burst-sale:before { content: "\f122"; }
+.fi-burst:before { content: "\f123"; }
+.fi-calendar:before { content: "\f124"; }
+.fi-camera:before { content: "\f125"; }
+.fi-check:before { content: "\f126"; }
+.fi-checkbox:before { content: "\f127"; }
+.fi-clipboard-notes:before { content: "\f128"; }
+.fi-clipboard-pencil:before { content: "\f129"; }
+.fi-clipboard:before { content: "\f12a"; }
+.fi-clock:before { content: "\f12b"; }
+.fi-closed-caption:before { content: "\f12c"; }
+.fi-cloud:before { content: "\f12d"; }
+.fi-comment-minus:before { content: "\f12e"; }
+.fi-comment-quotes:before { content: "\f12f"; }
+.fi-comment-video:before { content: "\f130"; }
+.fi-comment:before { content: "\f131"; }
+.fi-comments:before { content: "\f132"; }
+.fi-compass:before { content: "\f133"; }
+.fi-contrast:before { content: "\f134"; }
+.fi-credit-card:before { content: "\f135"; }
+.fi-crop:before { content: "\f136"; }
+.fi-crown:before { content: "\f137"; }
+.fi-css3:before { content: "\f138"; }
+.fi-database:before { content: "\f139"; }
+.fi-die-five:before { content: "\f13a"; }
+.fi-die-four:before { content: "\f13b"; }
+.fi-die-one:before { content: "\f13c"; }
+.fi-die-six:before { content: "\f13d"; }
+.fi-die-three:before { content: "\f13e"; }
+.fi-die-two:before { content: "\f13f"; }
+.fi-dislike:before { content: "\f140"; }
+.fi-dollar-bill:before { content: "\f141"; }
+.fi-dollar:before { content: "\f142"; }
+.fi-download:before { content: "\f143"; }
+.fi-eject:before { content: "\f144"; }
+.fi-elevator:before { content: "\f145"; }
+.fi-euro:before { content: "\f146"; }
+.fi-eye:before { content: "\f147"; }
+.fi-fast-forward:before { content: "\f148"; }
+.fi-female-symbol:before { content: "\f149"; }
+.fi-female:before { content: "\f14a"; }
+.fi-filter:before { content: "\f14b"; }
+.fi-first-aid:before { content: "\f14c"; }
+.fi-flag:before { content: "\f14d"; }
+.fi-folder-add:before { content: "\f14e"; }
+.fi-folder-lock:before { content: "\f14f"; }
+.fi-folder:before { content: "\f150"; }
+.fi-foot:before { content: "\f151"; }
+.fi-foundation:before { content: "\f152"; }
+.fi-graph-bar:before { content: "\f153"; }
+.fi-graph-horizontal:before { content: "\f154"; }
+.fi-graph-pie:before { content: "\f155"; }
+.fi-graph-trend:before { content: "\f156"; }
+.fi-guide-dog:before { content: "\f157"; }
+.fi-hearing-aid:before { content: "\f158"; }
+.fi-heart:before { content: "\f159"; }
+.fi-home:before { content: "\f15a"; }
+.fi-html5:before { content: "\f15b"; }
+.fi-indent-less:before { content: "\f15c"; }
+.fi-indent-more:before { content: "\f15d"; }
+.fi-info:before { content: "\f15e"; }
+.fi-italic:before { content: "\f15f"; }
+.fi-key:before { content: "\f160"; }
+.fi-laptop:before { content: "\f161"; }
+.fi-layout:before { content: "\f162"; }
+.fi-lightbulb:before { content: "\f163"; }
+.fi-like:before { content: "\f164"; }
+.fi-link:before { content: "\f165"; }
+.fi-list-bullet:before { content: "\f166"; }
+.fi-list-number:before { content: "\f167"; }
+.fi-list-thumbnails:before { content: "\f168"; }
+.fi-list:before { content: "\f169"; }
+.fi-lock:before { content: "\f16a"; }
+.fi-loop:before { content: "\f16b"; }
+.fi-magnifying-glass:before { content: "\f16c"; }
+.fi-mail:before { content: "\f16d"; }
+.fi-male-female:before { content: "\f16e"; }
+.fi-male-symbol:before { content: "\f16f"; }
+.fi-male:before { content: "\f170"; }
+.fi-map:before { content: "\f171"; }
+.fi-marker:before { content: "\f172"; }
+.fi-megaphone:before { content: "\f173"; }
+.fi-microphone:before { content: "\f174"; }
+.fi-minus-circle:before { content: "\f175"; }
+.fi-minus:before { content: "\f176"; }
+.fi-mobile-signal:before { content: "\f177"; }
+.fi-mobile:before { content: "\f178"; }
+.fi-monitor:before { content: "\f179"; }
+.fi-mountains:before { content: "\f17a"; }
+.fi-music:before { content: "\f17b"; }
+.fi-next:before { content: "\f17c"; }
+.fi-no-dogs:before { content: "\f17d"; }
+.fi-no-smoking:before { content: "\f17e"; }
+.fi-page-add:before { content: "\f17f"; }
+.fi-page-copy:before { content: "\f180"; }
+.fi-page-csv:before { content: "\f181"; }
+.fi-page-delete:before { content: "\f182"; }
+.fi-page-doc:before { content: "\f183"; }
+.fi-page-edit:before { content: "\f184"; }
+.fi-page-export-csv:before { content: "\f185"; }
+.fi-page-export-doc:before { content: "\f186"; }
+.fi-page-export-pdf:before { content: "\f187"; }
+.fi-page-export:before { content: "\f188"; }
+.fi-page-filled:before { content: "\f189"; }
+.fi-page-multiple:before { content: "\f18a"; }
+.fi-page-pdf:before { content: "\f18b"; }
+.fi-page-remove:before { content: "\f18c"; }
+.fi-page-search:before { content: "\f18d"; }
+.fi-page:before { content: "\f18e"; }
+.fi-paint-bucket:before { content: "\f18f"; }
+.fi-paperclip:before { content: "\f190"; }
+.fi-pause:before { content: "\f191"; }
+.fi-paw:before { content: "\f192"; }
+.fi-paypal:before { content: "\f193"; }
+.fi-pencil:before { content: "\f194"; }
+.fi-photo:before { content: "\f195"; }
+.fi-play-circle:before { content: "\f196"; }
+.fi-play-video:before { content: "\f197"; }
+.fi-play:before { content: "\f198"; }
+.fi-plus:before { content: "\f199"; }
+.fi-pound:before { content: "\f19a"; }
+.fi-power:before { content: "\f19b"; }
+.fi-previous:before { content: "\f19c"; }
+.fi-price-tag:before { content: "\f19d"; }
+.fi-pricetag-multiple:before { content: "\f19e"; }
+.fi-print:before { content: "\f19f"; }
+.fi-prohibited:before { content: "\f1a0"; }
+.fi-projection-screen:before { content: "\f1a1"; }
+.fi-puzzle:before { content: "\f1a2"; }
+.fi-quote:before { content: "\f1a3"; }
+.fi-record:before { content: "\f1a4"; }
+.fi-refresh:before { content: "\f1a5"; }
+.fi-results-demographics:before { content: "\f1a6"; }
+.fi-results:before { content: "\f1a7"; }
+.fi-rewind-ten:before { content: "\f1a8"; }
+.fi-rewind:before { content: "\f1a9"; }
+.fi-rss:before { content: "\f1aa"; }
+.fi-safety-cone:before { content: "\f1ab"; }
+.fi-save:before { content: "\f1ac"; }
+.fi-share:before { content: "\f1ad"; }
+.fi-sheriff-badge:before { content: "\f1ae"; }
+.fi-shield:before { content: "\f1af"; }
+.fi-shopping-bag:before { content: "\f1b0"; }
+.fi-shopping-cart:before { content: "\f1b1"; }
+.fi-shuffle:before { content: "\f1b2"; }
+.fi-skull:before { content: "\f1b3"; }
+.fi-social-500px:before { content: "\f1b4"; }
+.fi-social-adobe:before { content: "\f1b5"; }
+.fi-social-amazon:before { content: "\f1b6"; }
+.fi-social-android:before { content: "\f1b7"; }
+.fi-social-apple:before { content: "\f1b8"; }
+.fi-social-behance:before { content: "\f1b9"; }
+.fi-social-bing:before { content: "\f1ba"; }
+.fi-social-blogger:before { content: "\f1bb"; }
+.fi-social-delicious:before { content: "\f1bc"; }
+.fi-social-designer-news:before { content: "\f1bd"; }
+.fi-social-deviant-art:before { content: "\f1be"; }
+.fi-social-digg:before { content: "\f1bf"; }
+.fi-social-dribbble:before { content: "\f1c0"; }
+.fi-social-drive:before { content: "\f1c1"; }
+.fi-social-dropbox:before { content: "\f1c2"; }
+.fi-social-evernote:before { content: "\f1c3"; }
+.fi-social-facebook:before { content: "\f1c4"; }
+.fi-social-flickr:before { content: "\f1c5"; }
+.fi-social-forrst:before { content: "\f1c6"; }
+.fi-social-foursquare:before { content: "\f1c7"; }
+.fi-social-game-center:before { content: "\f1c8"; }
+.fi-social-github:before { content: "\f1c9"; }
+.fi-social-google-plus:before { content: "\f1ca"; }
+.fi-social-hacker-news:before { content: "\f1cb"; }
+.fi-social-hi5:before { content: "\f1cc"; }
+.fi-social-instagram:before { content: "\f1cd"; }
+.fi-social-joomla:before { content: "\f1ce"; }
+.fi-social-lastfm:before { content: "\f1cf"; }
+.fi-social-linkedin:before { content: "\f1d0"; }
+.fi-social-medium:before { content: "\f1d1"; }
+.fi-social-myspace:before { content: "\f1d2"; }
+.fi-social-orkut:before { content: "\f1d3"; }
+.fi-social-path:before { content: "\f1d4"; }
+.fi-social-picasa:before { content: "\f1d5"; }
+.fi-social-pinterest:before { content: "\f1d6"; }
+.fi-social-rdio:before { content: "\f1d7"; }
+.fi-social-reddit:before { content: "\f1d8"; }
+.fi-social-skillshare:before { content: "\f1d9"; }
+.fi-social-skype:before { content: "\f1da"; }
+.fi-social-smashing-mag:before { content: "\f1db"; }
+.fi-social-snapchat:before { content: "\f1dc"; }
+.fi-social-spotify:before { content: "\f1dd"; }
+.fi-social-squidoo:before { content: "\f1de"; }
+.fi-social-stack-overflow:before { content: "\f1df"; }
+.fi-social-steam:before { content: "\f1e0"; }
+.fi-social-stumbleupon:before { content: "\f1e1"; }
+.fi-social-treehouse:before { content: "\f1e2"; }
+.fi-social-tumblr:before { content: "\f1e3"; }
+.fi-social-twitter:before { content: "\f1e4"; }
+.fi-social-vimeo:before { content: "\f1e5"; }
+.fi-social-windows:before { content: "\f1e6"; }
+.fi-social-xbox:before { content: "\f1e7"; }
+.fi-social-yahoo:before { content: "\f1e8"; }
+.fi-social-yelp:before { content: "\f1e9"; }
+.fi-social-youtube:before { content: "\f1ea"; }
+.fi-social-zerply:before { content: "\f1eb"; }
+.fi-social-zurb:before { content: "\f1ec"; }
+.fi-sound:before { content: "\f1ed"; }
+.fi-star:before { content: "\f1ee"; }
+.fi-stop:before { content: "\f1ef"; }
+.fi-strikethrough:before { content: "\f1f0"; }
+.fi-subscript:before { content: "\f1f1"; }
+.fi-superscript:before { content: "\f1f2"; }
+.fi-tablet-landscape:before { content: "\f1f3"; }
+.fi-tablet-portrait:before { content: "\f1f4"; }
+.fi-target-two:before { content: "\f1f5"; }
+.fi-target:before { content: "\f1f6"; }
+.fi-telephone-accessible:before { content: "\f1f7"; }
+.fi-telephone:before { content: "\f1f8"; }
+.fi-text-color:before { content: "\f1f9"; }
+.fi-thumbnails:before { content: "\f1fa"; }
+.fi-ticket:before { content: "\f1fb"; }
+.fi-torso-business:before { content: "\f1fc"; }
+.fi-torso-female:before { content: "\f1fd"; }
+.fi-torso:before { content: "\f1fe"; }
+.fi-torsos-all-female:before { content: "\f1ff"; }
+.fi-torsos-all:before { content: "\f200"; }
+.fi-torsos-female-male:before { content: "\f201"; }
+.fi-torsos-male-female:before { content: "\f202"; }
+.fi-torsos:before { content: "\f203"; }
+.fi-trash:before { content: "\f204"; }
+.fi-trees:before { content: "\f205"; }
+.fi-trophy:before { content: "\f206"; }
+.fi-underline:before { content: "\f207"; }
+.fi-universal-access:before { content: "\f208"; }
+.fi-unlink:before { content: "\f209"; }
+.fi-unlock:before { content: "\f20a"; }
+.fi-upload-cloud:before { content: "\f20b"; }
+.fi-upload:before { content: "\f20c"; }
+.fi-usb:before { content: "\f20d"; }
+.fi-video:before { content: "\f20e"; }
+.fi-volume-none:before { content: "\f20f"; }
+.fi-volume-strike:before { content: "\f210"; }
+.fi-volume:before { content: "\f211"; }
+.fi-web:before { content: "\f212"; }
+.fi-wheelchair:before { content: "\f213"; }
+.fi-widget:before { content: "\f214"; }
+.fi-wrench:before { content: "\f215"; }
+.fi-x-circle:before { content: "\f216"; }
+.fi-x:before { content: "\f217"; }
+.fi-yen:before { content: "\f218"; }
+.fi-zoom-in:before { content: "\f219"; }
+.fi-zoom-out:before { content: "\f21a"; }
diff --git a/afb-client/bower_components/foundation-icon-fonts/foundation-icons.eot b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.eot
new file mode 100644
index 0000000..1746ad4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.eot
Binary files differ
diff --git a/afb-client/bower_components/foundation-icon-fonts/foundation-icons.svg b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.svg
new file mode 100644
index 0000000..4e014ff
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.svg
@@ -0,0 +1,970 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<!--
+2013-8-23: Created.
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+Created by FontForge 20120731 at Fri Aug 23 09:25:55 2013
+ By Jordan Humphreys
+Created by Jordan Humphreys with FontForge 2.0 (http://fontforge.sf.net)
+</metadata>
+<defs>
+<font id="fontcustom" horiz-adv-x="369" >
+ <font-face
+ font-family="fontcustom"
+ font-weight="500"
+ font-stretch="normal"
+ units-per-em="512"
+ panose-1="2 0 6 3 0 0 0 0 0 0"
+ ascent="448"
+ descent="-64"
+ bbox="-0.584459 -64.25 512.25 448.25"
+ underline-thickness="25.6"
+ underline-position="-51.2"
+ unicode-range="U+F100-F21A"
+ />
+ <missing-glyph />
+ <glyph glyph-name="uniF100" unicode="&#xf100;" horiz-adv-x="340"
+d="M330 287v0h-24v-30h24c6 0 10 -4 10 -10v-30c0 -6 -4 -10 -10 -10h-24v-29h24c6 0 10 -5 10 -11v-30c0 -6 -4 -10 -10 -10h-24v-29h24c6 0 10 -5 10 -11v-30c0 -6 -4 -10 -10 -10h-24v-9c0 -9 -7 -16 -16 -16h-274c-9 0 -16 7 -16 16v308c0 9 7 16 16 16h274
+c9 0 16 -7 16 -16v-9h24c6 0 10 -4 10 -10v-30c0 -6 -4 -10 -10 -10zM234 122v0v44c0 4 -3 8 -6 10l-55 26c13 8 21 24 21 42c0 26 -18 48 -41 48s-41 -22 -41 -48c0 -19 9 -34 22 -42l-56 -26c-3 -2 -5 -6 -5 -10v-44c0 -6 4 -11 9 -11h142c5 0 10 5 10 11z" />
+ <glyph glyph-name="uniF101" unicode="&#xf101;" horiz-adv-x="425"
+d="M423 31c1 -2 2 -4 2 -7c0 -10 -9 -18 -19 -18v0h-388v0c-10 0 -18 8 -18 18c0 4 1 9 4 12v0l191 331h1c3 6 8 11 16 11c7 0 13 -3 16 -9l193 -334c0 -1 1 -1 1 -2l1 -2v0zM213 40c14 0 26 12 26 27s-12 26 -26 26c-15 0 -27 -11 -27 -26s12 -27 27 -27zM239 273v0v0v0v0
+c0 6 -5 10 -11 10v0h-32v0c-5 0 -10 -4 -10 -10v-1v-144v0v0c0 -6 5 -11 11 -11h31v0v0c6 0 11 5 11 11v0v0v145z" />
+ <glyph glyph-name="uniF102" unicode="&#xf102;" horiz-adv-x="355"
+d="M337 370c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM312 235c0 -10 -8 -17 -18 -17v0h-233c-10 0 -18 7 -18 17v16c0 10 8 17 18 17h233v0c10 0 18 -7 18 -17v0v-16v0zM320 64c10 0 17 -7 17 -17v0v-16v0
+c0 -10 -7 -17 -17 -17v0h-285c-10 0 -18 7 -18 17v16c0 10 8 17 18 17h285v0zM294 149v0v-16v0c0 -10 -7 -17 -17 -17v0v0h-199c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h199v0v0c10 0 17 -7 17 -17z" />
+ <glyph glyph-name="uniF103" unicode="&#xf103;" horiz-adv-x="355"
+d="M337 369c10 0 18 -7 18 -17v-16c0 -10 -8 -18 -18 -18h-320c-10 0 -17 8 -17 18v16c0 10 7 17 17 17h320zM337 268c10 0 18 -7 18 -17v-16c0 -10 -8 -18 -18 -18h-320c-10 0 -17 8 -17 18v16c0 10 7 17 17 17h320zM337 167c10 0 18 -8 18 -18v-16c0 -10 -8 -17 -18 -17
+h-320c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h320zM337 66c10 0 18 -8 18 -18v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h320z" />
+ <glyph glyph-name="uniF104" unicode="&#xf104;" horiz-adv-x="355"
+d="M337 370c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM17 218c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h234v0c10 0 18 -8 18 -18v0v-16v0c0 -10 -8 -17 -18 -17v0h-234zM302 64c10 0 18 -7 18 -17v0v-16v0
+c0 -10 -8 -17 -18 -17v0h-285c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h285v0zM17 116c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h199v0v0c10 0 18 -7 18 -17v0v-16v0c0 -10 -8 -17 -18 -17v0v0h-199z" />
+ <glyph glyph-name="uniF105" unicode="&#xf105;" horiz-adv-x="355"
+d="M337 370c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM337 268c10 0 18 -7 18 -17v0v-16v0c0 -10 -8 -17 -18 -17v0h-233c-10 0 -18 7 -18 17v16c0 10 8 17 18 17h233v0zM337 64c10 0 18 -7 18 -17v0v-16v0
+c0 -10 -8 -17 -18 -17v0h-285c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h285v0v0zM355 149v0v-16v0c0 -10 -8 -17 -18 -17v0v0h-199c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h199v0v0c10 0 18 -7 18 -17z" />
+ <glyph glyph-name="uniF106" unicode="&#xf106;" horiz-adv-x="393"
+d="M392 104c1 -1 1 -3 1 -4c0 -4 -4 -8 -8 -8h-21c-33 -58 -95 -97 -167 -97s-134 39 -167 97h-22c-4 0 -8 4 -8 8c0 2 1 4 2 5l47 82c1 3 4 5 7 5s6 -2 7 -4v0l48 -84v0c1 -1 2 -3 2 -4c0 -4 -5 -8 -9 -8h-12c20 -22 48 -38 79 -44v150h-46c-4 0 -8 4 -8 8v0v35v0
+c0 4 4 8 8 8v0h46v27c-20 10 -34 30 -34 54c0 33 27 59 60 59s59 -26 59 -59c0 -24 -14 -44 -34 -54v-27h47v0c4 0 8 -4 8 -8v0v-35v0c0 -4 -4 -8 -8 -8h-47v-150c31 6 59 22 79 44h-12c-4 0 -8 4 -8 8c0 2 1 4 2 5l46 82c1 3 5 5 8 5s6 -2 7 -4v0l48 -84v0zM197 296
+c18 0 33 16 33 34s-15 33 -33 33s-34 -15 -34 -33s16 -34 34 -34z" />
+ <glyph glyph-name="uniF107" unicode="&#xf107;" horiz-adv-x="388"
+d="M360 98c17 -9 28 -27 28 -47c0 -29 -24 -54 -53 -54c-22 0 -42 14 -50 34h-182c-8 -20 -28 -34 -50 -34c-29 0 -53 25 -53 54c0 20 11 38 28 47v188c-17 9 -28 27 -28 47c0 29 24 54 53 54c18 0 34 -10 44 -24h194c10 14 26 24 44 24c29 0 53 -25 53 -54
+c0 -20 -11 -38 -28 -47v-188zM79 98c7 -4 13 -10 18 -16h195c5 6 10 12 17 16v188c-11 6 -18 15 -23 26h-184c-5 -11 -12 -20 -23 -26v-188z" />
+ <glyph glyph-name="uniF108" unicode="&#xf108;" horiz-adv-x="401"
+d="M401 279v0v-247v0c0 -12 -9 -21 -21 -21h-1h-357h-1c-12 0 -21 9 -21 21v0v247v1c0 5 2 10 5 14v0l42 72v0c2 4 6 7 11 7v0v0h284v0h1c6 0 12 -4 13 -10l40 -69v-1c3 -4 5 -8 5 -13v-1zM269 154c1 2 2 4 1 6s-4 3 -6 3h-30v81c0 3 -3 6 -6 6h-55c-3 0 -6 -3 -6 -6v-81
+h-30c-2 0 -5 -1 -6 -3s0 -4 1 -6l64 -90c1 -2 3 -2 5 -2v0c2 0 4 0 5 2zM39 301h323l-27 47h-269z" />
+ <glyph glyph-name="uniF109" unicode="&#xf109;" horiz-adv-x="292"
+d="M2 188c-3 4 -3 9 -1 13s7 7 12 7h62v167c0 7 6 13 13 13h116c7 0 12 -6 12 -13v-167h63c5 0 9 -3 11 -7s2 -9 -1 -13l-132 -187c-2 -3 -7 -5 -11 -5v0c-4 0 -8 2 -10 5z" />
+ <glyph glyph-name="uniF10A" unicode="&#xf10a;" horiz-adv-x="393"
+d="M192 335c4 3 9 3 13 1s7 -6 7 -11v-62h168c7 0 13 -6 13 -13v-116c0 -7 -6 -13 -13 -13h-168v-62c0 -5 -3 -9 -7 -11s-9 -2 -13 1l-187 132c-3 2 -5 7 -5 11v0c0 4 2 8 5 10z" />
+ <glyph glyph-name="uniF10B" unicode="&#xf10b;" horiz-adv-x="393"
+d="M201 49c-4 -3 -10 -3 -14 -1s-7 6 -7 11v62h-167c-7 0 -13 6 -13 13v116c0 7 6 13 13 13h167v62c0 5 3 9 7 11s10 2 14 -1l186 -132c3 -2 6 -7 6 -11v0c0 -4 -3 -8 -6 -10z" />
+ <glyph glyph-name="uniF10C" unicode="&#xf10c;" horiz-adv-x="292"
+d="M289 196c3 -4 3 -9 1 -13s-6 -7 -11 -7h-63v-167c0 -7 -5 -13 -12 -13h-116c-7 0 -13 6 -13 13v167h-62c-5 0 -10 3 -12 7s-2 9 1 13l133 187c2 3 6 5 10 5v0c4 0 9 -2 11 -5z" />
+ <glyph glyph-name="uniF10D" unicode="&#xf10d;" horiz-adv-x="512"
+d="M201 -5c-1 -3 -4 -6 -7 -7s-7 0 -9 2l-30 31l-83 -82c-4 -4 -9 -4 -13 0l-56 56c-4 4 -4 9 0 13l82 83l-31 30c-2 2 -3 6 -2 9s4 6 7 7l157 26c3 0 6 0 8 -2v0c2 -2 3 -5 3 -8zM311 389c1 3 4 6 7 7s7 0 9 -2l30 -31l83 82c4 4 9 4 13 0l56 -56c4 -4 4 -9 0 -13l-82 -83
+l31 -30c2 -2 3 -6 2 -9s-4 -6 -7 -7l-157 -26c-3 0 -6 0 -8 2v0c-2 2 -3 5 -3 8z" />
+ <glyph glyph-name="uniF10E" unicode="&#xf10e;" horiz-adv-x="512"
+d="M26 104c1 3 3 6 6 7s7 0 9 -2l31 -31l83 83c4 4 8 4 12 0l57 -57c4 -4 4 -9 0 -13l-82 -82l30 -31c2 -2 4 -6 3 -9s-4 -5 -7 -6l-158 -27c-3 0 -5 1 -7 3v0c-2 2 -3 4 -3 7zM486 280c-1 -3 -3 -6 -6 -7s-7 0 -9 2l-31 31l-83 -83c-4 -4 -8 -4 -12 0l-57 57
+c-4 4 -4 9 0 13l82 82l-30 31c-2 2 -4 6 -3 9s4 5 7 6l158 27c3 0 5 -1 7 -3v0c2 -2 3 -4 3 -7z" />
+ <glyph glyph-name="uniF10F" unicode="&#xf10f;" horiz-adv-x="512"
+d="M184 -10c-1 -3 -2 -5 -5 -6s-7 0 -9 2l-28 28l-76 -76c-3 -3 -8 -3 -11 0l-53 53c-3 3 -3 8 0 11l76 76l-28 28c-2 2 -3 6 -2 9s3 4 6 5l145 25c3 0 5 -1 7 -3v0c2 -2 2 -4 2 -7zM328 394c1 3 2 5 5 6s7 0 9 -2l28 -28l76 76c3 3 8 3 11 0l53 -53c3 -3 3 -8 0 -11
+l-76 -76l28 -28c2 -2 3 -6 2 -9s-3 -4 -6 -5l-145 -25c-3 0 -5 1 -7 3v0c-2 2 -2 4 -2 7zM458 120c3 -1 5 -2 6 -5s0 -7 -2 -9l-28 -28l76 -76c3 -3 3 -8 0 -11l-53 -53c-3 -3 -8 -3 -11 0l-76 76l-28 -28c-2 -2 -6 -3 -9 -2s-4 3 -5 6l-25 145c0 3 1 5 3 7v0c2 2 4 2 7 2z
+M54 264c-3 1 -5 2 -6 5s0 7 2 9l28 28l-76 76c-3 3 -3 8 0 11l53 53c3 3 8 3 11 0l76 -76l28 28c2 2 6 3 9 2s4 -3 5 -6l25 -145c0 -3 -1 -5 -3 -7v0c-2 -2 -4 -2 -7 -2z" />
+ <glyph glyph-name="uniF110" unicode="&#xf110;" horiz-adv-x="512"
+d="M24 90c1 3 3 6 6 7s6 0 8 -2l28 -28l76 75c3 3 9 3 12 0l52 -52c3 -3 3 -9 0 -12l-76 -75l28 -29c2 -2 3 -5 2 -8s-3 -4 -6 -5l-144 -25c-3 0 -6 0 -8 2v0c-2 2 -2 5 -2 8zM488 294c-1 -3 -3 -6 -6 -7s-6 0 -8 2l-28 28l-76 -75c-3 -3 -9 -3 -12 0l-52 52c-3 3 -3 9 0 12
+l76 75l-28 29c-2 2 -3 5 -2 8s3 4 6 5l144 25c3 0 6 0 8 -2v0c2 -2 2 -5 2 -8zM358 -40c-3 1 -6 3 -7 6s0 6 2 8l28 28l-75 76c-3 3 -3 9 0 12l52 52c3 3 9 3 12 0l75 -76l29 28c2 2 5 3 8 2s4 -3 5 -6l25 -144c0 -3 0 -6 -2 -8v0c-2 -2 -5 -2 -8 -2zM154 424
+c3 -1 6 -3 7 -6s0 -6 -2 -8l-28 -28l75 -76c3 -3 3 -9 0 -12l-52 -52c-3 -3 -9 -3 -12 0l-75 76l-29 -28c-2 -2 -5 -3 -8 -2s-4 3 -5 6l-25 144c0 3 0 6 2 8v0c2 2 5 2 8 2z" />
+ <glyph glyph-name="uniF111" unicode="&#xf111;" horiz-adv-x="440"
+d="M94 315c2 1 3 2 5 3c17 15 37 27 59 34c11 3 23 4 35 5c2 0 6 -2 7 -4s0 -6 -2 -8c-3 -3 -6 -5 -10 -6c-15 -5 -29 -9 -44 -14c-3 -1 -6 -6 -9 -8c-7 -6 -14 -10 -21 -16l-3 -3v-1c4 2 7 3 11 4c12 4 23 9 35 11c10 2 21 -1 32 -2c2 0 5 -2 7 -4c8 -6 15 -13 23 -19
+c3 -2 3 -4 1 -7c-5 -7 -11 -8 -18 -4c-6 3 -10 7 -15 11c-3 2 -5 4 -9 3c-7 -1 -15 -1 -22 -2c-3 0 -5 -1 -7 -2c-10 -7 -20 -15 -30 -22c-2 -1 -3 -4 -3 -7c1 0 2 0 3 1c8 5 17 6 26 7c3 0 6 1 9 1c12 2 20 -3 29 -10c7 -5 14 -10 21 -16c4 -3 6 -8 6 -13
+c0 -9 0 -18 -3 -27c0 -1 -1 -3 0 -3c6 -4 2 -9 1 -13c-3 -9 -7 -18 -10 -27c-3 -8 -9 -13 -18 -16c-21 -6 -41 -13 -62 -20c-8 -3 -17 -4 -26 -2c-17 4 -33 2 -49 -5c-7 -3 -15 -7 -23 -11c-9 13 -14 27 -17 41c-4 17 -4 35 -2 52c0 1 2 3 3 4c17 7 25 21 31 37
+c7 19 9 40 21 57c13 19 23 39 40 55c8 8 16 18 23 27c3 4 5 4 8 -1s3 -11 -1 -16c-10 -13 -21 -26 -31 -39c-1 -1 -1 -2 -2 -4zM167 170c4 0 8 -1 10 3c4 9 11 16 18 22c2 2 2 3 1 5c-4 7 -6 14 -10 21c-1 2 -3 4 -5 5c-6 4 -12 8 -19 12c-2 1 -4 2 -6 1
+c-5 -2 -10 -5 -15 -7c-4 -2 -9 -3 -13 -5c-11 -4 -14 -13 -17 -23c-2 -6 -1 -11 4 -16c6 -6 12 -13 17 -20c2 -2 3 -2 6 -1c10 3 19 5 29 3zM346 69c-3 -3 -7 -4 -10 -7c-15 -14 -34 -24 -53 -30c-11 -4 -23 -5 -35 -6c-7 -1 -10 7 -6 12c3 3 7 7 11 8c12 4 25 7 37 11
+c5 2 9 5 13 8c8 6 16 13 24 19c1 1 2 2 2 4c-4 -2 -9 -4 -13 -6c-11 -4 -21 -9 -32 -10s-22 1 -33 2c-2 0 -5 2 -7 4c-7 5 -13 11 -20 16s-6 12 3 15c3 1 8 1 11 -1c6 -3 11 -8 17 -12c2 -1 4 -2 6 -2c8 0 15 1 22 2c3 0 7 1 10 3c9 7 19 14 28 21c2 1 2 4 3 7
+c-12 -8 -26 -8 -39 -9c-9 -1 -16 1 -23 7c-9 7 -19 14 -28 21c-2 2 -4 5 -4 8c0 9 1 18 2 27c0 3 2 6 -1 9c-1 1 0 3 0 4c1 4 3 7 4 11c3 7 5 13 7 20c3 9 9 15 19 18c21 6 42 13 62 20c9 3 17 4 26 2c18 -5 35 -2 52 6c6 3 12 7 19 10c8 -9 12 -21 15 -32
+c6 -20 6 -40 4 -61c0 -5 -4 -5 -7 -6c-10 -4 -17 -13 -21 -22c-5 -10 -8 -21 -11 -32c-5 -15 -10 -30 -19 -43c-7 -10 -13 -20 -20 -30c-6 -8 -13 -15 -19 -23l-21 -24c-4 -4 -5 -4 -8 1s-2 10 2 16c10 13 20 25 30 38c1 1 1 3 2 5c-1 0 -1 1 -1 1zM245 186
+c3 -8 6 -16 10 -24c1 -2 2 -3 4 -4c6 -4 13 -8 19 -12c2 -1 4 -2 7 -1c8 3 15 7 23 10s14 6 17 14c2 4 3 9 4 13c1 5 1 9 -3 13c-7 7 -13 14 -19 21c-1 1 -3 1 -4 1c-11 -3 -22 -5 -33 -3c-2 0 -6 -1 -7 -3c-7 -8 -12 -17 -18 -25z" />
+ <glyph glyph-name="uniF112" unicode="&#xf112;" horiz-adv-x="343"
+d="M338 140c4 -3 6 -7 4 -12v0v-2v0h-1l-28 -49v0c-3 -5 -9 -6 -14 -3c-1 0 -1 0 -2 1l-87 50v-103v0v0c0 -5 -4 -9 -9 -10v0h-58v0c-6 0 -10 4 -10 10v3v100l-89 -51v0v0c-4 -3 -10 -2 -13 2v0l-30 51v0c-3 5 -1 11 4 14c1 0 1 1 2 1l88 50l-90 51v1v0v0v0c-5 3 -7 8 -4 13
+v0l29 49v0v1c3 5 9 7 14 4v0l89 -52v103v0c0 5 5 10 10 10v0h57v0v0c6 0 10 -4 10 -10v0v-103l90 51v0c5 3 10 2 13 -3v0l28 -49v0l1 -1c3 -5 1 -11 -4 -14v0l-89 -51l89 -51v0v-1z" />
+ <glyph glyph-name="uniF113" unicode="&#xf113;" horiz-adv-x="384"
+d="M384 192v-9v0c0 -76 -46 -102 -85 -102c-27 0 -75 22 -78 39v3c-16 -22 -41 -36 -65 -36c-44 0 -70 31 -70 75c0 60 50 111 102 111c27 0 47 -13 56 -30l4 18v0c1 3 4 5 7 5h37c4 0 7 -2 7 -6l-1 -2h1l-22 -101c0 -2 -1 -8 -1 -11c0 -14 8 -21 17 -21c18 0 39 29 39 80
+c-7 72 -67 128 -140 128c-78 0 -141 -63 -141 -141s63 -141 141 -141c19 0 37 3 53 10v0c1 0 2 1 3 1c2 0 4 -1 5 -2v0l34 -21v0c3 -1 4 -4 4 -7c0 -4 -2 -6 -5 -7c-28 -16 -60 -25 -94 -25c-106 0 -192 86 -192 192s86 192 192 192s192 -86 192 -192zM226 157l11 52
+c-5 10 -16 23 -36 23c-36 0 -62 -32 -62 -65c0 -23 14 -40 37 -40c24 0 40 16 50 30z" />
+ <glyph glyph-name="uniF114" unicode="&#xf114;"
+d="M122 53h133l17 -45h-167zM136 98l52 138l53 -138h-105zM333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-3l-106 270v0c-2 5 -7 9 -13 9h-45c-6 0 -11 -4 -13 -9v0l-106 -270h-11c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297z" />
+ <glyph glyph-name="uniF115" unicode="&#xf115;" horiz-adv-x="484"
+d="M476 236c5 0 8 -4 8 -9v-62c0 -5 -3 -9 -8 -9h-40v-95v0v0c0 -5 -4 -9 -9 -9h-418c-5 0 -9 4 -9 9v0v0v262v0v0c0 5 4 9 9 9h418c5 0 9 -4 9 -9v0v0v-87h40zM385 103v177h-333v-177h333z" />
+ <glyph glyph-name="uniF116" unicode="&#xf116;" horiz-adv-x="484"
+d="M476 236c5 0 8 -4 8 -9v-62c0 -5 -3 -9 -8 -9h-40v-95v0v0c0 -5 -4 -9 -9 -9h-418c-5 0 -9 4 -9 9v0v0v262v0v0c0 5 4 9 9 9h418c5 0 9 -4 9 -9v0v0v-87h40zM385 103v177h-333v-177h333zM78 128v129h281v-129h-281z" />
+ <glyph glyph-name="uniF117" unicode="&#xf117;" horiz-adv-x="484"
+d="M476 236c5 0 8 -4 8 -9v-62c0 -5 -3 -9 -8 -9h-40v-95v0v0c0 -5 -4 -9 -9 -9h-418c-5 0 -9 4 -9 9v0v0v262v0v0c0 5 4 9 9 9h418c5 0 9 -4 9 -9v0v0v-87h40zM385 103v177h-333v-177h333zM276 255l-50 -126h-149v126h199z" />
+ <glyph glyph-name="uniF118" unicode="&#xf118;" horiz-adv-x="384"
+d="M191 253c12 -3 50 -8 44 -33c-6 -24 -43 -12 -55 -9zM175 190c14 -4 60 -11 53 -38c-7 -26 -50 -13 -64 -9zM238 378c103 -26 166 -129 140 -232s-129 -166 -232 -140s-166 129 -140 232s129 166 232 140zM277 219c4 26 -16 40 -43 49l9 34l-21 6l-8 -34
+c-6 1 -11 3 -17 4l8 34l-21 5l-9 -34c-5 1 -9 2 -13 3v0l-29 7l-6 -22l16 -4c9 -2 9 -9 9 -13l-9 -39c1 0 1 -1 2 -1c-1 0 -1 1 -2 1l-14 -55c-1 -3 -4 -6 -10 -5l-15 3l-11 -24l28 -6c5 -1 10 -3 15 -4l-9 -35l21 -6l9 35c6 -2 12 -3 17 -4l-9 -35l21 -5l9 35
+c36 -7 63 -4 74 28c9 26 0 41 -19 51c14 3 24 12 27 31z" />
+ <glyph glyph-name="uniF119" unicode="&#xf119;" horiz-adv-x="260"
+d="M213 205c31 -7 51 -26 47 -67c-5 -51 -44 -65 -98 -68v-47v0v0c0 -4 -2 -7 -6 -7v0v0v0h-20v0v0c-4 0 -6 3 -6 7v0v46c-8 0 -17 1 -26 1v-47v0v0c0 -4 -2 -7 -6 -7v0v0v0h-20v0v0c-4 0 -6 3 -6 7v0v47h-23h-42v0c-3 0 -6 4 -6 7v0v0l5 27h1c1 3 3 5 6 5v0v0h23
+c9 0 12 7 13 11v85v0v61c-1 7 -6 14 -19 14h-24v0v0c-4 0 -6 2 -6 6v22c0 4 2 6 6 6v0h45v0h21v47v0v0c0 4 2 7 6 7v0v0v0v0h20v0v0c4 0 6 -3 6 -7v0v-46c9 0 17 1 26 1v45v0v0c0 4 2 7 6 7v0v0v0v0h20v0v0c4 0 6 -3 6 -7v0v-47c42 -4 75 -16 79 -54c3 -28 -9 -45 -28 -55z
+M105 277v-64c18 0 76 -5 76 32c0 38 -58 32 -76 32zM105 109c22 0 91 -5 91 35c0 42 -69 36 -91 36v-71z" />
+ <glyph glyph-name="uniF11A" unicode="&#xf11a;" horiz-adv-x="342"
+d="M91 347c0 24 12 36 36 36s37 -12 37 -36s-13 -37 -37 -37s-36 13 -36 37zM341 15c1 -1 1 -2 1 -3c0 -4 -2 -6 -6 -6c-2 0 -4 1 -5 3v0v0v1l-107 184h-3c-3 0 -6 1 -8 2v0v0v1h-1l-35 20v0v0v0v0l-23 23v-76l45 -44v0l49 -85c3 -4 4 -8 4 -13c0 -6 -2 -11 -6 -15
+s-9 -6 -15 -6c-8 0 -15 4 -19 11v0l-47 81l-37 37l-41 -72v0l-49 -49c-4 -5 -10 -8 -17 -8c-6 0 -11 2 -15 6s-6 9 -6 15s2 12 7 16v0l45 45l36 62v0v96l-19 -18v-52v0c0 -4 -1 -8 -4 -11s-7 -4 -11 -4c-3 0 -6 1 -8 2s-5 4 -6 6s-2 4 -2 7v0v62h1h-1c0 1 1 2 2 3v0l54 55
+c7 8 17 11 27 11c12 0 21 -4 28 -13l47 -47l31 -18c6 -3 9 -7 9 -14c0 -3 0 -6 -2 -9l107 -186v0z" />
+ <glyph glyph-name="uniF11B" unicode="&#xf11b;" horiz-adv-x="239"
+d="M231 120c5 -4 8 -10 8 -17c0 -5 -3 -10 -6 -14v0l-1 -1v0l-102 -102v0c-4 -4 -10 -7 -16 -7c-12 0 -21 9 -21 21v0v0v1v0v124l-55 -55c-4 -5 -9 -7 -16 -7c-12 0 -22 10 -22 22c0 6 2 11 6 15v0v0v0l87 86v11l-86 86c-4 4 -7 9 -7 15c0 12 10 22 22 22c6 0 12 -3 16 -7
+l55 -55v119c-1 2 -1 4 -1 6c0 12 9 22 21 22c7 0 13 -3 17 -8l101 -101c5 -4 8 -9 8 -16c0 -5 -3 -10 -6 -14v0v0c-1 -1 -1 -2 -2 -3l-72 -71zM186 103l-50 51v-101zM136 230l50 50l-50 50v-100z" />
+ <glyph glyph-name="uniF11C" unicode="&#xf11c;" horiz-adv-x="242"
+d="M186 197c31 -5 56 -35 56 -71c0 -44 -29 -79 -85 -79h-144c-7 0 -13 6 -13 13v264c0 7 6 13 13 13h140c55 0 83 -35 83 -74c0 -36 -23 -60 -50 -66zM62 283v-61h77c21 0 34 11 34 30c0 18 -13 31 -34 31h-77zM142 101c23 0 37 12 37 33c0 18 -13 33 -37 33h-80v-66h80z
+" />
+ <glyph glyph-name="uniF11D" unicode="&#xf11d;" horiz-adv-x="328"
+d="M328 334v-327v0c0 -5 -3 -8 -8 -8v0v0h-312v0c-4 0 -8 4 -8 8v0v0v0v1v65v303v1c0 5 3 8 8 8h153v-66v-84v-29c0 -2 2 -4 4 -4c1 0 2 0 3 1v0l29 30h1c1 1 1 1 2 1s2 0 3 -1v0l29 -29c1 -1 2 -2 3 -2c2 0 4 2 4 4v29v84v66h29v0h1c5 0 8 -3 8 -8v-319v0c0 -5 -3 -8 -8 -8
+h-1v0h-242v-19c1 -4 4 -7 8 -7h261v0c5 0 8 4 8 9v0v309h17v0c4 0 8 -4 8 -8v0z" />
+ <glyph glyph-name="uniF11E" unicode="&#xf11e;" horiz-adv-x="328"
+d="M328 334v-327v0c0 -5 -3 -8 -8 -8v0v0h-312v0c-4 0 -8 4 -8 8v0v0v0v1v65v303v1c0 5 3 8 8 8h260v0h1c5 0 8 -3 8 -8v-319v0c0 -5 -3 -8 -8 -8h-1v0h-242v-19c1 -4 4 -7 8 -7h261v0c5 0 8 4 8 9v0v309h17v0c4 0 8 -4 8 -8v0zM25 326v0v-64c0 -5 4 -8 9 -8h209v0
+c5 0 8 3 8 8v0v64v0c0 5 -3 8 -8 8h-209c-5 0 -9 -3 -9 -8z" />
+ <glyph glyph-name="uniF11F" unicode="&#xf11f;" horiz-adv-x="218"
+d="M203 381c9 0 15 -7 15 -16v-34v-235v-82c0 -6 -5 -11 -11 -11c-3 0 -7 2 -9 4l-81 82v0c-2 2 -5 3 -8 3s-5 -1 -7 -3v0l-83 -83v0c-2 -2 -5 -3 -8 -3c-6 0 -11 5 -11 11v82v235v34c0 9 6 16 15 16h188z" />
+ <glyph glyph-name="uniF120" unicode="&#xf120;" horiz-adv-x="265"
+d="M0 325c0 24 12 36 36 36s35 -12 35 -36s-11 -35 -35 -35s-36 11 -36 35zM194 325c0 24 11 36 35 36s36 -12 36 -36s-12 -35 -36 -35s-35 11 -35 35zM0 192c0 24 12 36 36 36s35 -12 35 -36s-11 -36 -35 -36s-36 12 -36 36zM194 192c0 24 11 36 35 36s36 -12 36 -36
+s-12 -36 -36 -36s-35 12 -35 36zM0 59c0 24 12 36 36 36s35 -12 35 -36s-11 -36 -35 -36s-36 12 -36 36zM194 59c0 24 11 36 35 36s36 -12 36 -36s-12 -36 -36 -36s-35 12 -35 36z" />
+ <glyph glyph-name="uniF121" unicode="&#xf121;" horiz-adv-x="395"
+d="M395 192c0 -5 -3 -9 -6 -11v0l-48 -28l27 -46v0c2 -4 1 -9 -1 -13s-6 -6 -10 -6v0h-54v-55h-1c0 -4 -2 -8 -6 -10s-9 -3 -13 -1v0l-47 27l-27 -47v0c-2 -3 -6 -6 -11 -6s-9 3 -11 6v0l-27 46l-49 -28v0c-4 -2 -8 -1 -12 1s-7 6 -7 10v0v55h-55v0c-4 0 -8 3 -10 7
+s-3 8 -1 12v0l27 48l-47 28v0c-3 2 -6 6 -6 11s3 9 6 11v0l48 28l-27 46v0c-2 4 -1 9 1 13s6 6 10 6v0h54v55v0c0 4 3 8 7 10s8 3 12 1v0l48 -27l27 47v0c2 3 6 6 11 6s9 -3 11 -6v0l27 -46l49 28v0c4 2 8 1 12 -1s7 -6 7 -10v0v-55h55v0c4 0 8 -3 10 -7s3 -8 1 -12v-1
+l-27 -47l47 -28v0c3 -2 6 -6 6 -11zM165 134l12 7l-34 59l-12 -7l21 -37l-49 21l-13 -8l34 -59l13 8l-22 38zM189 148l42 24l-7 11l-29 -17l-8 13l29 17l-6 11l-29 -17l-7 13l29 17l-6 11l-42 -24zM286 204l13 7l-17 69l-14 -8l14 -49l-36 36l-9 -5l13 -49l-35 36l-14 -8
+l51 -49l13 8l-13 46z" />
+ <glyph glyph-name="uniF122" unicode="&#xf122;" horiz-adv-x="395"
+d="M167 163l-5 31l24 -20zM395 192c0 -5 -3 -9 -6 -11v0l-48 -28l27 -46v0c2 -4 1 -9 -1 -13s-6 -6 -10 -6v0h-54v-55h-1c0 -4 -2 -8 -6 -10s-9 -3 -13 -1v0l-47 27l-27 -47v0c-2 -3 -6 -6 -11 -6s-9 3 -11 6v0l-27 46l-49 -28v0c-4 -2 -8 -1 -12 1s-7 6 -7 10v0v55h-55v0
+c-4 0 -8 3 -10 7s-3 8 -1 12v0l27 48l-47 28v0c-3 2 -6 6 -6 11s3 9 6 11v0l48 28l-27 46v0c-2 4 -1 9 1 13s6 6 10 6v0h54v55v0c0 4 3 8 7 10s8 3 12 1v0l48 -27l27 47v0c2 3 6 6 11 6s9 -3 11 -6v0l27 -46l49 28v0c4 2 8 1 12 -1s7 -6 7 -10v0v-55h55v0c4 0 8 -3 10 -7
+s3 -8 1 -12v-1l-27 -47l47 -28v0c3 -2 6 -6 6 -11zM134 114c16 9 18 22 12 33c-13 22 -43 -4 -48 5c-2 4 0 8 5 11c6 3 14 5 21 3l1 14c-9 2 -18 0 -27 -5c-14 -8 -18 -21 -12 -31c13 -22 42 4 48 -6c2 -3 1 -8 -6 -12c-8 -5 -17 -5 -24 -3l-1 -14c9 -2 20 -2 31 5zM205 157
+l14 8l-57 46l-15 -9l11 -72l14 8l-2 12l25 15zM224 168l38 22l-7 11l-25 -15l-27 48l-13 -7zM270 195l42 24l-6 11l-29 -17l-8 13l28 17l-6 11l-29 -17l-7 13l29 17l-6 11l-42 -24z" />
+ <glyph glyph-name="uniF123" unicode="&#xf123;" horiz-adv-x="395"
+d="M395 192c0 -5 -3 -9 -6 -11v0l-48 -28l27 -46v0c2 -4 1 -9 -1 -13s-6 -6 -10 -6v0h-54v-55h-1c0 -4 -2 -8 -6 -10s-9 -3 -13 -1v0l-47 27l-27 -47v0c-2 -3 -6 -6 -11 -6s-9 3 -11 6v0l-27 46l-49 -28v0c-4 -2 -8 -1 -12 1s-7 6 -7 10v0v55h-55v0c-4 0 -8 3 -10 7
+s-3 8 -1 12v0l27 48l-47 28v0c-3 2 -6 6 -6 11s3 9 6 11v0l48 28l-27 46v0c-2 4 -1 9 1 13s6 6 10 6v0h54v55v0c0 4 3 8 7 10s8 3 12 1v0l48 -27l27 47v0c2 3 6 6 11 6s9 -3 11 -6v0l27 -46l49 28v0c4 2 8 1 12 -1s7 -6 7 -10v0v-55h55v0c4 0 8 -3 10 -7s3 -8 1 -12v-1
+l-27 -47l47 -28v0c3 -2 6 -6 6 -11z" />
+ <glyph glyph-name="uniF124" unicode="&#xf124;" horiz-adv-x="326"
+d="M320 246c4 0 6 -3 6 -7v-225c0 -4 -2 -6 -6 -6h-314c-4 0 -6 2 -6 6v225c0 4 2 7 6 7h314zM109 55c34 0 56 18 56 44c0 18 -13 26 -25 31c14 7 21 17 21 31c0 18 -18 30 -44 30c-15 0 -27 -2 -37 -7c-1 -1 -2 -2 -2 -3l3 -22c0 -1 1 -2 2 -2h3c8 4 16 6 24 6
+c15 0 15 -6 15 -9c0 -5 -3 -11 -24 -13c-2 0 -3 -1 -3 -3v-22c0 -2 1 -3 3 -3c25 -1 30 -7 30 -16c0 -8 -9 -13 -20 -13s-19 1 -29 5c-1 0 -2 1 -3 0s-1 -1 -1 -2l-3 -22c0 -1 1 -3 2 -4c9 -4 21 -6 32 -6zM245 61v0v125c0 2 -1 3 -3 3h-13h-2l-38 -19c-1 -1 -2 -2 -2 -3
+l3 -22c0 -1 1 -3 2 -3c1 -1 2 0 3 0l17 7v-88c0 -2 1 -4 3 -4h27c2 0 3 2 3 4zM320 347c4 0 6 -2 6 -6v-66c0 -4 -2 -7 -6 -7h-314c-4 0 -6 3 -6 7v66c0 4 2 6 6 6h34v-16c0 -17 9 -34 36 -34s36 17 36 34v16h102v-16c0 -17 9 -34 36 -34s36 17 36 34v16h34zM76 318
+c-11 0 -15 4 -15 13v16v16c0 9 4 13 15 13s15 -4 15 -13v-16v-16c0 -9 -4 -13 -15 -13zM250 318c-11 0 -15 4 -15 13v16v16c0 9 4 13 15 13s15 -4 15 -13v-16v-16c0 -9 -4 -13 -15 -13z" />
+ <glyph glyph-name="uniF125" unicode="&#xf125;" horiz-adv-x="415"
+d="M159 175c0 32 17 49 49 49s48 -17 48 -49s-16 -48 -48 -48s-49 16 -49 48zM396 324c5 0 9 -1 13 -5s6 -9 6 -14v-259c0 -5 -2 -10 -6 -14s-8 -5 -13 -5v-1h-377v1c-5 0 -9 1 -13 5s-6 9 -6 14v259c0 5 2 10 6 14s8 5 13 5v0h85v15c0 5 2 9 6 13s8 6 13 6h168
+c5 0 10 -2 14 -6s5 -8 5 -13v-15h86v0zM209 77c18 0 34 4 49 13s27 21 36 36s13 31 13 49c0 27 -10 51 -29 70s-42 29 -69 29s-51 -10 -70 -29s-29 -43 -29 -70s10 -50 29 -69s43 -29 70 -29zM389 248v0v51h-75v-51h75z" />
+ <glyph glyph-name="uniF126" unicode="&#xf126;" horiz-adv-x="397"
+d="M393 293c5 -5 5 -13 0 -18l-250 -250c-2 -2 -6 -4 -9 -4v1l-1 -1c-3 0 -6 2 -8 4l-121 121c-2 2 -4 6 -4 9s2 7 4 9l66 66c5 5 12 5 17 0l47 -47l176 176c2 2 5 4 8 4s7 -2 9 -4z" />
+ <glyph glyph-name="uniF127" unicode="&#xf127;" horiz-adv-x="381"
+d="M379 323c3 -3 3 -8 0 -11l-209 -209c-2 -2 -4 -3 -6 -3v0v0c-2 0 -4 1 -6 3l-81 80c-2 2 -3 4 -3 6s1 4 3 6l44 44c3 3 9 3 12 0l31 -31l159 160c2 2 4 2 6 2s4 0 6 -2zM277 173l51 52v-185v0c0 -14 -12 -26 -26 -26v0h-1v0v0h-275v0v0v0v0c-14 0 -26 12 -26 26v0v276v0
+c0 14 12 26 26 26h1v0h234l-51 -51h-159v-226h226v108z" />
+ <glyph glyph-name="uniF128" unicode="&#xf128;" horiz-adv-x="315"
+d="M315 360v0v-362v0v0c0 -15 -12 -27 -27 -27h-1h-259v0h-1c-15 0 -27 12 -27 27v0v0v362v0v0c0 15 12 27 27 27v0h75v17v1c0 5 3 8 8 8v0v0h95v0c5 0 8 -3 8 -8v0v0v-18h75v0c15 0 27 -12 27 -27v0v0zM264 22v0v314h-25v-16v0c0 -5 -5 -9 -10 -9h-143v0v0
+c-5 0 -10 4 -10 9v1v15h-25v-314h213zM102 237v0v0v-13v0v0c0 -3 -3 -6 -6 -6h-1v0h-12v0c-3 0 -7 3 -7 6v0v0v13c0 3 4 7 7 7h12v-1l1 1c3 0 6 -4 6 -7zM239 237v0v0v-13v0v0c0 -3 -4 -6 -7 -6h-98v0c-3 0 -7 3 -7 6v0v0v13c0 3 4 7 7 7h98v0c3 0 7 -4 7 -7zM102 186v0v0
+v-13v0v0c0 -3 -3 -6 -6 -6h-1v0h-12v0c-3 0 -7 3 -7 6v0v0v13c0 3 4 7 7 7h12v-1l1 1c3 0 6 -4 6 -7zM239 186v0v0v-13v0v0c0 -3 -4 -6 -7 -6h-98v0c-3 0 -7 3 -7 6v0v0v13c0 3 4 7 7 7h98v0c3 0 7 -4 7 -7zM102 135v0v0v-13v0v0c0 -3 -3 -6 -6 -6h-1v0h-12v0
+c-3 0 -7 3 -7 6v0v0v13c0 3 4 6 7 6h12v0h1c3 0 6 -3 6 -6zM239 135v0v0v-13v0v0c0 -3 -4 -6 -7 -6h-98v0c-3 0 -7 3 -7 6v0v0v13c0 3 4 6 7 6h98v0c3 0 7 -3 7 -6z" />
+ <glyph glyph-name="uniF129" unicode="&#xf129;" horiz-adv-x="392"
+d="M391 228c2 -2 2 -7 0 -9l-116 -116v0v0l-59 -16v0c-2 -1 -5 0 -7 2s-2 4 -1 6v0l16 59v0v0l115 116c2 2 7 2 9 0zM227 107l35 9l-25 26zM309 73c3 0 6 -3 6 -6v0v0v-69v0v0c0 -15 -12 -27 -27 -27h-1h-259v0h-1c-15 0 -27 12 -27 27v0v0v362v0v0c0 15 12 27 27 27v0h75
+v17v1c0 5 3 8 8 8v0v0h95v0c4 0 8 -3 8 -8v0v0v-18h75v0c15 0 27 -12 27 -27v0v0v-68v0c0 -3 -3 -7 -6 -7v0h-39c-3 0 -6 4 -6 7v0v44h-25v-16v0c0 -5 -5 -9 -10 -9h-143v0v0c-5 0 -10 4 -10 9v1v15h-25v-314h213v45v0c0 3 3 6 6 6v0v0h39v0z" />
+ <glyph glyph-name="uniF12A" unicode="&#xf12a;" horiz-adv-x="315"
+d="M315 360v0v-362v0v0c0 -15 -12 -27 -27 -27h-1h-259v0h-1c-15 0 -27 12 -27 27v0v0v362v0v0c0 15 12 27 27 27v0h75v17v1c0 5 3 8 8 8v0v0h95v0c5 0 8 -3 8 -8v0v0v-18h75v0c15 0 27 -12 27 -27v0v0zM264 22v0v314h-25v-16v0c0 -5 -5 -9 -10 -9h-143v0v0
+c-5 0 -10 4 -10 9v1v15h-25v-314h213z" />
+ <glyph glyph-name="uniF12B" unicode="&#xf12b;" horiz-adv-x="384"
+d="M192 333c-78 0 -141 -63 -141 -141s63 -141 141 -141s141 63 141 141s-63 141 -141 141zM192 384v0c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM290 263c4 -4 4 -10 0 -14l-91 -91c-2 -2 -4 -3 -7 -3v0c-3 0 -5 1 -7 3l-62 62
+c-2 2 -3 4 -3 7s1 6 3 8l20 20c4 4 10 4 14 0l35 -36l64 64c4 4 10 4 14 0z" />
+ <glyph glyph-name="uniF12C" unicode="&#xf12c;" horiz-adv-x="342"
+d="M333 300c5 -1 9 -6 9 -11v-94v-6v-94c0 -5 -4 -10 -9 -11l-160 -32h-4l-160 32c-5 1 -9 6 -9 11v94v6v94c0 5 4 10 9 11l160 32h4zM149 150c1 2 1 5 0 7s-3 4 -5 5l-19 8c-2 1 -4 1 -6 0s-4 -3 -5 -5c-2 -4 -7 -14 -17 -14c-14 0 -24 17 -24 41s10 41 24 41
+c9 0 14 -7 17 -13c2 -4 8 -6 12 -4l18 8c2 1 4 3 5 5s0 4 -1 6c-11 23 -28 35 -51 35c-38 0 -64 -31 -64 -78s26 -78 64 -78c23 0 41 12 52 36zM308 150c1 2 1 5 0 7s-3 4 -5 5l-18 8c-2 1 -5 1 -7 0s-4 -3 -5 -5c-2 -4 -6 -14 -16 -14c-14 0 -25 17 -25 41s11 41 25 41
+c9 0 14 -7 17 -13c2 -4 7 -6 11 -4l18 8c2 1 4 3 5 5s0 4 -1 6c-11 23 -27 35 -50 35c-38 0 -65 -31 -65 -78s27 -78 65 -78c23 0 40 12 51 36z" />
+ <glyph glyph-name="uniF12D" unicode="&#xf12d;" horiz-adv-x="473"
+d="M387 206c46 6 86 -35 86 -84c0 -18 -6 -35 -16 -50c-3 -4 -7 -7 -12 -7h-414c-5 0 -10 3 -13 8c-12 20 -18 42 -18 66c0 66 49 121 110 121c8 0 15 -1 23 -3c27 39 70 62 115 62c65 0 121 -47 139 -113z" />
+ <glyph glyph-name="uniF12E" unicode="&#xf12e;" horiz-adv-x="470"
+d="M302 166h92v-93v0c-2 -8 -9 -14 -17 -14h-225l-44 -44c-3 -5 -9 -8 -15 -8c-10 0 -17 7 -17 17v35h-59v0c-8 0 -15 6 -17 14v0v288v0c1 9 8 16 17 16v0h360c9 0 16 -7 17 -16v0v-91h-92c-5 0 -9 -4 -9 -9v0v-86v0c0 -5 4 -9 9 -9zM461 245c5 0 9 -4 9 -9v-36
+c0 -5 -4 -8 -9 -8h-133c-5 0 -9 3 -9 8v36c0 5 4 9 9 9h133z" />
+ <glyph glyph-name="uniF12F" unicode="&#xf12f;" horiz-adv-x="394"
+d="M394 361v0v-288v0c-2 -8 -9 -14 -17 -14h-225l-44 -44c-3 -5 -9 -8 -15 -8c-10 0 -17 7 -17 17v35h-59v0c-8 0 -15 6 -17 14v0v288v0c1 9 8 16 17 16v0h360c9 0 16 -7 17 -16zM87 189c14 0 26 12 26 26s-10 24 -23 24c-3 0 -5 0 -6 -1c3 12 13 25 24 31v0h1v0
+c1 1 2 2 2 3s-1 2 -2 3v0l-14 9v0c-1 0 -1 1 -2 1s-1 -1 -2 -1v0c-21 -15 -34 -36 -34 -61c0 -22 14 -34 30 -34zM154 189c14 0 27 12 27 26s-10 24 -23 24c-3 0 -6 0 -7 -1c3 12 14 25 25 31v0v0v0c1 1 2 2 2 3s0 2 -1 3v0l-14 9v0c-1 0 -1 1 -2 1s-1 -1 -2 -1v0
+c-21 -15 -34 -36 -34 -61c0 -22 13 -34 29 -34zM235 152c21 15 35 37 35 62c0 22 -14 34 -30 34c-14 0 -26 -13 -26 -27s9 -24 22 -24c3 0 6 0 7 1c-3 -12 -14 -25 -25 -31v0v0v0c-1 -1 -2 -2 -2 -3s1 -2 2 -3h-1l14 -9v0c1 0 2 -1 3 -1s0 1 1 1v0zM303 152
+c21 15 34 37 34 62c0 22 -13 34 -29 34c-14 0 -27 -13 -27 -27s10 -24 23 -24c3 0 6 0 7 1c-3 -12 -14 -25 -25 -31v0v0v0c-1 -1 -2 -2 -2 -3s0 -2 1 -3v0l14 -9v0c1 0 1 -1 2 -1s1 1 2 1v0z" />
+ <glyph glyph-name="uniF130" unicode="&#xf130;" horiz-adv-x="394"
+d="M394 361v0v-288v0c-2 -8 -9 -14 -17 -14h-225l-44 -44c-3 -5 -9 -8 -15 -8c-10 0 -17 7 -17 17v35h-59v0c-8 0 -15 6 -17 14v0v288v0c1 9 8 16 17 16v0h360c9 0 16 -7 17 -16zM305 155v124l-65 -30v28c0 7 -6 12 -13 12h-110c-7 0 -12 -5 -12 -12v-120c0 -7 5 -12 12 -12
+h110c7 0 13 5 13 12v29z" />
+ <glyph glyph-name="uniF131" unicode="&#xf131;" horiz-adv-x="394"
+d="M394 361v0v-288v0c-2 -8 -9 -14 -17 -14h-225l-44 -44c-3 -5 -9 -8 -15 -8c-10 0 -17 7 -17 17v35h-59v0c-8 0 -15 6 -17 14v0v288v0c1 9 8 16 17 16v0h360c9 0 16 -7 17 -16z" />
+ <glyph glyph-name="uniF132" unicode="&#xf132;" horiz-adv-x="461"
+d="M461 357v0v-217v0c-1 -6 -7 -11 -13 -11v0h-44v-26c0 -7 -6 -13 -13 -13c-4 0 -9 3 -11 6l-33 33h-57v150v0c-1 6 -5 10 -11 10h-115v68v0c1 7 6 11 13 11h271v0c7 0 12 -5 13 -11zM253 264c6 0 11 -5 12 -11v0v-193h-1c-1 -5 -5 -10 -11 -10h-151l-30 -29
+c-2 -3 -5 -5 -9 -5c-6 0 -12 5 -12 11v23h-40v0c-5 0 -10 5 -11 10v0v193v0c1 6 5 11 11 11v0h242z" />
+ <glyph glyph-name="uniF133" unicode="&#xf133;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51c78 0 141 63 141 141s-63 141 -141 141s-141 -63 -141 -141s63 -141 141 -141zM267 281c4 2 9 1 12 -2s4 -8 2 -12l-60 -100l-3 -3l-101 -61c-2 -1 -3 -1 -5 -1s-5 1 -7 3v0
+c-3 3 -4 8 -2 12l61 101l3 3z" />
+ <glyph glyph-name="uniF134" unicode="&#xf134;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM193 333v-282c78 0 140 63 140 141s-62 141 -140 141z" />
+ <glyph glyph-name="uniF135" unicode="&#xf135;" horiz-adv-x="378"
+d="M378 314v-1v0v-37h-378v36v2c0 8 6 13 14 13h1h349h1c8 0 13 -5 13 -13zM0 70v155h378v-155v0c0 -7 -6 -13 -13 -13v0h-350v0h-1c-8 0 -14 5 -14 13v0v0z" />
+ <glyph glyph-name="uniF136" unicode="&#xf136;" horiz-adv-x="419"
+d="M405 84c8 0 14 -6 14 -14v-23c0 -8 -6 -14 -14 -14v0h-37v-36c0 -8 -6 -14 -14 -14h-23c-8 0 -14 6 -14 14v36h-241v0c-13 0 -25 12 -25 25v1v0v241h-37v0c-8 0 -14 6 -14 14v23c0 8 6 14 14 14v0h37v36v0c0 8 6 14 14 14h23c8 0 14 -6 14 -14v0v-36h241v0
+c13 0 25 -12 25 -25v-1v0v-241h37v0zM102 84v0h215v216h-215v-216z" />
+ <glyph glyph-name="uniF137" unicode="&#xf137;" horiz-adv-x="348"
+d="M348 38v-19v0v0c0 -9 -6 -16 -15 -16h-317v0c-9 0 -16 7 -16 16v0v0v19v0c0 9 7 16 16 16v0h317c9 0 15 -7 15 -16v0zM44 251c1 -1 1 0 2 -1l34 -35l82 81v0c3 3 7 5 12 5s9 -2 12 -5v0l82 -81l35 35c0 1 0 2 1 2h1v0c3 2 6 4 10 4c9 0 17 -8 17 -17v-3v-145v0v0v-2v0
+c-1 -8 -8 -14 -17 -14v0v-1h-282v0v0c-9 0 -15 7 -16 15h-1v150h1c0 9 7 16 16 16c4 0 8 -1 11 -4v0v0zM292 208v0h-1h1zM2 309c0 21 10 31 31 31s30 -10 30 -31s-9 -31 -30 -31s-31 10 -31 31zM283 309c0 21 10 31 31 31s31 -10 31 -31s-10 -31 -31 -31s-31 10 -31 31z
+M145 350c0 21 10 31 31 31s31 -10 31 -31s-10 -31 -31 -31s-31 10 -31 31z" />
+ <glyph glyph-name="uniF138" unicode="&#xf138;" horiz-adv-x="325"
+d="M0 375h325l-30 -330l-132 -36l-133 36zM260 268l4 40h-102h-103l5 -40h98h6l-6 -2l-94 -40l3 -39h91h49l-3 -52l-46 -13v0v0l-44 11l-3 32v0h-41v0l5 -62l83 -25v0h1l82 25l11 123h-94v0v0z" />
+ <glyph glyph-name="uniF139" unicode="&#xf139;" horiz-adv-x="422"
+d="M124 323v-262v0v0c0 -12 -11 -22 -23 -22v0h-80v1c-12 0 -21 9 -21 21v0v262v0c0 12 9 22 21 22v0h80v0c12 0 22 -10 22 -22h1zM62 65c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM98 180v139h-72v-139h72zM273 323v-262v0v0c0 -12 -10 -22 -22 -22
+v0h-81v1c-12 0 -21 9 -21 21v0v262v0c0 12 9 22 21 22v0h81v0c12 0 22 -10 22 -22v0zM211 65c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM247 180v0v139h-72v-139h72zM422 323v-262v0v0c0 -12 -10 -22 -22 -22v0h-81v1c-12 0 -21 9 -21 21v0v262v0
+c0 12 9 22 21 22v0h81v0c12 0 22 -10 22 -22v0zM360 65c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM396 180v139h-72v-139h72z" />
+ <glyph glyph-name="uniF13A" unicode="&#xf13a;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM87 71c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM87 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36
+s16 -36 36 -36zM174 156c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 69c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36z" />
+ <glyph glyph-name="uniF13B" unicode="&#xf13b;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM87 71c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM87 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36
+s16 -36 36 -36zM261 69c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36z" />
+ <glyph glyph-name="uniF13C" unicode="&#xf13c;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM174 153c22 0 39 17 39 39s-17 39 -39 39s-39 -17 -39 -39s17 -39 39 -39z" />
+ <glyph glyph-name="uniF13D" unicode="&#xf13d;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM87 71c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM87 156c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36
+s16 -36 36 -36zM87 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 69c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 156c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 243c20 0 36 16 36 36
+s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36z" />
+ <glyph glyph-name="uniF13E" unicode="&#xf13e;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM87 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM174 156c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36
+s16 -36 36 -36zM261 69c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36z" />
+ <glyph glyph-name="uniF13F" unicode="&#xf13f;" horiz-adv-x="348"
+d="M348 329v0v-274v0c0 -20 -17 -37 -37 -37v0h-274v0c-20 0 -37 17 -37 37v0v274v0c0 20 17 37 37 37v0h274v0c20 -1 37 -17 37 -37zM87 243c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36s16 -36 36 -36zM261 69c20 0 36 16 36 36s-16 36 -36 36s-36 -16 -36 -36
+s16 -36 36 -36z" />
+ <glyph glyph-name="uniF140" unicode="&#xf140;" horiz-adv-x="333"
+d="M333 295v0v-144v0c0 -7 -5 -13 -12 -13v0h-71v-58v-1v-17v0c0 -16 -13 -29 -29 -29c-11 0 -21 6 -26 15v0l-50 86v0v0v1l-3 3h-51h-1c-7 0 -13 6 -13 13v0v0v144v0v43v0v1v0v0c0 7 6 12 13 12h1h185c2 0 4 0 5 -1v0l50 -50v0c1 -1 2 -3 2 -5v0zM51 316v-138v-2
+c0 -7 -6 -13 -13 -13v0v0v0v0h-25v0c-7 0 -12 6 -13 12v0v141v0c0 7 6 12 13 12v0h24l1 1c7 0 13 -6 13 -13v0v0z" />
+ <glyph glyph-name="uniF141" unicode="&#xf141;" horiz-adv-x="447"
+d="M447 294v-204v0v0c0 -11 -9 -20 -20 -20v0v0h-407c-11 0 -20 9 -20 20v0v0v204v0c0 11 9 20 20 20h407v0v0c11 0 20 -9 20 -20v0zM371 266v0v0c0 -2 2 -4 4 -4v0v0h21v-21v0c0 -2 2 -4 4 -4v0h17v0h1c2 0 4 2 4 4v0v43c0 2 -2 4 -4 4h-1v0h-42v0v0c-2 0 -4 -2 -4 -4v-18z
+M77 118v0v0c0 2 -2 4 -4 4h-1v0h-21v21v0c0 2 -2 4 -4 4v0h-17v0v0c-2 0 -4 -2 -4 -4v0v-43c0 -2 2 -4 4 -4v0v0h42v0h1c2 0 4 2 4 4v18zM77 284v0v0c0 2 -2 4 -4 4h-43c-2 0 -4 -2 -4 -4v0v0v-43v0v0c0 -2 2 -4 4 -4h17v0v0c2 0 4 2 4 4v0v0v21h22v0c2 0 4 3 4 5v0v17z
+M224 96c53 0 96 43 96 96s-43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96zM422 143v0v0c0 2 -2 4 -4 4h-18v0c-2 0 -4 -2 -4 -4v0v0v-21h-21v0c-2 0 -4 -3 -4 -5v0v-17v0v0c0 -2 2 -4 4 -4h43c2 0 4 2 4 4v0v0v43zM224 263c39 0 70 -32 70 -71c0 -15 -4 -29 -12 -40v0
+c0 3 -2 7 -4 8l-28 13l-12 6c5 3 9 8 12 14c2 5 3 10 3 16c0 3 0 6 -1 9c-4 14 -14 25 -28 25c-13 0 -25 -10 -29 -24c-1 -3 -1 -6 -1 -10c0 -6 2 -12 4 -17c3 -6 7 -11 12 -14l-11 -5l-29 -13c-3 -1 -4 -5 -4 -8v0c-8 11 -13 25 -13 40c0 39 32 71 71 71z" />
+ <glyph glyph-name="uniF142" unicode="&#xf142;" horiz-adv-x="209"
+d="M126 219c39 -10 83 -26 83 -77c0 -42 -28 -73 -83 -79v-28v0c0 -3 -3 -6 -6 -6h-23v0c-3 0 -6 3 -6 6v28c-39 3 -68 18 -89 39v0c-1 1 -2 3 -2 5c0 1 0 2 1 3v0l22 32v0c1 2 3 3 5 3c1 0 2 0 3 -1v0l1 -1v0c14 -14 34 -28 59 -32v58c-39 9 -81 25 -81 76
+c0 38 30 70 81 75v29c0 3 3 6 6 6h23c3 0 6 -3 6 -6v0v-30c30 -3 57 -14 77 -33c1 -1 2 -2 2 -4c0 -1 -1 -3 -2 -4v0l-21 -31h-1c-1 -1 -2 -2 -4 -2c-1 0 -3 0 -4 1v0c-14 12 -30 20 -47 24v-51zM91 227v46c-17 -2 -26 -11 -26 -24c0 -11 11 -17 26 -22zM126 111
+c19 4 29 14 29 26s-12 19 -29 24v-50z" />
+ <glyph glyph-name="uniF143" unicode="&#xf143;" horiz-adv-x="404"
+d="M379 194c14 0 25 -11 25 -25v-144c0 -14 -11 -25 -25 -25h-354c-14 0 -25 11 -25 25v144c0 14 11 25 25 25h90c11 0 21 -7 24 -17c9 -28 34 -46 63 -46s54 18 63 46c3 10 13 17 24 17h90zM197 181l-70 98c-1 2 -2 5 -1 7s3 3 6 3h33v88c0 4 3 7 7 7h60c4 0 7 -3 7 -7v-88
+h33c3 0 5 -1 6 -3s0 -5 -1 -7l-69 -98c-1 -2 -4 -3 -6 -3v0c-2 0 -4 1 -5 3z" />
+ <glyph glyph-name="uniF144" unicode="&#xf144;" horiz-adv-x="382"
+d="M13 141c-7 0 -13 6 -13 13c0 4 2 7 4 9l176 177c2 3 7 5 11 5s7 -2 9 -5v0l178 -177c3 -2 4 -5 4 -9c0 -7 -5 -13 -12 -13v0h-357v0zM382 52v0c0 -7 -6 -13 -13 -13v0h-357v0c-7 1 -12 6 -12 13v1v49v0c0 7 5 12 12 13v0l357 1v0c7 0 13 -6 13 -13v0v0v-51z" />
+ <glyph glyph-name="uniF145" unicode="&#xf145;" horiz-adv-x="493"
+d="M389 393c7 0 13 -6 13 -13v-376c0 -7 -6 -13 -13 -13v0v0h-376v0v0v0v0c-7 0 -13 6 -13 13v376c0 7 6 13 13 13v0h376v0v0zM51 341v-298h299v298h-299zM490 120c1 0 2 0 3 -1s0 -2 -1 -3l-31 -44c-1 -1 -1 -2 -2 -2v0c-1 0 -2 1 -3 2l-31 44c-1 1 -2 2 -1 3s2 1 3 1h15
+v40c0 2 1 3 3 3h27c2 0 3 -1 3 -3v-40h15zM427 264c-1 0 -2 0 -3 1s0 2 1 3l31 44c1 1 2 2 3 2v0c1 0 1 -1 2 -2l32 -44c1 -1 1 -2 0 -3s-2 -1 -3 -1h-15v-40c0 -2 -1 -3 -3 -3h-27c-2 0 -3 1 -3 3v40h-15zM109 284c0 17 8 26 25 26s25 -9 25 -26s-8 -25 -25 -25
+s-25 8 -25 25zM182 252c6 -1 11 -6 11 -12v-72v0c0 -3 -1 -5 -3 -7c-4 -4 -12 -4 -16 0c-2 2 -3 4 -3 7v0v50v0c0 2 -1 4 -3 4s-4 -2 -4 -4v0v-32v-33v-66c0 -7 -5 -13 -12 -13s-13 6 -13 13v66v0c0 2 -1 4 -3 4s-4 -2 -4 -4v0v-66c0 -7 -5 -13 -12 -13s-13 6 -13 13v99v32
+v0v0c0 2 -1 4 -3 4s-3 -2 -3 -4v0v0v-50v0c0 -3 -2 -5 -4 -7c-4 -4 -11 -4 -15 0c-2 2 -3 4 -3 7v0v72v0c0 7 5 12 12 12v0h91v0zM238 284c0 17 9 26 26 26s25 -9 25 -26s-8 -25 -25 -25s-26 8 -26 25zM312 252c6 -1 10 -6 10 -12v-72v0c0 -3 -1 -5 -3 -7
+c-4 -4 -11 -4 -15 0c-2 2 -3 4 -3 7v0v50v0c0 2 -1 4 -3 4s-4 -2 -4 -4v0v-32v-33v-66c0 -7 -5 -13 -12 -13s-13 6 -13 13v66v0c0 2 -1 4 -3 4s-4 -2 -4 -4v0v-66c0 -7 -5 -13 -12 -13s-13 6 -13 13v99v32v0v0c0 2 -1 4 -3 4s-4 -2 -4 -4v0v0v-50v0c0 -3 -1 -5 -3 -7
+c-4 -4 -11 -4 -15 0c-2 2 -3 4 -3 7v0v72v0c0 7 5 12 12 12v0h91v0z" />
+ <glyph glyph-name="uniF146" unicode="&#xf146;" horiz-adv-x="283"
+d="M280 125c3 -2 3 -5 2 -8v0v0v0v0c-19 -34 -55 -67 -115 -67c-68 0 -122 38 -140 98h-21v-1c-3 0 -6 3 -6 6v21c0 3 3 6 6 6v0h15v12v13h-15v0c-3 0 -6 3 -6 6v21c0 3 3 6 6 6v0h21c19 59 73 96 140 96c60 0 96 -33 115 -67v0v0v0v0c1 -3 1 -6 -2 -8h-1v0l-40 -19v0
+c-3 -1 -5 -1 -7 2v0c-12 22 -37 40 -65 40c-34 0 -61 -17 -75 -44h100v0c3 0 6 -3 6 -6v-21c0 -3 -3 -6 -6 -6v0v0v0v0h-110c-1 -5 -1 -8 -1 -13v-12h111v0c3 0 6 -3 6 -6v-21c0 -3 -3 -6 -6 -6v0h-101c14 -28 41 -45 76 -45c28 0 52 17 64 39l1 1c2 3 4 3 7 2v0l40 -19v0h1
+z" />
+ <glyph glyph-name="uniF147" unicode="&#xf147;" horiz-adv-x="365"
+d="M359 204c4 -2 6 -6 6 -11c0 -4 -2 -8 -4 -10v0v0l-1 -1l-79 -79v0c-24 -27 -60 -44 -99 -44c-35 0 -66 14 -90 36v-1l-87 87c-3 3 -5 7 -5 11c0 3 1 7 3 9v0l80 79c24 27 60 45 99 45c35 0 67 -14 91 -36v1zM182 102c50 0 90 40 90 90s-40 90 -90 90s-90 -40 -90 -90
+s40 -90 90 -90zM139 192c0 29 14 43 43 43s44 -14 44 -43s-15 -44 -44 -44s-43 15 -43 44z" />
+ <glyph glyph-name="uniF148" unicode="&#xf148;" horiz-adv-x="372"
+d="M372 192c0 -3 -1 -5 -4 -7v-1l-192 -111c-2 -2 -5 -2 -7 -2c-5 0 -8 3 -8 8v78l-146 -84c-2 -2 -4 -2 -6 -2c-5 0 -9 3 -9 8v226v0c0 5 4 8 9 8c2 0 4 0 6 -2l146 -84v78v0c0 5 3 8 8 8c2 0 5 0 7 -2l191 -111v0c3 -1 5 -4 5 -8z" />
+ <glyph glyph-name="uniF149" unicode="&#xf149;" horiz-adv-x="268"
+d="M229 163c-20 -20 -44 -32 -70 -37v-41h28v0c2 0 4 0 6 -2s2 -4 2 -6v-35c0 -4 -4 -8 -8 -8v0h-28v-34v0c0 -4 -4 -8 -8 -8v0h-35v0v0h-2v0c-4 1 -6 4 -6 8v0v34h-27v0c-4 0 -8 4 -8 8v0v35v0c0 2 0 4 2 6s4 2 6 2v0h27v41c-25 5 -50 18 -69 37c-52 52 -52 138 0 190
+s138 52 190 0s52 -138 0 -190zM134 175c46 0 83 37 83 83s-37 83 -83 83s-83 -37 -83 -83s37 -83 83 -83z" />
+ <glyph glyph-name="uniF14A" unicode="&#xf14a;" horiz-adv-x="227"
+d="M68 345c0 28 14 42 42 42s42 -14 42 -42s-14 -42 -42 -42s-42 14 -42 42zM227 171v0v-3c0 -3 -1 -6 -3 -9s-3 -4 -6 -6s-6 -3 -9 -3c-8 0 -14 4 -17 12v0l-20 76v0c-1 3 -3 5 -6 5c-4 0 -5 -2 -5 -6v-2v0l32 -122c1 -1 1 -2 1 -3l1 -1h-1h1c0 -6 -4 -10 -10 -10h-24v-81
+c0 -4 -1 -7 -3 -10s-5 -6 -8 -8s-6 -3 -10 -3c-6 0 -11 3 -15 7s-6 8 -6 14v81h-12v-81c0 -6 -2 -10 -6 -14s-8 -7 -14 -7s-11 3 -15 7s-6 8 -6 14v81h-24c-6 0 -10 4 -10 10v0v0v1c0 1 0 2 1 3l33 123v1v0v0v1v0c-1 3 -2 5 -5 5s-5 -2 -6 -5v0v0l-20 -76h-1
+c-3 -8 -8 -12 -16 -12c-5 0 -10 3 -13 6s-5 7 -5 12v3v0l28 105v0l1 2v0c3 9 8 13 18 13v1h132v-1v0c10 0 16 -4 19 -13v0l1 -2v0z" />
+ <glyph glyph-name="uniF14B" unicode="&#xf14b;" horiz-adv-x="410"
+d="M410 334c0 -10 -4 -19 -11 -25v0l-156 -155v-118v0v-2c0 -10 -7 -17 -17 -17c-3 0 -6 1 -9 2v0v0l-1 1l-40 23v0c-5 3 -9 9 -9 15v0v0v96l-155 154c-8 6 -12 16 -12 26c0 18 15 33 33 33h2v0h343v0c18 -1 32 -15 32 -33zM114 301v0v0v0z" />
+ <glyph glyph-name="uniF14C" unicode="&#xf14c;" horiz-adv-x="411"
+d="M100 308v45v1c0 7 6 12 13 12v0v0h185v0c7 0 12 -5 12 -12v0v-47h-31v27h-148v-26h-31zM76 18v262h259v-262h-259zM128 167v-37c0 -1 0 -1 1 -2s2 -1 3 -1h52v-53c0 -1 0 -2 1 -3s2 -1 3 -1h37c1 0 1 0 2 1s2 2 2 3v53h52c1 0 2 0 3 1s1 1 1 2v37c0 2 -2 4 -4 4h-52v52
+c0 2 -2 4 -4 4h-37c-2 0 -4 -2 -4 -4v-52h-52c-2 0 -4 -2 -4 -4zM20 280v0h31v-262h-31v0c-11 0 -20 9 -20 20v1v220v0c0 11 9 21 20 21zM411 38v0c0 -11 -9 -20 -20 -20v0v0h-31v262h31c11 0 20 -9 20 -20v0v-222z" />
+ <glyph glyph-name="uniF14D" unicode="&#xf14d;" horiz-adv-x="372"
+d="M364 325c4 0 8 -4 8 -8v-169c0 -2 -1 -5 -3 -6c-21 -22 -51 -36 -84 -36c-31 0 -58 11 -79 31c-23 27 -57 45 -96 45c-20 0 -39 -4 -56 -13v-145c0 -15 -12 -27 -27 -27s-27 12 -27 27v322c0 15 12 27 27 27c11 0 20 -6 24 -15c20 18 47 29 77 29c31 0 59 -11 80 -31
+c23 -27 56 -45 95 -45c21 0 41 5 58 14v0h3z" />
+ <glyph glyph-name="uniF14E" unicode="&#xf14e;" horiz-adv-x="425"
+d="M397 325c15 0 28 -13 28 -28v-248c0 -15 -13 -28 -28 -28h-369c-15 0 -28 13 -28 28v248c0 15 13 28 28 28h30l26 32c3 4 8 6 13 6h74c6 0 12 -5 15 -10c3 -4 13 -16 23 -28h188zM374 124v31c0 2 -1 4 -3 4h-45v45c0 2 -2 3 -4 3h-31c-2 0 -4 -1 -4 -3v-45h-45
+c-2 0 -3 -2 -3 -4v-31c0 -1 0 -1 1 -2s1 -1 2 -1h45v-45c0 -1 0 -2 1 -3s2 -1 3 -1h31c1 0 2 0 3 1s1 2 1 3v45h45c1 0 1 0 2 1s1 1 1 2z" />
+ <glyph glyph-name="uniF14F" unicode="&#xf14f;" horiz-adv-x="425"
+d="M312 181c9 0 17 -8 17 -17v0v0v0v-15h-34v15c0 9 8 17 17 17zM397 325c15 0 28 -13 28 -28v-248c0 -15 -13 -28 -28 -28h-369c-15 0 -28 13 -28 28v248c0 15 13 28 28 28h30l26 32c3 4 8 6 13 6h74c6 0 12 -5 15 -10c3 -4 13 -16 23 -28h188zM374 77v0v67c0 3 -2 5 -5 5
+h-6h-9v15v0c0 23 -19 42 -42 42s-41 -19 -41 -42v-15h-8h-6c-3 0 -5 -2 -5 -5v-67c0 -3 2 -5 5 -5h112c3 0 5 2 5 5z" />
+ <glyph glyph-name="uniF150" unicode="&#xf150;" horiz-adv-x="425"
+d="M397 325c15 0 28 -13 28 -28v-248c0 -15 -13 -28 -28 -28h-369c-15 0 -28 13 -28 28v248c0 15 13 28 28 28h30l26 32c3 4 8 6 13 6h74c6 0 12 -5 15 -10c3 -4 13 -16 23 -28h188z" />
+ <glyph glyph-name="uniF151" unicode="&#xf151;" horiz-adv-x="264"
+d="M0 264c0 15 7 22 22 22s22 -7 22 -22s-7 -22 -22 -22s-22 7 -22 22zM168 368c0 30 15 45 45 45s45 -15 45 -45s-15 -44 -45 -44s-45 14 -45 44zM92 354c0 19 9 28 28 28s28 -9 28 -28s-9 -28 -28 -28s-28 9 -28 28zM249 69v0c9 -11 13 -24 13 -38c0 -17 -5 -31 -17 -43
+s-26 -17 -43 -17c-13 0 -25 3 -35 11s-18 18 -22 30l-76 131l1 1c-5 8 -9 16 -11 25c-3 11 -5 22 -5 33c0 29 10 53 31 74s45 31 74 31c19 0 37 -5 53 -14s29 -23 38 -39s14 -33 14 -52c0 -21 -5 -41 -17 -59v0c-6 -11 -9 -23 -9 -35c0 -14 3 -27 11 -39zM39 311
+c0 15 7 23 22 23s22 -8 22 -23s-7 -22 -22 -22s-22 7 -22 22z" />
+ <glyph glyph-name="uniF152" unicode="&#xf152;" horiz-adv-x="356"
+d="M325 59c1 0 1 -1 1 -2v-1l-6 -12c0 -1 -1 -1 -2 -1h-1l-16 8c-1 0 -1 1 -1 2s1 0 1 1l6 12c1 1 2 2 3 1zM325 328c1 0 1 -1 1 -2v-1l-7 -11c0 -1 0 -2 -1 -2l-2 1l-15 9c-1 0 -1 0 -1 1v2l7 11c1 1 2 2 3 1zM295 75c1 -1 2 -2 1 -3l-7 -12c0 -1 -1 -1 -2 -1h-1l-4 3l-5 2
+l-62 -34v0v0c-1 -1 -4 -1 -5 -1s-3 0 -4 1v0v0l-63 34l-62 -34v0h-1c-1 -1 -3 -1 -4 -1s-3 0 -4 1h-1v0l-67 37c-3 1 -4 3 -4 6v274c0 3 2 6 5 7s6 0 9 -1l62 -34l62 34h1v1h2h2h2h2l1 -1v0l62 -34l62 34c2 2 6 3 9 1l7 -5l7 -3c1 0 1 -1 1 -2s-1 0 -1 -1l-6 -12
+c0 -1 -1 -1 -2 -1l-1 1l-9 5v-252zM76 46v256l-58 31v-256zM210 46v256l-67 36v-256zM354 160c1 0 2 -2 2 -3v-27c0 -1 -1 -2 -2 -2h-13c-1 0 -3 1 -3 2v27c0 1 2 3 3 3h13zM354 52c1 0 2 -1 2 -2v-10c0 -8 -5 -11 -10 -11c-2 0 -4 1 -6 2l-8 4c-1 0 -1 1 -1 2v1l6 12l1 1
+l2 1h1h13zM349 314c0 0 7 -4 7 -12v-10c0 -1 -1 -2 -2 -2h-13c-1 0 -3 1 -3 2v8l-6 4c-1 0 -1 0 -1 1v2l6 11c1 1 2 2 3 1zM354 267c1 0 2 -1 2 -2v-27c0 -1 -1 -2 -2 -2h-13c-1 0 -3 1 -3 2v27c0 1 2 2 3 2h13zM354 106c1 0 2 -1 2 -2v-27c0 -1 -1 -3 -2 -3h-13
+c-1 0 -3 2 -3 3v27c0 1 2 2 3 2h13zM354 213c1 0 2 -1 2 -2v-27c0 -1 -1 -2 -2 -2h-13c-1 0 -3 1 -3 2v27c0 1 2 2 3 2h13z" />
+ <glyph glyph-name="uniF153" unicode="&#xf153;" horiz-adv-x="427"
+d="M193 140c4 0 8 -4 8 -8v-112c0 -4 -4 -8 -8 -8h-72c-4 0 -8 4 -8 8v112c0 4 4 8 8 8h72zM306 372c4 0 8 -4 8 -8v-344c0 -4 -4 -8 -8 -8h-72c-4 0 -8 4 -8 8v344c0 4 4 8 8 8h72zM420 267c4 0 7 -3 7 -7v-240c0 -4 -3 -8 -7 -8h-73c-4 0 -8 4 -8 8v240c0 4 4 7 8 7h73z
+M80 267c4 0 8 -3 8 -7v-240c0 -4 -4 -8 -8 -8h-72c-4 0 -8 4 -8 8v240c0 4 4 7 8 7h72z" />
+ <glyph glyph-name="uniF154" unicode="&#xf154;" horiz-adv-x="387"
+d="M380 238c4 0 7 -4 7 -8v-77c0 -4 -3 -8 -7 -8h-372c-4 0 -8 4 -8 8v77c0 4 4 8 8 8h372zM226 357c3 -1 5 -4 5 -8v-77c0 -4 -2 -7 -5 -8v0h-218c-4 0 -8 4 -8 8v77c0 4 4 8 8 8h218v0zM275 120c4 0 8 -4 8 -8v-77c0 -4 -4 -8 -8 -8h-267c-4 0 -8 4 -8 8v77c0 4 4 8 8 8
+h267z" />
+ <glyph glyph-name="uniF155" unicode="&#xf155;" horiz-adv-x="380"
+d="M212 382c93 -1 167 -76 168 -169c0 -4 -2 -6 -6 -6h-1v0h-161c-4 0 -7 2 -7 6v161v0v1c0 4 3 7 7 7zM341 174v0v-2c0 -94 -76 -170 -170 -170s-171 76 -171 170s77 171 171 171h1v0h1c4 0 7 -3 7 -7l-1 -1h1v-147c0 -4 2 -7 6 -7h148c4 0 7 -3 7 -7z" />
+ <glyph glyph-name="uniF156" unicode="&#xf156;" horiz-adv-x="410"
+d="M384 37h-359c-14 0 -25 11 -25 25v260c0 14 11 25 25 25h359c14 0 26 -11 26 -25v-260c0 -14 -12 -25 -26 -25zM359 87v210h-309v-210h309zM162 111c-5 0 -10 2 -13 5l-25 25l-31 -25c-8 -6 -19 -6 -25 2s-6 19 2 25l44 36c7 6 17 6 24 -1l21 -21l46 72c4 5 9 8 16 8
+s12 -4 15 -10l27 -58l52 92c5 9 16 12 25 7s12 -15 7 -24l-70 -123c-3 -6 -9 -9 -16 -9s-13 5 -16 11l-28 59l-40 -63c-3 -5 -8 -7 -13 -8h-2z" />
+ <glyph glyph-name="uniF157" unicode="&#xf157;" horiz-adv-x="399"
+d="M148 320c-3 2 -5 5 -5 9c0 6 4 10 10 10c3 0 6 -1 8 -3l60 -60c3 -2 5 -5 5 -9c0 -6 -5 -10 -11 -10c-2 0 -4 1 -6 2v0h-1v1zM215 111h-25c-14 0 -28 0 -41 1l24 -42c2 -3 4 -7 4 -11c0 -10 -8 -18 -18 -18c-6 0 -11 3 -14 7v0l-38 65l-37 -65h-1c-3 -4 -8 -7 -14 -7
+c-10 0 -18 8 -18 18c0 4 2 8 4 11l32 56c-8 6 -14 29 -14 56c0 13 2 24 4 34l-57 33v0c-4 2 -6 6 -6 11c0 7 6 13 13 13c2 0 4 0 6 -1v0l56 -33c1 0 2 1 3 1h137v-129zM306 125l31 -55c2 -3 4 -7 4 -11c0 -10 -8 -18 -18 -18c-6 0 -11 3 -14 7h-1l-37 65l-38 -65v0
+c-3 -4 -8 -7 -14 -7c-10 0 -18 8 -18 18c0 4 2 8 4 11l31 54v116l83 -83c-2 -17 -7 -29 -13 -32zM399 235c0 -4 -2 -8 -4 -10v0l-11 -11v0h-10h-40l-14 -14c1 -5 1 -11 1 -16l-72 72l42 42l26 45l13 -22c3 0 5 -2 7 -3v1l26 -15c7 -3 11 -10 11 -18v-21l20 -20
+c3 -2 5 -6 5 -10z" />
+ <glyph glyph-name="uniF158" unicode="&#xf158;" horiz-adv-x="321"
+d="M148 302c58 0 104 -48 104 -106c0 -13 -2 -24 -6 -36c0 -1 -1 -2 -1 -3c0 0 -15 -26 -25 -38c-1 -2 -3 -3 -4 -5c-7 -8 -10 -11 -10 -24c1 -27 1 -37 -1 -45c-4 -26 -23 -39 -55 -40v0v0c-9 0 -17 7 -17 16c0 5 1 10 4 13s7 5 12 5c21 1 22 7 23 11v2c1 5 0 21 0 37
+c-1 26 10 38 18 48l4 4c6 7 17 24 21 32c2 7 3 15 3 23c0 39 -31 72 -70 72s-71 -33 -71 -72c0 -9 -8 -17 -17 -17s-17 8 -17 17c0 58 47 106 105 106zM172 194c0 13 -11 24 -24 24s-24 -11 -24 -24c0 -8 -7 -15 -15 -15s-14 7 -14 15c0 29 24 52 53 52s52 -23 52 -52
+c0 -8 -6 -15 -14 -15s-14 7 -14 15zM75 142c6 6 16 6 22 0c3 -3 5 -8 5 -12s-2 -8 -5 -11l-70 -71c-3 -3 -7 -4 -11 -4s-8 1 -11 4s-5 8 -5 12s2 8 5 11zM207 334c38 0 69 -30 69 -68v0v-7v0c0 -3 -3 -6 -6 -6v0h-12v0c-3 0 -6 3 -6 6v0v7v0c0 24 -21 44 -45 44v0v0h-7v0
+c-3 0 -5 3 -5 6v0v11v0c0 3 2 7 5 7v0h7v0v0zM321 266v0v-7v0c0 -3 -3 -6 -6 -6v0h-11v0c-3 0 -7 3 -7 6v0v7v0c0 49 -41 89 -90 89v0v0h-7v0c-3 0 -5 3 -5 6v0v12v0c0 3 2 6 5 6v0h7v0v0c63 0 114 -50 114 -113z" />
+ <glyph glyph-name="uniF159" unicode="&#xf159;" horiz-adv-x="409"
+d="M295 379c63 0 114 -51 114 -114c0 -68 -33 -108 -59 -140l-6 -7c-31 -38 -128 -108 -132 -111c-2 -2 -5 -2 -8 -2s-5 0 -7 2c-4 3 -101 73 -132 111l-6 7c-26 32 -59 72 -59 140c0 63 51 114 114 114c36 0 69 -16 90 -44c21 28 55 44 91 44z" />
+ <glyph glyph-name="uniF15A" unicode="&#xf15a;" horiz-adv-x="353"
+d="M348 254c3 -2 5 -6 5 -10v-233c0 -7 -6 -13 -13 -13h-96c-7 0 -12 6 -12 13v143h-111v-143c0 -7 -5 -13 -12 -13h-96c-7 0 -13 6 -13 13v233c0 4 2 8 5 10l161 129c5 4 11 4 16 0z" />
+ <glyph glyph-name="uniF15B" unicode="&#xf15b;" horiz-adv-x="300"
+d="M0 362v0h300l-27 -306l-123 -34l-123 34zM243 289l1 11h-94v0h-94l1 -11l9 -103h84v0h46l-4 -49l-42 -11v0v0l-42 11l-3 30h-20h-17l5 -59l77 -21v0v0l77 21v7l9 98l1 11h-10h-77v0h-50l-3 38h53v0h90h1v8z" />
+ <glyph glyph-name="uniF15C" unicode="&#xf15c;" horiz-adv-x="355"
+d="M337 370c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM337 64c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM355 149v0v-16v0c0 -10 -8 -17 -18 -17v0h-198
+c-10 0 -18 7 -18 17v16c0 10 8 17 18 17h198v0v0c10 0 18 -7 18 -17zM355 250v0v-16v0c0 -10 -8 -17 -18 -17v0h-198c-10 0 -18 7 -18 17v16c0 10 8 18 18 18h198v0v0c10 0 18 -8 18 -18zM0 192c0 1 0 1 1 2v1l64 36c1 1 1 1 2 1c2 0 3 -1 3 -3v-74v0c0 -2 -1 -3 -3 -3
+c-1 0 -1 0 -2 1l-63 36v0c-1 0 -2 2 -2 3z" />
+ <glyph glyph-name="uniF15D" unicode="&#xf15d;" horiz-adv-x="355"
+d="M337 370c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM337 64c10 0 18 -7 18 -17v-16c0 -10 -8 -17 -18 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM355 149v0v-16v0c0 -10 -8 -17 -18 -17v0h-199
+c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h199v0c10 0 18 -7 18 -17zM355 250v0v-16v0c0 -10 -8 -17 -18 -17v0h-199c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h199v0c10 0 18 -8 18 -18zM3 152c-2 0 -3 1 -3 3v74v0c0 2 1 3 3 3c1 0 1 0 2 -1l63 -36v0c1 0 2 -2 2 -3
+s0 -1 -1 -2v-1l-64 -36c-1 -1 -1 -1 -2 -1z" />
+ <glyph glyph-name="uniF15E" unicode="&#xf15e;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM212 85v124c0 4 -3 7 -7 7h-26c-4 0 -7 -3 -7 -7v-124c0 -4 3 -6 7 -6h26c4 0 7 2 7 6zM192 244c13 0 23 10 23 23s-10 23 -23 23s-23 -10 -23 -23s10 -23 23 -23z" />
+ <glyph glyph-name="uniF15F" unicode="&#xf15f;" horiz-adv-x="108"
+d="M108 324v-4v0l-58 -261v0c-1 -7 -6 -12 -13 -12h-25v0c-7 1 -12 6 -12 13v3v0v0v0l58 261v0c0 7 6 13 13 13h24c7 0 13 -6 13 -13z" />
+ <glyph glyph-name="uniF160" unicode="&#xf160;" horiz-adv-x="445"
+d="M445 218v0v0v-32v0c0 -2 0 -5 -2 -7s-5 -2 -7 -2v0h-27h-1v-61v0v-39v0c0 -5 -4 -9 -9 -9h-1h-31v0c-5 0 -10 4 -10 9v0v21v0v79h-25v-26v0v-39v0c0 -5 -5 -9 -10 -9v0h-31v0h-1c-5 0 -9 4 -9 9v0v16v23v26h-45c-10 -56 -58 -99 -117 -99c-66 0 -119 53 -119 119
+s53 119 119 119c55 0 102 -38 115 -89h163h12h27c2 0 5 -1 7 -3s2 -4 2 -6zM119 128c38 0 68 30 68 68s-30 68 -68 68s-68 -30 -68 -68s30 -68 68 -68z" />
+ <glyph glyph-name="uniF161" unicode="&#xf161;" horiz-adv-x="488"
+d="M60 101c-14 0 -26 12 -26 26v226c0 14 12 25 26 25h368c14 0 25 -11 25 -25v-226c0 -14 -11 -26 -25 -26h-368zM85 327v-175h318v175h-318zM476 76c6 0 12 -6 12 -12v-28c0 -3 -2 -7 -4 -9l-18 -18c-2 -2 -5 -3 -8 -3h-430c-3 0 -6 2 -8 4l-17 18c-2 2 -3 5 -3 8v28
+c0 6 6 12 12 12h464zM288 35v12c0 1 -1 2 -2 2h-84c-1 0 -3 -1 -3 -2v-12c0 -1 2 -3 3 -3h84c1 0 2 2 2 3z" />
+ <glyph glyph-name="uniF162" unicode="&#xf162;" horiz-adv-x="381"
+d="M76 173v119h229v-119h-229zM82 92v56h57v-56h-57zM246 92v56h57v-56h-57zM164 92v56h57v-56h-57zM358 368c13 0 23 -10 23 -23v-307v0c-1 -12 -11 -22 -23 -22h-335v0v0c-12 0 -22 10 -23 22v0v307v0c0 13 10 23 23 23v0h335v0zM330 67v0v250h-279v-250h279z" />
+ <glyph glyph-name="uniF163" unicode="&#xf163;" horiz-adv-x="426"
+d="M368 351v0l-45 -45c-3 -3 -7 -3 -10 0v0l-11 11v0c-3 3 -3 7 0 10l45 45v0c3 3 8 3 11 0v0v0l10 -10v0c3 -3 3 -8 0 -11v0v0v0zM206 349c-4 0 -8 3 -8 7v0v64c0 4 4 8 8 8v0h14v0c4 0 8 -4 8 -8v-64v0c0 -4 -4 -7 -8 -7v0h-14v0zM426 243v0v-15v0c0 -4 -3 -7 -7 -7v0h-64
+c-4 0 -7 3 -7 7v0v15v0c0 4 3 8 7 8h64v0c4 0 7 -4 7 -8zM213 324c60 0 109 -49 109 -109c0 -22 -7 -42 -18 -59c-18 -26 -28 -60 -29 -99c-1 -2 -4 -5 -7 -5h-1v0h-108v0h-1c-3 0 -5 2 -6 4c-1 37 -12 71 -28 96v0c-13 18 -20 39 -20 63c0 60 49 109 109 109zM268 -12
+c4 0 7 -3 7 -7v-17c0 -4 -3 -8 -7 -8h-1v0h-108v0h-1c-4 0 -8 4 -8 8v17c0 4 4 7 8 7h1v0h108v0h1zM268 37c4 0 7 -4 7 -8v-17c0 -4 -3 -8 -7 -8l-1 1v-1h-108v1l-1 -1c-4 0 -8 4 -8 8v17v0c0 4 4 8 8 8h1v0h108v0h1zM71 245c4 0 8 -4 8 -8v0v-14v0c0 -4 -4 -8 -8 -8v0h-64
+c-4 0 -7 4 -7 8v14c0 4 3 8 7 8h64v0zM60 354c-3 3 -3 7 0 10v0l11 11v0v0c3 3 8 3 11 0l45 -46v0c3 -3 3 -7 0 -10v0l-11 -10v0c-3 -3 -7 -4 -10 -1v0z" />
+ <glyph glyph-name="uniF164" unicode="&#xf164;" horiz-adv-x="333"
+d="M333 67c0 -7 -6 -13 -13 -13v0v0v0v0h-26v1c-7 0 -11 5 -12 11v0v141v0c0 7 5 13 12 13v0h25h1c7 0 12 -6 12 -13v0v0v-138c0 -1 1 -1 1 -2zM256 46v0v-1v0v0c0 -7 -6 -12 -13 -12h-1h-185c-2 0 -4 0 -5 1v0l-50 50v0c-1 1 -2 3 -2 5v0v144v0c0 7 6 13 13 13v0h70v58v1
+v17v0v0c0 16 13 29 29 29c11 0 21 -6 26 -15v0l51 -87c1 -1 1 -2 2 -3h51h1c7 0 13 -6 13 -13v0v0v-144v0v-43zM15 89l1 -1l-1 1v0z" />
+ <glyph glyph-name="uniF165" unicode="&#xf165;" horiz-adv-x="353"
+d="M323 339c39 -39 40 -101 4 -141v0l-52 -52c-9 -9 -20 -16 -31 -21c-4 -10 -10 -20 -18 -28v0l-51 -52c-40 -40 -105 -40 -145 0s-40 105 0 145l52 52v-1c8 8 17 14 27 18c5 11 13 23 22 32l52 51v0c40 36 101 36 140 -3zM140 82l37 38c-17 4 -33 13 -46 26s-23 30 -27 47
+l-37 -38v0c-20 -20 -20 -53 0 -73s53 -20 73 0v0zM168 183c9 -9 21 -14 33 -15c-1 12 -6 24 -15 33s-21 14 -33 15c1 -12 6 -24 15 -33zM290 232v0c17 20 16 51 -3 70s-50 20 -70 3v0l-3 -3v0v0l-38 -38c17 -4 33 -13 46 -26s23 -30 27 -47l38 38v0v0z" />
+ <glyph glyph-name="uniF166" unicode="&#xf166;" horiz-adv-x="431"
+d="M414 345c10 0 17 -8 17 -18v-16c0 -10 -7 -17 -17 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h320zM414 217c10 0 17 -7 17 -17v-16c0 -10 -7 -17 -17 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 17 17 17h320zM414 90c10 0 17 -7 17 -17v-16c0 -10 -7 -18 -17 -18
+h-320c-10 0 -17 8 -17 18v16c0 10 7 17 17 17h320zM0 319c0 17 9 26 26 26s25 -9 25 -26s-8 -25 -25 -25s-26 8 -26 25zM0 197c0 17 9 26 26 26s25 -9 25 -26s-8 -25 -25 -25s-26 8 -26 25zM0 65c0 17 9 25 26 25s25 -8 25 -25s-8 -26 -25 -26s-26 9 -26 26z" />
+ <glyph glyph-name="uniF167" unicode="&#xf167;" horiz-adv-x="423"
+d="M29 333l-9 -9l-6 7l17 17h10v-55h-12v40zM21 210c-6 0 -10 -2 -14 -6l-7 8c5 6 13 9 21 9c12 0 21 -7 21 -18c0 -9 -8 -18 -22 -28h22v-10h-41v9c22 17 29 22 29 29c0 5 -4 7 -9 7zM30 65c6 -1 13 -5 13 -13c0 -9 -8 -16 -21 -16c-10 0 -18 4 -22 9l6 8c4 -4 10 -7 15 -7
+c7 0 11 3 11 7s-3 7 -11 7h-7v10h7c6 0 10 2 10 6s-4 6 -10 6c-5 0 -10 -1 -14 -5l-6 7c4 5 11 9 21 9c13 0 20 -6 20 -15c0 -7 -6 -12 -12 -13zM406 346c10 0 17 -7 17 -17v-16c0 -10 -7 -18 -17 -18h-320c-10 0 -17 8 -17 18v16c0 10 7 17 17 17h320zM406 219
+c10 0 17 -8 17 -18v-16c0 -10 -7 -17 -17 -17h-320c-10 0 -17 7 -17 17v16c0 10 7 18 17 18h320zM406 91c10 0 17 -7 17 -17v-16c0 -10 -7 -18 -17 -18h-320c-10 0 -17 8 -17 18v16c0 10 7 17 17 17h320z" />
+ <glyph glyph-name="uniF168" unicode="&#xf168;" horiz-adv-x="332"
+d="M321 103c6 0 11 -6 11 -12v-1v-53c0 -6 -5 -11 -11 -11v0h-182v0c-6 0 -11 5 -11 11v0v53v1c0 6 5 12 11 12v0v0h182v0zM65 103c6 0 12 -6 12 -12v0v0v-54v0c0 -6 -6 -11 -12 -11v0h-53v0v0c-6 0 -12 5 -12 11v0v54v0v0c0 6 6 12 12 12v0v0h53v0zM321 231
+c6 0 11 -6 11 -12v-1v-53c0 -6 -5 -11 -11 -11v0h-182v0c-6 0 -11 5 -11 11v0v53v1c0 6 5 12 11 12v0v0h182v0zM65 231c6 0 12 -6 12 -12v0v0v-54v0c0 -6 -6 -11 -12 -11v0h-53v0v0c-6 0 -12 5 -12 11v0v54v0v0c0 6 6 12 12 12v0v0h53v0zM128 293v0v53v1c0 6 5 11 11 11v0v0
+h182v0c6 0 11 -5 11 -11v-1v-53c0 -6 -5 -12 -11 -12v0h-182v0c-6 0 -11 6 -11 12v0zM65 358c6 0 12 -5 12 -11v0v0v-54v0c0 -6 -6 -12 -12 -12v0h-53v0v0c-6 0 -12 6 -12 12v0v54v0v0c0 6 6 11 12 11v0v0h53v0z" />
+ <glyph glyph-name="uniF169" unicode="&#xf169;" horiz-adv-x="332"
+d="M0 293v53v1c0 6 6 11 12 11v0v0h309v0c6 0 11 -5 11 -11v0v-54v0c0 -6 -5 -12 -11 -12v0h-309v0c-6 0 -12 6 -12 12v0zM321 230c6 0 11 -5 11 -11v0v-54v0c0 -6 -5 -11 -11 -11v0h-309v0c-6 0 -12 5 -12 11v0v53v1c0 6 6 11 12 11v0v0h309v0zM321 103c6 0 11 -6 11 -12v0
+v-54v0c0 -6 -5 -11 -11 -11v0h-309v0c-6 0 -12 5 -12 11v0v53v1c0 6 6 12 12 12v0v0h309v0z" />
+ <glyph glyph-name="uniF16A" unicode="&#xf16a;" horiz-adv-x="356"
+d="M342 222c7 0 14 -7 14 -14v-197c0 -7 -7 -14 -14 -14h-329c-7 0 -13 7 -13 14v197c0 7 6 14 13 14h19h22v43c0 67 54 122 121 122s122 -55 122 -122v0v-43h26h19zM126 265v-43h99v43v1v0v0c0 27 -23 49 -50 49c-28 0 -49 -22 -49 -50z" />
+ <glyph glyph-name="uniF16B" unicode="&#xf16b;" horiz-adv-x="346"
+d="M346 327v-137c0 -2 -1 -5 -3 -6s-5 -2 -7 -1l-130 44c-3 1 -5 3 -5 6s1 6 3 8l30 21l5 4c-18 14 -41 23 -66 23c-40 0 -75 -22 -93 -55v0c-4 -6 -12 -9 -18 -5l-42 24v0c-6 3 -8 11 -5 17v0c31 56 90 93 158 93c50 0 95 -20 128 -53l2 2l31 22c2 2 5 1 8 0s4 -4 4 -7z
+M326 131c6 -3 9 -11 6 -17v0c-31 -56 -91 -93 -159 -93c-50 0 -94 20 -127 53l-3 -2l-30 -22c-2 -2 -5 -1 -8 0s-5 4 -5 7v137c0 2 1 5 3 6s5 2 7 1l130 -44c3 -1 6 -3 6 -6s-1 -6 -3 -8l-31 -21l-5 -4c18 -14 41 -23 66 -23c40 0 76 22 94 55v0c4 6 12 9 18 5l41 -24v0z
+" />
+ <glyph glyph-name="uniF16C" unicode="&#xf16c;" horiz-adv-x="397"
+d="M233 395c91 0 164 -74 164 -164s-73 -164 -164 -164c-26 0 -51 6 -73 17l-82 -82v1c-8 -8 -20 -14 -33 -14c-25 0 -45 20 -45 45c0 13 6 25 14 33h-1l80 79c-15 25 -24 54 -24 85c0 90 73 164 164 164zM234 132c57 0 103 45 103 102s-46 102 -103 102s-102 -45 -102 -102
+s45 -102 102 -102z" />
+ <glyph glyph-name="uniF16D" unicode="&#xf16d;" horiz-adv-x="394"
+d="M381 345c7 0 13 -6 13 -13v-24c0 -2 -1 -2 -2 -3s-4 -2 -5 -3l-188 -110c-1 0 -1 -1 -2 -1s0 1 -1 1l-194 110c-1 1 -2 2 -2 3v27c0 7 6 13 13 13h368zM393 265c1 -1 1 -1 1 -2v-177c0 -1 -1 -3 -2 -3l-1 -1c-1 0 -1 0 -2 1l-107 115c-1 1 0 2 0 3s0 2 1 2l106 62
+c1 1 3 1 4 0zM253 182l127 -137c1 -1 1 -3 0 -4s-2 -2 -3 -2h-364c-2 0 -4 1 -6 2c-1 1 -2 2 -2 3s0 2 1 3l142 131c1 1 3 2 4 1l38 -22c5 -3 11 -2 16 1l42 25c1 1 4 0 5 -1zM117 194l-112 -103c-1 -1 -1 -1 -2 -1h-1c-1 1 -2 2 -2 3v167c0 1 1 2 2 3s2 1 3 0l111 -64
+c1 -1 2 -1 2 -2s0 -2 -1 -3z" />
+ <glyph glyph-name="uniF16E" unicode="&#xf16e;" horiz-adv-x="466"
+d="M49 347c0 28 14 42 42 42s43 -14 43 -42s-15 -42 -43 -42s-42 14 -42 42zM172 293c5 -1 9 -2 12 -6s6 -8 6 -13v-120v0c0 -5 -3 -10 -6 -13s-7 -5 -12 -5s-10 2 -13 5s-5 8 -5 13v0v82v1c0 4 -2 6 -6 6s-6 -2 -6 -6v-1v-53v-55v-110c0 -6 -2 -11 -6 -15s-8 -6 -14 -6
+s-11 2 -15 6s-6 9 -6 15v110v0c0 4 -2 6 -6 6s-6 -2 -6 -6v0v-110c0 -6 -2 -11 -6 -15s-9 -6 -15 -6s-11 2 -15 6s-6 9 -6 15v165v53v1v0c0 4 -1 6 -5 6s-6 -2 -6 -6v0v-1v-82v0c0 -5 -2 -10 -5 -13s-8 -5 -13 -5s-10 2 -13 5s-5 8 -5 13v0v120v0c0 5 2 10 6 14s9 5 14 5v0
+h152v0zM305 347c0 28 14 42 42 42s43 -14 43 -42s-15 -43 -43 -43s-42 15 -42 43zM466 171v0v-3c0 -3 0 -6 -2 -9s-4 -5 -7 -7s-6 -2 -9 -2c-8 0 -14 3 -17 11v0l-21 78v0c-1 3 -2 4 -5 4c-4 0 -6 -1 -6 -5v-2v0l33 -124c1 -1 1 -3 1 -4h1h-1h1c0 -6 -4 -10 -10 -10h-25v-82
+c0 -6 -2 -11 -6 -15s-9 -6 -15 -6s-11 2 -15 6s-6 9 -6 15v82h-12v-82c0 -4 -1 -8 -3 -11s-4 -6 -7 -8s-7 -2 -11 -2c-6 0 -11 2 -15 6s-6 9 -6 15v82h-24c-6 0 -10 4 -10 10v0v0v0c0 1 0 3 1 4l33 124v1v1v0v1v0c-1 3 -2 4 -5 4s-5 -1 -6 -4v0v0l-21 -78v0
+c-3 -8 -9 -11 -17 -11c-5 0 -9 1 -13 5s-5 8 -5 13v3v0l29 106v0v2v0c3 9 9 14 19 14v0h134v0v0c10 0 16 -5 19 -14v0l1 -2v0z" />
+ <glyph glyph-name="uniF16F" unicode="&#xf16f;" horiz-adv-x="342"
+d="M342 354v0v-106v0c0 -4 -4 -8 -8 -8h-35c-4 0 -8 4 -8 8v28l-46 -46c14 -21 23 -46 23 -74c0 -74 -60 -134 -134 -134s-134 60 -134 134s60 134 134 134c28 0 54 -9 76 -24l44 45h-26v0c-4 0 -8 4 -8 8v0v0v35c0 4 4 8 8 8v0h106v0c4 0 8 -4 8 -8v0zM134 73
+c46 0 83 37 83 83s-37 83 -83 83s-83 -37 -83 -83s37 -83 83 -83z" />
+ <glyph glyph-name="uniF170" unicode="&#xf170;" horiz-adv-x="190"
+d="M49 346c0 28 14 42 42 42s43 -14 43 -42s-15 -42 -43 -42s-42 14 -42 42zM172 292c5 -1 9 -2 12 -6s6 -9 6 -14v-120v0c0 -5 -3 -9 -6 -12s-7 -5 -12 -5s-10 2 -13 5s-5 7 -5 12v0v83v1c0 4 -2 6 -6 6s-6 -2 -6 -6v-1v-53v-55v-110c0 -6 -2 -11 -6 -15s-8 -6 -14 -6
+s-11 2 -15 6s-6 9 -6 15v110v0c0 4 -2 6 -6 6s-6 -2 -6 -6v0v-110c0 -6 -2 -11 -6 -15s-9 -6 -15 -6s-11 2 -15 6s-6 9 -6 15v165v53v1v0c0 4 -1 6 -5 6s-6 -2 -6 -6v0v-1v-83v0c0 -5 -2 -9 -5 -12s-8 -5 -13 -5s-10 2 -13 5s-5 7 -5 12v0v120v0c0 4 1 7 3 10s4 6 7 8
+s6 2 10 2v0h152v0z" />
+ <glyph glyph-name="uniF171" unicode="&#xf171;" horiz-adv-x="430"
+d="M430 407v-430v0v-1v-2h-1c-1 -6 -6 -11 -13 -11v0h-402v0c-8 0 -14 6 -14 14v0v0v283v0l161 161v0v0v0v0h255v0v0v0v0c8 0 14 -6 14 -14v0zM305 370l-19 -33l93 -92v125h-74zM161 246h-110v-31l86 -85l139 240h-101v-110v0v0c0 -8 -6 -14 -14 -14v0zM51 14h19l53 93
+l-72 72v-165zM99 14h280v194l-106 106zM276 215c34 0 62 -28 62 -62c0 -14 -4 -27 -12 -37l-39 -67c0 -1 -1 -2 -2 -3v0v0c-2 -2 -5 -4 -8 -4c-4 0 -8 1 -10 4v0v1v1l-40 69c-7 10 -12 22 -12 36c0 34 27 62 61 62zM276 122c17 0 30 13 30 30s-13 31 -30 31s-30 -14 -30 -31
+s13 -30 30 -30z" />
+ <glyph glyph-name="uniF172" unicode="&#xf172;" horiz-adv-x="289"
+d="M144 395c80 0 145 -65 145 -145c0 -33 -12 -63 -30 -87l-90 -157c-1 -2 -3 -4 -4 -6l-1 -2v1c-5 -6 -12 -10 -20 -10c-9 0 -16 4 -21 11v0v0c-1 1 -1 2 -2 3l-92 161c-18 24 -29 54 -29 86c0 80 64 145 144 145zM143 177c39 0 71 32 71 71s-32 71 -71 71s-71 -32 -71 -71
+s32 -71 71 -71z" />
+ <glyph glyph-name="uniF173" unicode="&#xf173;" horiz-adv-x="385"
+d="M76 302c8 0 14 -6 14 -14v-127v0c-1 -7 -7 -12 -14 -12c-42 0 -76 35 -76 77s34 76 76 76zM385 364v0v0v-24v-236v-23v0v-2c0 -8 -6 -14 -14 -14c-4 0 -7 2 -9 4l-134 77h-98c-7 0 -13 6 -14 13v0v132c0 8 6 14 14 14h110l123 70c2 2 5 3 8 3c8 0 14 -6 14 -14zM224 41v0
+c3 -6 2 -13 -3 -17v-1l-26 -14v0c-1 -1 -1 -2 -2 -2c-6 -4 -14 -1 -18 5v0l-1 1v0v0l-49 85v1s-1 0 -1 1c-4 7 -2 15 5 19c2 1 4 2 6 2v0h37v0c4 0 7 -3 9 -6v0l43 -73v-1v0v0z" />
+ <glyph glyph-name="uniF174" unicode="&#xf174;" horiz-adv-x="261"
+d="M261 196c0 -65 -48 -119 -111 -128v-28h68v0c11 0 19 -8 19 -19s-8 -20 -19 -20v0h-175v0c-11 0 -20 9 -20 20s9 19 20 19v0h68v28c-63 9 -111 63 -111 128v0v74c0 11 8 19 19 19s20 -8 20 -19v-73v0c0 -51 40 -92 91 -92s92 41 92 92v73c0 11 8 19 19 19s20 -8 20 -19
+v-73v0v0v-1v0zM65 197v2v0v119v0c1 36 29 65 65 65s65 -29 66 -65v0v-119v0v-2c0 -36 -30 -65 -66 -65s-65 29 -65 65z" />
+ <glyph glyph-name="uniF175" unicode="&#xf175;" horiz-adv-x="384"
+d="M281 219c3 0 5 -2 5 -5v-44c0 -3 -2 -5 -5 -5h-178c-3 0 -5 2 -5 5v44c0 3 2 5 5 5h178zM192 333c-78 0 -141 -63 -141 -141s63 -141 141 -141s141 63 141 141s-63 141 -141 141zM192 384v0c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192z
+" />
+ <glyph glyph-name="uniF176" unicode="&#xf176;" horiz-adv-x="414"
+d="M404 251c6 0 10 -5 10 -11v-96c0 -6 -4 -11 -10 -11h-394c-6 0 -10 5 -10 11v96c0 6 4 11 10 11h394z" />
+ <glyph glyph-name="uniF177" unicode="&#xf177;" horiz-adv-x="224"
+d="M211 295c7 0 13 -6 13 -13v-307c0 -7 -6 -13 -13 -13h-199v0c-7 0 -12 6 -12 13v307c0 7 5 13 12 13v0h199zM112 -24c7 0 13 5 13 12s-6 13 -13 13s-12 -6 -12 -13s5 -12 12 -12zM173 13v0v231h-122v-231h122zM212 368v0v-1v0v0l-9 -9v0v0h-1v0c-3 -3 -7 -3 -10 -1v0v1v0
+v0l-5 5v0c-41 41 -109 40 -150 -1v0v0l-6 -5v0c-3 -2 -6 -2 -9 0v0l-10 9v0c-3 3 -3 7 -1 10v1h1v0v0l5 5v0v0c52 52 138 53 190 1v0v-1v0v0l5 -5v0c2 -3 2 -6 0 -9zM174 339c2 -3 2 -6 0 -9v0l-9 -10v0v0v0v0c-3 -3 -8 -3 -11 -1v0v1v0v0l-5 5v0c-21 20 -54 20 -74 0v-1v0
+l-6 -5v0c-3 -2 -6 -2 -9 0v0l-10 9v1c-3 3 -3 7 -1 10v0l6 5v0v1c31 31 82 31 114 0v0l5 -6v0z" />
+ <glyph glyph-name="uniF178" unicode="&#xf178;" horiz-adv-x="224"
+d="M211 358c7 0 13 -5 13 -12v-308c0 -7 -6 -12 -13 -12h-199v0c-7 0 -12 5 -12 12v308c0 7 5 12 12 12v0h199zM112 39c7 0 13 5 13 12s-6 13 -13 13s-12 -6 -12 -13s5 -12 12 -12zM173 77v0v230h-122v-230h122z" />
+ <glyph glyph-name="uniF179" unicode="&#xf179;" horiz-adv-x="471"
+d="M442 381c16 0 29 -12 29 -28v-252c0 -16 -13 -29 -29 -29h-156v-44h44c5 0 9 -3 9 -8v-9c0 -5 -4 -8 -9 -8h-194c-5 0 -8 3 -8 8v9c0 5 3 8 8 8h48v44h-155c-16 0 -29 13 -29 29v252c0 16 13 28 29 28h413zM51 123h368v208h-368v-208z" />
+ <glyph glyph-name="uniF17A" unicode="&#xf17a;" horiz-adv-x="467"
+d="M465 48c1 -2 2 -4 2 -6c0 -7 -5 -13 -12 -14v0h-256h-103h-87v1c-1 0 -1 -1 -2 -1c-4 0 -7 3 -7 7c0 2 0 4 1 5l8 13v1h1l81 140c2 4 6 7 11 7s9 -3 11 -7v0l27 -48l114 196c4 8 12 14 21 14s16 -5 20 -13v0l171 -295h-1z" />
+ <glyph glyph-name="uniF17B" unicode="&#xf17b;" horiz-adv-x="382"
+d="M366 378c9 0 16 -7 16 -16v-253c0 -31 -31 -56 -69 -56s-69 25 -69 56s31 56 69 56c6 0 12 -1 18 -2v135h-193v-236c0 -31 -31 -56 -69 -56s-69 25 -69 56s31 56 69 56c6 0 12 -1 18 -2v246c0 9 8 16 17 16v0h262v0z" />
+ <glyph glyph-name="uniF17C" unicode="&#xf17c;" horiz-adv-x="397"
+d="M397 52v0c0 -7 -6 -13 -13 -13v-1h-25v0c-7 0 -13 6 -13 13v1v0v120l-170 -99c-2 -2 -5 -2 -7 -2c-5 0 -8 3 -8 8v78l-146 -84c-2 -2 -4 -2 -6 -2c-5 0 -9 3 -9 8v226v0c0 5 4 8 9 8c2 0 4 0 6 -2l146 -84v78v0c0 5 3 8 8 8c2 0 5 0 7 -2l170 -99v119v2c0 7 6 13 13 13
+l1 -1h24v0c7 0 12 -4 13 -11v0v-2v0v0v-280z" />
+ <glyph glyph-name="uniF17D" unicode="&#xf17d;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51c34 0 66 13 90 33l-24 24c-3 0 -4 1 -6 3v0l-4 7l-21 21l-16 -28h-1c-2 -2 -4 -4 -7 -4c-5 0 -10 5 -10 10c0 2 1 4 2 6l13 23h-21h-23l13 -23c1 -2 3 -4 3 -6
+c0 -5 -5 -10 -10 -10c-3 0 -6 2 -8 4v0l-21 36l-21 -36v0c-2 -2 -5 -4 -8 -4c-5 0 -10 5 -10 10c0 2 2 4 3 6l17 31c-4 4 -7 16 -7 31c0 7 1 14 2 19l-32 18v0c-2 1 -3 3 -3 6c0 4 3 7 7 7c1 0 3 0 4 -1v0l31 -18v1v0h25l-65 65c-20 -24 -33 -56 -33 -90
+c0 -78 63 -141 141 -141zM300 102c20 24 33 56 33 90c0 78 -63 141 -141 141c-34 0 -66 -13 -90 -33l83 -83h26l30 30h-1l17 30l10 -17h1v0l14 -8c4 -2 6 -6 6 -10v-11l11 -11c2 -1 3 -4 3 -6s-1 -4 -2 -5v0l-6 -6v0h-6h-22l-8 -8c0 -3 1 -6 1 -10c0 -16 -4 -29 -9 -32l3 -4
+z" />
+ <glyph glyph-name="uniF17E" unicode="&#xf17e;" horiz-adv-x="384"
+d="M272 213c3 0 5 -3 5 -6v-31v0c0 -3 -2 -5 -5 -5v0v0h-4v0c-3 0 -6 2 -6 5v0v1v0v0v30v0c0 3 3 6 6 6v0h4v0zM293 213c3 0 6 -3 6 -6v0v-30v-1v0c0 -3 -3 -5 -6 -5v0v0h-3v0c-3 0 -6 2 -6 5v0v31v0c0 3 3 6 6 6v0h3v0zM192 384c106 0 192 -86 192 -192s-86 -192 -192 -192
+s-192 86 -192 192s86 192 192 192zM192 51c34 0 66 13 90 33l-87 87h-104c-3 0 -6 3 -6 6v0v30v0v0c0 3 3 6 6 6v0h62l-69 69c-20 -24 -33 -56 -33 -90c0 -78 63 -141 141 -141zM300 102c20 24 33 56 33 90c0 78 -63 141 -141 141c-34 0 -66 -13 -90 -33l87 -87h60v0
+c3 0 6 -3 6 -6v0v-30v0c0 -3 -3 -6 -6 -6h-18z" />
+ <glyph glyph-name="uniF17F" unicode="&#xf17f;" horiz-adv-x="360"
+d="M301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0v-127v0v0v0v0c0 -5 -4 -9 -9 -9h-33c-5 0 -9 4 -9 9v0v105h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33z
+M351 174c5 0 9 -4 9 -9v-36c0 -5 -4 -8 -9 -8h-40v-40c0 -5 -4 -9 -9 -9h-35c-5 0 -9 4 -9 9v40h-40c-5 0 -9 3 -9 8v36c0 5 4 9 9 9h40v40c0 5 4 8 9 8h35c5 0 9 -3 9 -8v-40h40z" />
+ <glyph glyph-name="uniF180" unicode="&#xf180;" horiz-adv-x="361"
+d="M310 410v-392v0v-13c0 -5 -4 -9 -9 -9h-8h-276h-8c-5 0 -9 4 -9 9v13v271v5v12l133 133h9v0h147v0h12c5 0 9 -4 9 -9v-20v0zM51 47h208v341h-108v-91c0 -5 -4 -8 -9 -8h-91v-242zM354 321c4 0 7 -4 7 -8v-360c0 -4 -3 -8 -7 -8h-272v0v0c-4 0 -7 4 -7 8v17h253
+c4 0 8 4 8 8v343h18z" />
+ <glyph glyph-name="uniF181" unicode="&#xf181;" horiz-adv-x="310"
+d="M106 119c-7 0 -12 -4 -12 -11s5 -12 12 -12c4 0 8 3 9 7l12 -6c-3 -6 -9 -14 -21 -14c-15 0 -26 10 -26 25s11 24 26 24c12 0 18 -7 21 -14l-12 -5c-1 4 -5 6 -9 6zM148 118c0 -4 26 0 26 -18c0 -10 -7 -17 -20 -17c-10 0 -17 3 -22 8l7 10c4 -3 9 -6 15 -6c3 0 6 1 6 3
+c0 5 -27 -1 -27 18c0 8 7 16 20 16c8 0 15 -3 20 -7l-8 -10c-4 3 -10 5 -14 5c-3 0 -3 -1 -3 -2zM204 99l10 32h16l-17 -47h-18l-18 47h16zM310 384v-392v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0zM51 22
+h208v340h-108v-90c0 -5 -4 -9 -9 -9h-91v-241z" />
+ <glyph glyph-name="uniF182" unicode="&#xf182;" horiz-adv-x="361"
+d="M301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0v-127v0v0v0v0c0 -5 -4 -9 -9 -9h-33c-5 0 -9 4 -9 9v0v105h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33z
+M330 147l28 -28c3 -3 3 -10 0 -13l-25 -25c-3 -3 -9 -3 -12 0l-29 29l-28 -29c-3 -3 -9 -3 -12 0l-25 25c-3 3 -3 10 0 13l28 28l-28 28c-3 3 -3 10 0 13l25 25c3 3 9 3 12 0l28 -28l28 28c3 3 10 3 13 0l25 -25c3 -3 3 -10 0 -13z" />
+ <glyph glyph-name="uniF183" unicode="&#xf183;" horiz-adv-x="310"
+d="M310 384v-392v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0zM51 22h208v340h-108v-90c0 -5 -4 -9 -9 -9h-91v-241zM97 131c15 0 26 -8 26 -23s-11 -24 -26 -24h-21v47h21zM97 96c7 0 11 6 11 12
+s-3 11 -11 11h-7v-23h7zM155 132c15 0 26 -9 26 -24s-11 -25 -26 -25s-26 10 -26 25s11 24 26 24zM155 96c7 0 11 5 11 12s-4 11 -11 11s-12 -4 -12 -11s5 -12 12 -12zM213 119c-7 0 -12 -4 -12 -11s5 -12 12 -12c4 0 8 3 9 7l12 -6c-3 -6 -9 -14 -21 -14
+c-15 0 -26 10 -26 25s11 24 26 24c12 0 18 -7 21 -14l-12 -5c-1 4 -5 6 -9 6z" />
+ <glyph glyph-name="uniF184" unicode="&#xf184;" horiz-adv-x="428"
+d="M301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0v-84v0v0v-1v0c0 -5 -4 -8 -9 -8h-33c-5 0 -9 3 -9 8v0v63h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33z
+M425 248c3 -3 3 -9 0 -12l-163 -163v0v0l-82 -22v0c-3 -2 -7 -2 -10 1c-2 2 -3 6 -2 9v0l22 84l1 -1l-1 1l163 163c3 3 10 3 13 0zM195 78l49 13l-36 36z" />
+ <glyph glyph-name="uniF185" unicode="&#xf185;" horiz-adv-x="458"
+d="M456 112c2 -1 2 -3 2 -5v0c0 -2 0 -4 -2 -5l-94 -68c-2 -1 -5 -2 -7 -1s-3 4 -3 6v32h-86c-4 0 -7 3 -7 7v58c0 4 3 6 7 6h85v32c0 2 2 5 4 6s4 1 6 0zM301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12
+c5 0 9 -3 9 -8v-21v0v-207v0v0v-1v0c0 -5 -4 -8 -9 -8h-33c-5 0 -9 3 -9 8v0v186h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33zM107 119c-7 0 -11 -4 -11 -11s4 -12 11 -12c4 0 8 3 9 7l13 -6c-3 -6 -10 -14 -22 -14c-15 0 -26 10 -26 25s11 24 26 24
+c12 0 19 -7 22 -14l-13 -5c-1 4 -5 6 -9 6zM156 95c3 0 5 1 5 3c0 5 -26 -1 -26 18c0 8 6 16 19 16c8 0 15 -3 20 -7l-7 -10c-4 3 -10 5 -14 5c-3 0 -4 -1 -4 -2c0 -4 26 0 26 -18c0 -10 -7 -17 -20 -17c-10 0 -17 3 -22 8l8 10c4 -3 9 -6 15 -6zM195 131l10 -32l10 32h16
+l-17 -47h-18l-17 47h16z" />
+ <glyph glyph-name="uniF186" unicode="&#xf186;" horiz-adv-x="458"
+d="M456 112c2 -1 2 -3 2 -5v0c0 -2 0 -4 -2 -5l-94 -68c-2 -1 -5 -2 -7 -1s-3 4 -3 6v32h-86c-4 0 -7 3 -7 7v58c0 4 3 6 7 6h85v32c0 2 2 5 4 6s4 1 6 0zM301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12
+c5 0 9 -3 9 -8v-21v0v-207v0v0v-1v0c0 -5 -4 -8 -9 -8h-33c-5 0 -9 3 -9 8v0v186h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33zM77 131h22c15 0 26 -8 26 -23s-11 -24 -26 -24h-22v47zM110 108c0 6 -3 11 -11 11h-7v-23h7c7 0 11 6 11 12zM131 108
+c0 15 10 24 25 24s26 -9 26 -24s-11 -25 -26 -25s-25 10 -25 25zM168 108c0 7 -5 11 -12 11s-11 -4 -11 -11s4 -12 11 -12s12 5 12 12zM214 119c-7 0 -11 -4 -11 -11s4 -12 11 -12c4 0 8 3 9 7l13 -6c-3 -6 -10 -14 -22 -14c-15 0 -26 10 -26 25s11 24 26 24
+c12 0 19 -7 22 -14l-13 -5c-1 4 -5 6 -9 6z" />
+ <glyph glyph-name="uniF187" unicode="&#xf187;" horiz-adv-x="458"
+d="M456 112c2 -1 2 -3 2 -5v0c0 -2 0 -4 -2 -5l-94 -68c-2 -1 -5 -2 -7 -1s-3 4 -3 6v32h-86c-4 0 -7 3 -7 7v58c0 4 3 6 7 6h85v32c0 2 2 5 4 6s4 1 6 0zM301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12
+c5 0 9 -3 9 -8v-21v0v-207v0v0v-1v0c0 -5 -4 -8 -9 -8h-33c-5 0 -9 3 -9 8v0v186h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33zM83 131h26c11 0 17 -7 17 -16s-6 -16 -17 -16h-11v-15h-15v47zM111 115c0 3 -2 4 -4 4h-9v-8h9c2 0 4 2 4 4zM133 131h21
+c15 0 26 -8 26 -23s-11 -24 -26 -24h-21v47zM166 108c0 6 -4 11 -12 11h-7v-23h7c7 0 12 6 12 12zM225 119h-22v-5h21v-12h-21v-18h-14v47h36v-12z" />
+ <glyph glyph-name="uniF188" unicode="&#xf188;" horiz-adv-x="458"
+d="M456 112c2 -1 2 -3 2 -5v0c0 -2 0 -4 -2 -5l-94 -68c-2 -1 -5 -2 -7 -1s-3 4 -3 6v32h-86c-4 0 -7 3 -7 7v58c0 4 3 6 7 6h85v32c0 2 2 5 4 6s4 1 6 0zM301 46c5 0 9 -4 9 -9v0v-45v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12
+c5 0 9 -3 9 -8v-21v0v-207v0v0v-1v0c0 -5 -4 -8 -9 -8h-33c-5 0 -9 3 -9 8v0v186h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v15v0c0 5 4 9 9 9v0h33z" />
+ <glyph glyph-name="uniF189" unicode="&#xf189;" horiz-adv-x="310"
+d="M9 263c-5 0 -9 4 -9 9v9l133 132h9c5 0 9 -3 9 -8v-133c0 -5 -4 -9 -9 -9h-133zM301 413c5 0 9 -3 9 -8v-426c0 -5 -4 -8 -9 -8h-292c-5 0 -9 3 -9 8v224v0c1 4 5 8 9 8h184v0v0c5 0 9 4 9 9v0v0v187v0c1 4 4 6 8 6h91z" />
+ <glyph glyph-name="uniF18A" unicode="&#xf18a;" horiz-adv-x="389"
+d="M381 329c4 0 8 -4 8 -8v-360c0 -4 -4 -8 -8 -8h-271v0v0c-4 0 -8 4 -8 8v18h253c4 0 8 3 8 7v343h18zM338 12c0 -4 -4 -8 -8 -8h-271v0c-4 0 -8 4 -8 8v18h253c4 0 8 3 8 7v343h18c4 0 8 -4 8 -8v-360zM287 63c0 -4 -4 -8 -8 -8h-271c-4 0 -8 4 -8 8v360c0 4 4 8 8 8h271
+c4 0 8 -4 8 -8v-360z" />
+ <glyph glyph-name="uniF18B" unicode="&#xf18b;" horiz-adv-x="310"
+d="M110 131c11 0 17 -7 17 -16s-6 -16 -17 -16h-11v-15h-15v47h26zM108 111c2 0 4 2 4 4c0 3 -2 4 -4 4h-9v-8h9zM155 131c15 0 26 -8 26 -23s-11 -24 -26 -24h-21v47h21zM155 96c7 0 12 6 12 12s-4 11 -12 11h-7v-23h7zM190 84v47h36v-12h-22v-5h21v-12h-21v-18h-14z
+M310 384v-392v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0zM51 22h208v340h-108v-90c0 -5 -4 -9 -9 -9h-91v-241z" />
+ <glyph glyph-name="uniF18C" unicode="&#xf18c;" horiz-adv-x="360"
+d="M310 86v0v0v-94v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0v-176v0v0v0v0c0 -5 -4 -9 -9 -9h-33c-5 0 -9 4 -9 9v0v154h-108v-90c0 -5 -4 -9 -9 -9h-91v-241h208v64v0c0 5 4 9 9 9v0h33c5 0 9 -4 9 -9v0v0
+zM351 174c5 0 9 -4 9 -9v-36c0 -5 -4 -8 -9 -8h-133c-5 0 -9 3 -9 8v36c0 5 4 9 9 9h133z" />
+ <glyph glyph-name="uniF18D" unicode="&#xf18d;" horiz-adv-x="403"
+d="M403 384l-1 -392v0v-13c0 -5 -3 -8 -8 -8h-8h-277h-8c-5 0 -9 3 -9 8v13v45v0c0 5 4 9 9 9v0h34c5 0 8 -4 8 -9v0v-15h209v340h-109v-90c0 -5 -4 -9 -9 -9h-91v-9v0c0 -5 -3 -8 -8 -8v0h-34c-5 0 -8 3 -8 8h-1v9v5v13l133 132h9v0h147v0h13c5 0 8 -3 8 -8v-21h1zM199 146
+c0 -45 -37 -82 -82 -82c-13 0 -26 3 -37 9l-41 -41v0c-4 -4 -10 -7 -16 -7c-13 0 -23 9 -23 22c0 7 3 13 7 17v0l40 40c-7 12 -12 27 -12 42c0 45 37 82 82 82s82 -37 82 -82zM70 146c0 -26 21 -48 47 -48s48 22 48 48s-22 47 -48 47s-47 -21 -47 -47z" />
+ <glyph glyph-name="uniF18E" unicode="&#xf18e;" horiz-adv-x="310"
+d="M310 384v-392v0v-13c0 -5 -4 -8 -9 -8h-8h-276h-8c-5 0 -9 3 -9 8v13v271v5v13l133 132h9v0h147v0h12c5 0 9 -3 9 -8v-21v0zM51 22h208v340h-108v-90c0 -5 -4 -9 -9 -9h-91v-241z" />
+ <glyph glyph-name="uniF18F" unicode="&#xf18f;" horiz-adv-x="439"
+d="M389 203c5 -5 5 -13 0 -18l-203 -203v0c-5 -5 -13 -5 -18 0l-164 164c-5 5 -5 14 0 19v0l139 139l-57 58c-5 5 -8 11 -8 18c0 14 12 26 26 26c7 0 13 -3 18 -8l57 -58l27 27c5 5 14 5 19 0v0v0l164 -164v0zM288 156l38 38l-110 110l-149 -148h221zM430 70
+c6 -8 9 -17 9 -27c0 -26 -21 -48 -47 -48s-48 22 -48 48c0 11 4 20 10 28l30 52c0 1 1 0 1 1v1v0c2 2 4 3 7 3s5 -2 7 -4v0v0v-1z" />
+ <glyph glyph-name="uniF190" unicode="&#xf190;" horiz-adv-x="356"
+d="M77 -5c-14 0 -32 5 -50 23c-24 24 -27 47 -25 62c2 18 11 34 27 50l150 151c42 42 70 26 83 13c16 -16 26 -42 -14 -82l-138 -139l-27 27l138 139c21 21 16 26 14 28s-8 8 -29 -13l-150 -151c-7 -7 -15 -17 -16 -28c-1 -10 3 -19 14 -30c13 -13 23 -11 26 -11
+c9 1 20 8 30 18l178 178c15 15 24 29 28 42c5 19 -1 38 -20 57c-20 20 -50 40 -98 -8l-165 -165c-7 -7 -20 -7 -27 0s-7 20 0 27l165 165c51 51 106 54 152 8c36 -36 36 -71 30 -94c-6 -20 -18 -39 -38 -59l-178 -178c-16 -16 -34 -27 -51 -29c-3 0 -6 -1 -9 -1z" />
+ <glyph glyph-name="uniF191" unicode="&#xf191;" horiz-adv-x="228"
+d="M65 346c6 0 12 -5 12 -11v0v0v-286v0v0c0 -6 -6 -11 -12 -11v0h-54v0v0c-6 0 -11 5 -11 11v0v0v286v0v0c0 6 5 11 11 11v0h53v0h1zM228 49v0v0c0 -6 -5 -11 -11 -11v0h-55v0v0c-6 0 -11 5 -11 11v0v0v286v0v0c0 6 5 11 11 11v0h53v0h2c6 0 11 -5 11 -11v0v0v-286z" />
+ <glyph glyph-name="uniF192" unicode="&#xf192;" horiz-adv-x="363"
+d="M104 240c0 -29 -23 -52 -52 -52s-52 23 -52 52s23 51 52 51s52 -22 52 -51zM311 281c29 0 52 -23 52 -52s-23 -51 -52 -51s-52 22 -52 51s23 52 52 52zM264 172l3 -4c16 -19 35 -44 35 -84c0 -37 -31 -68 -68 -68c-21 0 -40 10 -53 27c-13 -17 -33 -27 -54 -27
+c-37 0 -68 31 -68 68c0 40 19 65 35 84l3 4c5 6 13 13 22 21c16 17 37 27 62 27c28 0 52 -13 68 -33c6 -5 11 -11 15 -15zM128 310c0 38 19 58 57 58s57 -20 57 -58s-19 -57 -57 -57s-57 19 -57 57z" />
+ <glyph glyph-name="uniF193" unicode="&#xf193;" horiz-adv-x="315"
+d="M73 88c-2 -9 -11 -16 -20 -16h-40c-9 0 -15 8 -13 16l58 248c2 8 10 16 19 16h85c18 0 34 -2 48 -4c14 -3 25 -7 35 -13s17 -14 22 -24s8 -22 8 -37c0 -33 -13 -60 -41 -80s-66 -31 -116 -31h-12c-9 0 -17 -7 -19 -15zM106 232c-2 -9 3 -16 12 -16h10c22 0 40 5 52 14
+s18 22 18 38c0 11 -4 19 -12 24s-19 8 -35 8h-13c-9 0 -18 -7 -20 -15zM307 271c5 -10 8 -21 8 -36c0 -33 -14 -61 -42 -81s-65 -30 -115 -30h-12c-9 0 -17 -8 -19 -16l-14 -60c-2 -9 -11 -16 -20 -16h-40c-9 0 -15 8 -13 16l2 8h28c9 0 17 6 19 15l14 61c2 8 10 15 19 15
+h12c50 0 88 11 116 31s41 47 41 80c0 15 -3 27 -8 37v1c1 0 1 -1 2 -1c10 -6 17 -14 22 -24z" />
+ <glyph glyph-name="uniF194" unicode="&#xf194;" horiz-adv-x="405"
+d="M401 298c5 -5 5 -14 0 -19l-253 -254v0v0l-128 -34v0c-5 -2 -12 -2 -16 2s-5 9 -3 14v0l34 130h1v0l253 254c5 5 15 5 20 0zM43 33l77 20l-57 56z" />
+ <glyph glyph-name="uniF195" unicode="&#xf195;" horiz-adv-x="443"
+d="M442 356h1v-330h-1c-1 -11 -10 -21 -22 -21c-1 0 -3 1 -4 1v-1h-393v0c-12 0 -22 10 -23 21v0v2v0v0v328v0c0 13 10 23 23 23v0h393v-1c1 0 3 1 4 1c13 0 22 -10 22 -23zM392 56v272h-341v-218l28 48c1 3 5 5 8 5s6 -2 7 -5v0l19 -33l77 134c2 5 9 10 15 10s11 -4 14 -9
+v0l116 -202v0c0 -1 1 -1 1 -2h56zM262 250c0 34 18 52 52 52s52 -18 52 -52s-18 -51 -52 -51s-52 17 -52 51z" />
+ <glyph glyph-name="uniF196" unicode="&#xf196;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51c78 0 141 63 141 141s-63 141 -141 141s-141 -63 -141 -141s63 -141 141 -141zM276 197c2 -1 2 -3 2 -5s0 -4 -2 -5v0l-120 -69v0h-3c-3 0 -5 1 -5 4v0v138v0v1c0 3 2 6 5 6
+c1 0 2 -1 3 -1v0l120 -69v0z" />
+ <glyph glyph-name="uniF197" unicode="&#xf197;" horiz-adv-x="415"
+d="M389 35h-364c-14 0 -25 12 -25 26v262c0 14 11 26 25 26h364c14 0 26 -12 26 -26v-262c0 -14 -12 -26 -26 -26zM364 86v212h-313v-212h313zM283 191l-61 -36l-61 -35v71v70l61 -35z" />
+ <glyph glyph-name="uniF198" unicode="&#xf198;" horiz-adv-x="276"
+d="M276 192c0 -4 -2 -8 -5 -10v0l-254 -146v0c-2 -1 -4 -2 -6 -2c-6 0 -10 4 -11 10v0v293v0v1c0 6 5 12 11 12c2 0 5 -1 7 -2l252 -146c4 -2 6 -6 6 -10z" />
+ <glyph glyph-name="uniF199" unicode="&#xf199;" horiz-adv-x="371"
+d="M362 245c5 0 9 -5 9 -10v-86c0 -3 -1 -5 -3 -7s-3 -3 -6 -3h-124v-123c0 -2 -1 -5 -3 -7s-4 -3 -6 -3h-87c-2 0 -4 1 -6 3s-3 5 -3 7v123h-124c-2 0 -4 1 -6 3s-3 5 -3 7v86c0 5 4 10 9 10h124v123c0 5 4 10 9 10h87c5 0 9 -5 9 -10v-123h124z" />
+ <glyph glyph-name="uniF19A" unicode="&#xf19a;" horiz-adv-x="221"
+d="M221 75c0 -2 -1 -4 -2 -5v0c-12 -12 -31 -20 -61 -20c-36 0 -50 18 -75 18c-14 0 -32 -7 -48 -16v0h-2c-2 0 -4 1 -5 3v0h-1v0l-14 30v0v0v0v2c0 2 1 4 3 5v0v1v0c26 12 45 30 45 51c0 8 -2 15 -5 22h-50v0v0c-3 0 -6 2 -6 5v0v22v0c0 3 3 6 6 6v0v0h28
+c-10 14 -19 30 -19 50c0 52 51 85 100 85c46 0 79 -16 96 -50v0c1 -1 1 -2 1 -3c0 -2 -1 -4 -3 -5v0l-37 -22v0v0h-2c-2 0 -5 1 -6 3c-7 17 -23 29 -42 29c-24 0 -43 -15 -43 -38c0 -21 11 -34 20 -49h60v0c3 0 5 -2 5 -5v0v-22v0c0 -3 -2 -6 -5 -6v0h-47c0 -2 1 -6 1 -8
+c0 -19 -12 -37 -27 -46c6 2 14 4 20 4c24 0 34 -14 54 -14c18 0 30 8 35 15v0c1 1 3 2 5 2s4 -2 5 -4v0v0v0l15 -37v0c0 -1 1 -2 1 -3z" />
+ <glyph glyph-name="uniF19B" unicode="&#xf19b;" horiz-adv-x="384"
+d="M328 332c35 -35 56 -82 56 -135c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 51 20 98 53 132c2 3 6 6 10 6c3 0 5 -1 7 -3v0h1v0l21 -19v-1v0v0c2 -2 4 -4 4 -7s-2 -7 -4 -9v0c-25 -26 -41 -60 -41 -99c0 -78 63 -141 141 -141s141 63 141 141c0 38 -15 73 -40 98
+c-3 2 -5 6 -5 10c0 3 1 5 3 7v0v0v1l21 19v0h1v0c2 2 4 3 7 3s6 -1 8 -3v0zM178 127c-6 0 -11 5 -11 11v0v0v230v0v0c0 6 5 11 11 11v0h28v0v0c6 0 11 -5 11 -11v0v0v-230v0v0c0 -6 -5 -11 -11 -11v0v0h-28v0v0v0v0z" />
+ <glyph glyph-name="uniF19C" unicode="&#xf19c;" horiz-adv-x="397"
+d="M388 313c5 0 9 -3 9 -8v-226v0c0 -5 -4 -8 -9 -8c-2 0 -4 0 -6 2l-146 84v-78v0c0 -5 -3 -8 -8 -8c-2 0 -4 0 -6 2l-171 99v-119v-2c0 -7 -6 -13 -13 -13l-1 1h-23h-1c-7 0 -12 4 -13 11v0v2v0v0v280v0c0 7 6 13 13 13v1h25v0c7 0 13 -6 13 -13v-1v0v-120l170 99
+c2 2 5 2 7 2c5 0 8 -3 8 -8v-78l146 84c2 2 4 2 6 2z" />
+ <glyph glyph-name="uniF19D" unicode="&#xf19d;" horiz-adv-x="325"
+d="M324 109c3 -5 1 -11 -4 -14v0l-166 -96v0c-5 -3 -12 -1 -15 4v1l-137 238v0h-1c-1 2 -1 4 -1 6v0v65v0c0 4 2 7 5 9l109 63v0v0l1 1v0c3 1 6 1 9 -1v0l57 -32v0c2 -1 3 -2 4 -4h1l137 -239v0zM93 298c9 5 12 18 7 27s-18 12 -27 7s-12 -18 -7 -27s18 -12 27 -7z" />
+ <glyph glyph-name="uniF19E" unicode="&#xf19e;" horiz-adv-x="395"
+d="M393 100c3 -5 2 -12 -3 -15v0l-167 -96v0c-5 -3 -11 -1 -14 4v1l-7 12l153 88v0c5 3 7 10 4 15v0v0l-104 179l-45 79l41 -24v0c2 -1 3 -2 4 -4v0l138 -238v0v-1zM320 104v0l-166 -96v0c-5 -3 -12 -1 -15 4v1l-137 238v0h-1c-1 2 -1 5 -1 7v0v65v0c0 4 2 7 5 9l109 62v0v1
+h1v0c3 1 6 1 9 -1v1l57 -33v0c2 -1 3 -2 4 -4h1l137 -239v0h1c3 -5 1 -12 -4 -15zM93 307c9 5 12 18 7 27s-18 12 -27 7s-12 -18 -7 -27s18 -12 27 -7z" />
+ <glyph glyph-name="uniF19F" unicode="&#xf19f;" horiz-adv-x="414"
+d="M414 268v0v-188c0 -5 -4 -10 -9 -10h-67v79v0h-26h-210h-25v0v-79h-68v0c-5 0 -9 5 -9 10v188v0c0 5 4 9 9 9v0h68v0v110c0 5 4 10 9 10h242c5 0 10 -5 10 -10v-110v0v0h67c5 0 9 -4 9 -9zM312 235v0v127c0 5 -4 9 -9 9h-192v0c-5 0 -9 -4 -9 -9v-127h210zM103 -3v126
+h209v-126c0 -5 -5 -10 -10 -10h-190c-5 0 -9 5 -9 10z" />
+ <glyph glyph-name="uniF1A0" unicode="&#xf1a0;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51c34 0 66 13 90 33l-198 198c-20 -24 -33 -56 -33 -90c0 -78 63 -141 141 -141zM300 102c20 24 33 56 33 90c0 78 -63 141 -141 141c-34 0 -66 -13 -90 -33z" />
+ <glyph glyph-name="uniF1A1" unicode="&#xf1a1;" horiz-adv-x="391"
+d="M391 363v0v-32v0c0 -5 -4 -9 -9 -9h-373v0c-5 0 -9 4 -9 9v0v32v0c0 5 4 10 9 10v0h373c5 0 9 -5 9 -10v0zM359 296c5 0 9 -4 9 -9v0v-190c0 -11 -9 -21 -21 -21h-139v-27c5 -4 8 -10 8 -17c0 -12 -9 -21 -21 -21s-21 9 -21 21c0 7 4 13 9 17v27h-139
+c-12 0 -22 10 -22 21v190v0v0c0 5 4 9 9 9h328z" />
+ <glyph glyph-name="uniF1A2" unicode="&#xf1a2;" horiz-adv-x="293"
+d="M293 198v0v0v-3h-1c-1 -5 -6 -8 -11 -8v0v-1c-4 1 -8 2 -13 2c-28 0 -50 -22 -50 -50s22 -50 50 -50c5 0 9 1 13 2v-1c6 0 11 -4 12 -10v0v-67v0c0 -11 -10 -20 -21 -20h-65v0c-6 0 -12 6 -12 12c0 2 0 3 1 4v0c1 4 2 9 2 14c0 28 -22 50 -50 50s-50 -22 -50 -50
+c0 -5 1 -10 2 -14v0v-1v0c0 -1 1 -2 1 -3c0 -6 -5 -12 -11 -12h-68h-2c-11 0 -20 9 -20 20v1v66v0v2c0 6 6 12 12 12c1 0 3 -1 4 -1v0c6 -3 12 -4 19 -4c28 0 50 22 50 50s-22 50 -50 50c-7 0 -14 -1 -20 -4c-1 0 -2 -1 -3 -1c-6 0 -12 6 -12 12v0v68v1c0 11 9 21 20 21v0
+h75v0c14 1 25 12 25 27c0 6 -1 12 -5 17v0c-4 6 -6 13 -6 21c0 23 20 42 43 42s42 -19 42 -42c0 -8 -2 -15 -6 -21h1c-4 -5 -6 -11 -6 -17c0 -15 11 -26 25 -27v0h1h1h1h62v-1c11 0 20 -9 20 -20v0v-66z" />
+ <glyph glyph-name="uniF1A3" unicode="&#xf1a3;" horiz-adv-x="435"
+d="M52 224c20 0 35 -15 35 -37s-19 -41 -41 -41c-24 0 -46 19 -46 53c0 39 21 73 53 96v0c1 0 2 1 3 1s2 -1 3 -2v0l22 -13v0c2 -1 2 -3 2 -5s-1 -4 -3 -5v0v0v0c-16 -9 -34 -30 -39 -48c2 1 7 1 11 1zM157 224c20 0 35 -15 35 -37s-19 -41 -41 -41c-24 0 -46 19 -46 53
+c0 39 21 73 53 96h1c1 0 1 1 2 1s3 -1 4 -2v0l21 -13v0c2 -1 3 -3 3 -5s-2 -4 -4 -5v0v0v0c-16 -9 -33 -30 -38 -48c2 1 6 1 10 1zM284 238c24 0 46 -19 46 -53c0 -39 -21 -73 -53 -96v0c-1 0 -2 -1 -3 -1s-2 1 -3 2v0l-22 13v0c-2 1 -2 3 -2 5s1 4 3 5v0v0v0
+c16 9 34 30 39 48c-2 -1 -6 -1 -10 -1c-20 0 -36 15 -36 37s19 41 41 41zM389 238c24 0 46 -19 46 -53c0 -39 -21 -73 -53 -96v0c-1 0 -1 -1 -2 -1s-3 1 -4 2v0l-21 13v0c-2 1 -3 3 -3 5s1 4 3 5v0h1v0c16 9 33 30 38 48c-2 -1 -6 -1 -10 -1c-20 0 -35 15 -35 37
+s18 41 40 41z" />
+ <glyph glyph-name="uniF1A4" unicode="&#xf1a4;" horiz-adv-x="380"
+d="M190 382c105 0 190 -85 190 -190s-85 -190 -190 -190s-190 85 -190 190s85 190 190 190zM190 130c34 0 62 28 62 62s-28 62 -62 62s-63 -28 -63 -62s29 -62 63 -62z" />
+ <glyph glyph-name="uniF1A5" unicode="&#xf1a5;" horiz-adv-x="355"
+d="M354 337l1 -137c0 -2 -2 -5 -4 -6s-5 -2 -7 -1l-130 44c-3 1 -5 3 -5 6s1 6 3 8l31 22l5 3c-18 14 -41 23 -66 23c-59 0 -108 -48 -108 -107s49 -107 108 -107c36 0 69 17 89 47c3 4 9 6 13 3l45 -32c2 -1 4 -4 4 -6s0 -4 -1 -6c-34 -50 -91 -80 -151 -80
+c-100 0 -181 81 -181 181s81 181 181 181c50 0 95 -20 128 -53l2 2l31 22c2 2 5 1 8 0s4 -4 4 -7z" />
+ <glyph glyph-name="uniF1A6" unicode="&#xf1a6;" horiz-adv-x="471"
+d="M123 210c2 -3 3 -7 5 -10l-53 -24c-14 -7 -23 -22 -23 -39v-56h-41c-6 0 -11 6 -11 13v54c0 5 3 10 7 12l69 32c-16 10 -28 29 -28 52c0 33 23 59 51 59c8 0 15 -2 21 -5c-2 -4 -3 -9 -4 -13c-3 -10 -4 -19 -4 -28c0 -16 4 -33 11 -47zM287 270c-1 4 -1 8 -2 13
+c-3 14 -10 27 -18 38h195v0v0c5 0 9 -4 9 -9v0v-33v0c0 -5 -4 -9 -9 -9v0v0h-175zM471 108v0v-33v0c0 -5 -4 -9 -9 -9v0v0h-114v4v11v36h114v0v0c5 0 9 -4 9 -9zM462 219c5 0 9 -4 9 -9v0v-33v0c0 -5 -4 -9 -9 -9v0v0h-126c-3 3 -7 6 -11 8l-53 25c2 4 5 7 7 11c1 2 1 5 2 7
+h181v0v0zM314 153c5 -3 9 -9 9 -16v-56v-11c0 -9 -6 -16 -14 -16h-218c-8 0 -14 7 -14 16v11v56c0 7 4 14 9 16l61 28l24 11c-11 7 -19 17 -25 29c-5 11 -9 23 -9 36c0 8 1 14 3 21c8 30 32 52 60 52c29 0 53 -22 60 -53c2 -6 3 -13 3 -20c0 -12 -3 -24 -8 -34
+c-6 -13 -14 -23 -25 -30l25 -12z" />
+ <glyph glyph-name="uniF1A7" unicode="&#xf1a7;" horiz-adv-x="431"
+d="M431 336v-33v0c0 -5 -4 -9 -9 -9v0v0h-235v0c-5 0 -9 4 -9 9v0v33v0v0v0v0c0 5 4 9 9 9v0h235v0v0c5 0 9 -4 9 -9v0zM431 259v-32v0c0 -5 -4 -10 -9 -10v0v0h-235v0c-5 0 -9 5 -9 10v0v32v0v0v0v0c0 5 4 9 9 9v0h235v0v0c5 0 9 -4 9 -9v0zM127 336v-109v0v0
+c0 -5 -4 -10 -9 -10v0v0h-109v0c-5 0 -9 5 -9 10v0v0v109v0c0 5 4 9 9 9h1h108v0c5 0 9 -4 9 -9v0zM431 157v-32v0c0 -5 -4 -9 -9 -9v0v0h-235v0c-5 0 -9 4 -9 9v0v32v0v0v0v0c0 5 4 9 9 9v1h235v-1v0c5 0 9 -4 9 -9v0zM431 81v-33v0c0 -5 -4 -9 -9 -9v0v0h-235v0
+c-5 0 -9 4 -9 9v1v32v0v0v0v0c0 5 4 9 9 9v0h235v0v0c5 0 9 -4 9 -9v0zM127 157v-109v0v0c0 -5 -4 -9 -9 -9v0h-109v0c-5 0 -9 4 -9 9v0v0v109v0c0 5 4 10 9 10l1 -1h108v1c5 0 9 -5 9 -10v0z" />
+ <glyph glyph-name="uniF1A8" unicode="&#xf1a8;" horiz-adv-x="406"
+d="M351 197c-2 -2 -5 -2 -7 -1l-131 42c-3 1 -5 3 -5 6s1 5 3 7l30 23l5 4c-19 14 -42 21 -67 21c-59 -1 -106 -50 -105 -109s51 -106 110 -105h10v0v0c7 0 14 -6 14 -13v0v0l1 -47v0c0 -3 -2 -7 -4 -9v0v0v-1l-2 -1v0c-1 0 -1 -1 -2 -1v0c-3 -1 -5 -2 -5 -2h-11
+c-100 -2 -183 78 -185 178s78 182 178 184c50 1 96 -18 129 -50l2 1l30 23c2 2 5 2 8 1s4 -4 4 -7l3 -138c0 -2 -1 -4 -3 -6zM291 142h18l2 -99h-21l-1 72l-16 -17l-13 12zM365 145c28 1 41 -25 41 -50s-11 -51 -39 -52s-42 25 -42 50s12 51 40 52zM366 61c14 0 19 15 19 33
+s-6 32 -20 32s-19 -15 -19 -33s6 -32 20 -32z" />
+ <glyph glyph-name="uniF1A9" unicode="&#xf1a9;" horiz-adv-x="372"
+d="M363 313c5 0 9 -3 9 -8v-226v0c0 -5 -4 -8 -9 -8c-2 0 -4 0 -6 2l-145 84v-78v0c0 -5 -4 -8 -9 -8c-2 0 -4 0 -6 2l-192 111v0c-3 1 -5 4 -5 8c0 3 1 5 4 7v1l192 111c2 2 5 2 7 2c5 0 9 -3 9 -8v-78l145 84c2 2 4 2 6 2z" />
+ <glyph glyph-name="uniF1AA" unicode="&#xf1aa;" horiz-adv-x="339"
+d="M48 115c25 0 45 -20 45 -45s-20 -44 -45 -44s-45 19 -45 44s20 45 45 45zM34 239c101 0 183 -81 184 -182v0v-18v0c-1 -8 -8 -14 -16 -15v-1h-31v0c-9 0 -17 7 -18 16v0v18v0c-1 65 -54 118 -119 118h-1v0h-17v0c-8 1 -15 7 -16 15v0v32v0c0 9 7 16 16 17v0h17v0h1z
+M339 57v0v0v-18v0c-1 -8 -7 -14 -15 -15v-1h-32v0c-9 0 -16 7 -17 16v0v18v0c-1 132 -109 239 -241 239h-1v0h-17v0c-8 1 -15 8 -16 16v0v31v0c0 9 7 16 16 17v1h17v0h1c168 0 304 -136 305 -304z" />
+ <glyph glyph-name="uniF1AB" unicode="&#xf1ab;" horiz-adv-x="482"
+d="M482 28v-2c0 -7 -6 -12 -13 -12v0v0h-457c-7 0 -12 5 -12 12v1v0v25c0 7 5 12 12 12h39l169 293c4 8 12 13 21 13s17 -5 21 -13v0l169 -293h38v0c7 0 13 -5 13 -12v0v0v-24zM228 319l-29 -51h84l-29 51h-26zM169 217l-29 -51h202l-29 51h-144zM81 64h320l-30 51h-261z
+" />
+ <glyph glyph-name="uniF1AC" unicode="&#xf1ac;" horiz-adv-x="379"
+d="M204 251v110h53v-110h-53zM375 350c2 -2 4 -5 4 -9v-1v-324v0v0c0 -7 -5 -12 -12 -12v0h-39v169v0c0 6 -6 11 -12 11v0v0v0v0h-253v0h-1h-1v0c-5 -1 -10 -5 -10 -11v0v-1v0v0v0v-156v0v-12h-39v0c-7 0 -12 5 -12 12v0v168v49v135v0c0 7 5 12 12 12v0v0h67v0c2 0 3 0 5 -2
+c1 -1 2 -2 2 -3v0v-130v0c0 -6 6 -12 12 -12v0h175h1c7 0 13 5 13 12v0v130v0c0 1 1 3 2 4s3 1 4 1v0v0v0h46v0c4 0 7 -2 9 -4l27 -26v0z" />
+ <glyph glyph-name="uniF1AD" unicode="&#xf1ad;" horiz-adv-x="358"
+d="M298 252c33 0 60 -27 60 -60s-27 -60 -60 -60c-7 0 -14 2 -21 4l-157 -91v-3c0 -33 -27 -61 -60 -61s-60 28 -60 61s27 60 60 60c13 0 26 -5 36 -12l144 84c-2 6 -2 12 -2 18s0 12 2 18l-145 84c-10 -7 -22 -12 -35 -12c-33 0 -60 27 -60 60s27 61 60 61s60 -28 60 -61
+v-4l156 -90c7 3 14 4 22 4z" />
+ <glyph glyph-name="uniF1AE" unicode="&#xf1ae;" horiz-adv-x="384"
+d="M356 130c15 0 28 -12 28 -27s-13 -28 -28 -28c-10 0 -19 6 -24 15h-80l-35 -61c2 -4 3 -7 3 -12c0 -15 -12 -28 -27 -28s-28 13 -28 28c0 5 1 9 3 13l-34 60h-78c-5 -7 -14 -12 -23 -12c-15 0 -27 12 -27 27s12 28 27 28c2 0 5 0 7 -1l35 60l-35 60c-4 -2 -8 -3 -12 -3
+c-15 0 -28 13 -28 28s13 27 28 27c10 0 19 -5 24 -14h79l37 63c-3 4 -5 9 -5 14c0 15 13 28 28 28s27 -13 27 -28c0 -6 -1 -11 -4 -15l36 -62h78c5 7 13 12 22 12c15 0 28 -13 28 -28s-13 -27 -28 -27c-2 0 -5 0 -7 1l-34 -60l35 -60c4 2 8 2 12 2z" />
+ <glyph glyph-name="uniF1AF" unicode="&#xf1af;" horiz-adv-x="344"
+d="M172 394l172 -99v0v-118c-1 -98 -76 -178 -172 -188c-96 10 -171 90 -172 188v0v118v0l172 100v-1zM172 41c67 10 120 66 121 136v0v6h-121v152l-121 -70v-82h121v-142z" />
+ <glyph glyph-name="uniF1B0" unicode="&#xf1b0;" horiz-adv-x="441"
+d="M441 250v0v-216c0 -11 -9 -20 -20 -20v0v0h-401v0c-11 0 -20 9 -20 20v0v216v0c1 10 10 18 20 18h31c32 61 97 102 170 102s137 -41 169 -102h31v0c10 0 19 -8 20 -18zM112 268h217c-26 31 -64 51 -108 51s-83 -20 -109 -51z" />
+ <glyph glyph-name="uniF1B1" unicode="&#xf1b1;" horiz-adv-x="425"
+d="M95 33c0 20 10 30 30 30s31 -10 31 -30s-11 -30 -31 -30s-30 10 -30 30zM307 33c0 20 10 30 30 30s30 -10 30 -30s-10 -30 -30 -30s-30 10 -30 30zM333 165v0h-200v-25h270v0c5 0 9 -3 12 -6s5 -7 5 -12v0v-15v0v-1v-2v0c-1 -9 -8 -14 -17 -15v0h-303v0v0
+c-5 0 -9 2 -12 5s-6 7 -6 12v0v224h-63v0v0h-1c-5 0 -10 2 -13 5s-5 8 -5 13v0v17v0c1 4 3 9 6 12s8 4 12 4v0h1v0h97v0v0c5 0 9 -2 12 -5s5 -8 5 -13v0v-33h54h146h75v0c5 0 9 -2 12 -5s5 -8 5 -13c0 -3 0 -5 -1 -7v0l-75 -130v0c-3 -7 -9 -10 -16 -10z" />
+ <glyph glyph-name="uniF1B2" unicode="&#xf1b2;" horiz-adv-x="462"
+d="M74 129l44 45l55 -55l-54 -54c-4 -7 -12 -12 -21 -12v0h-87v0c-5 1 -9 5 -10 10h-1v56h1c1 6 6 11 12 11c1 0 2 -1 3 -1h58zM460 290c2 -1 2 -3 2 -5v0c0 -2 0 -4 -2 -5l-95 -69c-2 -1 -5 -1 -7 0s-4 4 -4 6v30h-53l-38 -37l-54 54l54 54v0c4 3 10 6 15 6v0h76v29
+c0 2 2 5 4 6s4 0 6 -1zM459 104c2 -1 3 -3 3 -5v0c0 -2 -1 -4 -3 -5l-95 -68c-2 -1 -5 -2 -7 -1s-3 4 -3 6v29h-77v0c-5 0 -10 3 -14 6v0l-189 189h-58c-1 0 -2 -1 -3 -1c-6 0 -12 5 -13 11v0v56v0c1 5 6 9 11 10v0h87v0c9 0 17 -5 21 -12l182 -182h53v30c0 2 1 5 3 6
+s5 1 7 0z" />
+ <glyph glyph-name="uniF1B3" unicode="&#xf1b3;" horiz-adv-x="399"
+d="M390 78c12 -12 13 -31 1 -43c-7 -7 -18 -10 -27 -8c2 -9 -1 -19 -8 -26c-12 -12 -30 -11 -42 1s-12 29 -1 41l-45 45v-31c-19 -15 -42 -24 -68 -24s-50 9 -69 24v31l-45 -45c11 -12 11 -30 -1 -42s-30 -12 -42 0c-7 7 -10 17 -8 26c-9 -2 -19 2 -26 9c-12 12 -12 30 0 42
+c12 11 30 12 42 1l46 46c-13 19 -20 42 -20 67s7 48 20 67l-46 46c-12 -11 -30 -11 -42 1s-12 31 0 43c7 7 17 10 26 8c-2 9 1 19 8 26c12 12 31 11 43 -1s12 -29 1 -41l46 -46c19 13 42 20 67 20s48 -7 67 -20l46 46c-11 12 -10 30 1 42c12 12 30 12 42 0
+c7 -7 11 -17 9 -26c9 2 18 -2 25 -9c12 -12 12 -30 0 -42s-29 -12 -41 -1l-46 -46c13 -19 20 -42 20 -67s-7 -48 -20 -67l46 -46c12 11 29 10 41 -1zM166 146c13 0 24 10 24 23s-11 24 -24 24s-23 -11 -23 -24s10 -23 23 -23zM233 146c13 0 24 10 24 23s-11 24 -24 24
+s-23 -11 -23 -24s10 -23 23 -23z" />
+ <glyph glyph-name="uniF1B4" unicode="&#xf1b4;"
+d="M262 227c10 0 17 -3 23 -10s9 -14 9 -23s-3 -18 -8 -24s-13 -9 -23 -9c-6 0 -10 1 -15 3s-10 4 -14 7s-9 6 -13 10s-8 8 -11 12l11 11s8 8 12 11s9 7 14 9s10 3 15 3zM151 204l11 -11c-3 -4 -6 -8 -10 -12s-9 -7 -13 -10s-9 -5 -14 -7s-10 -3 -15 -3c-10 0 -17 3 -23 9
+s-8 14 -8 23s3 17 8 24s13 10 22 10c5 0 10 -1 15 -3s9 -6 14 -9s9 -7 13 -11zM333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM326 166c3 9 5 19 5 29s-2 19 -5 28s-7 17 -13 23s-14 11 -22 15s-17 6 -28 6
+c-8 0 -17 -1 -24 -4s-14 -7 -20 -11s-12 -9 -17 -15s-11 -12 -16 -18c-5 6 -11 12 -16 18s-11 11 -17 15s-13 8 -20 11s-15 4 -24 4c-11 0 -21 -2 -29 -6s-15 -9 -21 -15s-10 -14 -13 -23s-5 -19 -5 -29s2 -20 5 -29s8 -17 14 -23s13 -11 21 -15s18 -6 29 -6c9 0 17 1 24 4
+s13 5 19 9s12 10 17 15l16 16c5 -6 10 -11 16 -16s12 -11 18 -15s13 -6 20 -9s15 -4 23 -4c11 0 19 2 28 6s16 8 22 15s10 15 13 24z" />
+ <glyph glyph-name="uniF1B5" unicode="&#xf1b5;"
+d="M232 355h137v-326zM0 355h136l-136 -326v326zM125 94l59 141l87 -206h-57l-26 65h-63z" />
+ <glyph glyph-name="uniF1B6" unicode="&#xf1b6;" horiz-adv-x="377"
+d="M199 264h7c1 0 1 1 3 1c-1 10 0 21 -2 31c-2 12 -11 20 -24 22c-20 3 -41 -8 -46 -29c-2 -7 -6 -9 -13 -8c-13 2 -26 3 -39 5c-9 1 -11 4 -9 13c6 27 22 47 47 58c38 17 75 18 113 1c25 -11 38 -31 39 -58c1 -35 2 -69 1 -104c0 -19 4 -36 17 -51c5 -6 5 -10 -1 -15
+c-11 -9 -22 -20 -33 -29c-6 -5 -12 -5 -17 1c-9 9 -16 18 -25 27c-5 -5 -11 -9 -17 -14c-21 -17 -45 -22 -70 -19c-39 4 -62 30 -63 70c-1 44 22 74 66 87c21 6 44 9 66 11zM198 163c13 20 10 41 10 64c-11 -1 -22 -2 -33 -4c-26 -5 -40 -23 -38 -50c1 -20 15 -32 34 -29
+c12 2 21 9 27 19zM318 85c6 2 11 0 14 -5s2 -10 -3 -14c-7 -5 -15 -10 -22 -14c-41 -24 -85 -37 -126 -38c-50 0 -88 14 -123 38c-19 13 -35 28 -53 42c-5 4 -6 9 -3 13s7 5 13 2c18 -9 36 -19 54 -28c28 -14 57 -25 89 -28c26 -2 52 0 77 5c27 5 53 14 78 25c2 1 3 1 5 2z
+M357 124c18 -2 21 -6 19 -24c-2 -19 -9 -35 -22 -49c-2 -2 -3 -4 -5 -4c-3 0 -7 -1 -9 1s-3 6 -2 9c2 8 5 15 7 23c1 4 2 9 3 13s0 6 -4 6h-10v0c-9 -1 -17 -2 -26 -3c-5 -1 -8 0 -10 4c-2 5 0 9 4 12c17 12 35 14 55 12z" />
+ <glyph glyph-name="uniF1B7" unicode="&#xf1b7;" horiz-adv-x="338"
+d="M223 355c34 -17 57 -51 57 -89h-222c0 38 23 72 57 89l-18 32c-1 2 0 3 2 4s3 1 4 -1l18 -32c15 6 31 10 48 10s33 -4 48 -10l18 32c1 2 2 2 4 1s3 -2 2 -4zM118 307c5 0 10 4 10 9s-5 9 -10 9s-9 -4 -9 -9s4 -9 9 -9zM220 307c5 0 9 4 9 9s-4 9 -9 9s-10 -4 -10 -9
+s5 -9 10 -9zM338 238v-103c0 -14 -11 -25 -25 -25s-24 11 -24 25v103c0 14 10 25 24 25s25 -11 25 -25zM279 258v0v-160c0 -10 -5 -18 -13 -23c-4 -2 -8 -3 -13 -3h-18v-55c0 -14 -11 -25 -25 -25c-2 0 -3 1 -5 1c-11 2 -19 12 -19 24v55h-34v-55c0 -12 -8 -22 -19 -24
+c-2 0 -3 -1 -5 -1c-12 0 -22 9 -24 20c0 2 -1 3 -1 5v55h-18c-10 0 -19 5 -23 14c-2 4 -3 8 -3 12v160h220v0zM25 263c14 0 24 -11 24 -25v-103v-5c-2 -11 -12 -20 -24 -20c-5 0 -10 1 -14 4c-7 4 -11 12 -11 21v103c0 14 11 25 25 25z" />
+ <glyph glyph-name="uniF1B8" unicode="&#xf1b8;" horiz-adv-x="352"
+d="M340 259c-69 -38 -58 -137 12 -163c-10 -21 -15 -30 -27 -49c-17 -26 -41 -60 -71 -60c-27 0 -35 18 -71 18s-43 -18 -70 -18c-30 0 -54 30 -71 56c-48 74 -53 160 -23 206c21 33 55 52 86 52c32 0 52 -18 78 -18s41 18 78 18c28 0 58 -16 79 -42zM233 330
+c-14 -18 -39 -33 -63 -32c-4 24 7 48 21 65c15 18 40 32 62 34c4 -25 -7 -50 -20 -67z" />
+ <glyph glyph-name="uniF1B9" unicode="&#xf1b9;" horiz-adv-x="365"
+d="M255 160c6 0 11 -1 15 -5s6 -11 6 -14h-45c2 6 7 19 24 19zM140 136c1 0 14 0 14 -18c0 -15 -9 -18 -16 -18h-41v36h43v0zM331 376c16 0 29 -10 34 -24v-320c-4 -12 -14 -21 -26 -24h-312c-13 3 -23 13 -27 25v318c4 15 18 25 34 25h297zM220 220v-19c0 -1 1 -2 2 -2h64
+c1 0 3 1 3 2v19c0 1 -2 3 -3 3h-64c-1 0 -2 -2 -2 -3zM193 115c0 1 0 20 -11 32c-3 3 -6 6 -10 7c7 4 15 12 15 29c0 27 -17 43 -46 43h-80c-1 0 -3 -1 -3 -2v-155c0 -1 2 -2 3 -2h81c3 0 15 0 27 6c11 6 24 18 24 42zM312 117c0 1 4 33 -14 53c-10 11 -24 17 -42 17
+c-32 0 -48 -17 -55 -31c-8 -15 -7 -31 -7 -31c0 -1 -2 -26 15 -44c11 -12 26 -18 46 -18v0h3c9 0 53 2 53 44c0 1 -1 3 -2 3h-28c-1 0 -2 0 -2 -1c-1 -1 0 -1 0 -2c0 0 0 -4 -4 -8s-10 -6 -19 -6v0c-2 0 -9 1 -14 4c-6 4 -9 10 -10 18h77c1 0 3 1 3 2zM148 181
+c0 -15 -5 -16 -11 -16h-40v30h37h6s8 -1 8 -14z" />
+ <glyph glyph-name="uniF1BA" unicode="&#xf1ba;" horiz-adv-x="388"
+d="M95 160c0 46 34 69 100 69s99 -23 99 -69s-33 -70 -99 -70s-100 24 -100 70zM333 252c42 -29 60 -64 54 -105c0 -16 -5 -31 -15 -45s-23 -26 -40 -36c-20 -12 -40 -20 -61 -25c-24 -6 -49 -9 -77 -9c-29 0 -55 3 -79 9c-37 14 -66 30 -86 50s-29 47 -29 82v179h58v-99
+c38 26 87 40 149 39c49 -3 91 -16 126 -40zM211 64c32 1 60 12 84 34s35 43 33 66c-1 14 -6 27 -13 38s-16 20 -26 27s-21 12 -33 17s-24 7 -34 9s-20 2 -28 2c-44 -2 -78 -13 -101 -33s-33 -42 -31 -66s12 -43 28 -58s34 -25 54 -30s43 -7 67 -6z" />
+ <glyph glyph-name="uniF1BB" unicode="&#xf1bb;"
+d="M308 376c33 0 61 -28 61 -61v-246c0 -33 -28 -61 -61 -61h-247c-33 0 -61 28 -61 61v246c0 33 28 61 61 61h247zM296 151v58v3l-2 4l-3 2c-4 3 -25 0 -31 5c-4 4 -5 11 -6 20c-2 17 -3 18 -6 24c-10 21 -37 37 -55 39h-50c-39 0 -72 -33 -72 -72v-83c0 -39 33 -71 72 -71
+h82c39 0 71 32 71 71zM144 220c-8 0 -14 7 -14 14s6 13 14 13h39c8 0 14 -6 14 -13s-6 -14 -14 -14h-39zM224 166c7 0 14 -7 14 -14s-7 -13 -14 -13h-80c-8 0 -14 6 -14 13s6 14 14 14h80z" />
+ <glyph glyph-name="uniF1BC" unicode="&#xf1bc;" horiz-adv-x="348"
+d="M174 192h174v-174h-174v174h-174v174h174v-174z" />
+ <glyph glyph-name="uniF1BD" unicode="&#xf1bd;"
+d="M270 254h31v-57v-71h-28l-50 78l2 -78h-32v84v44h1h4h23l3 -5l47 -76zM333 376c20 0 36 -16 36 -36v-131l-63 50v0h-5h-31h-5v-5v-29l-39 31v1l-2 2h-3h-28h-5v-5v-40l-13 11c-1 3 -4 5 -6 8c-5 7 -11 12 -17 16c-12 7 -23 10 -43 10h-43h-3h-2h-5v-2v-10v-124l143 -115
+h-163c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM137 251v0c1 0 4 -1 5 -2v0v0c1 -1 3 -1 4 -2s3 -1 4 -2s3 -2 4 -3c1 0 0 -1 1 -1l2 -2l2 -2l1 -1l2 -2v0v0c1 -1 2 -3 3 -4c8 -11 12 -24 12 -40c0 -39 -24 -64 -60 -64h-51v123v5h20h5h18h3c11 0 18 -1 25 -3z
+M144 189c0 23 -11 36 -31 36h-14v-70h14c20 0 31 12 31 34z" />
+ <glyph glyph-name="uniF1BE" unicode="&#xf1be;"
+d="M166 219c9 -19 45 -93 45 -93l129 35v-118c0 -1 -1 -1 -2 -2s-2 -2 -3 -2h-303c-1 0 -2 1 -3 2s-1 1 -1 2v31l169 48l-48 101c82 18 123 11 165 -23c5 -5 3 -8 0 -9l-67 -16l-25 50c-19 3 -46 -2 -56 -6zM335 348c1 0 2 -1 3 -1c1 -1 2 -2 2 -3v-105l-1 1
+c-87 38 -186 21 -206 15c0 1 -15 33 -15 33h-56l20 -46c-23 -7 -48 -25 -54 -30v132c0 1 1 2 2 3c1 0 1 1 2 1h303zM68 131c-13 -3 -12 6 -12 6c-3 55 33 71 41 73l31 -63s-47 -13 -60 -16zM338 376c17 0 31 -14 31 -31v-306c0 -17 -14 -31 -31 -31h-307
+c-17 0 -31 14 -31 31v306c0 17 14 31 31 31h307zM350 43v301c0 8 -7 14 -15 14h-303c-8 0 -14 -6 -14 -14v-301c0 -8 6 -14 14 -14h303c8 0 15 6 15 14z" />
+ <glyph glyph-name="uniF1BF" unicode="&#xf1bf;" horiz-adv-x="436"
+d="M436 253v-173c0 -4 -1 -6 -6 -6h-106c-4 0 -5 1 -5 5v23c0 4 1 5 5 5h62c4 0 5 1 5 5v16h-5h-62c-4 0 -5 2 -5 6v120c0 4 1 5 5 5h107h4c0 -2 1 -4 1 -6zM387 161c3 0 4 2 4 5v49v11h-25c-1 0 -2 -3 -2 -4v-57c0 -3 1 -4 4 -4h19zM300 259c4 0 5 -1 5 -5v-175v-5h-5h-106
+c-4 0 -5 1 -5 5v28h5h62c4 0 5 1 5 5v11s-1 6 -6 6c-20 0 -40 -1 -61 -1c-4 0 -5 2 -5 6v120c0 4 1 5 5 5h106zM261 164v59c0 1 -2 3 -3 3h-25c0 -21 1 -41 1 -62c0 -1 1 -3 2 -3h22c1 0 3 2 3 3zM72 305v5h44v-193h-4h-107c-4 0 -5 1 -5 5v132c0 4 1 5 5 5h61c7 0 6 -1 6 6
+v40zM67 150c4 0 5 1 5 5v66v5h-27v-74c0 -1 2 -2 3 -2h19zM171 259c3 0 4 0 4 -3v-137v-2h-26h-14c-4 0 -4 1 -4 5v94v38c0 4 0 5 4 5h36zM134 276c-1 0 -3 2 -3 3v31h44v-17v-13c0 -3 0 -4 -3 -4h-38z" />
+ <glyph glyph-name="uniF1C0" unicode="&#xf1c0;" horiz-adv-x="371"
+d="M186 378c102 0 185 -84 185 -186s-83 -186 -185 -186s-186 84 -186 186s84 186 186 186zM308 292c-3 -5 -29 -39 -88 -63c4 -8 7 -14 10 -22c1 -3 3 -6 4 -9c53 7 105 -4 110 -5c0 37 -14 72 -36 99zM186 350c-13 0 -26 -1 -38 -4c4 -6 34 -45 60 -93c56 21 80 53 83 57
+c-28 25 -65 40 -105 40zM118 335c-44 -21 -78 -62 -88 -111c7 0 73 0 147 20c-26 47 -55 85 -59 91zM27 192c0 -41 16 -78 41 -106c4 6 47 78 129 104c2 1 4 1 6 2c-4 9 -8 18 -13 27c-79 -24 -156 -22 -163 -22v-5zM186 33c22 0 42 5 61 13c-2 14 -11 62 -33 120h-1
+c-89 -31 -122 -93 -125 -99c27 -21 61 -34 98 -34zM274 60c36 24 61 63 68 107c-5 2 -49 14 -99 6c21 -57 29 -103 31 -113z" />
+ <glyph glyph-name="uniF1C1" unicode="&#xf1c1;" horiz-adv-x="384"
+d="M144 143h240l-67 -115h-240zM376 149l-132 1l-121 208l133 -1zM120 349l66 -115l-120 -208l-66 115z" />
+ <glyph glyph-name="uniF1C2" unicode="&#xf1c2;" horiz-adv-x="396"
+d="M117 376l81 -68l-117 -72l-81 64zM0 171l81 65l117 -73l-81 -68zM198 163l118 73l80 -65l-116 -76zM396 300l-80 -64l-118 72l82 68zM198 148l82 -68l35 23v-25l-117 -70l-116 70v25l35 -23z" />
+ <glyph glyph-name="uniF1C3" unicode="&#xf1c3;" horiz-adv-x="335"
+d="M33 315c-9 0 -17 -2 -23 -5l-4 -2l1 1l73 72v0l-1 -2c-3 -5 -5 -12 -5 -19v0c0 -9 1 -42 1 -42c0 -2 -2 -3 -4 -3h-38v0zM325 322c5 -27 12 -135 9 -171c-5 -57 -14 -90 -18 -101c-18 -56 -33 -58 -77 -58c-56 0 -73 8 -73 53c0 49 24 50 63 49c6 0 -1 -5 -1 -15
+s4 -13 -1 -13c-11 0 -27 2 -27 -14c0 -19 10 -19 34 -19c30 0 35 4 35 31c0 45 -13 51 -30 53c-19 2 -38 6 -47 9c-23 8 -22 38 -22 47c0 1 -2 1 -2 0c0 -12 -1 -29 -7 -48c-2 -5 -3 -9 -3 -9c-7 -15 -20 -10 -39 -8s-61 11 -79 19c-8 4 -11 7 -15 16c-11 22 -22 95 -23 105
+c-2 13 -2 20 -2 20c0 8 1 17 6 24c3 3 5 6 10 8s11 4 19 4h38c8 0 15 6 15 14c0 0 -1 9 -1 18v24c0 8 2 13 5 17c4 6 13 11 20 13c9 3 45 4 68 -5c9 -4 16 -13 18 -24c13 0 36 0 55 -2c24 -3 42 -7 51 -10s18 -11 21 -27zM249 203c10 0 19 -3 27 -6c0 11 -2 28 -20 29
+c-16 1 -21 -13 -22 -24c5 1 10 1 15 1z" />
+ <glyph glyph-name="uniF1C4" unicode="&#xf1c4;"
+d="M348 376c11 0 21 -9 21 -20v-328c0 -11 -10 -20 -21 -20h-94v142h48l7 56h-55v36c0 16 5 27 28 27h29v49c-5 1 -23 3 -43 3c-42 0 -71 -26 -71 -74v-41h-48v-56h48v-142h-177c-11 0 -20 9 -20 20v328c0 11 9 20 20 20h328z" />
+ <glyph glyph-name="uniF1C5" unicode="&#xf1c5;"
+d="M333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM110 133c33 0 60 27 60 60s-27 60 -60 60s-60 -27 -60 -60s27 -60 60 -60zM261 133c33 0 60 27 60 60s-27 60 -60 60s-59 -27 -59 -60s26 -60 59 -60z" />
+ <glyph glyph-name="uniF1C6" unicode="&#xf1c6;" horiz-adv-x="350"
+d="M350 -18h-65v1h-92v66l73 36l-9 18l-64 -33v25l43 22l-10 18l-33 -18v43h-46v-67l-33 23l-11 -16l44 -31v-73v-13h-147l175 419z" />
+ <glyph glyph-name="uniF1C7" unicode="&#xf1c7;" horiz-adv-x="415"
+d="M137 239l67 -67l155 154c3 3 6 4 10 4s6 -1 9 -4l33 -32c5 -5 5 -14 0 -19l-197 -197c-3 -3 -6 -4 -10 -4v0v0h-1c-3 0 -6 2 -8 4l-110 110c-5 5 -5 14 0 19l33 32c3 3 5 4 9 4s7 -1 10 -4zM399 227v-1c19 -19 19 -49 0 -68l-158 -159c-19 -19 -50 -19 -69 0l-158 159
+c-19 19 -19 49 0 68l158 159c19 19 50 19 69 0l72 -72l-108 -107l-50 50c-7 7 -17 12 -27 12s-20 -5 -27 -12l-32 -32c-7 -7 -11 -17 -11 -27s4 -20 11 -27l109 -109c5 -5 11 -8 18 -10l2 -1h7c10 0 20 4 27 11z" />
+ <glyph glyph-name="uniF1C8" unicode="&#xf1c8;"
+d="M333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM215 350c-55 0 -99 -44 -99 -99c0 -36 20 -68 49 -85c14 28 43 47 77 47c20 0 39 -7 54 -19c11 16 18 36 18 57c0 55 -44 99 -99 99zM30 208
+c0 -41 22 -77 54 -98c9 22 31 36 56 36c6 0 11 0 17 -2c1 4 3 7 4 11c-33 19 -56 55 -56 96c0 28 11 53 28 72c-58 -7 -103 -55 -103 -115zM140 33c29 0 52 23 52 52s-23 52 -52 52s-52 -23 -52 -52s23 -52 52 -52zM242 50c42 0 77 34 77 76s-35 77 -77 77
+c-38 0 -69 -27 -75 -63c20 -10 34 -31 34 -55c0 -7 -2 -14 -4 -21c13 -9 28 -14 45 -14z" />
+ <glyph glyph-name="uniF1C9" unicode="&#xf1c9;" horiz-adv-x="399"
+d="M200 387c110 0 199 -90 199 -200c0 -88 -57 -163 -136 -189c-10 -2 -14 4 -14 9v55c0 19 -6 31 -13 37c44 5 91 22 91 99c0 22 -7 39 -20 53c2 5 9 25 -2 53c0 0 -17 5 -55 -21c-16 4 -33 7 -50 7s-34 -3 -50 -7c-38 26 -55 21 -55 21c-11 -28 -4 -48 -2 -53
+c-13 -14 -21 -31 -21 -53c0 -77 47 -94 91 -99c-6 -5 -10 -14 -12 -27c-11 -5 -41 -14 -59 17c0 0 -10 19 -30 20c0 0 -20 0 -2 -12c0 0 14 -6 23 -29c0 0 11 -39 67 -27v-34s-3 -11 -13 -9c-79 26 -137 101 -137 189c0 110 90 200 200 200z" />
+ <glyph glyph-name="uniF1CA" unicode="&#xf1ca;"
+d="M57 184c-9 7 -16 16 -22 26c-12 22 -17 42 -17 62c0 15 4 30 12 42c10 12 22 18 37 18c11 0 21 -4 30 -10c9 -7 16 -15 21 -26c11 -22 17 -45 17 -67c0 -5 0 -11 -1 -18s-4 -15 -9 -22c-10 -10 -22 -15 -37 -16c-12 0 -22 4 -31 11zM91 100c-13 0 -29 -2 -49 -5
+c-15 -3 -28 -7 -42 -13v99c15 -15 36 -23 62 -23c6 0 12 0 18 1l-3 -9s-2 -8 -2 -13c0 -8 1 -15 5 -21c3 -6 7 -11 11 -16zM106 84c21 -14 36 -27 46 -37c9 -10 14 -23 14 -37v-1h-140c-14 0 -26 12 -26 26v15c3 4 6 8 9 11c5 4 11 8 16 10s9 4 12 5c12 4 24 5 35 7
+c12 1 19 1 22 1h12zM343 375c14 0 26 -12 26 -26v-28v-286c0 -14 -12 -26 -26 -26h-145c2 7 3 15 3 23c0 19 -5 34 -13 46c-9 12 -18 22 -30 32l-19 15c-3 3 -6 6 -9 10s-5 8 -5 14s2 11 5 16c3 4 6 9 9 12c6 5 12 9 17 14s9 10 13 16c8 12 13 28 13 48c0 11 -2 21 -4 29
+c-3 8 -6 15 -10 21s-8 12 -12 16s-9 7 -12 9h34l35 20h-111c-15 0 -31 -2 -48 -5c-17 -4 -33 -12 -49 -25c-2 -2 -3 -4 -5 -6v7v28c0 14 12 26 26 26h65h93h93h66zM363 261v29h-58v58h-28v-58h-59v-29h59v-58h28v58h58z" />
+ <glyph glyph-name="uniF1CB" unicode="&#xf1cb;"
+d="M333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM200 178l70 119h-31l-29 -57c-8 -16 -15 -30 -21 -43h-1c-6 14 -12 27 -20 43l-30 57h-30l65 -119v-88h27v88z" />
+ <glyph glyph-name="uniF1CC" unicode="&#xf1cc;" horiz-adv-x="476"
+d="M459 222c13 -16 18 -36 16 -57c-2 -24 -12 -47 -30 -62c-17 -14 -41 -23 -71 -23c-22 0 -45 4 -64 15v-10h-310v76h15v66h-15v77h116v-55c19 7 45 7 62 -6v9h29v40h88v-31l8 43h160c-1 -27 -3 -55 -4 -82zM227 272v-32h48v32h-48zM195 105v0v36h-16v54c0 11 -5 39 -37 39
+c-22 0 -36 -12 -46 -28v78h-76v-37h15v-106h-15v-36h83v36h-7v23c0 34 24 42 24 21v-44h-8v-36h83zM290 105v36h-15v90h-76v-36h15v-54h-15v-36h91zM374 100c53 0 81 33 81 67c2 45 -26 62 -60 62c-13 0 -26 -4 -38 -9l2 16h81l2 48h-122l-17 -92l44 -6c6 7 13 9 18 9
+c13 0 19 -14 18 -28c-1 -15 -10 -29 -23 -29c-8 0 -18 4 -13 17c4 19 -7 28 -24 28c-26 0 -35 -31 -24 -51c10 -19 40 -32 75 -32z" />
+ <glyph glyph-name="uniF1CD" unicode="&#xf1cd;"
+d="M276 216c0 14 -3 28 -9 40h102v-215c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v215h102c-6 -12 -10 -26 -10 -40c0 -51 41 -92 92 -92s92 41 92 92zM333 379c20 0 36 -16 36 -36v-72h-111c-17 22 -44 37 -74 37s-56 -15 -73 -37h-111v72c0 20 16 36 36 36h297z
+M29 288v0v72c-8 -3 -13 -11 -13 -20v-52h13zM51 288v74h-12v-74h12zM73 288v74h-12v-74h12zM95 340v22h-13v-74h13v22v30zM350 310v30c0 12 -10 22 -22 22h-35c-12 0 -22 -10 -22 -22v-30c0 -12 10 -22 22 -22h35c12 0 22 10 22 22zM184 135c-45 0 -81 36 -81 81
+s36 81 81 81s81 -36 81 -81s-36 -81 -81 -81zM184 280c-36 0 -64 -28 -64 -64s28 -65 64 -65s65 29 65 65s-29 64 -65 64z" />
+ <glyph glyph-name="uniF1CE" unicode="&#xf1ce;" horiz-adv-x="357"
+d="M340 98c29 -24 22 -67 -13 -81c-2 -1 -3 -2 -5 -3h-24c-17 7 -31 18 -35 38c-31 -7 -59 -1 -81 22c12 12 23 22 33 32c9 -3 18 -7 27 -7c12 0 21 8 25 19c4 12 1 22 -8 31c-24 24 -46 47 -70 71c-2 2 -6 4 -8 6c12 13 23 25 36 39c12 -13 22 -25 33 -36
+c12 -12 22 -25 35 -36c25 -23 38 -49 32 -82c8 -4 17 -8 23 -13zM212 186c14 -12 25 -23 36 -33c-28 -28 -54 -56 -80 -82c-17 -17 -39 -24 -63 -21c-8 1 -11 -1 -14 -8c-5 -15 -17 -22 -31 -28h-22c-21 7 -33 21 -38 42v10c4 21 15 36 37 42c-5 30 1 56 23 77l35 -35
+c-1 -1 -3 -3 -4 -5c-9 -13 -8 -29 4 -39s27 -11 39 1c24 23 48 47 72 71c3 3 5 6 6 8zM107 228c29 29 56 59 85 87c17 16 40 20 63 15h6c4 15 11 29 27 35c10 3 21 5 31 4c20 -2 36 -21 38 -43c2 -23 -10 -39 -41 -52c6 -30 -1 -56 -23 -78l-34 34c3 5 7 11 9 17
+c3 12 -3 25 -14 31c-11 7 -24 6 -35 -4c-12 -11 -23 -23 -35 -35c-15 -14 -29 -29 -44 -44zM38 275c-28 10 -41 30 -35 60c4 19 22 33 41 35c25 2 39 -9 53 -40c29 5 53 -2 73 -22l-35 -35c0 0 -1 2 -3 3c-13 10 -29 8 -40 -4c-10 -12 -9 -27 2 -39c23 -24 47 -48 70 -72
+c3 -3 4 -5 7 -8c-12 -11 -22 -22 -35 -35c-11 12 -23 24 -34 36c-12 12 -23 24 -35 35c-25 23 -37 51 -29 86z" />
+ <glyph glyph-name="uniF1CF" unicode="&#xf1cf;" horiz-adv-x="417"
+d="M354 210c41 -10 63 -29 63 -68c0 -48 -40 -66 -99 -66c-83 0 -112 38 -127 84l-15 48c-11 35 -25 62 -67 62c-29 0 -59 -21 -59 -80c0 -46 24 -75 57 -75c37 0 62 28 62 28l15 -42s-26 -25 -80 -25c-67 0 -104 39 -104 112c0 75 37 120 107 120c64 0 96 -23 116 -85
+l16 -48c11 -35 32 -60 80 -60c32 0 49 7 49 25c0 14 -8 23 -32 29l-33 8c-40 10 -55 31 -55 63c0 52 42 68 85 68c49 0 78 -18 82 -61l-48 -6c-2 21 -14 30 -37 30c-21 0 -34 -10 -34 -26c0 -14 6 -23 27 -28z" />
+ <glyph glyph-name="uniF1D0" unicode="&#xf1d0;"
+d="M341 376c15 0 28 -11 28 -26v-316c0 -15 -13 -26 -28 -26h-314c-15 0 -27 11 -27 26v316c0 15 12 26 27 26h314zM109 62v176h-54v-176h54zM82 262c17 0 32 14 32 32c0 17 -15 32 -32 32c-18 0 -32 -15 -32 -32c0 -18 14 -32 32 -32zM314 62v0v97c0 47 -10 83 -65 83
+c-27 0 -45 -14 -52 -28h-1v24h-52v-176h54v87c0 23 5 45 33 45s28 -26 28 -46v-86h55z" />
+ <glyph glyph-name="uniF1D1" unicode="&#xf1d1;"
+d="M346 376c13 -5 23 -18 23 -33v-299c0 -20 -16 -36 -36 -36h-299c-16 0 -29 11 -34 25v321c3 10 10 18 20 22h326zM276 241v22h-68l-22 -84h-1l-22 84h-68v-22h7c3 0 6 -4 6 -6v-89c0 -2 -3 -6 -6 -6h-7v-21h54v21h-13v94v0l32 -115h24l32 115v0v-94h-12v-21h64v21h-7
+c-3 0 -6 4 -6 6v89c0 2 3 6 6 6h7z" />
+ <glyph glyph-name="uniF1D2" unicode="&#xf1d2;" horiz-adv-x="454"
+d="M375 187c-40 0 -73 32 -73 72s33 72 73 72s72 -32 72 -72s-32 -72 -72 -72zM147 238c0 43 22 65 65 65s65 -22 65 -65s-22 -65 -65 -65s-65 22 -65 65zM64 161c-32 0 -58 27 -58 59s26 58 58 58s59 -26 59 -58s-27 -59 -59 -59zM64 148c37 0 65 -32 65 -66v-23
+c0 -3 -3 -6 -6 -6h-2h-113h-2c-3 0 -6 3 -6 6v23c0 34 27 66 64 66zM212 159c41 0 71 -37 71 -74v-25c0 -4 -2 -7 -6 -7h-2h-126h-2c-4 0 -7 3 -7 7v25c0 37 31 74 72 74zM375 170c46 0 79 -40 79 -82v-27c0 -4 -3 -8 -7 -8h-3h-139h-2c-4 0 -8 4 -8 8v27c0 42 34 82 80 82z
+" />
+ <glyph glyph-name="uniF1D3" unicode="&#xf1d3;"
+d="M185 272c45 0 82 -37 82 -82s-37 -82 -82 -82s-82 37 -82 82s37 82 82 82zM333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM185 66c69 0 124 55 124 124s-55 124 -124 124s-125 -55 -125 -124
+s56 -124 125 -124z" />
+ <glyph glyph-name="uniF1D4" unicode="&#xf1d4;" horiz-adv-x="348"
+d="M348 235c0 -83 -67 -136 -171 -137v-23c0 -28 -16 -54 -41 -65c-6 -3 -17 -5 -28 -5c-10 0 -22 2 -35 8v65c21 -15 41 -7 41 11v181h63v-113c30 0 112 8 112 78c0 62 -60 85 -115 85c-57 0 -114 -27 -114 -85c0 -18 9 -45 18 -53l-41 -43c-24 22 -37 66 -37 96
+c0 85 72 144 174 144c104 0 174 -58 174 -144z" />
+ <glyph glyph-name="uniF1D5" unicode="&#xf1d5;" horiz-adv-x="399"
+d="M282 373v0v-133c-7 6 -147 133 -152 138c23 8 46 13 70 13c29 0 56 -6 82 -18zM97 21v0c-37 23 -67 57 -83 97c2 2 76 69 83 75v-172zM0 192v0c0 75 42 143 109 177c2 -2 72 -65 75 -68c-3 -3 -172 -156 -177 -161c-5 17 -7 35 -7 52zM118 105v0h261
+c-31 -63 -92 -106 -161 -112h-37c-22 2 -43 8 -63 17v95zM303 362v0c59 -36 96 -101 96 -170c0 -22 -4 -45 -11 -66h-85v236z" />
+ <glyph glyph-name="uniF1D6" unicode="&#xf1d6;" horiz-adv-x="399"
+d="M200 392c110 0 199 -90 199 -200s-89 -200 -199 -200c-20 0 -39 3 -57 8c8 12 16 28 20 43c2 9 14 55 14 55c7 -13 27 -25 49 -25c64 0 108 59 108 137c0 59 -51 115 -127 115c-95 0 -142 -68 -142 -125c0 -34 13 -66 41 -77c5 -2 9 0 10 5c1 4 3 13 4 17c1 5 1 7 -3 11
+c-8 9 -13 22 -13 39c0 50 37 95 98 95c54 0 83 -32 83 -76c0 -58 -25 -106 -63 -106c-21 0 -37 17 -32 38c6 25 18 53 18 71c0 16 -9 30 -27 30c-21 0 -39 -22 -39 -52c0 -19 7 -31 7 -31s-22 -93 -26 -109c-4 -15 -4 -32 -3 -46c-70 31 -120 101 -120 183
+c0 110 90 200 200 200z" />
+ <glyph glyph-name="uniF1D7" unicode="&#xf1d7;" horiz-adv-x="435"
+d="M424 291c27 -2 4 -60 -52 -75c1 -7 1 -15 1 -23v-1c0 -99 -80 -179 -187 -179s-186 79 -186 178v1c0 99 80 179 187 179c19 0 36 -3 53 -7v-105c-3 2 -6 4 -10 5c-46 16 -96 -7 -119 -45l-1 -1c-24 -39 -12 -83 33 -98c46 -16 95 7 119 45l1 1c8 13 12 27 12 40v0v145
+c3 -1 6 -3 8 -4s4 -3 6 -4c24 -15 85 -53 135 -52z" />
+ <glyph glyph-name="uniF1D8" unicode="&#xf1d8;" horiz-adv-x="458"
+d="M458 197c0 -18 -10 -35 -25 -45c1 -5 2 -10 2 -15c0 -76 -92 -138 -206 -138s-206 62 -206 138c0 5 0 11 1 16c-15 10 -24 26 -24 44c0 29 24 53 53 53c13 0 24 -5 34 -13c36 23 83 37 136 38l37 105l89 -22c6 16 22 27 40 27c24 0 43 -19 43 -43s-19 -43 -43 -43
+s-43 19 -43 43l-75 18l-31 -85c50 -2 97 -16 131 -38h1c10 8 21 13 34 13c29 0 52 -24 52 -53zM299 129c18 0 32 14 32 32s-14 33 -32 33s-33 -15 -33 -33s15 -32 33 -32zM305 73c3 3 3 9 0 12s-9 3 -12 0c0 0 -20 -20 -65 -20c-44 0 -62 19 -62 20c-3 3 -9 4 -12 1
+s-4 -9 -1 -12c1 -1 22 -25 75 -25s76 23 77 24zM131 161c0 -18 14 -32 32 -32s33 14 33 32s-15 33 -33 33s-32 -15 -32 -33z" />
+ <glyph glyph-name="uniF1D9" unicode="&#xf1d9;" horiz-adv-x="390"
+d="M103 162c0 0 -20 3 -44 14l275 3c-25 -12 -48 -16 -48 -16h-74s-6 -1 -8 -4s-2 -9 -2 -9v-9c-11 8 -18 21 -24 21h-75zM25 166c-2 1 -4 2 -5 4c2 -1 3 -2 5 -4zM39 368v-182c-11 6 -17 11 -21 13v180c0 6 4 10 10 10h332c6 0 10 -4 10 -10v-180c-4 -3 -9 -7 -20 -13v182
+h-311zM388 202c3 -2 1 -6 0 -8s-7 -17 -33 -34s-51 -27 -51 -27s16 -51 1 -89s-48 -48 -64 -48s-39 12 -39 34v77c6 -1 13 -2 21 -2c18 0 31 8 42 19s19 32 10 35s-12 -3 -20 -14c-7 -9 -22 -17 -44 -9c-3 1 -6 3 -9 5v9s0 6 2 9s7 4 8 4h74s23 3 48 15c1 1 3 1 4 2
+c4 2 9 4 12 6c11 6 16 10 20 13l6 3c6 2 9 2 12 0zM265 124c-11 -11 -24 -19 -42 -19c-8 0 -15 1 -21 2c-8 2 -14 4 -14 4v-83s-24 -33 -40 -33s-48 9 -63 47s1 89 1 89s-25 11 -51 28c-4 2 -7 5 -10 7c-2 2 -3 3 -5 4c-14 12 -19 21 -19 23c-1 2 -3 6 0 8s7 2 13 0
+c1 -1 2 -1 4 -2c4 -2 10 -7 21 -13c4 -2 7 -5 12 -7c2 -1 6 -2 8 -3c24 -11 44 -14 44 -14h75c6 0 13 -13 24 -21c3 -2 6 -4 9 -5c22 -8 37 0 44 9c8 11 11 17 20 14s1 -24 -10 -35zM251 272c26 0 47 -20 47 -46s-21 -47 -47 -47s-46 21 -46 47s20 46 46 46zM141 272
+c26 0 47 -20 47 -46s-21 -47 -47 -47s-46 21 -46 47s20 46 46 46z" />
+ <glyph glyph-name="uniF1DA" unicode="&#xf1da;" horiz-adv-x="394"
+d="M383 150c7 -15 11 -32 11 -49c0 -60 -49 -109 -109 -109c-19 0 -36 5 -51 13c-11 -2 -23 -3 -35 -3c-104 0 -188 84 -188 188c0 13 2 26 4 38c-10 16 -15 35 -15 55c0 60 49 109 109 109c21 0 41 -6 58 -17c10 2 21 3 32 3c104 0 188 -84 188 -188c0 -14 -1 -27 -4 -40z
+M296 100c9 12 13 27 13 42c0 13 -3 24 -8 33s-12 16 -21 22s-19 11 -32 15c-12 4 -27 8 -42 11c-12 3 -21 5 -26 6s-10 4 -15 6s-8 6 -11 9s-4 7 -4 11c0 7 4 13 12 18s19 8 32 8c14 0 26 -2 32 -7c7 -5 12 -12 17 -21c4 -7 7 -12 11 -15s9 -5 16 -5c8 0 14 3 19 8
+s8 11 8 18s-2 14 -6 21s-10 15 -18 21s-19 11 -31 15s-27 6 -44 6c-21 0 -39 -2 -55 -8s-29 -15 -37 -26s-12 -24 -12 -38c0 -15 4 -28 12 -38s19 -17 32 -23s29 -11 49 -15c14 -3 26 -5 35 -8c8 -3 15 -7 20 -12s7 -10 7 -17c0 -9 -5 -18 -14 -24c-10 -7 -22 -10 -38 -10
+c-11 0 -20 2 -27 5s-12 7 -16 12s-8 11 -11 19c-3 7 -7 13 -11 17c-5 4 -10 5 -16 5c-8 0 -15 -2 -20 -7s-8 -11 -8 -18c0 -11 4 -22 12 -34c8 -11 18 -20 31 -27c18 -9 41 -14 68 -14c23 0 41 3 58 10s30 17 39 29z" />
+ <glyph glyph-name="uniF1DB" unicode="&#xf1db;" horiz-adv-x="390"
+d="M173 165c98 -37 75 -98 23 -98s-89 32 -89 32l-30 -70c21 -11 43 -19 56 -23l-33 -8c-15 -4 -31 6 -35 21l-64 268c-4 16 6 31 21 35l77 19c-7 -8 -12 -17 -16 -26c0 -1 -1 -1 -1 -2c-1 -2 -1 -4 -2 -6c0 -1 -1 -2 -1 -3c-1 -2 -2 -4 -2 -6v-4c0 -2 -1 -4 -1 -6
+c0 -1 -1 -2 -1 -3v-7v-3v-10s1 -6 1 -8v-1c0 -2 1 -6 2 -8v0c1 -2 1 -5 2 -7c0 -1 1 0 1 -1c1 -2 2 -5 3 -7v-1c1 -2 3 -4 4 -6c0 -1 1 0 1 -1c1 -2 3 -4 5 -6v-1c1 -2 3 -4 5 -6c0 -1 1 0 1 -1l6 -6v-1c2 -2 4 -2 6 -4c1 0 0 -2 1 -2c2 -2 5 -3 7 -5l1 -1
+c15 -11 33 -20 52 -27zM390 97c4 -15 -7 -31 -22 -35l-56 -14c9 14 17 33 18 56c1 29 -10 60 -39 85v0c-2 1 -3 3 -5 4l-1 1c-2 1 -3 3 -5 4l-1 1c-2 1 -4 3 -6 4h-1c-2 1 -4 3 -6 4c-1 0 -1 1 -2 1l-6 3h-1c-2 1 -5 3 -8 4h-2l-6 3c-1 0 -1 1 -2 1l-9 3
+c-100 33 -71 88 -20 85c54 -3 74 -25 74 -25l24 67c-2 1 -5 2 -7 3c-1 0 -1 1 -2 1c-2 1 -3 1 -5 2c-1 0 -1 1 -2 1c-2 1 -5 2 -7 3c-1 0 -1 1 -2 1c-1 1 -3 1 -4 2h-3c-1 1 -3 2 -4 2s-1 1 -2 1c-2 1 -3 0 -5 1c-1 0 -1 1 -2 1s-3 1 -4 1h-2c-2 0 -3 2 -5 2
+c-7 2 -13 2 -17 3l56 13c16 4 30 -5 34 -21z" />
+ <glyph glyph-name="uniF1DC" unicode="&#xf1dc;" horiz-adv-x="379"
+d="M302 224c4 1 8 4 12 4c7 0 14 0 20 -3c10 -5 11 -16 2 -22c-7 -5 -16 -8 -24 -11c-18 -7 -21 -13 -12 -30c15 -29 37 -51 70 -59c3 -1 9 -4 9 -6c0 -5 -3 -11 -6 -13c-11 -5 -23 -9 -35 -12c-7 -2 -10 -4 -12 -11c-3 -15 -6 -17 -20 -14c-23 5 -44 0 -63 -14
+c-39 -28 -69 -27 -108 1c-19 14 -38 18 -61 13c-15 -3 -17 -1 -21 14c-1 6 -4 10 -11 11c-11 2 -24 6 -34 11c-4 2 -7 8 -8 13c0 2 7 7 11 8c36 10 57 34 72 66c3 8 0 13 -6 17c-6 3 -12 4 -18 7c-4 2 -8 4 -11 6c-7 4 -13 10 -9 19c3 8 14 12 23 9c5 -2 10 -4 15 -5
+c7 -1 10 1 10 9c-1 18 -1 36 0 54c3 38 26 65 60 78c50 19 109 4 136 -44c9 -17 10 -35 11 -54c-1 -12 -1 -23 -2 -35c-1 -8 4 -9 10 -7z" />
+ <glyph glyph-name="uniF1DD" unicode="&#xf1dd;" horiz-adv-x="399"
+d="M200 392c110 0 199 -90 199 -200c0 -71 -37 -133 -92 -168c-8 17 -19 32 -33 45c-29 26 -66 41 -105 41c-25 0 -48 -6 -70 -17c-18 -9 -34 -21 -47 -36c-33 36 -52 83 -52 135c0 110 90 200 200 200zM294 114c4 6 3 15 -3 19c-36 25 -77 38 -121 38c-25 0 -51 -4 -74 -13
+c-7 -3 -11 -10 -8 -17s11 -11 18 -8c20 8 42 11 64 11c38 0 75 -11 106 -33c2 -2 4 -2 7 -2c4 0 8 1 11 5zM323 176c4 7 3 16 -4 20c-45 28 -96 43 -149 43c-29 0 -58 -4 -86 -13c-8 -3 -13 -11 -10 -19s11 -13 19 -10c25 8 51 12 77 12c47 0 93 -13 133 -38c2 -2 5 -2 8 -2
+c5 0 9 2 12 7zM338 229c6 0 11 3 14 8c5 8 2 18 -6 23c-53 31 -114 48 -176 48c-34 0 -67 -5 -99 -14c-9 -3 -15 -12 -12 -21s12 -14 21 -11c29 9 60 13 90 13c56 0 112 -16 160 -44c3 -2 5 -2 8 -2zM225 16c6 -6 11 -13 15 -20c-13 -3 -26 -4 -40 -4c-32 0 -63 7 -90 21
+c6 6 13 12 21 16c12 6 25 9 38 9c21 0 41 -8 56 -22z" />
+ <glyph glyph-name="uniF1DE" unicode="&#xf1de;" horiz-adv-x="425"
+d="M420 109c6 -21 7 -44 0 -65c-15 -44 -45 -72 -92 -78c-30 -4 -56 5 -77 28c-17 19 -26 41 -28 66c0 4 0 8 -1 12c-4 21 -18 30 -39 27c-24 -3 -47 -8 -71 -7c-13 0 -26 4 -38 10c-19 10 -28 27 -31 48s0 42 4 63c2 8 3 16 4 25c1 17 -8 29 -21 39c1 1 3 0 4 0
+c23 -3 39 -23 38 -46c-1 -22 -2 -43 3 -65c1 -4 2 -8 3 -11c4 -12 15 -14 26 -15c20 -1 40 3 60 6c10 2 18 3 29 5c-9 6 -17 11 -25 16c-40 24 -65 57 -73 104c-1 9 -4 17 -6 26c-5 26 -21 41 -47 45c-13 2 -25 1 -38 -1c-1 0 -3 -1 -4 0c-1 2 1 2 2 3c24 12 49 15 75 8
+c14 -4 22 -15 28 -27c6 -13 9 -27 13 -41c1 -4 3 -8 4 -12c6 -20 19 -35 38 -44s39 -15 60 -18c2 0 4 -2 4 2c-1 11 -1 22 -2 33c-2 21 -14 35 -32 45c-13 8 -26 17 -38 27c-30 27 -42 60 -35 100v2h3c-1 -24 5 -45 23 -63c10 -10 22 -15 34 -21c32 -14 58 -35 77 -64
+c9 -14 13 -29 16 -44c0 -1 1 -2 1 -4c7 13 18 23 26 34c14 20 12 37 -4 55c-12 13 -28 21 -44 28c-2 1 -5 2 -7 3c-21 8 -31 25 -29 48c0 3 0 5 2 8c1 -5 2 -9 3 -14c4 -17 13 -27 30 -31c25 -6 50 -16 69 -34c12 -11 20 -23 23 -39c2 -14 0 -26 -6 -38
+c-4 -9 -10 -18 -14 -27c-5 -10 -4 -20 0 -30c3 -6 7 -9 14 -9c41 -2 75 -28 86 -68z" />
+ <glyph glyph-name="uniF1DF" unicode="&#xf1df;" horiz-adv-x="337"
+d="M247 12v144h34v-179h-281v179h33l-2 -144h216zM53 35v36h169v-36h-169zM53 99l4 37l169 -17l-4 -36zM62 173l10 36l164 -46l-10 -36zM93 260l19 31l145 -87l-19 -32zM293 232l-30 -22l-98 138l29 22zM301 234l-28 167l36 6l28 -167z" />
+ <glyph glyph-name="uniF1E0" unicode="&#xf1e0;" horiz-adv-x="497"
+d="M466 238c0 -20 -16 -36 -36 -36s-37 16 -37 36s17 36 37 36s36 -16 36 -36zM429 306c37 0 68 -31 68 -68s-31 -67 -68 -67l-64 -47c-2 -25 -24 -46 -50 -46c-24 0 -44 17 -49 40l-190 76c-8 -4 -17 -7 -26 -7c-28 0 -50 23 -50 51s22 50 50 50c24 0 44 -17 49 -40
+l190 -76c8 4 17 7 26 7h5l42 60c0 37 30 67 67 67zM429 283c-25 0 -45 -20 -45 -45s20 -45 45 -45s45 20 45 45s-20 45 -45 45zM50 275c-20 0 -37 -17 -37 -37s17 -37 37 -37c3 0 5 -1 8 0l-15 7v0c-14 6 -22 23 -16 38s23 21 38 16v0l18 -7c-6 12 -19 20 -33 20zM315 166
+c-3 0 -5 0 -8 -1l15 -6c15 -6 23 -24 17 -39s-24 -22 -39 -16c-6 2 -12 5 -18 7c6 -12 19 -19 33 -19c20 0 37 17 37 37s-17 37 -37 37z" />
+ <glyph glyph-name="uniF1E1" unicode="&#xf1e1;" horiz-adv-x="399"
+d="M357 314c26 -34 42 -76 42 -122c0 -110 -89 -200 -199 -200c-78 0 -145 44 -178 109h87c41 0 70 22 70 58c0 76 -87 45 -87 72c0 13 10 18 29 18h32h29c17 0 36 -4 36 -22v-60c0 -44 35 -66 70 -66c36 0 69 22 69 66v147v0zM200 392c42 0 80 -13 112 -35v-191
+c0 -13 -11 -24 -24 -24v0c-13 0 -24 11 -24 24v57c0 46 -24 65 -54 65h-98c-36 0 -65 -23 -65 -59c0 -18 8 -45 45 -52c30 -5 42 -4 42 -20s-17 -15 -40 -15h-88c-4 16 -6 33 -6 50c0 110 90 200 200 200v0z" />
+ <glyph glyph-name="uniF1E2" unicode="&#xf1e2;" horiz-adv-x="394"
+d="M193 244c-24 -18 -47 -38 -74 -52c-4 -2 -8 -4 -13 -5c-12 -3 -20 -14 -20 -27c0 -12 9 -24 21 -27s25 2 31 13c7 15 20 25 33 34c5 4 7 3 11 -2c4 9 9 18 13 27c1 -1 1 -1 1 -2c-7 -25 -14 -52 -22 -77c-2 -6 -5 -10 -10 -13c-14 -9 -18 -28 -9 -43c9 -14 27 -19 42 -11
+s21 26 14 41c-3 5 -3 11 -2 16c4 14 6 28 14 41c3 6 7 11 13 15c7 4 11 3 16 -3c6 -7 9 -15 8 -25c-1 -13 7 -25 19 -29s25 1 32 11c7 11 7 24 -2 34c-10 12 -21 23 -30 35c-16 21 -17 43 -4 66c7 12 15 25 22 38c6 11 15 21 26 27c10 5 19 6 29 0c6 -4 12 -7 19 -11
+c15 -9 23 -22 23 -39v-168c0 -17 -8 -30 -22 -38c-51 -29 -101 -58 -152 -86c-15 -8 -30 -8 -45 0c-51 29 -102 57 -153 86c-14 8 -22 21 -22 37v170c0 16 7 29 21 37c51 29 103 58 155 87c13 7 28 7 42 0c8 -4 15 -8 23 -12c6 -3 8 -9 9 -16c1 -12 -1 -23 -7 -33
+c-7 -12 -14 -25 -21 -37c-14 -22 -33 -36 -59 -40c-16 -3 -33 -1 -49 1c-12 1 -23 -5 -27 -16s0 -24 10 -30s23 -4 31 5c5 6 13 5 20 6c5 1 10 2 15 2c2 0 3 0 5 1c8 4 16 9 24 13z" />
+ <glyph glyph-name="uniF1E3" unicode="&#xf1e3;"
+d="M333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM270 68v0v44c-14 -9 -28 -14 -42 -14c-8 0 -15 2 -21 6c-5 3 -8 6 -10 11s-2 15 -2 31v71h66v44h-66v70h-40c-2 -14 -4 -27 -9 -36s-11 -16 -19 -23
+s-17 -12 -28 -16v-39h30v-97c0 -13 1 -22 4 -29s8 -13 15 -19s15 -11 25 -14s20 -5 33 -5c11 0 22 1 32 3s20 6 32 12z" />
+ <glyph glyph-name="uniF1E4" unicode="&#xf1e4;" horiz-adv-x="394"
+d="M394 314c-11 -16 -24 -31 -40 -42v-10c0 -107 -81 -230 -230 -230c-46 0 -88 13 -124 36c6 -1 12 -1 19 -1c38 0 73 13 101 35c-35 1 -66 24 -76 56c5 -1 10 -2 15 -2c7 0 15 1 22 3c-37 7 -65 40 -65 79v2c11 -6 23 -11 36 -11c-22 15 -35 40 -35 68c0 15 3 28 10 40
+c40 -49 100 -81 167 -84c-1 6 -2 12 -2 18c0 45 36 81 81 81c23 0 44 -9 59 -25c18 4 35 10 51 19c-6 -19 -18 -34 -35 -44c16 2 31 6 46 12z" />
+ <glyph glyph-name="uniF1E5" unicode="&#xf1e5;"
+d="M333 376c20 0 36 -15 36 -35v-298c0 -20 -16 -35 -36 -35h-297c-20 0 -36 15 -36 35v298c0 20 16 35 36 35h297zM309 259c1 7 2 15 0 22c-1 3 -2 6 -4 8c-9 11 -29 11 -42 9c-11 -2 -48 -17 -60 -55h6c14 0 22 -2 25 -12c1 -4 2 -8 1 -14c-1 -10 -6 -20 -12 -31
+c-7 -12 -19 -37 -35 -20c-2 2 -4 6 -5 6v0c-10 15 -9 42 -12 59c-2 11 -4 26 -8 37c0 1 0 5 -1 5v0c-4 10 -11 17 -18 19c-9 3 -22 -2 -29 -6c-22 -13 -39 -31 -59 -46v-1c5 -1 4 -2 5 -4c2 -3 4 -5 8 -6c13 -2 25 11 34 -3c1 -2 2 -3 3 -5h-1l1 -1v1v-1c3 -7 4 -15 7 -22
+c5 -13 8 -26 12 -41c4 -16 8 -37 17 -52c5 -9 11 -16 19 -19c11 -5 28 2 36 7c23 13 40 32 55 52c35 46 54 99 57 114z" />
+ <glyph glyph-name="uniF1E6" unicode="&#xf1e6;" horiz-adv-x="368"
+d="M368 203h-205v149l205 29v-178zM149 349v-146h-149v125zM0 183h149v-148l-149 22v126zM163 33v150h205v-180z" />
+ <glyph glyph-name="uniF1E7" unicode="&#xf1e7;" horiz-adv-x="399"
+d="M147 277c-131 -136 -103 -210 -103 -210c-27 34 -44 78 -44 125c0 53 21 100 54 136c0 0 34 -15 93 -51zM200 315c-80 58 -130 29 -130 29c35 30 81 48 130 48s94 -18 129 -48c0 0 -49 29 -129 -29v0v0zM199 233c124 -92 145 -179 145 -179c-36 -38 -87 -62 -144 -62
+s-109 24 -145 62c0 0 33 97 144 179zM399 192c0 -47 -16 -91 -43 -125c0 0 27 74 -104 210c59 36 94 51 94 51c33 -36 53 -83 53 -136z" />
+ <glyph glyph-name="uniF1E8" unicode="&#xf1e8;" horiz-adv-x="512"
+d="M460 50l-53 6l6 46l53 -6zM512 328l-50 -202l-39 6l-1 207zM332 292c35 -27 53 -61 53 -103c0 -43 -18 -78 -53 -105c-30 -22 -67 -35 -111 -39h-56c-44 4 -82 17 -111 39c-36 27 -54 62 -54 105c0 42 18 76 54 103c35 27 82 41 139 41c56 0 103 -14 139 -41zM305 224
+l7 10h-48h-50l2 -10l30 -5c-1 -6 -16 -20 -46 -43c-23 28 -39 51 -50 67l35 4l2 8c-16 1 -36 1 -60 0c-34 1 -52 1 -54 0v-10l33 -5c6 -5 18 -17 37 -40c18 -22 27 -36 28 -39l1 -15v-7c0 -12 -1 -20 -2 -21c-2 -2 -6 -2 -15 -3l-17 -1l-2 -10h52h59l1 11l-36 1l-3 22l1 9
+l1 14c2 5 13 16 33 32c19 16 30 24 34 25z" />
+ <glyph glyph-name="uniF1E9" unicode="&#xf1e9;" horiz-adv-x="344"
+d="M212 133c7 7 17 4 17 4l101 -32s14 -2 14 -12c0 -7 -4 -15 -4 -15l-43 -61s-7 -6 -15 -6s-17 12 -17 12l-54 90s-6 13 1 20zM207 179c-5 8 0 17 0 17l57 89s6 12 16 11c9 -1 13 -8 13 -8l48 -57s4 -9 2 -16s-16 -13 -16 -13l-100 -29s-15 -3 -20 6zM159 214
+c-11 -3 -19 6 -19 6l-87 118s-12 14 -6 24c4 7 12 10 12 10l84 31c4 1 8 5 20 -3c8 -5 9 -23 9 -23l1 -143s-2 -17 -14 -20zM139 156c0 -15 -8 -15 -12 -18l-105 -23s-15 -6 -20 2c-3 6 -2 18 -2 18l6 73c0 5 5 9 10 12c6 4 20 -1 20 -1l90 -46s13 -6 13 -17zM165 117
+c8 -4 9 -15 9 -15l-2 -105s1 -14 -8 -17c-6 -2 -15 0 -15 0l-70 23c-5 2 -9 5 -11 12s7 19 7 19l70 78s11 10 20 5z" />
+ <glyph glyph-name="uniF1EA" unicode="&#xf1ea;"
+d="M160 88v67h16v-88h-16v9c-6 -7 -13 -11 -19 -11c-5 0 -8 3 -10 7c-1 3 -1 7 -1 13v70h16v-65v-6c0 -2 2 -4 4 -4c3 0 6 3 10 8zM71 169v17h56v-17h-19v-102h-18v102h-19zM181 247c-5 0 -8 4 -8 12v38c0 8 3 12 8 12s7 -4 7 -12v-38c0 -8 -2 -12 -7 -12zM222 156
+c6 0 11 -3 13 -10c1 -4 2 -9 2 -17v-36c0 -8 -1 -14 -2 -18c-2 -7 -7 -10 -13 -10s-11 3 -16 10v-8h-16v119h16v-39c5 6 10 9 16 9zM221 92v38c0 8 -2 12 -7 12c-3 0 -5 -1 -8 -4v-54c3 -3 5 -4 8 -4c5 0 7 4 7 12zM274 156c8 0 15 -3 19 -9c3 -4 5 -11 5 -20v-19h-33v-16
+c0 -8 3 -12 9 -12c4 0 6 3 7 7v10h17v-2c0 -5 -1 -8 -1 -10c-1 -4 -2 -7 -4 -10c-4 -6 -11 -10 -19 -10s-14 4 -19 10c-3 4 -6 11 -6 20v31c0 9 2 17 5 21c5 6 12 9 20 9zM281 122v8c0 8 -3 12 -8 12s-8 -4 -8 -12v-8h16zM333 376c20 0 36 -16 36 -36v-296
+c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM218 323v-71c0 -6 0 -11 1 -14c2 -5 6 -6 11 -6c6 0 12 4 18 11v-10h17v90h-17v-69c-4 -5 -7 -7 -10 -7c-2 0 -4 0 -4 3v7v66h-16zM157 293v-31c0 -10 2 -17 5 -21c4 -6 11 -9 19 -9s14 3 19 9
+c3 4 5 11 5 21v31c0 10 -2 17 -5 22c-5 6 -11 9 -19 9s-15 -3 -19 -9c-3 -5 -5 -12 -5 -22zM113 353h-19l12 -33c6 -17 9 -29 11 -38v-49h18v49l21 71h-18l-12 -47zM313 61c5 20 4 42 4 63s1 43 -4 63c-3 14 -15 24 -29 26c-33 4 -67 4 -100 4s-66 0 -99 -4
+c-14 -2 -26 -12 -29 -26c-5 -20 -5 -42 -5 -63s0 -43 5 -63c3 -14 15 -24 29 -26c33 -4 66 -3 99 -3s67 -1 100 3c14 2 26 12 29 26z" />
+ <glyph glyph-name="uniF1EB" unicode="&#xf1eb;" horiz-adv-x="281"
+d="M76 133c37 -3 66 -23 96 -41c21 -13 44 -20 69 -20c12 0 22 4 31 12c4 3 6 2 7 -3c9 -37 -21 -75 -59 -76c-19 -1 -35 6 -50 16c-17 11 -35 25 -52 36c-32 21 -67 28 -105 24c-11 -1 -12 -1 -13 11c-2 22 6 40 21 56c42 46 83 91 122 140c3 4 7 9 10 13c1 1 3 2 2 4
+s-2 1 -4 1c-18 -1 -37 -2 -56 -2c-10 0 -18 2 -27 6c-15 7 -20 17 -14 32c5 12 11 23 19 34c2 3 4 4 7 2c17 -9 36 -11 55 -13c40 -3 80 0 119 8c5 1 6 -1 6 -5c2 -18 -4 -33 -16 -46c-42 -48 -82 -98 -127 -143c-14 -14 -29 -28 -41 -46z" />
+ <glyph glyph-name="uniF1EC" unicode="&#xf1ec;"
+d="M333 376c20 0 36 -16 36 -36v-296c0 -20 -16 -36 -36 -36h-297c-20 0 -36 16 -36 36v296c0 20 16 36 36 36h297zM289 155h-165l135 39c9 3 16 7 21 13s9 15 9 23c0 10 -5 19 -13 26s-18 11 -29 11h-155c-5 -1 -9 -6 -9 -11v-27h164l-135 -38c-8 -3 -16 -7 -21 -14
+s-8 -14 -8 -22c0 -10 4 -20 12 -27s18 -11 29 -11h154c5 1 10 6 11 11v27z" />
+ <glyph glyph-name="uniF1ED" unicode="&#xf1ed;" horiz-adv-x="394"
+d="M175 214c12 12 32 12 44 0s12 -32 0 -44s-32 -12 -44 0s-12 32 0 44zM333 43v0v-1h-1v0l-8 -8v0c-4 -4 -11 -3 -15 0v0l-1 1v0v0l-7 7v0v0l-7 7v0v0v0v0c-4 4 -5 11 -1 16v1h1v1v0l7 7h1c64 65 64 171 -1 236v0v0l-8 7v0v0l-1 1v1c-4 4 -3 11 0 15v0l1 1v0v0l14 14v0v0v0
+v0c4 4 11 5 16 1v0l9 -9v0v0c82 -82 83 -216 1 -298zM274 102v0h-1v0v0l-8 -9v1c-4 -4 -11 -3 -15 0v-1l-2 1v0v0l-14 15v0c-4 4 -5 11 -1 16v0l1 1v0v0l8 8v0c32 32 31 84 -1 116v0v0l-8 8v0v0l-1 1v0c-4 4 -3 11 0 15v0l1 1v0v0l14 14l1 1v0v0v0c4 4 11 4 16 0v0l9 -8v0
+v-1c49 -49 50 -129 1 -179zM219 214c12 -12 12 -32 0 -44s-32 -12 -44 0s-12 32 0 44s32 12 44 0zM162 125c4 -4 3 -11 0 -15v0l-1 -1v0v0l-14 -14v0v-1v0v0c-4 -4 -12 -4 -17 0v0l-8 8v0l-1 1c-49 49 -49 129 0 179v0v0v0v0l7 8v0v0l1 1v-1c4 4 12 3 16 0v1l15 -16v0
+c4 -4 5 -11 1 -16v0l-9 -9v0c-32 -32 -31 -84 1 -116v0v0l8 -8v0v0l1 -1v0zM102 65c4 -4 3 -11 0 -15v0l-1 -1v0v0l-14 -14v0v0v0v0c-4 -4 -11 -5 -16 -1v0l-9 9v0v0c-82 82 -83 216 -1 298v0l9 9v0c4 4 11 3 15 0v0l8 -8v0v0l8 -7v0c4 -4 4 -11 0 -16v-1h-1v-1v0l-7 -7v0
+c-64 -65 -65 -171 0 -236h1v0l7 -7v0v0l1 -1v-1z" />
+ <glyph glyph-name="uniF1EE" unicode="&#xf1ee;" horiz-adv-x="426"
+d="M426 244c1 -4 0 -8 -3 -11l-113 -90l50 -142c1 -4 0 -8 -3 -11c-2 -2 -4 -3 -6 -3s-4 1 -6 2l-132 79l-132 -79c-4 -2 -9 -2 -12 1s-4 7 -3 11l50 142l-112 90c-3 3 -4 7 -3 11s5 7 9 7h144l50 139c1 4 5 7 9 7s9 -3 10 -7l49 -139h144c4 0 9 -3 10 -7z" />
+ <glyph glyph-name="uniF1EF" unicode="&#xf1ef;" horiz-adv-x="308"
+d="M308 335v0v-286v0c0 -6 -5 -11 -11 -11v0h-285v0h-1c-6 0 -11 5 -11 11v0v0v284v2c0 6 5 11 11 11h1h284v0h1c6 0 11 -5 11 -11z" />
+ <glyph glyph-name="uniF1F0" unicode="&#xf1f0;" horiz-adv-x="312"
+d="M297 193c8 0 15 -7 15 -15s-7 -15 -15 -15h-1v0h-281v0c-8 0 -15 7 -15 15s7 15 15 15v0h281v0h1zM263 144c4 0 8 -4 8 -8v-1v-3c0 -48 -34 -90 -112 -90c-53 0 -91 19 -117 46c-2 1 -4 3 -4 6c0 2 1 4 2 5v0l18 27v0v0v0c1 2 4 4 7 4s5 -2 6 -4c20 -21 50 -39 90 -39
+c42 0 58 20 58 40c0 2 -1 5 -1 7v0v2c0 4 4 8 8 8l1 -1v1h36zM63 214v0c-8 11 -12 25 -12 43c0 48 41 85 105 85c45 0 82 -15 108 -41v0c2 -1 3 -4 3 -6s-1 -4 -2 -5v0l-17 -25h-1v-1v0c-1 -2 -3 -3 -6 -3c-2 0 -4 1 -5 2v0c-23 23 -55 34 -85 34s-48 -15 -48 -36
+c0 -28 45 -33 88 -46v0c1 0 2 -1 2 -2s-1 -3 -2 -3h-121c-3 0 -6 2 -7 4z" />
+ <glyph glyph-name="uniF1F1" unicode="&#xf1f1;" horiz-adv-x="315"
+d="M313 54c1 -1 2 -3 2 -4v-11c0 -1 -1 -3 -2 -4s-2 -1 -3 -1h-67v0h-1c-1 0 -2 1 -2 2v13v0c0 1 1 2 2 3l1 1v0c37 26 41 30 41 36c0 4 -5 6 -10 6c-8 0 -15 -3 -21 -8v0v0v0v0c-2 -1 -5 -2 -7 0v0l-7 10v0c-1 2 -1 4 0 6v0v0l1 1v0c9 9 23 13 34 13c21 0 35 -12 35 -28
+c0 -11 -6 -21 -26 -34h27v0c1 0 2 0 3 -1zM210 277c5 -5 5 -14 0 -19v0l-67 -66l67 -67v0c5 -5 5 -14 0 -19l-17 -17c-5 -5 -14 -5 -19 0v0v0l-67 66l-67 -66v0c-5 -5 -14 -5 -19 0l-17 17c-5 5 -5 14 0 19v0v0l67 67l-67 66v1c-5 5 -5 13 0 18l17 18c5 5 14 5 19 0l67 -67
+l67 67v0c5 5 14 5 19 0z" />
+ <glyph glyph-name="uniF1F2" unicode="&#xf1f2;" horiz-adv-x="315"
+d="M313 287c1 -1 2 -2 2 -3v-12c0 -1 -1 -2 -2 -3s-2 -2 -3 -2h-67v0h-1c-1 0 -2 1 -2 2v14v0c0 1 1 2 2 3h1v0c37 26 41 30 41 36c0 4 -5 6 -10 6c-8 0 -15 -3 -21 -8v0v0v0v0c-2 -1 -5 -2 -7 0v0l-7 11v0c-1 2 -1 3 0 5v0v1h1v1c9 9 23 12 34 12c21 0 35 -12 35 -28
+c0 -11 -6 -20 -26 -33h27v0c1 0 2 -1 3 -2zM210 277c5 -5 5 -14 0 -19v0l-67 -67l67 -67v0c5 -5 5 -14 0 -19l-17 -17c-5 -5 -14 -5 -19 0v0v0l-67 67l-67 -67v0c-5 -5 -14 -5 -19 0l-17 17c-5 5 -5 14 0 19v0v0l67 67l-67 67v0c-5 5 -5 14 0 19l17 17c5 5 14 5 19 0l67 -67
+l67 67v0c5 5 14 5 19 0z" />
+ <glyph glyph-name="uniF1F3" unicode="&#xf1f3;" horiz-adv-x="436"
+d="M436 335v-1v0v-286v0c0 -8 -8 -14 -16 -14h-404c-8 0 -16 6 -16 14v0v286v0v1c0 9 7 15 16 15h404c9 0 16 -6 16 -15zM385 84v0v216h-334v-216h334zM410 179c7 0 13 5 13 12s-6 13 -13 13s-12 -6 -12 -13s5 -12 12 -12z" />
+ <glyph glyph-name="uniF1F4" unicode="&#xf1f4;" horiz-adv-x="317"
+d="M301 410c9 0 16 -7 16 -16v-404c0 -9 -7 -16 -16 -16v0v0h-286v0c-8 0 -15 8 -15 16v404c0 8 7 16 15 16v0h286v0v0zM158 -13c7 0 13 6 13 13s-6 12 -13 12s-13 -5 -13 -12s6 -13 13 -13zM266 25v0v334h-215v-334h215z" />
+ <glyph glyph-name="uniF1F5" unicode="&#xf1f5;" horiz-adv-x="486"
+d="M473 205c7 0 13 -6 13 -13s-6 -13 -13 -13h-38c-6 -96 -83 -173 -179 -179v-38c0 -7 -6 -13 -13 -13s-13 6 -13 13v38c-96 6 -172 83 -178 179h-39c-7 0 -13 6 -13 13s6 13 13 13h39c6 96 82 173 178 179v38c0 7 6 13 13 13s13 -6 13 -13v-38c96 -6 173 -83 179 -179h38z
+M230 51v26c-54 6 -96 48 -102 102h-25c6 -68 59 -122 127 -128zM230 307v0v26c-68 -6 -121 -60 -127 -128h25c6 54 48 96 102 102zM256 333v-26c54 -6 96 -48 102 -102h26c-6 68 -60 122 -128 128zM256 51c68 6 122 60 128 128h-26c-6 -54 -48 -96 -102 -102v-26z" />
+ <glyph glyph-name="uniF1F6" unicode="&#xf1f6;" horiz-adv-x="384"
+d="M192 307c64 0 115 -51 115 -115s-51 -115 -115 -115s-116 51 -116 115s52 115 116 115zM192 127c36 0 64 29 64 65s-28 65 -64 65s-65 -29 -65 -65s29 -65 65 -65zM192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51
+c78 0 141 63 141 141s-63 141 -141 141s-141 -63 -141 -141s63 -141 141 -141zM153 192c0 26 13 39 39 39s39 -13 39 -39s-13 -39 -39 -39s-39 13 -39 39z" />
+ <glyph glyph-name="uniF1F7" unicode="&#xf1f7;" horiz-adv-x="333"
+d="M12 256c-3 3 -6 6 -6 11v56c0 5 3 12 6 16c0 0 1 3 3 5c11 11 54 45 153 45c117 0 154 -48 156 -50c3 -4 6 -11 6 -16v-56c0 -4 -1 -7 -4 -9c-4 -4 -9 -5 -14 -3l-65 20c-7 2 -12 9 -12 16v21c0 1 0 3 -1 4c0 0 -15 13 -66 13s-66 -13 -66 -13c0 -1 -1 -3 -1 -4v-24
+c0 -5 -3 -10 -6 -13c-2 -2 -4 -3 -6 -4h-1l-65 -17c-4 -1 -8 0 -11 2zM35 148c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13zM161 135c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13z
+M230 135c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13zM299 135c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13zM11 189c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13
+c0 -6 -5 -11 -11 -11h-35zM115 189h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13c0 -6 -5 -11 -11 -11zM184 189h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13c0 -6 -5 -11 -11 -11zM253 224c6 0 11 -5 11 -11v-13
+c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35zM322 224c6 0 11 -5 11 -11v-13c0 -6 -5 -11 -11 -11h-35c-6 0 -11 5 -11 11v13c0 6 5 11 11 11h35zM57 70c0 -6 -5 -10 -11 -10h-35c-6 0 -11 4 -11 10v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13zM80 60
+c-6 0 -11 4 -11 10v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13c0 -6 -5 -10 -11 -10h-35zM149 60c-6 0 -11 4 -11 10v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13c0 -6 -5 -10 -11 -10h-35zM218 60c-6 0 -11 4 -11 10v13c0 6 5 11 11 11h35c6 0 11 -5 11 -11v-13
+c0 -6 -5 -10 -11 -10h-35zM322 94c6 0 11 -5 11 -11v-13c0 -6 -5 -10 -11 -10h-35c-6 0 -11 4 -11 10v13c0 6 5 11 11 11h35zM281 30c6 0 11 -5 11 -11v-13c0 -6 -5 -11 -11 -11h-233c-6 0 -10 5 -10 11v13c0 6 4 11 10 11h233z" />
+ <glyph glyph-name="uniF1F8" unicode="&#xf1f8;" horiz-adv-x="358"
+d="M358 88c1 -5 -1 -11 -5 -15l-50 -50c-5 -5 -13 -9 -20 -10h-7v0c-19 0 -89 7 -179 97c-106 106 -97 183 -97 186c1 7 5 15 10 20l51 50c3 3 7 5 12 5c6 0 12 -4 15 -10l41 -76c4 -8 2 -19 -5 -26l-18 -19c-1 -1 -2 -4 -2 -5c0 0 1 -25 47 -71s72 -48 72 -48c1 0 3 2 4 3
+l22 21c4 4 10 7 16 7c4 0 7 -1 10 -3h1l73 -43c5 -3 8 -8 9 -13z" />
+ <glyph glyph-name="uniF1F9" unicode="&#xf1f9;" horiz-adv-x="379"
+d="M364 45c8 0 15 -8 15 -16s-7 -15 -15 -15h-1v0h-348v0c-8 0 -15 7 -15 15s7 16 15 16v0h348v0h1zM63 80c-7 0 -13 6 -13 13c0 2 1 4 1 5v0l103 263v0c2 5 7 9 13 9h45c6 0 11 -4 13 -9v0l103 -262v-1v-1v0c0 -1 1 -3 1 -4c0 -7 -7 -13 -14 -13h-1v0h-29v0
+c-5 0 -9 4 -11 8v0l-18 48h-133l-18 -47c-2 -5 -7 -9 -13 -9h-29zM189 319l-52 -138h104z" />
+ <glyph glyph-name="uniF1FA" unicode="&#xf1fa;" horiz-adv-x="332"
+d="M65 358c6 0 12 -5 12 -11v0v0v-54v0c0 -6 -6 -12 -12 -12v0h-53v0v0c-6 0 -12 6 -12 12v0v54v0v0c0 6 6 11 12 11v0v0h53v0zM193 358c6 0 12 -5 12 -11v0v0v-54v0c0 -6 -6 -12 -12 -12v0h-54v0v0c-6 0 -11 6 -11 12v0v54v0v0c0 6 5 11 11 11v0v0h54v0zM332 347v0v0v-54v0
+c0 -6 -5 -12 -11 -12v0h-54v0v0c-6 0 -12 6 -12 12v0v54v0c0 6 6 11 12 11v0v0h54v0c6 0 11 -5 11 -11zM65 230c6 0 12 -5 12 -11v0v0v-54v0c0 -6 -6 -11 -12 -11v0h-53v0v0c-6 0 -12 5 -12 11v0v54v0v0c0 6 6 11 12 11v0v0h53v0zM193 230c6 0 12 -5 12 -11v0v0v-54v0
+c0 -6 -6 -11 -12 -11v0h-54v0v0c-6 0 -11 5 -11 11v0v54v0v0c0 6 5 11 11 11v0v0h54v0zM321 230c6 0 11 -5 11 -11v0v0v-54v0c0 -6 -5 -11 -11 -11v0h-54v0v0c-6 0 -12 5 -12 11v0v54v0c0 6 6 11 12 11v0v0h54v0zM65 103c6 0 12 -6 12 -12v0v0v-54v0c0 -6 -6 -11 -12 -11v0
+h-53v0v0c-6 0 -12 5 -12 11v0v54v0v0c0 6 6 12 12 12v0v0h53v0zM193 103c6 0 12 -6 12 -12v0v0v-54v0c0 -6 -6 -11 -12 -11v0h-54v0v0c-6 0 -11 5 -11 11v0v54v0v0c0 6 5 12 11 12v0v0h54v0zM321 103c6 0 11 -6 11 -12v0v0v-54v0c0 -6 -5 -11 -11 -11v0h-54v0v0
+c-6 0 -12 5 -12 11v0v54v0c0 6 6 12 12 12v0v0h54v0z" />
+ <glyph glyph-name="uniF1FB" unicode="&#xf1fb;" horiz-adv-x="512"
+d="M509 276c4 -4 4 -9 0 -13v0l-324 -324v0c-4 -4 -9 -4 -13 0v1l-63 62c8 12 7 28 -4 39s-27 12 -39 4l-63 63v0v0c-4 4 -4 9 0 13v0l324 324v0c4 4 9 4 13 0l63 -63c-8 -12 -7 -28 4 -39s27 -12 39 -4l63 -63v0zM438 263c4 4 4 9 0 13l-98 98v0c-4 4 -9 4 -13 0v0
+l-253 -253v0c-4 -4 -4 -9 0 -13v0l98 -98v0v0c4 -4 9 -4 13 0v0v0zM317 184c1 0 2 -1 2 -2s-1 -2 -1 -2l-1 -1l-39 -9l-9 -39c0 -1 -2 -2 -3 -2s-2 1 -2 2l-17 35l-36 -4c-1 0 -3 0 -3 1s-1 2 0 3l27 26l-17 34c0 1 0 2 1 3s2 1 3 1l34 -17l26 27c1 1 2 0 3 0s1 -2 1 -3
+l-4 -36z" />
+ <glyph glyph-name="uniF1FC" unicode="&#xf1fc;" horiz-adv-x="332"
+d="M321 139c7 -3 11 -12 11 -21v-77v-14c0 -12 -9 -22 -19 -22h-123v70v2v0l-20 34v0v1v0c-1 1 -2 2 -4 2s-2 -1 -3 -2v0l-21 -35h1c0 -1 -1 -1 -1 -2v-70h-123c-10 0 -19 10 -19 22v14v77c0 9 5 18 12 21l83 38l32 15c-15 9 -27 22 -35 39c-7 14 -11 31 -11 49
+c0 10 2 20 4 29c11 40 43 70 81 70c39 0 72 -30 82 -72c2 -9 3 -18 3 -27c0 -17 -4 -32 -10 -46c-8 -17 -19 -32 -34 -41l33 -16zM190 162v2c0 2 -2 4 -4 4h-40c-2 0 -4 -2 -4 -4c0 -1 1 -1 1 -2v0l19 -35v0h1v0c1 -1 1 -2 3 -2s3 1 4 2v0l20 35v0z" />
+ <glyph glyph-name="uniF1FD" unicode="&#xf1fd;" horiz-adv-x="332"
+d="M321 139c7 -3 11 -12 11 -21v-77v-14c0 -12 -9 -22 -19 -22h-294c-10 0 -19 10 -19 22v14v77c0 9 5 18 12 21l83 38l32 15c-1 1 -3 2 -4 3h-44c-7 0 -13 5 -13 12v33v0c1 46 18 87 42 112c13 14 29 23 47 26h2s2 1 3 1h6v0v0v0h6c1 0 2 -1 3 -1h3c18 -3 34 -13 47 -27
+c24 -25 40 -65 41 -111v0v-33c0 -7 -5 -12 -12 -12h-45l-2 -2l33 -16z" />
+ <glyph glyph-name="uniF1FE" unicode="&#xf1fe;" horiz-adv-x="332"
+d="M321 139c7 -3 11 -12 11 -21v-77v-14c0 -12 -9 -22 -19 -22h-294c-10 0 -19 10 -19 22v14v77c0 9 5 18 12 21l83 38l32 15c-15 9 -27 22 -35 39c-7 14 -11 31 -11 49c0 10 2 20 4 29c11 40 43 70 81 70c39 0 72 -30 82 -72c2 -9 3 -18 3 -27c0 -17 -4 -32 -10 -46
+c-8 -17 -19 -32 -34 -41l33 -16z" />
+ <glyph glyph-name="uniF1FF" unicode="&#xf1ff;" horiz-adv-x="488"
+d="M382 145c4 -2 7 -5 9 -9c2 -3 3 -7 3 -11v-69v-13c0 -11 -8 -20 -17 -20h-266c-9 0 -17 9 -17 20v13v69v3c1 7 5 14 11 17l74 34l29 14c-1 1 -2 0 -3 1h-40c-6 0 -11 5 -11 11v30v0c1 37 12 69 30 92c14 21 36 34 60 34c22 0 42 -11 56 -29c20 -23 33 -58 34 -97v0v-30
+c0 -6 -5 -11 -11 -11h-40c-1 0 -1 -1 -2 -1l29 -14zM119 179l-25 -11c-15 -7 -25 -24 -25 -42v-69h-55c-8 0 -14 7 -14 16v66c0 7 4 13 9 15l83 39c-20 12 -33 36 -33 64c0 40 28 71 62 71c10 0 20 -3 28 -8c-17 -30 -29 -68 -30 -110v0v-31zM479 153c5 -2 9 -8 9 -15v-66
+c0 -9 -6 -16 -14 -16h-55v69c0 18 -11 35 -26 42l-24 11v31h-1c-1 42 -12 80 -29 110c8 5 18 9 28 9c34 0 62 -32 62 -72c0 -28 -14 -52 -34 -64z" />
+ <glyph glyph-name="uniF200" unicode="&#xf200;" horiz-adv-x="489"
+d="M481 153c5 -3 8 -8 8 -15v-66c0 -9 -5 -16 -13 -16h-58v70c0 18 -9 34 -24 41l-54 25v0c-5 3 -10 7 -14 12c12 19 19 43 19 67c0 16 -2 32 -8 46c9 7 20 11 32 11c34 0 61 -32 61 -72c0 -27 -13 -51 -32 -63zM150 193l-56 -26c-15 -7 -25 -23 -25 -41v-70h-55
+c-8 0 -14 7 -14 16v66c0 7 4 13 9 15l83 39c-20 12 -33 36 -33 64c0 40 28 72 62 72c11 0 21 -4 30 -10c-6 -14 -9 -30 -9 -47c0 -25 7 -49 20 -68c-4 -4 -8 -7 -12 -10zM383 144c6 -3 10 -10 10 -18v-70v-12c0 -11 -8 -20 -17 -20h-265c-9 0 -17 9 -17 20v12v70
+c0 8 5 15 11 18l75 35l29 13c-13 8 -25 20 -32 35c-6 13 -10 28 -10 44c0 9 2 18 4 26c10 36 39 63 73 63c35 0 64 -28 73 -65c2 -8 3 -16 3 -24c0 -15 -3 -29 -9 -41c-7 -16 -18 -29 -31 -37l31 -15z" />
+ <glyph glyph-name="uniF201" unicode="&#xf201;" horiz-adv-x="442"
+d="M140 207v0v-24l-39 -18c-16 -8 -27 -25 -27 -44v-74h-59c-8 0 -15 8 -15 17v71c0 7 3 13 9 16l90 41c-21 13 -36 38 -36 68c0 42 30 77 66 77c12 0 22 -4 32 -10c-1 -4 -3 -7 -4 -11c-10 -22 -16 -48 -17 -76v0v-28v-5zM430 139c7 -3 12 -12 12 -21v-77v-14
+c0 -12 -9 -22 -19 -22h-295c-10 0 -19 10 -19 22v14v77c0 9 5 18 12 21l83 38l33 15c-1 1 -3 2 -4 3h-45c-7 0 -12 5 -12 12v33v0c1 46 18 87 42 112c13 14 28 23 46 26h3s2 1 3 1h6h6c1 0 2 -1 3 -1h2c18 -3 34 -13 47 -27c24 -25 40 -65 41 -111h1v-33
+c0 -7 -6 -12 -13 -12h-44c-1 -1 -2 -1 -3 -2l34 -16z" />
+ <glyph glyph-name="uniF202" unicode="&#xf202;" horiz-adv-x="420"
+d="M419 124c0 -1 1 -2 1 -3v-74v-13c0 -12 -9 -21 -19 -21h-282c-10 0 -18 9 -18 21v13v74c0 2 0 4 1 6c2 6 5 12 10 14l80 37l31 14c-14 8 -26 22 -34 38c-6 12 -9 25 -10 40v6v8c1 7 2 13 4 20c1 4 2 8 3 11c13 33 41 56 74 56v0v0c37 0 68 -29 78 -69c2 -8 4 -17 4 -26
+c0 -16 -4 -31 -10 -44c-8 -17 -19 -30 -33 -39l32 -16l77 -36c6 -3 10 -10 11 -17zM155 190l-54 -25c-16 -8 -27 -25 -27 -44v-74h-59c-8 0 -15 8 -15 17v71c0 7 3 13 9 16l90 41l-2 1h-36c-5 0 -10 5 -10 10v26v0c2 62 37 111 80 111c9 0 17 -2 25 -6
+c-8 -17 -13 -37 -13 -58c0 -30 10 -56 26 -78z" />
+ <glyph glyph-name="uniF203" unicode="&#xf203;" horiz-adv-x="420"
+d="M160 193l-59 -28c-16 -8 -27 -25 -27 -44v-74h-59c-8 0 -15 8 -15 17v71c0 7 3 13 9 16l90 41c-21 13 -36 38 -36 68c0 42 30 77 66 77c12 0 22 -4 32 -10c-6 -15 -9 -33 -9 -51c0 -27 7 -51 21 -72c-4 -4 -8 -8 -13 -11zM408 141c7 -3 12 -11 12 -20v-74v-13
+c0 -12 -9 -21 -19 -21h-282c-10 0 -18 9 -18 21v13v74c0 9 4 17 11 20l80 37l31 14c-14 8 -26 22 -34 38c-7 14 -10 29 -10 46c0 10 2 19 4 28c10 39 40 67 77 67s68 -29 78 -69c2 -8 4 -17 4 -26c0 -16 -4 -31 -10 -44c-8 -17 -19 -30 -33 -39l32 -16z" />
+ <glyph glyph-name="uniF204" unicode="&#xf204;" horiz-adv-x="321"
+d="M293 277c7 0 12 -5 12 -12v-256c0 -7 -5 -12 -12 -12h-265c-7 0 -12 5 -12 12v256c0 7 5 12 12 12h265zM309 359c7 0 12 -5 12 -12v-35c0 -7 -5 -13 -12 -13h-297c-7 0 -12 6 -12 13v35c0 7 5 12 12 12h101v16c0 7 5 12 12 12h72c7 0 12 -5 12 -12v-16h100z" />
+ <glyph glyph-name="uniF205" unicode="&#xf205;" horiz-adv-x="431"
+d="M431 33c1 -1 0 -2 0 -3c0 -4 -2 -7 -6 -7v0h-72v-20c0 -3 -3 -5 -6 -5h-26c-3 0 -6 2 -6 5v20h-72v0c-4 0 -6 3 -6 7c0 1 0 2 1 3v0l8 16h-82v-44c0 -4 -4 -7 -8 -7h-38c-4 0 -7 3 -7 7v44h-101v0c-5 0 -10 4 -10 9c0 2 1 4 2 6l52 90h-21v0c-4 0 -8 4 -8 8c0 2 1 4 2 5
+l48 83h-12v0c-3 0 -6 2 -6 5c0 1 1 2 1 3v0l71 123c2 3 4 5 8 5s7 -2 9 -5v0l71 -123v0c0 -1 1 -2 1 -3c0 -3 -3 -5 -6 -5v0h-12l49 -84v-1c1 -1 1 -2 1 -3c0 -4 -4 -8 -8 -8v0h-21l43 -75l11 19h-15v0c-3 0 -5 3 -5 6v2v0l35 60h-9v0c-2 0 -4 2 -4 4c0 1 1 1 1 2v0l50 87v0
+c1 2 3 4 6 4s5 -2 6 -4v0l50 -87v0c0 -1 1 -1 1 -2c0 -2 -2 -4 -4 -4v0h-8l34 -60v0c0 -1 1 -1 1 -2c0 -3 -3 -6 -6 -6v0h-15l38 -65v0z" />
+ <glyph glyph-name="uniF206" unicode="&#xf206;" horiz-adv-x="331"
+d="M331 325v0v-133v0c0 -5 -5 -10 -10 -10v0h-43c-7 -47 -42 -84 -87 -94v-65h51v0c7 0 13 -6 13 -13s-6 -13 -13 -13v0v0h-153v0c-7 0 -13 6 -13 13s6 13 13 13h51v65c-45 10 -81 47 -88 94h-42v0c-5 0 -10 5 -10 10v0v0v0v0v133v0v1v0v0c0 5 5 9 10 9h41v36v1
+c0 8 6 14 14 15v0h199v0h1c8 0 15 -7 15 -15v-1v-36h41v0c5 0 10 -5 10 -10zM51 208v102h-25v-102h25zM305 208v102h-25v-102h25z" />
+ <glyph glyph-name="uniF207" unicode="&#xf207;" horiz-adv-x="312"
+d="M297 61c8 0 15 -7 15 -15s-7 -16 -15 -16l-1 1v-1h-281v1c-8 0 -15 7 -15 15s7 15 15 15v0h281v0h1zM156 79c-81 0 -121 46 -121 115v145c0 8 7 15 15 15h20c8 0 15 -7 15 -15v-1v-143c0 -44 25 -73 71 -73s71 29 71 73v143v1c0 8 7 15 15 15h20c8 0 15 -7 15 -15v-145
+c0 -69 -40 -115 -121 -115z" />
+ <glyph glyph-name="uniF208" unicode="&#xf208;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM192 51c78 0 141 63 141 141s-63 141 -141 141s-141 -63 -141 -141s63 -141 141 -141zM166 281c0 16 8 25 24 25s24 -9 24 -25s-8 -24 -24 -24s-24 8 -24 24zM273 201v0
+c2 -2 3 -4 3 -7c0 -6 -4 -10 -10 -10c-3 0 -5 1 -7 3v0l-34 34v0h-1v0c-1 0 -1 1 -2 1c-2 0 -3 -1 -3 -3v-1v0v-30v-32v-63c0 -7 -5 -12 -12 -12s-12 5 -12 12v63v0c0 2 -1 4 -3 4s-3 -2 -3 -4v0v-63c0 -7 -5 -12 -12 -12s-12 5 -12 12v63v32v31v0c0 2 -1 3 -3 3
+c-1 0 -2 0 -3 -1v0l-34 -34v0c-2 -2 -4 -3 -7 -3c-6 0 -10 4 -10 10c0 3 1 5 3 7v0l46 46v1v0v0c2 2 5 3 8 3v0h53h1c3 0 6 -1 8 -3v0v0v-1z" />
+ <glyph glyph-name="uniF209" unicode="&#xf209;" horiz-adv-x="463"
+d="M59 344v0c-6 6 -6 14 0 20s14 6 20 0v0v0v0h1l49 -49c6 -6 6 -15 0 -21s-15 -6 -21 0zM144 363v0c-2 8 2 16 10 18s16 -2 18 -10v0v0v0v0l19 -68c2 -8 -3 -16 -11 -18s-16 2 -18 10zM58 246c-8 2 -12 10 -10 18s9 12 17 10v0h1v0v0l67 -18c8 -2 13 -10 11 -18
+s-10 -12 -18 -10l-68 18v0v0v0v0zM405 40v0c6 -6 5 -14 -1 -20s-14 -6 -20 0v0v0v0v0l-50 49c-6 6 -6 15 0 21s15 6 21 0zM319 21v0c2 -8 -2 -16 -10 -18s-16 2 -18 10v0v0v0v0l-18 68c-2 8 2 16 10 18s16 -2 18 -10zM405 138c8 -2 13 -10 11 -18s-10 -12 -18 -10v0v0v0v0
+l-68 18c-8 2 -13 10 -11 18s10 12 18 10l68 -18v0v0v0v0zM222 183c39 -39 40 -101 4 -141v0l-51 -52c-40 -40 -105 -40 -145 0s-40 105 0 145l52 52v0c40 36 101 35 140 -4zM189 77v0c17 20 16 50 -3 69s-50 20 -70 3v0l-3 -3v0v0l-46 -46v0c-20 -20 -20 -53 0 -73
+s53 -20 73 0v0l46 46v0v0zM433 394c39 -39 40 -101 4 -141v0l-52 -52c-40 -40 -104 -40 -144 0s-40 105 0 145l51 51h1c40 36 101 36 140 -3zM400 287v0c17 20 16 51 -3 70s-50 20 -70 3v0l-3 -3v0v0l-46 -46h-1c-20 -20 -20 -53 0 -73s53 -20 73 0v0l47 46v0v0z" />
+ <glyph glyph-name="uniF20A" unicode="&#xf20a;" horiz-adv-x="356"
+d="M342 215c7 0 14 -6 14 -13v-192c0 -7 -7 -13 -14 -13h-329c-7 0 -13 6 -13 13v192c0 7 6 13 13 13h19h29v54c0 65 55 118 122 118c66 0 120 -52 121 -116v-2c0 -5 -4 -10 -10 -10v0h-51c-6 0 -10 5 -10 10c0 27 -22 48 -50 48s-50 -21 -50 -48v-54h123h67h19z" />
+ <glyph glyph-name="uniF20B" unicode="&#xf20b;" horiz-adv-x="473"
+d="M387 259c46 6 86 -34 86 -83c0 -18 -6 -35 -16 -50c-3 -4 -7 -7 -12 -7h-138c-1 47 -39 86 -87 86s-86 -39 -87 -86h-102c-5 0 -10 3 -13 8c-12 20 -18 42 -18 66c0 66 49 121 110 121c8 0 15 -1 23 -3c27 39 70 61 115 61c65 0 121 -47 139 -113zM274 88c1 -2 1 -3 0 -5
+s-2 -3 -4 -3h-24v-64c0 -3 -2 -4 -5 -4h-44c-3 0 -4 1 -4 4v64h-24c-2 0 -4 1 -5 3s0 4 1 5l50 71c1 1 2 2 4 2v0c2 0 3 -1 4 -2z" />
+ <glyph glyph-name="uniF20C" unicode="&#xf20c;" horiz-adv-x="420"
+d="M394 194c14 0 26 -11 26 -25v-144c0 -14 -12 -25 -26 -25h-368c-14 0 -26 11 -26 25v144c0 14 12 25 26 25h93c11 0 22 -7 25 -17c9 -28 36 -46 66 -46s57 18 66 46c3 10 13 17 24 17h94zM137 273c-3 0 -5 1 -6 3s-1 5 1 7l72 98c1 2 4 3 6 3v0c2 0 4 -1 5 -3l73 -98
+c2 -2 2 -5 1 -7s-3 -3 -6 -3h-35v-88c0 -4 -3 -7 -7 -7h-63c-4 0 -7 3 -7 7v88h-34z" />
+ <glyph glyph-name="uniF20D" unicode="&#xf20d;" horiz-adv-x="150"
+d="M150 266v0v-233v0c0 -8 -7 -15 -15 -15v0h-121v0c-8 0 -14 7 -14 15v0v233v0c0 8 6 14 14 14h1h11v77v0c0 4 3 7 7 8v1h83c5 0 8 -4 8 -9v0v0v-77h11v0c8 0 15 -6 15 -14zM99 280v60h-48v-60h48zM62 294v11h26v-11h-26z" />
+ <glyph glyph-name="uniF20E" unicode="&#xf20e;" horiz-adv-x="410"
+d="M288 134v-54c0 -13 -10 -23 -23 -23h-242c-13 0 -23 10 -23 23v224c0 13 10 23 23 23h242c13 0 23 -10 23 -23v-53v0l122 57v-232z" />
+ <glyph glyph-name="uniF20F" unicode="&#xf20f;" horiz-adv-x="243"
+d="M243 328v-270h-1l1 -1c0 -6 -5 -11 -11 -11c-2 0 -4 1 -6 2l-85 49v0l-59 34h-74v0v0c-4 0 -8 4 -8 8v106c0 4 4 8 8 8v0v0h74l40 23v0l105 60v0c2 1 3 2 5 2c5 0 9 -5 10 -10h1z" />
+ <glyph glyph-name="uniF210" unicode="&#xf210;" horiz-adv-x="436"
+d="M271 268c-4 5 -4 12 0 17v0l1 1v0v0l16 16v0v0v0v0c5 5 14 5 19 1v0l10 -10v0v0c43 -43 53 -106 31 -159l-41 41c5 29 -4 60 -26 82v1v0l-10 10v0zM366 361c77 -77 90 -194 40 -285l-37 37c31 70 18 155 -39 212v0h-1l-8 9v0v0l-1 1v0c-4 5 -4 12 0 17v0l17 18v0
+c5 5 13 5 18 1v0l10 -10v0h1zM243 316v0v-77l-60 60l44 25v0c2 1 3 2 5 2c5 0 9 -5 10 -10h1zM82 241l9 5l152 -151v-49h-1l1 -1c0 -6 -5 -10 -11 -10c-2 0 -4 0 -6 1l-85 49v0l-59 34h-74v0v0c-4 0 -8 4 -8 8v106c0 4 4 8 8 8v0v0h74zM401 45v0c5 -5 5 -13 0 -18l-1 -1
+l-17 -18v0c-5 -5 -13 -5 -18 0v0l-331 331c-5 5 -5 13 0 18v0l18 18v1c5 5 13 5 18 0v0v0z" />
+ <glyph glyph-name="uniF211" unicode="&#xf211;" horiz-adv-x="436"
+d="M366 361c93 -93 93 -245 0 -338v0l-8 -9v0v0l-1 -1h-1c-5 -4 -12 -4 -17 0v0l-17 17v0c-5 5 -5 14 -1 19v0l1 1v0v0l9 9v-1c73 74 73 193 -1 267v1l-1 -1l-8 9v0v0l-1 1v0c-4 5 -4 13 0 18v0l17 17v0c5 5 13 5 18 1v0l10 -10v0h1zM317 293c56 -56 56 -147 1 -203v0
+l-10 -10v0c-5 -4 -12 -4 -17 0v0l-18 18v0c-5 5 -5 13 -1 18v0l1 1v0v0l9 9v0c36 37 35 96 -1 132v0v0l-10 10v0c-4 5 -4 12 0 17v0l1 1v0v0l16 16v1v0v0v0c5 5 14 5 19 1v0l10 -10v0v-1zM232 326c5 0 9 -4 10 -9h1v-270h-1l1 -1c0 -6 -5 -11 -11 -11c-2 0 -4 1 -6 2l-85 49
+v0l-59 34h-74v0v0c-4 0 -8 4 -8 8v105c0 4 4 8 8 8v0v0h74l40 23v0l105 61v0c2 1 3 1 5 1z" />
+ <glyph glyph-name="uniF212" unicode="&#xf212;" horiz-adv-x="384"
+d="M192 384c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192zM53 167c8 -44 37 -81 75 -101c-24 28 -40 63 -45 101h-30zM83 217c5 38 21 73 45 101c-38 -20 -67 -57 -75 -101h30zM167 100v67h-33c5 -25 17 -48 33 -67zM167 217v67
+c-16 -19 -28 -42 -33 -67h33zM331 217c-8 44 -37 81 -75 101c24 -28 40 -63 45 -101h30zM217 100c16 19 28 42 33 67h-33v-67zM217 217h33c-5 25 -17 48 -33 67v-67zM256 66c38 20 67 57 75 101h-30c-5 -38 -21 -73 -45 -101z" />
+ <glyph glyph-name="uniF213" unicode="&#xf213;" horiz-adv-x="285"
+d="M152 62l29 -29c-19 -15 -44 -25 -70 -25c-61 0 -111 50 -111 111c0 26 10 51 25 70l27 -28c-8 -12 -13 -25 -13 -40c0 -39 33 -72 72 -72c15 0 29 5 41 13zM202 340c0 24 13 36 37 36s37 -12 37 -36s-13 -37 -37 -37s-37 13 -37 37zM262 215c13 0 23 -10 23 -23v-117
+c0 -13 -10 -23 -23 -23s-23 10 -23 23v94h-29c8 -15 12 -32 12 -50c0 -26 -8 -49 -23 -68l-29 29c8 12 12 26 12 41c0 39 -32 71 -71 71c-15 0 -29 -5 -41 -13l-27 27c10 8 22 15 35 19l67 66l-28 17l-33 -33h-1v-1v0c-4 -4 -10 -6 -16 -6c-13 0 -23 10 -23 23
+c0 6 3 12 7 16v0l45 45l1 1v1v-1c4 4 10 6 16 6c3 0 6 -1 9 -2v1l103 -60v0c7 -4 11 -11 11 -19c0 -5 -1 -10 -4 -14v0l-1 -1c-1 -1 -3 -2 -4 -3l-46 -46h81z" />
+ <glyph glyph-name="uniF214" unicode="&#xf214;" horiz-adv-x="415"
+d="M405 226c6 -1 10 -5 10 -11v-46c0 -6 -4 -10 -10 -11l-53 -5c-3 -13 -8 -25 -15 -36l34 -41c4 -4 3 -11 -1 -15l-32 -32c-2 -2 -5 -3 -8 -3c-2 0 -5 1 -7 3l-41 33c-11 -7 -23 -12 -36 -15l-5 -52c-1 -6 -5 -10 -11 -10h-45c-6 0 -10 4 -11 10l-5 52c-13 3 -26 8 -37 15
+l-40 -33c-2 -2 -5 -3 -7 -3c-3 0 -6 1 -8 3l-32 32c-4 4 -5 11 -1 15l34 41c-7 11 -12 23 -15 36l-53 5c-6 1 -10 5 -10 11v46c0 6 4 10 10 11l53 5c3 13 8 25 15 36l-34 41c-4 4 -3 11 1 15l32 32c2 2 5 3 8 3c2 0 5 -1 7 -3l40 -33c11 7 24 12 37 15l5 52c1 6 5 10 11 10
+h45c6 0 10 -4 11 -10l5 -52c13 -3 25 -8 36 -15l41 33c2 2 5 3 7 3c3 0 6 -1 8 -3l32 -32c4 -4 5 -11 1 -15l-34 -41c7 -11 12 -23 15 -36zM207 131c34 0 62 27 62 61s-28 61 -62 61s-61 -27 -61 -61s27 -61 61 -61z" />
+ <glyph glyph-name="uniF215" unicode="&#xf215;" horiz-adv-x="401"
+d="M386 328c1 1 4 1 5 0v0v0l1 -1v0c6 -14 9 -29 9 -45c0 -61 -49 -111 -110 -111c-12 0 -23 3 -34 6l-115 -116c-1 -39 -32 -70 -71 -70s-71 32 -71 71s31 70 70 71l115 116c-3 11 -5 21 -5 33c0 61 50 111 111 111c16 0 30 -4 44 -10h1v0v0l1 -1c1 -1 1 -3 0 -4l-20 -20
+l-19 -19l-24 -25c-1 -13 3 -26 13 -36s23 -14 36 -13l24 24l20 19zM100 62c0 16 -13 30 -29 30s-29 -14 -29 -30s13 -29 29 -29s29 13 29 29z" />
+ <glyph glyph-name="uniF216" unicode="&#xf216;" horiz-adv-x="384"
+d="M284 142c2 -2 2 -5 0 -7l-35 -35c-1 -1 -2 -2 -3 -2s-3 1 -4 2l-50 50l-50 -50c-1 -1 -3 -2 -4 -2s-2 1 -3 2l-35 35c-1 1 -2 2 -2 3s1 3 2 4l50 50l-50 50c-1 1 -2 3 -2 4s1 2 2 3l35 35c2 2 5 2 7 0l50 -50l50 50c2 2 5 2 7 0l35 -35c2 -2 2 -5 0 -7l-50 -50zM192 333
+c-78 0 -141 -63 -141 -141s63 -141 141 -141s141 63 141 141s-63 141 -141 141zM192 384v0c106 0 192 -86 192 -192s-86 -192 -192 -192s-192 86 -192 192s86 192 192 192z" />
+ <glyph glyph-name="uniF217" unicode="&#xf217;" horiz-adv-x="361"
+d="M358 96c4 -4 4 -10 0 -14l-67 -68c-2 -2 -4 -3 -7 -3s-5 1 -7 3l-96 96l-96 -96c-2 -2 -5 -3 -8 -3s-5 1 -7 3l-67 68c-2 2 -3 4 -3 7s1 5 3 7l96 96l-96 96c-2 2 -3 4 -3 7s1 5 3 7l67 68c4 4 11 4 15 0l96 -96l96 96c4 4 10 4 14 0l67 -68c4 -4 4 -10 0 -14l-96 -96z
+" />
+ <glyph glyph-name="uniF218" unicode="&#xf218;" horiz-adv-x="270"
+d="M269 331h1l-85 -130h74v0v0c3 0 6 -2 6 -5v0v-21c0 -3 -3 -6 -6 -6v0v0h-95v-33h95v0v0c3 0 6 -3 6 -6v-20c0 -3 -3 -6 -6 -6v0v0h-95v-48v0c0 -3 -2 -6 -5 -6v0h-47v0v0c-3 0 -6 3 -6 6v1v47h-94v0v0c-3 0 -6 3 -6 6v20c0 3 3 6 6 6v0v0h94v33h-94v0v0c-3 0 -6 2 -6 5v0
+v1v0v0v20v0c0 3 3 6 6 6v0v0h72l-84 130v0v1c0 1 0 2 1 2h3h2h57c2 0 3 -2 4 -3v0l68 -110l68 110v0c1 1 2 3 4 3h57h2h3v-1c1 0 1 0 1 -1z" />
+ <glyph glyph-name="uniF219" unicode="&#xf219;" horiz-adv-x="397"
+d="M233 395c91 0 164 -74 164 -164s-73 -164 -164 -164c-26 0 -51 6 -73 17l-82 -82v1c-8 -8 -20 -14 -33 -14c-25 0 -45 20 -45 45c0 13 6 25 14 33h-1l80 79c-15 25 -24 54 -24 85c0 90 73 164 164 164zM234 132c57 0 103 45 103 102s-46 102 -103 102s-102 -45 -102 -102
+s45 -102 102 -102zM295 258c4 0 7 -4 7 -8v-32c0 -4 -4 -8 -8 -8v0v0h-36v-36v0c0 -4 -4 -8 -8 -8v0h-32v0v0c-4 0 -8 4 -8 8v0v0v36h-35h-1c-4 0 -8 4 -8 8v32c0 4 4 8 8 8h36v35v1c0 4 4 8 8 8h1h31v0c4 0 8 -4 8 -8v-36h37v0z" />
+ <glyph glyph-name="uniF21A" unicode="&#xf21a;" horiz-adv-x="397"
+d="M233 395c91 0 164 -74 164 -164s-73 -164 -164 -164c-26 0 -51 6 -73 17l-82 -82v1c-8 -8 -20 -14 -33 -14c-25 0 -45 20 -45 45c0 13 6 25 14 33h-1l80 79c-15 25 -24 54 -24 85c0 90 73 164 164 164zM234 132c57 0 103 45 103 102s-46 102 -103 102s-102 -45 -102 -102
+s45 -102 102 -102zM294 258c4 0 9 -4 9 -8v0v-32c0 -4 -5 -8 -9 -8h-120c-4 0 -8 4 -8 8v32v0c0 4 4 8 8 8h120z" />
+ </font>
+</defs></svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/foundation-icons.ttf b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.ttf
new file mode 100644
index 0000000..6cce217
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.ttf
Binary files differ
diff --git a/afb-client/bower_components/foundation-icon-fonts/foundation-icons.woff b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.woff
new file mode 100644
index 0000000..e2cfe25
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/foundation-icons.woff
Binary files differ
diff --git a/afb-client/bower_components/foundation-icon-fonts/index.html b/afb-client/bower_components/foundation-icon-fonts/index.html
new file mode 100644
index 0000000..cda4677
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/index.html
@@ -0,0 +1,3797 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Foundation Icons glyphs preview</title>
+ <link rel="stylesheet" href="foundation-icons.css" />
+
+ <style>
+ * {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ background: #fff;
+ color: #444;
+ font: 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ }
+
+ a,
+ a:visited {
+ color: #888;
+ text-decoration: underline;
+ }
+ a:hover,
+ a:focus { color: #000; }
+
+ h1 {
+ border-bottom: 2px solid #ddd;
+ color: #888;
+ font-size: 36px;
+ font-weight: 300;
+ margin-bottom: 20px;
+ padding: 20px 0;
+ }
+
+ .container {
+ margin: 0 auto;
+ min-width: 880px;
+ padding: 0 40px;
+ width: 80%;
+ }
+
+ .glyph {
+ border-bottom: 1px dotted #ccc;
+ padding: 10px 0 20px;
+ margin-bottom: 20px;
+ }
+
+ .preview-glyphs { vertical-align: bottom; }
+
+ .preview-scale {
+ color: #888;
+ font-size: 12px;
+ margin-top: 5px;
+ }
+
+ .step {
+ display: inline-block;
+ line-height: 1;
+ width: 10%;
+ }
+
+
+ .size-12 { font-size: 12px; }
+
+ .size-14 { font-size: 14px; }
+
+ .size-16 { font-size: 16px; }
+
+ .size-18 { font-size: 18px; }
+
+ .size-21 { font-size: 21px; }
+
+ .size-24 { font-size: 24px; }
+
+ .size-36 { font-size: 36px; }
+
+ .size-48 { font-size: 48px; }
+
+ .size-60 { font-size: 60px; }
+
+ .size-72 { font-size: 72px; }
+
+
+ .usage { margin-top: 10px; }
+
+ .usage input {
+ font-family: monospace;
+ margin-right: 3px;
+ padding: 2px 5px;
+ text-align: center;
+ }
+
+ .usage .point { width: 150px; }
+
+ .usage .class { width: 250px; }
+
+ .footer {
+ color: #888;
+ font-size: 12px;
+ padding: 20px 0;
+ }
+ </style>
+
+ <!--[if lte IE 8]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
+ </head>
+
+ <body>
+ <div class="container">
+ <h1>Foundation Icons contains 283 glyphs:</h1>
+
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-address-book size-12"></i><i class="step fi-address-book size-14"></i><i class="step fi-address-book size-16"></i><i class="step fi-address-book size-18"></i><i class="step fi-address-book size-21"></i><i class="step fi-address-book size-24"></i><i class="step fi-address-book size-36"></i><i class="step fi-address-book size-48"></i><i class="step fi-address-book size-60"></i><i class="step fi-address-book size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-address-book" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf100;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-alert size-12"></i><i class="step fi-alert size-14"></i><i class="step fi-alert size-16"></i><i class="step fi-alert size-18"></i><i class="step fi-alert size-21"></i><i class="step fi-alert size-24"></i><i class="step fi-alert size-36"></i><i class="step fi-alert size-48"></i><i class="step fi-alert size-60"></i><i class="step fi-alert size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-alert" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf101;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-align-center size-12"></i><i class="step fi-align-center size-14"></i><i class="step fi-align-center size-16"></i><i class="step fi-align-center size-18"></i><i class="step fi-align-center size-21"></i><i class="step fi-align-center size-24"></i><i class="step fi-align-center size-36"></i><i class="step fi-align-center size-48"></i><i class="step fi-align-center size-60"></i><i class="step fi-align-center size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-align-center" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf102;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-align-justify size-12"></i><i class="step fi-align-justify size-14"></i><i class="step fi-align-justify size-16"></i><i class="step fi-align-justify size-18"></i><i class="step fi-align-justify size-21"></i><i class="step fi-align-justify size-24"></i><i class="step fi-align-justify size-36"></i><i class="step fi-align-justify size-48"></i><i class="step fi-align-justify size-60"></i><i class="step fi-align-justify size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-align-justify" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf103;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-align-left size-12"></i><i class="step fi-align-left size-14"></i><i class="step fi-align-left size-16"></i><i class="step fi-align-left size-18"></i><i class="step fi-align-left size-21"></i><i class="step fi-align-left size-24"></i><i class="step fi-align-left size-36"></i><i class="step fi-align-left size-48"></i><i class="step fi-align-left size-60"></i><i class="step fi-align-left size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-align-left" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf104;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-align-right size-12"></i><i class="step fi-align-right size-14"></i><i class="step fi-align-right size-16"></i><i class="step fi-align-right size-18"></i><i class="step fi-align-right size-21"></i><i class="step fi-align-right size-24"></i><i class="step fi-align-right size-36"></i><i class="step fi-align-right size-48"></i><i class="step fi-align-right size-60"></i><i class="step fi-align-right size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-align-right" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf105;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-anchor size-12"></i><i class="step fi-anchor size-14"></i><i class="step fi-anchor size-16"></i><i class="step fi-anchor size-18"></i><i class="step fi-anchor size-21"></i><i class="step fi-anchor size-24"></i><i class="step fi-anchor size-36"></i><i class="step fi-anchor size-48"></i><i class="step fi-anchor size-60"></i><i class="step fi-anchor size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-anchor" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf106;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-annotate size-12"></i><i class="step fi-annotate size-14"></i><i class="step fi-annotate size-16"></i><i class="step fi-annotate size-18"></i><i class="step fi-annotate size-21"></i><i class="step fi-annotate size-24"></i><i class="step fi-annotate size-36"></i><i class="step fi-annotate size-48"></i><i class="step fi-annotate size-60"></i><i class="step fi-annotate size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-annotate" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf107;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-archive size-12"></i><i class="step fi-archive size-14"></i><i class="step fi-archive size-16"></i><i class="step fi-archive size-18"></i><i class="step fi-archive size-21"></i><i class="step fi-archive size-24"></i><i class="step fi-archive size-36"></i><i class="step fi-archive size-48"></i><i class="step fi-archive size-60"></i><i class="step fi-archive size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-archive" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf108;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrow-down size-12"></i><i class="step fi-arrow-down size-14"></i><i class="step fi-arrow-down size-16"></i><i class="step fi-arrow-down size-18"></i><i class="step fi-arrow-down size-21"></i><i class="step fi-arrow-down size-24"></i><i class="step fi-arrow-down size-36"></i><i class="step fi-arrow-down size-48"></i><i class="step fi-arrow-down size-60"></i><i class="step fi-arrow-down size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrow-down" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf109;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrow-left size-12"></i><i class="step fi-arrow-left size-14"></i><i class="step fi-arrow-left size-16"></i><i class="step fi-arrow-left size-18"></i><i class="step fi-arrow-left size-21"></i><i class="step fi-arrow-left size-24"></i><i class="step fi-arrow-left size-36"></i><i class="step fi-arrow-left size-48"></i><i class="step fi-arrow-left size-60"></i><i class="step fi-arrow-left size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrow-left" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrow-right size-12"></i><i class="step fi-arrow-right size-14"></i><i class="step fi-arrow-right size-16"></i><i class="step fi-arrow-right size-18"></i><i class="step fi-arrow-right size-21"></i><i class="step fi-arrow-right size-24"></i><i class="step fi-arrow-right size-36"></i><i class="step fi-arrow-right size-48"></i><i class="step fi-arrow-right size-60"></i><i class="step fi-arrow-right size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrow-right" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrow-up size-12"></i><i class="step fi-arrow-up size-14"></i><i class="step fi-arrow-up size-16"></i><i class="step fi-arrow-up size-18"></i><i class="step fi-arrow-up size-21"></i><i class="step fi-arrow-up size-24"></i><i class="step fi-arrow-up size-36"></i><i class="step fi-arrow-up size-48"></i><i class="step fi-arrow-up size-60"></i><i class="step fi-arrow-up size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrow-up" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrows-compress size-12"></i><i class="step fi-arrows-compress size-14"></i><i class="step fi-arrows-compress size-16"></i><i class="step fi-arrows-compress size-18"></i><i class="step fi-arrows-compress size-21"></i><i class="step fi-arrows-compress size-24"></i><i class="step fi-arrows-compress size-36"></i><i class="step fi-arrows-compress size-48"></i><i class="step fi-arrows-compress size-60"></i><i class="step fi-arrows-compress size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrows-compress" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrows-expand size-12"></i><i class="step fi-arrows-expand size-14"></i><i class="step fi-arrows-expand size-16"></i><i class="step fi-arrows-expand size-18"></i><i class="step fi-arrows-expand size-21"></i><i class="step fi-arrows-expand size-24"></i><i class="step fi-arrows-expand size-36"></i><i class="step fi-arrows-expand size-48"></i><i class="step fi-arrows-expand size-60"></i><i class="step fi-arrows-expand size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrows-expand" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrows-in size-12"></i><i class="step fi-arrows-in size-14"></i><i class="step fi-arrows-in size-16"></i><i class="step fi-arrows-in size-18"></i><i class="step fi-arrows-in size-21"></i><i class="step fi-arrows-in size-24"></i><i class="step fi-arrows-in size-36"></i><i class="step fi-arrows-in size-48"></i><i class="step fi-arrows-in size-60"></i><i class="step fi-arrows-in size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrows-in" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-arrows-out size-12"></i><i class="step fi-arrows-out size-14"></i><i class="step fi-arrows-out size-16"></i><i class="step fi-arrows-out size-18"></i><i class="step fi-arrows-out size-21"></i><i class="step fi-arrows-out size-24"></i><i class="step fi-arrows-out size-36"></i><i class="step fi-arrows-out size-48"></i><i class="step fi-arrows-out size-60"></i><i class="step fi-arrows-out size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-arrows-out" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf110;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-asl size-12"></i><i class="step fi-asl size-14"></i><i class="step fi-asl size-16"></i><i class="step fi-asl size-18"></i><i class="step fi-asl size-21"></i><i class="step fi-asl size-24"></i><i class="step fi-asl size-36"></i><i class="step fi-asl size-48"></i><i class="step fi-asl size-60"></i><i class="step fi-asl size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-asl" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf111;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-asterisk size-12"></i><i class="step fi-asterisk size-14"></i><i class="step fi-asterisk size-16"></i><i class="step fi-asterisk size-18"></i><i class="step fi-asterisk size-21"></i><i class="step fi-asterisk size-24"></i><i class="step fi-asterisk size-36"></i><i class="step fi-asterisk size-48"></i><i class="step fi-asterisk size-60"></i><i class="step fi-asterisk size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-asterisk" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf112;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-at-sign size-12"></i><i class="step fi-at-sign size-14"></i><i class="step fi-at-sign size-16"></i><i class="step fi-at-sign size-18"></i><i class="step fi-at-sign size-21"></i><i class="step fi-at-sign size-24"></i><i class="step fi-at-sign size-36"></i><i class="step fi-at-sign size-48"></i><i class="step fi-at-sign size-60"></i><i class="step fi-at-sign size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-at-sign" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf113;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-background-color size-12"></i><i class="step fi-background-color size-14"></i><i class="step fi-background-color size-16"></i><i class="step fi-background-color size-18"></i><i class="step fi-background-color size-21"></i><i class="step fi-background-color size-24"></i><i class="step fi-background-color size-36"></i><i class="step fi-background-color size-48"></i><i class="step fi-background-color size-60"></i><i class="step fi-background-color size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-background-color" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf114;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-battery-empty size-12"></i><i class="step fi-battery-empty size-14"></i><i class="step fi-battery-empty size-16"></i><i class="step fi-battery-empty size-18"></i><i class="step fi-battery-empty size-21"></i><i class="step fi-battery-empty size-24"></i><i class="step fi-battery-empty size-36"></i><i class="step fi-battery-empty size-48"></i><i class="step fi-battery-empty size-60"></i><i class="step fi-battery-empty size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-battery-empty" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf115;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-battery-full size-12"></i><i class="step fi-battery-full size-14"></i><i class="step fi-battery-full size-16"></i><i class="step fi-battery-full size-18"></i><i class="step fi-battery-full size-21"></i><i class="step fi-battery-full size-24"></i><i class="step fi-battery-full size-36"></i><i class="step fi-battery-full size-48"></i><i class="step fi-battery-full size-60"></i><i class="step fi-battery-full size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-battery-full" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf116;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-battery-half size-12"></i><i class="step fi-battery-half size-14"></i><i class="step fi-battery-half size-16"></i><i class="step fi-battery-half size-18"></i><i class="step fi-battery-half size-21"></i><i class="step fi-battery-half size-24"></i><i class="step fi-battery-half size-36"></i><i class="step fi-battery-half size-48"></i><i class="step fi-battery-half size-60"></i><i class="step fi-battery-half size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-battery-half" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf117;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-bitcoin-circle size-12"></i><i class="step fi-bitcoin-circle size-14"></i><i class="step fi-bitcoin-circle size-16"></i><i class="step fi-bitcoin-circle size-18"></i><i class="step fi-bitcoin-circle size-21"></i><i class="step fi-bitcoin-circle size-24"></i><i class="step fi-bitcoin-circle size-36"></i><i class="step fi-bitcoin-circle size-48"></i><i class="step fi-bitcoin-circle size-60"></i><i class="step fi-bitcoin-circle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-bitcoin-circle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf118;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-bitcoin size-12"></i><i class="step fi-bitcoin size-14"></i><i class="step fi-bitcoin size-16"></i><i class="step fi-bitcoin size-18"></i><i class="step fi-bitcoin size-21"></i><i class="step fi-bitcoin size-24"></i><i class="step fi-bitcoin size-36"></i><i class="step fi-bitcoin size-48"></i><i class="step fi-bitcoin size-60"></i><i class="step fi-bitcoin size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-bitcoin" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf119;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-blind size-12"></i><i class="step fi-blind size-14"></i><i class="step fi-blind size-16"></i><i class="step fi-blind size-18"></i><i class="step fi-blind size-21"></i><i class="step fi-blind size-24"></i><i class="step fi-blind size-36"></i><i class="step fi-blind size-48"></i><i class="step fi-blind size-60"></i><i class="step fi-blind size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-blind" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-bluetooth size-12"></i><i class="step fi-bluetooth size-14"></i><i class="step fi-bluetooth size-16"></i><i class="step fi-bluetooth size-18"></i><i class="step fi-bluetooth size-21"></i><i class="step fi-bluetooth size-24"></i><i class="step fi-bluetooth size-36"></i><i class="step fi-bluetooth size-48"></i><i class="step fi-bluetooth size-60"></i><i class="step fi-bluetooth size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-bluetooth" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-bold size-12"></i><i class="step fi-bold size-14"></i><i class="step fi-bold size-16"></i><i class="step fi-bold size-18"></i><i class="step fi-bold size-21"></i><i class="step fi-bold size-24"></i><i class="step fi-bold size-36"></i><i class="step fi-bold size-48"></i><i class="step fi-bold size-60"></i><i class="step fi-bold size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-bold" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-book-bookmark size-12"></i><i class="step fi-book-bookmark size-14"></i><i class="step fi-book-bookmark size-16"></i><i class="step fi-book-bookmark size-18"></i><i class="step fi-book-bookmark size-21"></i><i class="step fi-book-bookmark size-24"></i><i class="step fi-book-bookmark size-36"></i><i class="step fi-book-bookmark size-48"></i><i class="step fi-book-bookmark size-60"></i><i class="step fi-book-bookmark size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-book-bookmark" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-book size-12"></i><i class="step fi-book size-14"></i><i class="step fi-book size-16"></i><i class="step fi-book size-18"></i><i class="step fi-book size-21"></i><i class="step fi-book size-24"></i><i class="step fi-book size-36"></i><i class="step fi-book size-48"></i><i class="step fi-book size-60"></i><i class="step fi-book size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-book" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-bookmark size-12"></i><i class="step fi-bookmark size-14"></i><i class="step fi-bookmark size-16"></i><i class="step fi-bookmark size-18"></i><i class="step fi-bookmark size-21"></i><i class="step fi-bookmark size-24"></i><i class="step fi-bookmark size-36"></i><i class="step fi-bookmark size-48"></i><i class="step fi-bookmark size-60"></i><i class="step fi-bookmark size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-bookmark" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-braille size-12"></i><i class="step fi-braille size-14"></i><i class="step fi-braille size-16"></i><i class="step fi-braille size-18"></i><i class="step fi-braille size-21"></i><i class="step fi-braille size-24"></i><i class="step fi-braille size-36"></i><i class="step fi-braille size-48"></i><i class="step fi-braille size-60"></i><i class="step fi-braille size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-braille" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf120;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-burst-new size-12"></i><i class="step fi-burst-new size-14"></i><i class="step fi-burst-new size-16"></i><i class="step fi-burst-new size-18"></i><i class="step fi-burst-new size-21"></i><i class="step fi-burst-new size-24"></i><i class="step fi-burst-new size-36"></i><i class="step fi-burst-new size-48"></i><i class="step fi-burst-new size-60"></i><i class="step fi-burst-new size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-burst-new" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf121;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-burst-sale size-12"></i><i class="step fi-burst-sale size-14"></i><i class="step fi-burst-sale size-16"></i><i class="step fi-burst-sale size-18"></i><i class="step fi-burst-sale size-21"></i><i class="step fi-burst-sale size-24"></i><i class="step fi-burst-sale size-36"></i><i class="step fi-burst-sale size-48"></i><i class="step fi-burst-sale size-60"></i><i class="step fi-burst-sale size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-burst-sale" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf122;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-burst size-12"></i><i class="step fi-burst size-14"></i><i class="step fi-burst size-16"></i><i class="step fi-burst size-18"></i><i class="step fi-burst size-21"></i><i class="step fi-burst size-24"></i><i class="step fi-burst size-36"></i><i class="step fi-burst size-48"></i><i class="step fi-burst size-60"></i><i class="step fi-burst size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-burst" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf123;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-calendar size-12"></i><i class="step fi-calendar size-14"></i><i class="step fi-calendar size-16"></i><i class="step fi-calendar size-18"></i><i class="step fi-calendar size-21"></i><i class="step fi-calendar size-24"></i><i class="step fi-calendar size-36"></i><i class="step fi-calendar size-48"></i><i class="step fi-calendar size-60"></i><i class="step fi-calendar size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-calendar" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf124;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-camera size-12"></i><i class="step fi-camera size-14"></i><i class="step fi-camera size-16"></i><i class="step fi-camera size-18"></i><i class="step fi-camera size-21"></i><i class="step fi-camera size-24"></i><i class="step fi-camera size-36"></i><i class="step fi-camera size-48"></i><i class="step fi-camera size-60"></i><i class="step fi-camera size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-camera" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf125;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-check size-12"></i><i class="step fi-check size-14"></i><i class="step fi-check size-16"></i><i class="step fi-check size-18"></i><i class="step fi-check size-21"></i><i class="step fi-check size-24"></i><i class="step fi-check size-36"></i><i class="step fi-check size-48"></i><i class="step fi-check size-60"></i><i class="step fi-check size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-check" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf126;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-checkbox size-12"></i><i class="step fi-checkbox size-14"></i><i class="step fi-checkbox size-16"></i><i class="step fi-checkbox size-18"></i><i class="step fi-checkbox size-21"></i><i class="step fi-checkbox size-24"></i><i class="step fi-checkbox size-36"></i><i class="step fi-checkbox size-48"></i><i class="step fi-checkbox size-60"></i><i class="step fi-checkbox size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-checkbox" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf127;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-clipboard-notes size-12"></i><i class="step fi-clipboard-notes size-14"></i><i class="step fi-clipboard-notes size-16"></i><i class="step fi-clipboard-notes size-18"></i><i class="step fi-clipboard-notes size-21"></i><i class="step fi-clipboard-notes size-24"></i><i class="step fi-clipboard-notes size-36"></i><i class="step fi-clipboard-notes size-48"></i><i class="step fi-clipboard-notes size-60"></i><i class="step fi-clipboard-notes size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-clipboard-notes" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf128;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-clipboard-pencil size-12"></i><i class="step fi-clipboard-pencil size-14"></i><i class="step fi-clipboard-pencil size-16"></i><i class="step fi-clipboard-pencil size-18"></i><i class="step fi-clipboard-pencil size-21"></i><i class="step fi-clipboard-pencil size-24"></i><i class="step fi-clipboard-pencil size-36"></i><i class="step fi-clipboard-pencil size-48"></i><i class="step fi-clipboard-pencil size-60"></i><i class="step fi-clipboard-pencil size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-clipboard-pencil" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf129;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-clipboard size-12"></i><i class="step fi-clipboard size-14"></i><i class="step fi-clipboard size-16"></i><i class="step fi-clipboard size-18"></i><i class="step fi-clipboard size-21"></i><i class="step fi-clipboard size-24"></i><i class="step fi-clipboard size-36"></i><i class="step fi-clipboard size-48"></i><i class="step fi-clipboard size-60"></i><i class="step fi-clipboard size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-clipboard" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-clock size-12"></i><i class="step fi-clock size-14"></i><i class="step fi-clock size-16"></i><i class="step fi-clock size-18"></i><i class="step fi-clock size-21"></i><i class="step fi-clock size-24"></i><i class="step fi-clock size-36"></i><i class="step fi-clock size-48"></i><i class="step fi-clock size-60"></i><i class="step fi-clock size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-clock" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-closed-caption size-12"></i><i class="step fi-closed-caption size-14"></i><i class="step fi-closed-caption size-16"></i><i class="step fi-closed-caption size-18"></i><i class="step fi-closed-caption size-21"></i><i class="step fi-closed-caption size-24"></i><i class="step fi-closed-caption size-36"></i><i class="step fi-closed-caption size-48"></i><i class="step fi-closed-caption size-60"></i><i class="step fi-closed-caption size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-closed-caption" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-cloud size-12"></i><i class="step fi-cloud size-14"></i><i class="step fi-cloud size-16"></i><i class="step fi-cloud size-18"></i><i class="step fi-cloud size-21"></i><i class="step fi-cloud size-24"></i><i class="step fi-cloud size-36"></i><i class="step fi-cloud size-48"></i><i class="step fi-cloud size-60"></i><i class="step fi-cloud size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-cloud" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-comment-minus size-12"></i><i class="step fi-comment-minus size-14"></i><i class="step fi-comment-minus size-16"></i><i class="step fi-comment-minus size-18"></i><i class="step fi-comment-minus size-21"></i><i class="step fi-comment-minus size-24"></i><i class="step fi-comment-minus size-36"></i><i class="step fi-comment-minus size-48"></i><i class="step fi-comment-minus size-60"></i><i class="step fi-comment-minus size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-comment-minus" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-comment-quotes size-12"></i><i class="step fi-comment-quotes size-14"></i><i class="step fi-comment-quotes size-16"></i><i class="step fi-comment-quotes size-18"></i><i class="step fi-comment-quotes size-21"></i><i class="step fi-comment-quotes size-24"></i><i class="step fi-comment-quotes size-36"></i><i class="step fi-comment-quotes size-48"></i><i class="step fi-comment-quotes size-60"></i><i class="step fi-comment-quotes size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-comment-quotes" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-comment-video size-12"></i><i class="step fi-comment-video size-14"></i><i class="step fi-comment-video size-16"></i><i class="step fi-comment-video size-18"></i><i class="step fi-comment-video size-21"></i><i class="step fi-comment-video size-24"></i><i class="step fi-comment-video size-36"></i><i class="step fi-comment-video size-48"></i><i class="step fi-comment-video size-60"></i><i class="step fi-comment-video size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-comment-video" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf130;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-comment size-12"></i><i class="step fi-comment size-14"></i><i class="step fi-comment size-16"></i><i class="step fi-comment size-18"></i><i class="step fi-comment size-21"></i><i class="step fi-comment size-24"></i><i class="step fi-comment size-36"></i><i class="step fi-comment size-48"></i><i class="step fi-comment size-60"></i><i class="step fi-comment size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-comment" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf131;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-comments size-12"></i><i class="step fi-comments size-14"></i><i class="step fi-comments size-16"></i><i class="step fi-comments size-18"></i><i class="step fi-comments size-21"></i><i class="step fi-comments size-24"></i><i class="step fi-comments size-36"></i><i class="step fi-comments size-48"></i><i class="step fi-comments size-60"></i><i class="step fi-comments size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-comments" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf132;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-compass size-12"></i><i class="step fi-compass size-14"></i><i class="step fi-compass size-16"></i><i class="step fi-compass size-18"></i><i class="step fi-compass size-21"></i><i class="step fi-compass size-24"></i><i class="step fi-compass size-36"></i><i class="step fi-compass size-48"></i><i class="step fi-compass size-60"></i><i class="step fi-compass size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-compass" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf133;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-contrast size-12"></i><i class="step fi-contrast size-14"></i><i class="step fi-contrast size-16"></i><i class="step fi-contrast size-18"></i><i class="step fi-contrast size-21"></i><i class="step fi-contrast size-24"></i><i class="step fi-contrast size-36"></i><i class="step fi-contrast size-48"></i><i class="step fi-contrast size-60"></i><i class="step fi-contrast size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-contrast" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf134;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-credit-card size-12"></i><i class="step fi-credit-card size-14"></i><i class="step fi-credit-card size-16"></i><i class="step fi-credit-card size-18"></i><i class="step fi-credit-card size-21"></i><i class="step fi-credit-card size-24"></i><i class="step fi-credit-card size-36"></i><i class="step fi-credit-card size-48"></i><i class="step fi-credit-card size-60"></i><i class="step fi-credit-card size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-credit-card" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf135;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-crop size-12"></i><i class="step fi-crop size-14"></i><i class="step fi-crop size-16"></i><i class="step fi-crop size-18"></i><i class="step fi-crop size-21"></i><i class="step fi-crop size-24"></i><i class="step fi-crop size-36"></i><i class="step fi-crop size-48"></i><i class="step fi-crop size-60"></i><i class="step fi-crop size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-crop" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf136;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-crown size-12"></i><i class="step fi-crown size-14"></i><i class="step fi-crown size-16"></i><i class="step fi-crown size-18"></i><i class="step fi-crown size-21"></i><i class="step fi-crown size-24"></i><i class="step fi-crown size-36"></i><i class="step fi-crown size-48"></i><i class="step fi-crown size-60"></i><i class="step fi-crown size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-crown" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf137;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-css3 size-12"></i><i class="step fi-css3 size-14"></i><i class="step fi-css3 size-16"></i><i class="step fi-css3 size-18"></i><i class="step fi-css3 size-21"></i><i class="step fi-css3 size-24"></i><i class="step fi-css3 size-36"></i><i class="step fi-css3 size-48"></i><i class="step fi-css3 size-60"></i><i class="step fi-css3 size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-css3" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf138;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-database size-12"></i><i class="step fi-database size-14"></i><i class="step fi-database size-16"></i><i class="step fi-database size-18"></i><i class="step fi-database size-21"></i><i class="step fi-database size-24"></i><i class="step fi-database size-36"></i><i class="step fi-database size-48"></i><i class="step fi-database size-60"></i><i class="step fi-database size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-database" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf139;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-five size-12"></i><i class="step fi-die-five size-14"></i><i class="step fi-die-five size-16"></i><i class="step fi-die-five size-18"></i><i class="step fi-die-five size-21"></i><i class="step fi-die-five size-24"></i><i class="step fi-die-five size-36"></i><i class="step fi-die-five size-48"></i><i class="step fi-die-five size-60"></i><i class="step fi-die-five size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-five" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-four size-12"></i><i class="step fi-die-four size-14"></i><i class="step fi-die-four size-16"></i><i class="step fi-die-four size-18"></i><i class="step fi-die-four size-21"></i><i class="step fi-die-four size-24"></i><i class="step fi-die-four size-36"></i><i class="step fi-die-four size-48"></i><i class="step fi-die-four size-60"></i><i class="step fi-die-four size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-four" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-one size-12"></i><i class="step fi-die-one size-14"></i><i class="step fi-die-one size-16"></i><i class="step fi-die-one size-18"></i><i class="step fi-die-one size-21"></i><i class="step fi-die-one size-24"></i><i class="step fi-die-one size-36"></i><i class="step fi-die-one size-48"></i><i class="step fi-die-one size-60"></i><i class="step fi-die-one size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-one" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-six size-12"></i><i class="step fi-die-six size-14"></i><i class="step fi-die-six size-16"></i><i class="step fi-die-six size-18"></i><i class="step fi-die-six size-21"></i><i class="step fi-die-six size-24"></i><i class="step fi-die-six size-36"></i><i class="step fi-die-six size-48"></i><i class="step fi-die-six size-60"></i><i class="step fi-die-six size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-six" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-three size-12"></i><i class="step fi-die-three size-14"></i><i class="step fi-die-three size-16"></i><i class="step fi-die-three size-18"></i><i class="step fi-die-three size-21"></i><i class="step fi-die-three size-24"></i><i class="step fi-die-three size-36"></i><i class="step fi-die-three size-48"></i><i class="step fi-die-three size-60"></i><i class="step fi-die-three size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-three" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-die-two size-12"></i><i class="step fi-die-two size-14"></i><i class="step fi-die-two size-16"></i><i class="step fi-die-two size-18"></i><i class="step fi-die-two size-21"></i><i class="step fi-die-two size-24"></i><i class="step fi-die-two size-36"></i><i class="step fi-die-two size-48"></i><i class="step fi-die-two size-60"></i><i class="step fi-die-two size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-die-two" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf13f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-dislike size-12"></i><i class="step fi-dislike size-14"></i><i class="step fi-dislike size-16"></i><i class="step fi-dislike size-18"></i><i class="step fi-dislike size-21"></i><i class="step fi-dislike size-24"></i><i class="step fi-dislike size-36"></i><i class="step fi-dislike size-48"></i><i class="step fi-dislike size-60"></i><i class="step fi-dislike size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-dislike" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf140;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-dollar-bill size-12"></i><i class="step fi-dollar-bill size-14"></i><i class="step fi-dollar-bill size-16"></i><i class="step fi-dollar-bill size-18"></i><i class="step fi-dollar-bill size-21"></i><i class="step fi-dollar-bill size-24"></i><i class="step fi-dollar-bill size-36"></i><i class="step fi-dollar-bill size-48"></i><i class="step fi-dollar-bill size-60"></i><i class="step fi-dollar-bill size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-dollar-bill" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf141;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-dollar size-12"></i><i class="step fi-dollar size-14"></i><i class="step fi-dollar size-16"></i><i class="step fi-dollar size-18"></i><i class="step fi-dollar size-21"></i><i class="step fi-dollar size-24"></i><i class="step fi-dollar size-36"></i><i class="step fi-dollar size-48"></i><i class="step fi-dollar size-60"></i><i class="step fi-dollar size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-dollar" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf142;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-download size-12"></i><i class="step fi-download size-14"></i><i class="step fi-download size-16"></i><i class="step fi-download size-18"></i><i class="step fi-download size-21"></i><i class="step fi-download size-24"></i><i class="step fi-download size-36"></i><i class="step fi-download size-48"></i><i class="step fi-download size-60"></i><i class="step fi-download size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-download" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf143;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-eject size-12"></i><i class="step fi-eject size-14"></i><i class="step fi-eject size-16"></i><i class="step fi-eject size-18"></i><i class="step fi-eject size-21"></i><i class="step fi-eject size-24"></i><i class="step fi-eject size-36"></i><i class="step fi-eject size-48"></i><i class="step fi-eject size-60"></i><i class="step fi-eject size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-eject" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf144;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-elevator size-12"></i><i class="step fi-elevator size-14"></i><i class="step fi-elevator size-16"></i><i class="step fi-elevator size-18"></i><i class="step fi-elevator size-21"></i><i class="step fi-elevator size-24"></i><i class="step fi-elevator size-36"></i><i class="step fi-elevator size-48"></i><i class="step fi-elevator size-60"></i><i class="step fi-elevator size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-elevator" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf145;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-euro size-12"></i><i class="step fi-euro size-14"></i><i class="step fi-euro size-16"></i><i class="step fi-euro size-18"></i><i class="step fi-euro size-21"></i><i class="step fi-euro size-24"></i><i class="step fi-euro size-36"></i><i class="step fi-euro size-48"></i><i class="step fi-euro size-60"></i><i class="step fi-euro size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-euro" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf146;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-eye size-12"></i><i class="step fi-eye size-14"></i><i class="step fi-eye size-16"></i><i class="step fi-eye size-18"></i><i class="step fi-eye size-21"></i><i class="step fi-eye size-24"></i><i class="step fi-eye size-36"></i><i class="step fi-eye size-48"></i><i class="step fi-eye size-60"></i><i class="step fi-eye size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-eye" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf147;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-fast-forward size-12"></i><i class="step fi-fast-forward size-14"></i><i class="step fi-fast-forward size-16"></i><i class="step fi-fast-forward size-18"></i><i class="step fi-fast-forward size-21"></i><i class="step fi-fast-forward size-24"></i><i class="step fi-fast-forward size-36"></i><i class="step fi-fast-forward size-48"></i><i class="step fi-fast-forward size-60"></i><i class="step fi-fast-forward size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-fast-forward" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf148;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-female-symbol size-12"></i><i class="step fi-female-symbol size-14"></i><i class="step fi-female-symbol size-16"></i><i class="step fi-female-symbol size-18"></i><i class="step fi-female-symbol size-21"></i><i class="step fi-female-symbol size-24"></i><i class="step fi-female-symbol size-36"></i><i class="step fi-female-symbol size-48"></i><i class="step fi-female-symbol size-60"></i><i class="step fi-female-symbol size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-female-symbol" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf149;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-female size-12"></i><i class="step fi-female size-14"></i><i class="step fi-female size-16"></i><i class="step fi-female size-18"></i><i class="step fi-female size-21"></i><i class="step fi-female size-24"></i><i class="step fi-female size-36"></i><i class="step fi-female size-48"></i><i class="step fi-female size-60"></i><i class="step fi-female size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-female" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-filter size-12"></i><i class="step fi-filter size-14"></i><i class="step fi-filter size-16"></i><i class="step fi-filter size-18"></i><i class="step fi-filter size-21"></i><i class="step fi-filter size-24"></i><i class="step fi-filter size-36"></i><i class="step fi-filter size-48"></i><i class="step fi-filter size-60"></i><i class="step fi-filter size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-filter" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-first-aid size-12"></i><i class="step fi-first-aid size-14"></i><i class="step fi-first-aid size-16"></i><i class="step fi-first-aid size-18"></i><i class="step fi-first-aid size-21"></i><i class="step fi-first-aid size-24"></i><i class="step fi-first-aid size-36"></i><i class="step fi-first-aid size-48"></i><i class="step fi-first-aid size-60"></i><i class="step fi-first-aid size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-first-aid" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-flag size-12"></i><i class="step fi-flag size-14"></i><i class="step fi-flag size-16"></i><i class="step fi-flag size-18"></i><i class="step fi-flag size-21"></i><i class="step fi-flag size-24"></i><i class="step fi-flag size-36"></i><i class="step fi-flag size-48"></i><i class="step fi-flag size-60"></i><i class="step fi-flag size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-flag" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-folder-add size-12"></i><i class="step fi-folder-add size-14"></i><i class="step fi-folder-add size-16"></i><i class="step fi-folder-add size-18"></i><i class="step fi-folder-add size-21"></i><i class="step fi-folder-add size-24"></i><i class="step fi-folder-add size-36"></i><i class="step fi-folder-add size-48"></i><i class="step fi-folder-add size-60"></i><i class="step fi-folder-add size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-folder-add" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-folder-lock size-12"></i><i class="step fi-folder-lock size-14"></i><i class="step fi-folder-lock size-16"></i><i class="step fi-folder-lock size-18"></i><i class="step fi-folder-lock size-21"></i><i class="step fi-folder-lock size-24"></i><i class="step fi-folder-lock size-36"></i><i class="step fi-folder-lock size-48"></i><i class="step fi-folder-lock size-60"></i><i class="step fi-folder-lock size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-folder-lock" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf14f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-folder size-12"></i><i class="step fi-folder size-14"></i><i class="step fi-folder size-16"></i><i class="step fi-folder size-18"></i><i class="step fi-folder size-21"></i><i class="step fi-folder size-24"></i><i class="step fi-folder size-36"></i><i class="step fi-folder size-48"></i><i class="step fi-folder size-60"></i><i class="step fi-folder size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-folder" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf150;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-foot size-12"></i><i class="step fi-foot size-14"></i><i class="step fi-foot size-16"></i><i class="step fi-foot size-18"></i><i class="step fi-foot size-21"></i><i class="step fi-foot size-24"></i><i class="step fi-foot size-36"></i><i class="step fi-foot size-48"></i><i class="step fi-foot size-60"></i><i class="step fi-foot size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-foot" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf151;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-foundation size-12"></i><i class="step fi-foundation size-14"></i><i class="step fi-foundation size-16"></i><i class="step fi-foundation size-18"></i><i class="step fi-foundation size-21"></i><i class="step fi-foundation size-24"></i><i class="step fi-foundation size-36"></i><i class="step fi-foundation size-48"></i><i class="step fi-foundation size-60"></i><i class="step fi-foundation size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-foundation" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf152;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-graph-bar size-12"></i><i class="step fi-graph-bar size-14"></i><i class="step fi-graph-bar size-16"></i><i class="step fi-graph-bar size-18"></i><i class="step fi-graph-bar size-21"></i><i class="step fi-graph-bar size-24"></i><i class="step fi-graph-bar size-36"></i><i class="step fi-graph-bar size-48"></i><i class="step fi-graph-bar size-60"></i><i class="step fi-graph-bar size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-graph-bar" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf153;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-graph-horizontal size-12"></i><i class="step fi-graph-horizontal size-14"></i><i class="step fi-graph-horizontal size-16"></i><i class="step fi-graph-horizontal size-18"></i><i class="step fi-graph-horizontal size-21"></i><i class="step fi-graph-horizontal size-24"></i><i class="step fi-graph-horizontal size-36"></i><i class="step fi-graph-horizontal size-48"></i><i class="step fi-graph-horizontal size-60"></i><i class="step fi-graph-horizontal size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-graph-horizontal" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf154;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-graph-pie size-12"></i><i class="step fi-graph-pie size-14"></i><i class="step fi-graph-pie size-16"></i><i class="step fi-graph-pie size-18"></i><i class="step fi-graph-pie size-21"></i><i class="step fi-graph-pie size-24"></i><i class="step fi-graph-pie size-36"></i><i class="step fi-graph-pie size-48"></i><i class="step fi-graph-pie size-60"></i><i class="step fi-graph-pie size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-graph-pie" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf155;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-graph-trend size-12"></i><i class="step fi-graph-trend size-14"></i><i class="step fi-graph-trend size-16"></i><i class="step fi-graph-trend size-18"></i><i class="step fi-graph-trend size-21"></i><i class="step fi-graph-trend size-24"></i><i class="step fi-graph-trend size-36"></i><i class="step fi-graph-trend size-48"></i><i class="step fi-graph-trend size-60"></i><i class="step fi-graph-trend size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-graph-trend" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf156;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-guide-dog size-12"></i><i class="step fi-guide-dog size-14"></i><i class="step fi-guide-dog size-16"></i><i class="step fi-guide-dog size-18"></i><i class="step fi-guide-dog size-21"></i><i class="step fi-guide-dog size-24"></i><i class="step fi-guide-dog size-36"></i><i class="step fi-guide-dog size-48"></i><i class="step fi-guide-dog size-60"></i><i class="step fi-guide-dog size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-guide-dog" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf157;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-hearing-aid size-12"></i><i class="step fi-hearing-aid size-14"></i><i class="step fi-hearing-aid size-16"></i><i class="step fi-hearing-aid size-18"></i><i class="step fi-hearing-aid size-21"></i><i class="step fi-hearing-aid size-24"></i><i class="step fi-hearing-aid size-36"></i><i class="step fi-hearing-aid size-48"></i><i class="step fi-hearing-aid size-60"></i><i class="step fi-hearing-aid size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-hearing-aid" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf158;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-heart size-12"></i><i class="step fi-heart size-14"></i><i class="step fi-heart size-16"></i><i class="step fi-heart size-18"></i><i class="step fi-heart size-21"></i><i class="step fi-heart size-24"></i><i class="step fi-heart size-36"></i><i class="step fi-heart size-48"></i><i class="step fi-heart size-60"></i><i class="step fi-heart size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-heart" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf159;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-home size-12"></i><i class="step fi-home size-14"></i><i class="step fi-home size-16"></i><i class="step fi-home size-18"></i><i class="step fi-home size-21"></i><i class="step fi-home size-24"></i><i class="step fi-home size-36"></i><i class="step fi-home size-48"></i><i class="step fi-home size-60"></i><i class="step fi-home size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-home" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-html5 size-12"></i><i class="step fi-html5 size-14"></i><i class="step fi-html5 size-16"></i><i class="step fi-html5 size-18"></i><i class="step fi-html5 size-21"></i><i class="step fi-html5 size-24"></i><i class="step fi-html5 size-36"></i><i class="step fi-html5 size-48"></i><i class="step fi-html5 size-60"></i><i class="step fi-html5 size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-html5" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-indent-less size-12"></i><i class="step fi-indent-less size-14"></i><i class="step fi-indent-less size-16"></i><i class="step fi-indent-less size-18"></i><i class="step fi-indent-less size-21"></i><i class="step fi-indent-less size-24"></i><i class="step fi-indent-less size-36"></i><i class="step fi-indent-less size-48"></i><i class="step fi-indent-less size-60"></i><i class="step fi-indent-less size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-indent-less" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-indent-more size-12"></i><i class="step fi-indent-more size-14"></i><i class="step fi-indent-more size-16"></i><i class="step fi-indent-more size-18"></i><i class="step fi-indent-more size-21"></i><i class="step fi-indent-more size-24"></i><i class="step fi-indent-more size-36"></i><i class="step fi-indent-more size-48"></i><i class="step fi-indent-more size-60"></i><i class="step fi-indent-more size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-indent-more" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-info size-12"></i><i class="step fi-info size-14"></i><i class="step fi-info size-16"></i><i class="step fi-info size-18"></i><i class="step fi-info size-21"></i><i class="step fi-info size-24"></i><i class="step fi-info size-36"></i><i class="step fi-info size-48"></i><i class="step fi-info size-60"></i><i class="step fi-info size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-info" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-italic size-12"></i><i class="step fi-italic size-14"></i><i class="step fi-italic size-16"></i><i class="step fi-italic size-18"></i><i class="step fi-italic size-21"></i><i class="step fi-italic size-24"></i><i class="step fi-italic size-36"></i><i class="step fi-italic size-48"></i><i class="step fi-italic size-60"></i><i class="step fi-italic size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-italic" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf15f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-key size-12"></i><i class="step fi-key size-14"></i><i class="step fi-key size-16"></i><i class="step fi-key size-18"></i><i class="step fi-key size-21"></i><i class="step fi-key size-24"></i><i class="step fi-key size-36"></i><i class="step fi-key size-48"></i><i class="step fi-key size-60"></i><i class="step fi-key size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-key" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf160;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-laptop size-12"></i><i class="step fi-laptop size-14"></i><i class="step fi-laptop size-16"></i><i class="step fi-laptop size-18"></i><i class="step fi-laptop size-21"></i><i class="step fi-laptop size-24"></i><i class="step fi-laptop size-36"></i><i class="step fi-laptop size-48"></i><i class="step fi-laptop size-60"></i><i class="step fi-laptop size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-laptop" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf161;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-layout size-12"></i><i class="step fi-layout size-14"></i><i class="step fi-layout size-16"></i><i class="step fi-layout size-18"></i><i class="step fi-layout size-21"></i><i class="step fi-layout size-24"></i><i class="step fi-layout size-36"></i><i class="step fi-layout size-48"></i><i class="step fi-layout size-60"></i><i class="step fi-layout size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-layout" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf162;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-lightbulb size-12"></i><i class="step fi-lightbulb size-14"></i><i class="step fi-lightbulb size-16"></i><i class="step fi-lightbulb size-18"></i><i class="step fi-lightbulb size-21"></i><i class="step fi-lightbulb size-24"></i><i class="step fi-lightbulb size-36"></i><i class="step fi-lightbulb size-48"></i><i class="step fi-lightbulb size-60"></i><i class="step fi-lightbulb size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-lightbulb" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf163;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-like size-12"></i><i class="step fi-like size-14"></i><i class="step fi-like size-16"></i><i class="step fi-like size-18"></i><i class="step fi-like size-21"></i><i class="step fi-like size-24"></i><i class="step fi-like size-36"></i><i class="step fi-like size-48"></i><i class="step fi-like size-60"></i><i class="step fi-like size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-like" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf164;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-link size-12"></i><i class="step fi-link size-14"></i><i class="step fi-link size-16"></i><i class="step fi-link size-18"></i><i class="step fi-link size-21"></i><i class="step fi-link size-24"></i><i class="step fi-link size-36"></i><i class="step fi-link size-48"></i><i class="step fi-link size-60"></i><i class="step fi-link size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-link" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf165;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-list-bullet size-12"></i><i class="step fi-list-bullet size-14"></i><i class="step fi-list-bullet size-16"></i><i class="step fi-list-bullet size-18"></i><i class="step fi-list-bullet size-21"></i><i class="step fi-list-bullet size-24"></i><i class="step fi-list-bullet size-36"></i><i class="step fi-list-bullet size-48"></i><i class="step fi-list-bullet size-60"></i><i class="step fi-list-bullet size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-list-bullet" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf166;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-list-number size-12"></i><i class="step fi-list-number size-14"></i><i class="step fi-list-number size-16"></i><i class="step fi-list-number size-18"></i><i class="step fi-list-number size-21"></i><i class="step fi-list-number size-24"></i><i class="step fi-list-number size-36"></i><i class="step fi-list-number size-48"></i><i class="step fi-list-number size-60"></i><i class="step fi-list-number size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-list-number" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf167;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-list-thumbnails size-12"></i><i class="step fi-list-thumbnails size-14"></i><i class="step fi-list-thumbnails size-16"></i><i class="step fi-list-thumbnails size-18"></i><i class="step fi-list-thumbnails size-21"></i><i class="step fi-list-thumbnails size-24"></i><i class="step fi-list-thumbnails size-36"></i><i class="step fi-list-thumbnails size-48"></i><i class="step fi-list-thumbnails size-60"></i><i class="step fi-list-thumbnails size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-list-thumbnails" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf168;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-list size-12"></i><i class="step fi-list size-14"></i><i class="step fi-list size-16"></i><i class="step fi-list size-18"></i><i class="step fi-list size-21"></i><i class="step fi-list size-24"></i><i class="step fi-list size-36"></i><i class="step fi-list size-48"></i><i class="step fi-list size-60"></i><i class="step fi-list size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-list" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf169;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-lock size-12"></i><i class="step fi-lock size-14"></i><i class="step fi-lock size-16"></i><i class="step fi-lock size-18"></i><i class="step fi-lock size-21"></i><i class="step fi-lock size-24"></i><i class="step fi-lock size-36"></i><i class="step fi-lock size-48"></i><i class="step fi-lock size-60"></i><i class="step fi-lock size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-lock" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-loop size-12"></i><i class="step fi-loop size-14"></i><i class="step fi-loop size-16"></i><i class="step fi-loop size-18"></i><i class="step fi-loop size-21"></i><i class="step fi-loop size-24"></i><i class="step fi-loop size-36"></i><i class="step fi-loop size-48"></i><i class="step fi-loop size-60"></i><i class="step fi-loop size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-loop" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-magnifying-glass size-12"></i><i class="step fi-magnifying-glass size-14"></i><i class="step fi-magnifying-glass size-16"></i><i class="step fi-magnifying-glass size-18"></i><i class="step fi-magnifying-glass size-21"></i><i class="step fi-magnifying-glass size-24"></i><i class="step fi-magnifying-glass size-36"></i><i class="step fi-magnifying-glass size-48"></i><i class="step fi-magnifying-glass size-60"></i><i class="step fi-magnifying-glass size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-magnifying-glass" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-mail size-12"></i><i class="step fi-mail size-14"></i><i class="step fi-mail size-16"></i><i class="step fi-mail size-18"></i><i class="step fi-mail size-21"></i><i class="step fi-mail size-24"></i><i class="step fi-mail size-36"></i><i class="step fi-mail size-48"></i><i class="step fi-mail size-60"></i><i class="step fi-mail size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-mail" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-male-female size-12"></i><i class="step fi-male-female size-14"></i><i class="step fi-male-female size-16"></i><i class="step fi-male-female size-18"></i><i class="step fi-male-female size-21"></i><i class="step fi-male-female size-24"></i><i class="step fi-male-female size-36"></i><i class="step fi-male-female size-48"></i><i class="step fi-male-female size-60"></i><i class="step fi-male-female size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-male-female" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-male-symbol size-12"></i><i class="step fi-male-symbol size-14"></i><i class="step fi-male-symbol size-16"></i><i class="step fi-male-symbol size-18"></i><i class="step fi-male-symbol size-21"></i><i class="step fi-male-symbol size-24"></i><i class="step fi-male-symbol size-36"></i><i class="step fi-male-symbol size-48"></i><i class="step fi-male-symbol size-60"></i><i class="step fi-male-symbol size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-male-symbol" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf16f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-male size-12"></i><i class="step fi-male size-14"></i><i class="step fi-male size-16"></i><i class="step fi-male size-18"></i><i class="step fi-male size-21"></i><i class="step fi-male size-24"></i><i class="step fi-male size-36"></i><i class="step fi-male size-48"></i><i class="step fi-male size-60"></i><i class="step fi-male size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-male" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf170;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-map size-12"></i><i class="step fi-map size-14"></i><i class="step fi-map size-16"></i><i class="step fi-map size-18"></i><i class="step fi-map size-21"></i><i class="step fi-map size-24"></i><i class="step fi-map size-36"></i><i class="step fi-map size-48"></i><i class="step fi-map size-60"></i><i class="step fi-map size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-map" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf171;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-marker size-12"></i><i class="step fi-marker size-14"></i><i class="step fi-marker size-16"></i><i class="step fi-marker size-18"></i><i class="step fi-marker size-21"></i><i class="step fi-marker size-24"></i><i class="step fi-marker size-36"></i><i class="step fi-marker size-48"></i><i class="step fi-marker size-60"></i><i class="step fi-marker size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-marker" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf172;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-megaphone size-12"></i><i class="step fi-megaphone size-14"></i><i class="step fi-megaphone size-16"></i><i class="step fi-megaphone size-18"></i><i class="step fi-megaphone size-21"></i><i class="step fi-megaphone size-24"></i><i class="step fi-megaphone size-36"></i><i class="step fi-megaphone size-48"></i><i class="step fi-megaphone size-60"></i><i class="step fi-megaphone size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-megaphone" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf173;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-microphone size-12"></i><i class="step fi-microphone size-14"></i><i class="step fi-microphone size-16"></i><i class="step fi-microphone size-18"></i><i class="step fi-microphone size-21"></i><i class="step fi-microphone size-24"></i><i class="step fi-microphone size-36"></i><i class="step fi-microphone size-48"></i><i class="step fi-microphone size-60"></i><i class="step fi-microphone size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-microphone" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf174;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-minus-circle size-12"></i><i class="step fi-minus-circle size-14"></i><i class="step fi-minus-circle size-16"></i><i class="step fi-minus-circle size-18"></i><i class="step fi-minus-circle size-21"></i><i class="step fi-minus-circle size-24"></i><i class="step fi-minus-circle size-36"></i><i class="step fi-minus-circle size-48"></i><i class="step fi-minus-circle size-60"></i><i class="step fi-minus-circle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-minus-circle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf175;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-minus size-12"></i><i class="step fi-minus size-14"></i><i class="step fi-minus size-16"></i><i class="step fi-minus size-18"></i><i class="step fi-minus size-21"></i><i class="step fi-minus size-24"></i><i class="step fi-minus size-36"></i><i class="step fi-minus size-48"></i><i class="step fi-minus size-60"></i><i class="step fi-minus size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-minus" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf176;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-mobile-signal size-12"></i><i class="step fi-mobile-signal size-14"></i><i class="step fi-mobile-signal size-16"></i><i class="step fi-mobile-signal size-18"></i><i class="step fi-mobile-signal size-21"></i><i class="step fi-mobile-signal size-24"></i><i class="step fi-mobile-signal size-36"></i><i class="step fi-mobile-signal size-48"></i><i class="step fi-mobile-signal size-60"></i><i class="step fi-mobile-signal size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-mobile-signal" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf177;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-mobile size-12"></i><i class="step fi-mobile size-14"></i><i class="step fi-mobile size-16"></i><i class="step fi-mobile size-18"></i><i class="step fi-mobile size-21"></i><i class="step fi-mobile size-24"></i><i class="step fi-mobile size-36"></i><i class="step fi-mobile size-48"></i><i class="step fi-mobile size-60"></i><i class="step fi-mobile size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-mobile" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf178;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-monitor size-12"></i><i class="step fi-monitor size-14"></i><i class="step fi-monitor size-16"></i><i class="step fi-monitor size-18"></i><i class="step fi-monitor size-21"></i><i class="step fi-monitor size-24"></i><i class="step fi-monitor size-36"></i><i class="step fi-monitor size-48"></i><i class="step fi-monitor size-60"></i><i class="step fi-monitor size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-monitor" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf179;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-mountains size-12"></i><i class="step fi-mountains size-14"></i><i class="step fi-mountains size-16"></i><i class="step fi-mountains size-18"></i><i class="step fi-mountains size-21"></i><i class="step fi-mountains size-24"></i><i class="step fi-mountains size-36"></i><i class="step fi-mountains size-48"></i><i class="step fi-mountains size-60"></i><i class="step fi-mountains size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-mountains" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-music size-12"></i><i class="step fi-music size-14"></i><i class="step fi-music size-16"></i><i class="step fi-music size-18"></i><i class="step fi-music size-21"></i><i class="step fi-music size-24"></i><i class="step fi-music size-36"></i><i class="step fi-music size-48"></i><i class="step fi-music size-60"></i><i class="step fi-music size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-music" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-next size-12"></i><i class="step fi-next size-14"></i><i class="step fi-next size-16"></i><i class="step fi-next size-18"></i><i class="step fi-next size-21"></i><i class="step fi-next size-24"></i><i class="step fi-next size-36"></i><i class="step fi-next size-48"></i><i class="step fi-next size-60"></i><i class="step fi-next size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-next" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-no-dogs size-12"></i><i class="step fi-no-dogs size-14"></i><i class="step fi-no-dogs size-16"></i><i class="step fi-no-dogs size-18"></i><i class="step fi-no-dogs size-21"></i><i class="step fi-no-dogs size-24"></i><i class="step fi-no-dogs size-36"></i><i class="step fi-no-dogs size-48"></i><i class="step fi-no-dogs size-60"></i><i class="step fi-no-dogs size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-no-dogs" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-no-smoking size-12"></i><i class="step fi-no-smoking size-14"></i><i class="step fi-no-smoking size-16"></i><i class="step fi-no-smoking size-18"></i><i class="step fi-no-smoking size-21"></i><i class="step fi-no-smoking size-24"></i><i class="step fi-no-smoking size-36"></i><i class="step fi-no-smoking size-48"></i><i class="step fi-no-smoking size-60"></i><i class="step fi-no-smoking size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-no-smoking" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-add size-12"></i><i class="step fi-page-add size-14"></i><i class="step fi-page-add size-16"></i><i class="step fi-page-add size-18"></i><i class="step fi-page-add size-21"></i><i class="step fi-page-add size-24"></i><i class="step fi-page-add size-36"></i><i class="step fi-page-add size-48"></i><i class="step fi-page-add size-60"></i><i class="step fi-page-add size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-add" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf17f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-copy size-12"></i><i class="step fi-page-copy size-14"></i><i class="step fi-page-copy size-16"></i><i class="step fi-page-copy size-18"></i><i class="step fi-page-copy size-21"></i><i class="step fi-page-copy size-24"></i><i class="step fi-page-copy size-36"></i><i class="step fi-page-copy size-48"></i><i class="step fi-page-copy size-60"></i><i class="step fi-page-copy size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-copy" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf180;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-csv size-12"></i><i class="step fi-page-csv size-14"></i><i class="step fi-page-csv size-16"></i><i class="step fi-page-csv size-18"></i><i class="step fi-page-csv size-21"></i><i class="step fi-page-csv size-24"></i><i class="step fi-page-csv size-36"></i><i class="step fi-page-csv size-48"></i><i class="step fi-page-csv size-60"></i><i class="step fi-page-csv size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-csv" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf181;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-delete size-12"></i><i class="step fi-page-delete size-14"></i><i class="step fi-page-delete size-16"></i><i class="step fi-page-delete size-18"></i><i class="step fi-page-delete size-21"></i><i class="step fi-page-delete size-24"></i><i class="step fi-page-delete size-36"></i><i class="step fi-page-delete size-48"></i><i class="step fi-page-delete size-60"></i><i class="step fi-page-delete size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-delete" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf182;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-doc size-12"></i><i class="step fi-page-doc size-14"></i><i class="step fi-page-doc size-16"></i><i class="step fi-page-doc size-18"></i><i class="step fi-page-doc size-21"></i><i class="step fi-page-doc size-24"></i><i class="step fi-page-doc size-36"></i><i class="step fi-page-doc size-48"></i><i class="step fi-page-doc size-60"></i><i class="step fi-page-doc size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-doc" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf183;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-edit size-12"></i><i class="step fi-page-edit size-14"></i><i class="step fi-page-edit size-16"></i><i class="step fi-page-edit size-18"></i><i class="step fi-page-edit size-21"></i><i class="step fi-page-edit size-24"></i><i class="step fi-page-edit size-36"></i><i class="step fi-page-edit size-48"></i><i class="step fi-page-edit size-60"></i><i class="step fi-page-edit size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-edit" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf184;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-export-csv size-12"></i><i class="step fi-page-export-csv size-14"></i><i class="step fi-page-export-csv size-16"></i><i class="step fi-page-export-csv size-18"></i><i class="step fi-page-export-csv size-21"></i><i class="step fi-page-export-csv size-24"></i><i class="step fi-page-export-csv size-36"></i><i class="step fi-page-export-csv size-48"></i><i class="step fi-page-export-csv size-60"></i><i class="step fi-page-export-csv size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-export-csv" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf185;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-export-doc size-12"></i><i class="step fi-page-export-doc size-14"></i><i class="step fi-page-export-doc size-16"></i><i class="step fi-page-export-doc size-18"></i><i class="step fi-page-export-doc size-21"></i><i class="step fi-page-export-doc size-24"></i><i class="step fi-page-export-doc size-36"></i><i class="step fi-page-export-doc size-48"></i><i class="step fi-page-export-doc size-60"></i><i class="step fi-page-export-doc size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-export-doc" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf186;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-export-pdf size-12"></i><i class="step fi-page-export-pdf size-14"></i><i class="step fi-page-export-pdf size-16"></i><i class="step fi-page-export-pdf size-18"></i><i class="step fi-page-export-pdf size-21"></i><i class="step fi-page-export-pdf size-24"></i><i class="step fi-page-export-pdf size-36"></i><i class="step fi-page-export-pdf size-48"></i><i class="step fi-page-export-pdf size-60"></i><i class="step fi-page-export-pdf size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-export-pdf" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf187;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-export size-12"></i><i class="step fi-page-export size-14"></i><i class="step fi-page-export size-16"></i><i class="step fi-page-export size-18"></i><i class="step fi-page-export size-21"></i><i class="step fi-page-export size-24"></i><i class="step fi-page-export size-36"></i><i class="step fi-page-export size-48"></i><i class="step fi-page-export size-60"></i><i class="step fi-page-export size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-export" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf188;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-filled size-12"></i><i class="step fi-page-filled size-14"></i><i class="step fi-page-filled size-16"></i><i class="step fi-page-filled size-18"></i><i class="step fi-page-filled size-21"></i><i class="step fi-page-filled size-24"></i><i class="step fi-page-filled size-36"></i><i class="step fi-page-filled size-48"></i><i class="step fi-page-filled size-60"></i><i class="step fi-page-filled size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-filled" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf189;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-multiple size-12"></i><i class="step fi-page-multiple size-14"></i><i class="step fi-page-multiple size-16"></i><i class="step fi-page-multiple size-18"></i><i class="step fi-page-multiple size-21"></i><i class="step fi-page-multiple size-24"></i><i class="step fi-page-multiple size-36"></i><i class="step fi-page-multiple size-48"></i><i class="step fi-page-multiple size-60"></i><i class="step fi-page-multiple size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-multiple" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-pdf size-12"></i><i class="step fi-page-pdf size-14"></i><i class="step fi-page-pdf size-16"></i><i class="step fi-page-pdf size-18"></i><i class="step fi-page-pdf size-21"></i><i class="step fi-page-pdf size-24"></i><i class="step fi-page-pdf size-36"></i><i class="step fi-page-pdf size-48"></i><i class="step fi-page-pdf size-60"></i><i class="step fi-page-pdf size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-pdf" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-remove size-12"></i><i class="step fi-page-remove size-14"></i><i class="step fi-page-remove size-16"></i><i class="step fi-page-remove size-18"></i><i class="step fi-page-remove size-21"></i><i class="step fi-page-remove size-24"></i><i class="step fi-page-remove size-36"></i><i class="step fi-page-remove size-48"></i><i class="step fi-page-remove size-60"></i><i class="step fi-page-remove size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-remove" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page-search size-12"></i><i class="step fi-page-search size-14"></i><i class="step fi-page-search size-16"></i><i class="step fi-page-search size-18"></i><i class="step fi-page-search size-21"></i><i class="step fi-page-search size-24"></i><i class="step fi-page-search size-36"></i><i class="step fi-page-search size-48"></i><i class="step fi-page-search size-60"></i><i class="step fi-page-search size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page-search" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-page size-12"></i><i class="step fi-page size-14"></i><i class="step fi-page size-16"></i><i class="step fi-page size-18"></i><i class="step fi-page size-21"></i><i class="step fi-page size-24"></i><i class="step fi-page size-36"></i><i class="step fi-page size-48"></i><i class="step fi-page size-60"></i><i class="step fi-page size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-page" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-paint-bucket size-12"></i><i class="step fi-paint-bucket size-14"></i><i class="step fi-paint-bucket size-16"></i><i class="step fi-paint-bucket size-18"></i><i class="step fi-paint-bucket size-21"></i><i class="step fi-paint-bucket size-24"></i><i class="step fi-paint-bucket size-36"></i><i class="step fi-paint-bucket size-48"></i><i class="step fi-paint-bucket size-60"></i><i class="step fi-paint-bucket size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-paint-bucket" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf18f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-paperclip size-12"></i><i class="step fi-paperclip size-14"></i><i class="step fi-paperclip size-16"></i><i class="step fi-paperclip size-18"></i><i class="step fi-paperclip size-21"></i><i class="step fi-paperclip size-24"></i><i class="step fi-paperclip size-36"></i><i class="step fi-paperclip size-48"></i><i class="step fi-paperclip size-60"></i><i class="step fi-paperclip size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-paperclip" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf190;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-pause size-12"></i><i class="step fi-pause size-14"></i><i class="step fi-pause size-16"></i><i class="step fi-pause size-18"></i><i class="step fi-pause size-21"></i><i class="step fi-pause size-24"></i><i class="step fi-pause size-36"></i><i class="step fi-pause size-48"></i><i class="step fi-pause size-60"></i><i class="step fi-pause size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-pause" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf191;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-paw size-12"></i><i class="step fi-paw size-14"></i><i class="step fi-paw size-16"></i><i class="step fi-paw size-18"></i><i class="step fi-paw size-21"></i><i class="step fi-paw size-24"></i><i class="step fi-paw size-36"></i><i class="step fi-paw size-48"></i><i class="step fi-paw size-60"></i><i class="step fi-paw size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-paw" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf192;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-paypal size-12"></i><i class="step fi-paypal size-14"></i><i class="step fi-paypal size-16"></i><i class="step fi-paypal size-18"></i><i class="step fi-paypal size-21"></i><i class="step fi-paypal size-24"></i><i class="step fi-paypal size-36"></i><i class="step fi-paypal size-48"></i><i class="step fi-paypal size-60"></i><i class="step fi-paypal size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-paypal" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf193;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-pencil size-12"></i><i class="step fi-pencil size-14"></i><i class="step fi-pencil size-16"></i><i class="step fi-pencil size-18"></i><i class="step fi-pencil size-21"></i><i class="step fi-pencil size-24"></i><i class="step fi-pencil size-36"></i><i class="step fi-pencil size-48"></i><i class="step fi-pencil size-60"></i><i class="step fi-pencil size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-pencil" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf194;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-photo size-12"></i><i class="step fi-photo size-14"></i><i class="step fi-photo size-16"></i><i class="step fi-photo size-18"></i><i class="step fi-photo size-21"></i><i class="step fi-photo size-24"></i><i class="step fi-photo size-36"></i><i class="step fi-photo size-48"></i><i class="step fi-photo size-60"></i><i class="step fi-photo size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-photo" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf195;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-play-circle size-12"></i><i class="step fi-play-circle size-14"></i><i class="step fi-play-circle size-16"></i><i class="step fi-play-circle size-18"></i><i class="step fi-play-circle size-21"></i><i class="step fi-play-circle size-24"></i><i class="step fi-play-circle size-36"></i><i class="step fi-play-circle size-48"></i><i class="step fi-play-circle size-60"></i><i class="step fi-play-circle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-play-circle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf196;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-play-video size-12"></i><i class="step fi-play-video size-14"></i><i class="step fi-play-video size-16"></i><i class="step fi-play-video size-18"></i><i class="step fi-play-video size-21"></i><i class="step fi-play-video size-24"></i><i class="step fi-play-video size-36"></i><i class="step fi-play-video size-48"></i><i class="step fi-play-video size-60"></i><i class="step fi-play-video size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-play-video" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf197;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-play size-12"></i><i class="step fi-play size-14"></i><i class="step fi-play size-16"></i><i class="step fi-play size-18"></i><i class="step fi-play size-21"></i><i class="step fi-play size-24"></i><i class="step fi-play size-36"></i><i class="step fi-play size-48"></i><i class="step fi-play size-60"></i><i class="step fi-play size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-play" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf198;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-plus size-12"></i><i class="step fi-plus size-14"></i><i class="step fi-plus size-16"></i><i class="step fi-plus size-18"></i><i class="step fi-plus size-21"></i><i class="step fi-plus size-24"></i><i class="step fi-plus size-36"></i><i class="step fi-plus size-48"></i><i class="step fi-plus size-60"></i><i class="step fi-plus size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-plus" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf199;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-pound size-12"></i><i class="step fi-pound size-14"></i><i class="step fi-pound size-16"></i><i class="step fi-pound size-18"></i><i class="step fi-pound size-21"></i><i class="step fi-pound size-24"></i><i class="step fi-pound size-36"></i><i class="step fi-pound size-48"></i><i class="step fi-pound size-60"></i><i class="step fi-pound size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-pound" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-power size-12"></i><i class="step fi-power size-14"></i><i class="step fi-power size-16"></i><i class="step fi-power size-18"></i><i class="step fi-power size-21"></i><i class="step fi-power size-24"></i><i class="step fi-power size-36"></i><i class="step fi-power size-48"></i><i class="step fi-power size-60"></i><i class="step fi-power size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-power" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-previous size-12"></i><i class="step fi-previous size-14"></i><i class="step fi-previous size-16"></i><i class="step fi-previous size-18"></i><i class="step fi-previous size-21"></i><i class="step fi-previous size-24"></i><i class="step fi-previous size-36"></i><i class="step fi-previous size-48"></i><i class="step fi-previous size-60"></i><i class="step fi-previous size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-previous" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-price-tag size-12"></i><i class="step fi-price-tag size-14"></i><i class="step fi-price-tag size-16"></i><i class="step fi-price-tag size-18"></i><i class="step fi-price-tag size-21"></i><i class="step fi-price-tag size-24"></i><i class="step fi-price-tag size-36"></i><i class="step fi-price-tag size-48"></i><i class="step fi-price-tag size-60"></i><i class="step fi-price-tag size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-price-tag" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-pricetag-multiple size-12"></i><i class="step fi-pricetag-multiple size-14"></i><i class="step fi-pricetag-multiple size-16"></i><i class="step fi-pricetag-multiple size-18"></i><i class="step fi-pricetag-multiple size-21"></i><i class="step fi-pricetag-multiple size-24"></i><i class="step fi-pricetag-multiple size-36"></i><i class="step fi-pricetag-multiple size-48"></i><i class="step fi-pricetag-multiple size-60"></i><i class="step fi-pricetag-multiple size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-pricetag-multiple" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-print size-12"></i><i class="step fi-print size-14"></i><i class="step fi-print size-16"></i><i class="step fi-print size-18"></i><i class="step fi-print size-21"></i><i class="step fi-print size-24"></i><i class="step fi-print size-36"></i><i class="step fi-print size-48"></i><i class="step fi-print size-60"></i><i class="step fi-print size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-print" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf19f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-prohibited size-12"></i><i class="step fi-prohibited size-14"></i><i class="step fi-prohibited size-16"></i><i class="step fi-prohibited size-18"></i><i class="step fi-prohibited size-21"></i><i class="step fi-prohibited size-24"></i><i class="step fi-prohibited size-36"></i><i class="step fi-prohibited size-48"></i><i class="step fi-prohibited size-60"></i><i class="step fi-prohibited size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-prohibited" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-projection-screen size-12"></i><i class="step fi-projection-screen size-14"></i><i class="step fi-projection-screen size-16"></i><i class="step fi-projection-screen size-18"></i><i class="step fi-projection-screen size-21"></i><i class="step fi-projection-screen size-24"></i><i class="step fi-projection-screen size-36"></i><i class="step fi-projection-screen size-48"></i><i class="step fi-projection-screen size-60"></i><i class="step fi-projection-screen size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-projection-screen" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-puzzle size-12"></i><i class="step fi-puzzle size-14"></i><i class="step fi-puzzle size-16"></i><i class="step fi-puzzle size-18"></i><i class="step fi-puzzle size-21"></i><i class="step fi-puzzle size-24"></i><i class="step fi-puzzle size-36"></i><i class="step fi-puzzle size-48"></i><i class="step fi-puzzle size-60"></i><i class="step fi-puzzle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-puzzle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-quote size-12"></i><i class="step fi-quote size-14"></i><i class="step fi-quote size-16"></i><i class="step fi-quote size-18"></i><i class="step fi-quote size-21"></i><i class="step fi-quote size-24"></i><i class="step fi-quote size-36"></i><i class="step fi-quote size-48"></i><i class="step fi-quote size-60"></i><i class="step fi-quote size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-quote" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-record size-12"></i><i class="step fi-record size-14"></i><i class="step fi-record size-16"></i><i class="step fi-record size-18"></i><i class="step fi-record size-21"></i><i class="step fi-record size-24"></i><i class="step fi-record size-36"></i><i class="step fi-record size-48"></i><i class="step fi-record size-60"></i><i class="step fi-record size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-record" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-refresh size-12"></i><i class="step fi-refresh size-14"></i><i class="step fi-refresh size-16"></i><i class="step fi-refresh size-18"></i><i class="step fi-refresh size-21"></i><i class="step fi-refresh size-24"></i><i class="step fi-refresh size-36"></i><i class="step fi-refresh size-48"></i><i class="step fi-refresh size-60"></i><i class="step fi-refresh size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-refresh" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-results-demographics size-12"></i><i class="step fi-results-demographics size-14"></i><i class="step fi-results-demographics size-16"></i><i class="step fi-results-demographics size-18"></i><i class="step fi-results-demographics size-21"></i><i class="step fi-results-demographics size-24"></i><i class="step fi-results-demographics size-36"></i><i class="step fi-results-demographics size-48"></i><i class="step fi-results-demographics size-60"></i><i class="step fi-results-demographics size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-results-demographics" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-results size-12"></i><i class="step fi-results size-14"></i><i class="step fi-results size-16"></i><i class="step fi-results size-18"></i><i class="step fi-results size-21"></i><i class="step fi-results size-24"></i><i class="step fi-results size-36"></i><i class="step fi-results size-48"></i><i class="step fi-results size-60"></i><i class="step fi-results size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-results" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-rewind-ten size-12"></i><i class="step fi-rewind-ten size-14"></i><i class="step fi-rewind-ten size-16"></i><i class="step fi-rewind-ten size-18"></i><i class="step fi-rewind-ten size-21"></i><i class="step fi-rewind-ten size-24"></i><i class="step fi-rewind-ten size-36"></i><i class="step fi-rewind-ten size-48"></i><i class="step fi-rewind-ten size-60"></i><i class="step fi-rewind-ten size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-rewind-ten" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-rewind size-12"></i><i class="step fi-rewind size-14"></i><i class="step fi-rewind size-16"></i><i class="step fi-rewind size-18"></i><i class="step fi-rewind size-21"></i><i class="step fi-rewind size-24"></i><i class="step fi-rewind size-36"></i><i class="step fi-rewind size-48"></i><i class="step fi-rewind size-60"></i><i class="step fi-rewind size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-rewind" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1a9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-rss size-12"></i><i class="step fi-rss size-14"></i><i class="step fi-rss size-16"></i><i class="step fi-rss size-18"></i><i class="step fi-rss size-21"></i><i class="step fi-rss size-24"></i><i class="step fi-rss size-36"></i><i class="step fi-rss size-48"></i><i class="step fi-rss size-60"></i><i class="step fi-rss size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-rss" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1aa;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-safety-cone size-12"></i><i class="step fi-safety-cone size-14"></i><i class="step fi-safety-cone size-16"></i><i class="step fi-safety-cone size-18"></i><i class="step fi-safety-cone size-21"></i><i class="step fi-safety-cone size-24"></i><i class="step fi-safety-cone size-36"></i><i class="step fi-safety-cone size-48"></i><i class="step fi-safety-cone size-60"></i><i class="step fi-safety-cone size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-safety-cone" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ab;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-save size-12"></i><i class="step fi-save size-14"></i><i class="step fi-save size-16"></i><i class="step fi-save size-18"></i><i class="step fi-save size-21"></i><i class="step fi-save size-24"></i><i class="step fi-save size-36"></i><i class="step fi-save size-48"></i><i class="step fi-save size-60"></i><i class="step fi-save size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-save" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ac;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-share size-12"></i><i class="step fi-share size-14"></i><i class="step fi-share size-16"></i><i class="step fi-share size-18"></i><i class="step fi-share size-21"></i><i class="step fi-share size-24"></i><i class="step fi-share size-36"></i><i class="step fi-share size-48"></i><i class="step fi-share size-60"></i><i class="step fi-share size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-share" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ad;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-sheriff-badge size-12"></i><i class="step fi-sheriff-badge size-14"></i><i class="step fi-sheriff-badge size-16"></i><i class="step fi-sheriff-badge size-18"></i><i class="step fi-sheriff-badge size-21"></i><i class="step fi-sheriff-badge size-24"></i><i class="step fi-sheriff-badge size-36"></i><i class="step fi-sheriff-badge size-48"></i><i class="step fi-sheriff-badge size-60"></i><i class="step fi-sheriff-badge size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-sheriff-badge" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ae;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-shield size-12"></i><i class="step fi-shield size-14"></i><i class="step fi-shield size-16"></i><i class="step fi-shield size-18"></i><i class="step fi-shield size-21"></i><i class="step fi-shield size-24"></i><i class="step fi-shield size-36"></i><i class="step fi-shield size-48"></i><i class="step fi-shield size-60"></i><i class="step fi-shield size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-shield" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1af;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-shopping-bag size-12"></i><i class="step fi-shopping-bag size-14"></i><i class="step fi-shopping-bag size-16"></i><i class="step fi-shopping-bag size-18"></i><i class="step fi-shopping-bag size-21"></i><i class="step fi-shopping-bag size-24"></i><i class="step fi-shopping-bag size-36"></i><i class="step fi-shopping-bag size-48"></i><i class="step fi-shopping-bag size-60"></i><i class="step fi-shopping-bag size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-shopping-bag" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-shopping-cart size-12"></i><i class="step fi-shopping-cart size-14"></i><i class="step fi-shopping-cart size-16"></i><i class="step fi-shopping-cart size-18"></i><i class="step fi-shopping-cart size-21"></i><i class="step fi-shopping-cart size-24"></i><i class="step fi-shopping-cart size-36"></i><i class="step fi-shopping-cart size-48"></i><i class="step fi-shopping-cart size-60"></i><i class="step fi-shopping-cart size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-shopping-cart" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-shuffle size-12"></i><i class="step fi-shuffle size-14"></i><i class="step fi-shuffle size-16"></i><i class="step fi-shuffle size-18"></i><i class="step fi-shuffle size-21"></i><i class="step fi-shuffle size-24"></i><i class="step fi-shuffle size-36"></i><i class="step fi-shuffle size-48"></i><i class="step fi-shuffle size-60"></i><i class="step fi-shuffle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-shuffle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-skull size-12"></i><i class="step fi-skull size-14"></i><i class="step fi-skull size-16"></i><i class="step fi-skull size-18"></i><i class="step fi-skull size-21"></i><i class="step fi-skull size-24"></i><i class="step fi-skull size-36"></i><i class="step fi-skull size-48"></i><i class="step fi-skull size-60"></i><i class="step fi-skull size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-skull" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-500px size-12"></i><i class="step fi-social-500px size-14"></i><i class="step fi-social-500px size-16"></i><i class="step fi-social-500px size-18"></i><i class="step fi-social-500px size-21"></i><i class="step fi-social-500px size-24"></i><i class="step fi-social-500px size-36"></i><i class="step fi-social-500px size-48"></i><i class="step fi-social-500px size-60"></i><i class="step fi-social-500px size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-500px" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-adobe size-12"></i><i class="step fi-social-adobe size-14"></i><i class="step fi-social-adobe size-16"></i><i class="step fi-social-adobe size-18"></i><i class="step fi-social-adobe size-21"></i><i class="step fi-social-adobe size-24"></i><i class="step fi-social-adobe size-36"></i><i class="step fi-social-adobe size-48"></i><i class="step fi-social-adobe size-60"></i><i class="step fi-social-adobe size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-adobe" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-amazon size-12"></i><i class="step fi-social-amazon size-14"></i><i class="step fi-social-amazon size-16"></i><i class="step fi-social-amazon size-18"></i><i class="step fi-social-amazon size-21"></i><i class="step fi-social-amazon size-24"></i><i class="step fi-social-amazon size-36"></i><i class="step fi-social-amazon size-48"></i><i class="step fi-social-amazon size-60"></i><i class="step fi-social-amazon size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-amazon" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-android size-12"></i><i class="step fi-social-android size-14"></i><i class="step fi-social-android size-16"></i><i class="step fi-social-android size-18"></i><i class="step fi-social-android size-21"></i><i class="step fi-social-android size-24"></i><i class="step fi-social-android size-36"></i><i class="step fi-social-android size-48"></i><i class="step fi-social-android size-60"></i><i class="step fi-social-android size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-android" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-apple size-12"></i><i class="step fi-social-apple size-14"></i><i class="step fi-social-apple size-16"></i><i class="step fi-social-apple size-18"></i><i class="step fi-social-apple size-21"></i><i class="step fi-social-apple size-24"></i><i class="step fi-social-apple size-36"></i><i class="step fi-social-apple size-48"></i><i class="step fi-social-apple size-60"></i><i class="step fi-social-apple size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-apple" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-behance size-12"></i><i class="step fi-social-behance size-14"></i><i class="step fi-social-behance size-16"></i><i class="step fi-social-behance size-18"></i><i class="step fi-social-behance size-21"></i><i class="step fi-social-behance size-24"></i><i class="step fi-social-behance size-36"></i><i class="step fi-social-behance size-48"></i><i class="step fi-social-behance size-60"></i><i class="step fi-social-behance size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-behance" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1b9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-bing size-12"></i><i class="step fi-social-bing size-14"></i><i class="step fi-social-bing size-16"></i><i class="step fi-social-bing size-18"></i><i class="step fi-social-bing size-21"></i><i class="step fi-social-bing size-24"></i><i class="step fi-social-bing size-36"></i><i class="step fi-social-bing size-48"></i><i class="step fi-social-bing size-60"></i><i class="step fi-social-bing size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-bing" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ba;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-blogger size-12"></i><i class="step fi-social-blogger size-14"></i><i class="step fi-social-blogger size-16"></i><i class="step fi-social-blogger size-18"></i><i class="step fi-social-blogger size-21"></i><i class="step fi-social-blogger size-24"></i><i class="step fi-social-blogger size-36"></i><i class="step fi-social-blogger size-48"></i><i class="step fi-social-blogger size-60"></i><i class="step fi-social-blogger size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-blogger" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1bb;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-delicious size-12"></i><i class="step fi-social-delicious size-14"></i><i class="step fi-social-delicious size-16"></i><i class="step fi-social-delicious size-18"></i><i class="step fi-social-delicious size-21"></i><i class="step fi-social-delicious size-24"></i><i class="step fi-social-delicious size-36"></i><i class="step fi-social-delicious size-48"></i><i class="step fi-social-delicious size-60"></i><i class="step fi-social-delicious size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-delicious" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1bc;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-designer-news size-12"></i><i class="step fi-social-designer-news size-14"></i><i class="step fi-social-designer-news size-16"></i><i class="step fi-social-designer-news size-18"></i><i class="step fi-social-designer-news size-21"></i><i class="step fi-social-designer-news size-24"></i><i class="step fi-social-designer-news size-36"></i><i class="step fi-social-designer-news size-48"></i><i class="step fi-social-designer-news size-60"></i><i class="step fi-social-designer-news size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-designer-news" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1bd;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-deviant-art size-12"></i><i class="step fi-social-deviant-art size-14"></i><i class="step fi-social-deviant-art size-16"></i><i class="step fi-social-deviant-art size-18"></i><i class="step fi-social-deviant-art size-21"></i><i class="step fi-social-deviant-art size-24"></i><i class="step fi-social-deviant-art size-36"></i><i class="step fi-social-deviant-art size-48"></i><i class="step fi-social-deviant-art size-60"></i><i class="step fi-social-deviant-art size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-deviant-art" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1be;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-digg size-12"></i><i class="step fi-social-digg size-14"></i><i class="step fi-social-digg size-16"></i><i class="step fi-social-digg size-18"></i><i class="step fi-social-digg size-21"></i><i class="step fi-social-digg size-24"></i><i class="step fi-social-digg size-36"></i><i class="step fi-social-digg size-48"></i><i class="step fi-social-digg size-60"></i><i class="step fi-social-digg size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-digg" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1bf;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-dribbble size-12"></i><i class="step fi-social-dribbble size-14"></i><i class="step fi-social-dribbble size-16"></i><i class="step fi-social-dribbble size-18"></i><i class="step fi-social-dribbble size-21"></i><i class="step fi-social-dribbble size-24"></i><i class="step fi-social-dribbble size-36"></i><i class="step fi-social-dribbble size-48"></i><i class="step fi-social-dribbble size-60"></i><i class="step fi-social-dribbble size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-dribbble" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-drive size-12"></i><i class="step fi-social-drive size-14"></i><i class="step fi-social-drive size-16"></i><i class="step fi-social-drive size-18"></i><i class="step fi-social-drive size-21"></i><i class="step fi-social-drive size-24"></i><i class="step fi-social-drive size-36"></i><i class="step fi-social-drive size-48"></i><i class="step fi-social-drive size-60"></i><i class="step fi-social-drive size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-drive" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-dropbox size-12"></i><i class="step fi-social-dropbox size-14"></i><i class="step fi-social-dropbox size-16"></i><i class="step fi-social-dropbox size-18"></i><i class="step fi-social-dropbox size-21"></i><i class="step fi-social-dropbox size-24"></i><i class="step fi-social-dropbox size-36"></i><i class="step fi-social-dropbox size-48"></i><i class="step fi-social-dropbox size-60"></i><i class="step fi-social-dropbox size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-dropbox" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-evernote size-12"></i><i class="step fi-social-evernote size-14"></i><i class="step fi-social-evernote size-16"></i><i class="step fi-social-evernote size-18"></i><i class="step fi-social-evernote size-21"></i><i class="step fi-social-evernote size-24"></i><i class="step fi-social-evernote size-36"></i><i class="step fi-social-evernote size-48"></i><i class="step fi-social-evernote size-60"></i><i class="step fi-social-evernote size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-evernote" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-facebook size-12"></i><i class="step fi-social-facebook size-14"></i><i class="step fi-social-facebook size-16"></i><i class="step fi-social-facebook size-18"></i><i class="step fi-social-facebook size-21"></i><i class="step fi-social-facebook size-24"></i><i class="step fi-social-facebook size-36"></i><i class="step fi-social-facebook size-48"></i><i class="step fi-social-facebook size-60"></i><i class="step fi-social-facebook size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-facebook" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-flickr size-12"></i><i class="step fi-social-flickr size-14"></i><i class="step fi-social-flickr size-16"></i><i class="step fi-social-flickr size-18"></i><i class="step fi-social-flickr size-21"></i><i class="step fi-social-flickr size-24"></i><i class="step fi-social-flickr size-36"></i><i class="step fi-social-flickr size-48"></i><i class="step fi-social-flickr size-60"></i><i class="step fi-social-flickr size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-flickr" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-forrst size-12"></i><i class="step fi-social-forrst size-14"></i><i class="step fi-social-forrst size-16"></i><i class="step fi-social-forrst size-18"></i><i class="step fi-social-forrst size-21"></i><i class="step fi-social-forrst size-24"></i><i class="step fi-social-forrst size-36"></i><i class="step fi-social-forrst size-48"></i><i class="step fi-social-forrst size-60"></i><i class="step fi-social-forrst size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-forrst" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-foursquare size-12"></i><i class="step fi-social-foursquare size-14"></i><i class="step fi-social-foursquare size-16"></i><i class="step fi-social-foursquare size-18"></i><i class="step fi-social-foursquare size-21"></i><i class="step fi-social-foursquare size-24"></i><i class="step fi-social-foursquare size-36"></i><i class="step fi-social-foursquare size-48"></i><i class="step fi-social-foursquare size-60"></i><i class="step fi-social-foursquare size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-foursquare" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-game-center size-12"></i><i class="step fi-social-game-center size-14"></i><i class="step fi-social-game-center size-16"></i><i class="step fi-social-game-center size-18"></i><i class="step fi-social-game-center size-21"></i><i class="step fi-social-game-center size-24"></i><i class="step fi-social-game-center size-36"></i><i class="step fi-social-game-center size-48"></i><i class="step fi-social-game-center size-60"></i><i class="step fi-social-game-center size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-game-center" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-github size-12"></i><i class="step fi-social-github size-14"></i><i class="step fi-social-github size-16"></i><i class="step fi-social-github size-18"></i><i class="step fi-social-github size-21"></i><i class="step fi-social-github size-24"></i><i class="step fi-social-github size-36"></i><i class="step fi-social-github size-48"></i><i class="step fi-social-github size-60"></i><i class="step fi-social-github size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-github" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1c9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-google-plus size-12"></i><i class="step fi-social-google-plus size-14"></i><i class="step fi-social-google-plus size-16"></i><i class="step fi-social-google-plus size-18"></i><i class="step fi-social-google-plus size-21"></i><i class="step fi-social-google-plus size-24"></i><i class="step fi-social-google-plus size-36"></i><i class="step fi-social-google-plus size-48"></i><i class="step fi-social-google-plus size-60"></i><i class="step fi-social-google-plus size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-google-plus" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ca;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-hacker-news size-12"></i><i class="step fi-social-hacker-news size-14"></i><i class="step fi-social-hacker-news size-16"></i><i class="step fi-social-hacker-news size-18"></i><i class="step fi-social-hacker-news size-21"></i><i class="step fi-social-hacker-news size-24"></i><i class="step fi-social-hacker-news size-36"></i><i class="step fi-social-hacker-news size-48"></i><i class="step fi-social-hacker-news size-60"></i><i class="step fi-social-hacker-news size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-hacker-news" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1cb;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-hi5 size-12"></i><i class="step fi-social-hi5 size-14"></i><i class="step fi-social-hi5 size-16"></i><i class="step fi-social-hi5 size-18"></i><i class="step fi-social-hi5 size-21"></i><i class="step fi-social-hi5 size-24"></i><i class="step fi-social-hi5 size-36"></i><i class="step fi-social-hi5 size-48"></i><i class="step fi-social-hi5 size-60"></i><i class="step fi-social-hi5 size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-hi5" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1cc;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-instagram size-12"></i><i class="step fi-social-instagram size-14"></i><i class="step fi-social-instagram size-16"></i><i class="step fi-social-instagram size-18"></i><i class="step fi-social-instagram size-21"></i><i class="step fi-social-instagram size-24"></i><i class="step fi-social-instagram size-36"></i><i class="step fi-social-instagram size-48"></i><i class="step fi-social-instagram size-60"></i><i class="step fi-social-instagram size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-instagram" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1cd;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-joomla size-12"></i><i class="step fi-social-joomla size-14"></i><i class="step fi-social-joomla size-16"></i><i class="step fi-social-joomla size-18"></i><i class="step fi-social-joomla size-21"></i><i class="step fi-social-joomla size-24"></i><i class="step fi-social-joomla size-36"></i><i class="step fi-social-joomla size-48"></i><i class="step fi-social-joomla size-60"></i><i class="step fi-social-joomla size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-joomla" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ce;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-lastfm size-12"></i><i class="step fi-social-lastfm size-14"></i><i class="step fi-social-lastfm size-16"></i><i class="step fi-social-lastfm size-18"></i><i class="step fi-social-lastfm size-21"></i><i class="step fi-social-lastfm size-24"></i><i class="step fi-social-lastfm size-36"></i><i class="step fi-social-lastfm size-48"></i><i class="step fi-social-lastfm size-60"></i><i class="step fi-social-lastfm size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-lastfm" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1cf;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-linkedin size-12"></i><i class="step fi-social-linkedin size-14"></i><i class="step fi-social-linkedin size-16"></i><i class="step fi-social-linkedin size-18"></i><i class="step fi-social-linkedin size-21"></i><i class="step fi-social-linkedin size-24"></i><i class="step fi-social-linkedin size-36"></i><i class="step fi-social-linkedin size-48"></i><i class="step fi-social-linkedin size-60"></i><i class="step fi-social-linkedin size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-linkedin" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-medium size-12"></i><i class="step fi-social-medium size-14"></i><i class="step fi-social-medium size-16"></i><i class="step fi-social-medium size-18"></i><i class="step fi-social-medium size-21"></i><i class="step fi-social-medium size-24"></i><i class="step fi-social-medium size-36"></i><i class="step fi-social-medium size-48"></i><i class="step fi-social-medium size-60"></i><i class="step fi-social-medium size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-medium" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-myspace size-12"></i><i class="step fi-social-myspace size-14"></i><i class="step fi-social-myspace size-16"></i><i class="step fi-social-myspace size-18"></i><i class="step fi-social-myspace size-21"></i><i class="step fi-social-myspace size-24"></i><i class="step fi-social-myspace size-36"></i><i class="step fi-social-myspace size-48"></i><i class="step fi-social-myspace size-60"></i><i class="step fi-social-myspace size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-myspace" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-orkut size-12"></i><i class="step fi-social-orkut size-14"></i><i class="step fi-social-orkut size-16"></i><i class="step fi-social-orkut size-18"></i><i class="step fi-social-orkut size-21"></i><i class="step fi-social-orkut size-24"></i><i class="step fi-social-orkut size-36"></i><i class="step fi-social-orkut size-48"></i><i class="step fi-social-orkut size-60"></i><i class="step fi-social-orkut size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-orkut" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-path size-12"></i><i class="step fi-social-path size-14"></i><i class="step fi-social-path size-16"></i><i class="step fi-social-path size-18"></i><i class="step fi-social-path size-21"></i><i class="step fi-social-path size-24"></i><i class="step fi-social-path size-36"></i><i class="step fi-social-path size-48"></i><i class="step fi-social-path size-60"></i><i class="step fi-social-path size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-path" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-picasa size-12"></i><i class="step fi-social-picasa size-14"></i><i class="step fi-social-picasa size-16"></i><i class="step fi-social-picasa size-18"></i><i class="step fi-social-picasa size-21"></i><i class="step fi-social-picasa size-24"></i><i class="step fi-social-picasa size-36"></i><i class="step fi-social-picasa size-48"></i><i class="step fi-social-picasa size-60"></i><i class="step fi-social-picasa size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-picasa" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-pinterest size-12"></i><i class="step fi-social-pinterest size-14"></i><i class="step fi-social-pinterest size-16"></i><i class="step fi-social-pinterest size-18"></i><i class="step fi-social-pinterest size-21"></i><i class="step fi-social-pinterest size-24"></i><i class="step fi-social-pinterest size-36"></i><i class="step fi-social-pinterest size-48"></i><i class="step fi-social-pinterest size-60"></i><i class="step fi-social-pinterest size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-pinterest" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-rdio size-12"></i><i class="step fi-social-rdio size-14"></i><i class="step fi-social-rdio size-16"></i><i class="step fi-social-rdio size-18"></i><i class="step fi-social-rdio size-21"></i><i class="step fi-social-rdio size-24"></i><i class="step fi-social-rdio size-36"></i><i class="step fi-social-rdio size-48"></i><i class="step fi-social-rdio size-60"></i><i class="step fi-social-rdio size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-rdio" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-reddit size-12"></i><i class="step fi-social-reddit size-14"></i><i class="step fi-social-reddit size-16"></i><i class="step fi-social-reddit size-18"></i><i class="step fi-social-reddit size-21"></i><i class="step fi-social-reddit size-24"></i><i class="step fi-social-reddit size-36"></i><i class="step fi-social-reddit size-48"></i><i class="step fi-social-reddit size-60"></i><i class="step fi-social-reddit size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-reddit" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-skillshare size-12"></i><i class="step fi-social-skillshare size-14"></i><i class="step fi-social-skillshare size-16"></i><i class="step fi-social-skillshare size-18"></i><i class="step fi-social-skillshare size-21"></i><i class="step fi-social-skillshare size-24"></i><i class="step fi-social-skillshare size-36"></i><i class="step fi-social-skillshare size-48"></i><i class="step fi-social-skillshare size-60"></i><i class="step fi-social-skillshare size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-skillshare" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1d9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-skype size-12"></i><i class="step fi-social-skype size-14"></i><i class="step fi-social-skype size-16"></i><i class="step fi-social-skype size-18"></i><i class="step fi-social-skype size-21"></i><i class="step fi-social-skype size-24"></i><i class="step fi-social-skype size-36"></i><i class="step fi-social-skype size-48"></i><i class="step fi-social-skype size-60"></i><i class="step fi-social-skype size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-skype" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1da;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-smashing-mag size-12"></i><i class="step fi-social-smashing-mag size-14"></i><i class="step fi-social-smashing-mag size-16"></i><i class="step fi-social-smashing-mag size-18"></i><i class="step fi-social-smashing-mag size-21"></i><i class="step fi-social-smashing-mag size-24"></i><i class="step fi-social-smashing-mag size-36"></i><i class="step fi-social-smashing-mag size-48"></i><i class="step fi-social-smashing-mag size-60"></i><i class="step fi-social-smashing-mag size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-smashing-mag" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1db;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-snapchat size-12"></i><i class="step fi-social-snapchat size-14"></i><i class="step fi-social-snapchat size-16"></i><i class="step fi-social-snapchat size-18"></i><i class="step fi-social-snapchat size-21"></i><i class="step fi-social-snapchat size-24"></i><i class="step fi-social-snapchat size-36"></i><i class="step fi-social-snapchat size-48"></i><i class="step fi-social-snapchat size-60"></i><i class="step fi-social-snapchat size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-snapchat" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1dc;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-spotify size-12"></i><i class="step fi-social-spotify size-14"></i><i class="step fi-social-spotify size-16"></i><i class="step fi-social-spotify size-18"></i><i class="step fi-social-spotify size-21"></i><i class="step fi-social-spotify size-24"></i><i class="step fi-social-spotify size-36"></i><i class="step fi-social-spotify size-48"></i><i class="step fi-social-spotify size-60"></i><i class="step fi-social-spotify size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-spotify" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1dd;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-squidoo size-12"></i><i class="step fi-social-squidoo size-14"></i><i class="step fi-social-squidoo size-16"></i><i class="step fi-social-squidoo size-18"></i><i class="step fi-social-squidoo size-21"></i><i class="step fi-social-squidoo size-24"></i><i class="step fi-social-squidoo size-36"></i><i class="step fi-social-squidoo size-48"></i><i class="step fi-social-squidoo size-60"></i><i class="step fi-social-squidoo size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-squidoo" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1de;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-stack-overflow size-12"></i><i class="step fi-social-stack-overflow size-14"></i><i class="step fi-social-stack-overflow size-16"></i><i class="step fi-social-stack-overflow size-18"></i><i class="step fi-social-stack-overflow size-21"></i><i class="step fi-social-stack-overflow size-24"></i><i class="step fi-social-stack-overflow size-36"></i><i class="step fi-social-stack-overflow size-48"></i><i class="step fi-social-stack-overflow size-60"></i><i class="step fi-social-stack-overflow size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-stack-overflow" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1df;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-steam size-12"></i><i class="step fi-social-steam size-14"></i><i class="step fi-social-steam size-16"></i><i class="step fi-social-steam size-18"></i><i class="step fi-social-steam size-21"></i><i class="step fi-social-steam size-24"></i><i class="step fi-social-steam size-36"></i><i class="step fi-social-steam size-48"></i><i class="step fi-social-steam size-60"></i><i class="step fi-social-steam size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-steam" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-stumbleupon size-12"></i><i class="step fi-social-stumbleupon size-14"></i><i class="step fi-social-stumbleupon size-16"></i><i class="step fi-social-stumbleupon size-18"></i><i class="step fi-social-stumbleupon size-21"></i><i class="step fi-social-stumbleupon size-24"></i><i class="step fi-social-stumbleupon size-36"></i><i class="step fi-social-stumbleupon size-48"></i><i class="step fi-social-stumbleupon size-60"></i><i class="step fi-social-stumbleupon size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-stumbleupon" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-treehouse size-12"></i><i class="step fi-social-treehouse size-14"></i><i class="step fi-social-treehouse size-16"></i><i class="step fi-social-treehouse size-18"></i><i class="step fi-social-treehouse size-21"></i><i class="step fi-social-treehouse size-24"></i><i class="step fi-social-treehouse size-36"></i><i class="step fi-social-treehouse size-48"></i><i class="step fi-social-treehouse size-60"></i><i class="step fi-social-treehouse size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-treehouse" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-tumblr size-12"></i><i class="step fi-social-tumblr size-14"></i><i class="step fi-social-tumblr size-16"></i><i class="step fi-social-tumblr size-18"></i><i class="step fi-social-tumblr size-21"></i><i class="step fi-social-tumblr size-24"></i><i class="step fi-social-tumblr size-36"></i><i class="step fi-social-tumblr size-48"></i><i class="step fi-social-tumblr size-60"></i><i class="step fi-social-tumblr size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-tumblr" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-twitter size-12"></i><i class="step fi-social-twitter size-14"></i><i class="step fi-social-twitter size-16"></i><i class="step fi-social-twitter size-18"></i><i class="step fi-social-twitter size-21"></i><i class="step fi-social-twitter size-24"></i><i class="step fi-social-twitter size-36"></i><i class="step fi-social-twitter size-48"></i><i class="step fi-social-twitter size-60"></i><i class="step fi-social-twitter size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-twitter" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-vimeo size-12"></i><i class="step fi-social-vimeo size-14"></i><i class="step fi-social-vimeo size-16"></i><i class="step fi-social-vimeo size-18"></i><i class="step fi-social-vimeo size-21"></i><i class="step fi-social-vimeo size-24"></i><i class="step fi-social-vimeo size-36"></i><i class="step fi-social-vimeo size-48"></i><i class="step fi-social-vimeo size-60"></i><i class="step fi-social-vimeo size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-vimeo" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-windows size-12"></i><i class="step fi-social-windows size-14"></i><i class="step fi-social-windows size-16"></i><i class="step fi-social-windows size-18"></i><i class="step fi-social-windows size-21"></i><i class="step fi-social-windows size-24"></i><i class="step fi-social-windows size-36"></i><i class="step fi-social-windows size-48"></i><i class="step fi-social-windows size-60"></i><i class="step fi-social-windows size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-windows" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-xbox size-12"></i><i class="step fi-social-xbox size-14"></i><i class="step fi-social-xbox size-16"></i><i class="step fi-social-xbox size-18"></i><i class="step fi-social-xbox size-21"></i><i class="step fi-social-xbox size-24"></i><i class="step fi-social-xbox size-36"></i><i class="step fi-social-xbox size-48"></i><i class="step fi-social-xbox size-60"></i><i class="step fi-social-xbox size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-xbox" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-yahoo size-12"></i><i class="step fi-social-yahoo size-14"></i><i class="step fi-social-yahoo size-16"></i><i class="step fi-social-yahoo size-18"></i><i class="step fi-social-yahoo size-21"></i><i class="step fi-social-yahoo size-24"></i><i class="step fi-social-yahoo size-36"></i><i class="step fi-social-yahoo size-48"></i><i class="step fi-social-yahoo size-60"></i><i class="step fi-social-yahoo size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-yahoo" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-yelp size-12"></i><i class="step fi-social-yelp size-14"></i><i class="step fi-social-yelp size-16"></i><i class="step fi-social-yelp size-18"></i><i class="step fi-social-yelp size-21"></i><i class="step fi-social-yelp size-24"></i><i class="step fi-social-yelp size-36"></i><i class="step fi-social-yelp size-48"></i><i class="step fi-social-yelp size-60"></i><i class="step fi-social-yelp size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-yelp" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1e9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-youtube size-12"></i><i class="step fi-social-youtube size-14"></i><i class="step fi-social-youtube size-16"></i><i class="step fi-social-youtube size-18"></i><i class="step fi-social-youtube size-21"></i><i class="step fi-social-youtube size-24"></i><i class="step fi-social-youtube size-36"></i><i class="step fi-social-youtube size-48"></i><i class="step fi-social-youtube size-60"></i><i class="step fi-social-youtube size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-youtube" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ea;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-zerply size-12"></i><i class="step fi-social-zerply size-14"></i><i class="step fi-social-zerply size-16"></i><i class="step fi-social-zerply size-18"></i><i class="step fi-social-zerply size-21"></i><i class="step fi-social-zerply size-24"></i><i class="step fi-social-zerply size-36"></i><i class="step fi-social-zerply size-48"></i><i class="step fi-social-zerply size-60"></i><i class="step fi-social-zerply size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-zerply" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1eb;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-social-zurb size-12"></i><i class="step fi-social-zurb size-14"></i><i class="step fi-social-zurb size-16"></i><i class="step fi-social-zurb size-18"></i><i class="step fi-social-zurb size-21"></i><i class="step fi-social-zurb size-24"></i><i class="step fi-social-zurb size-36"></i><i class="step fi-social-zurb size-48"></i><i class="step fi-social-zurb size-60"></i><i class="step fi-social-zurb size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-social-zurb" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ec;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-sound size-12"></i><i class="step fi-sound size-14"></i><i class="step fi-sound size-16"></i><i class="step fi-sound size-18"></i><i class="step fi-sound size-21"></i><i class="step fi-sound size-24"></i><i class="step fi-sound size-36"></i><i class="step fi-sound size-48"></i><i class="step fi-sound size-60"></i><i class="step fi-sound size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-sound" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ed;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-star size-12"></i><i class="step fi-star size-14"></i><i class="step fi-star size-16"></i><i class="step fi-star size-18"></i><i class="step fi-star size-21"></i><i class="step fi-star size-24"></i><i class="step fi-star size-36"></i><i class="step fi-star size-48"></i><i class="step fi-star size-60"></i><i class="step fi-star size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-star" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ee;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-stop size-12"></i><i class="step fi-stop size-14"></i><i class="step fi-stop size-16"></i><i class="step fi-stop size-18"></i><i class="step fi-stop size-21"></i><i class="step fi-stop size-24"></i><i class="step fi-stop size-36"></i><i class="step fi-stop size-48"></i><i class="step fi-stop size-60"></i><i class="step fi-stop size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-stop" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ef;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-strikethrough size-12"></i><i class="step fi-strikethrough size-14"></i><i class="step fi-strikethrough size-16"></i><i class="step fi-strikethrough size-18"></i><i class="step fi-strikethrough size-21"></i><i class="step fi-strikethrough size-24"></i><i class="step fi-strikethrough size-36"></i><i class="step fi-strikethrough size-48"></i><i class="step fi-strikethrough size-60"></i><i class="step fi-strikethrough size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-strikethrough" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f0;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-subscript size-12"></i><i class="step fi-subscript size-14"></i><i class="step fi-subscript size-16"></i><i class="step fi-subscript size-18"></i><i class="step fi-subscript size-21"></i><i class="step fi-subscript size-24"></i><i class="step fi-subscript size-36"></i><i class="step fi-subscript size-48"></i><i class="step fi-subscript size-60"></i><i class="step fi-subscript size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-subscript" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f1;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-superscript size-12"></i><i class="step fi-superscript size-14"></i><i class="step fi-superscript size-16"></i><i class="step fi-superscript size-18"></i><i class="step fi-superscript size-21"></i><i class="step fi-superscript size-24"></i><i class="step fi-superscript size-36"></i><i class="step fi-superscript size-48"></i><i class="step fi-superscript size-60"></i><i class="step fi-superscript size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-superscript" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f2;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-tablet-landscape size-12"></i><i class="step fi-tablet-landscape size-14"></i><i class="step fi-tablet-landscape size-16"></i><i class="step fi-tablet-landscape size-18"></i><i class="step fi-tablet-landscape size-21"></i><i class="step fi-tablet-landscape size-24"></i><i class="step fi-tablet-landscape size-36"></i><i class="step fi-tablet-landscape size-48"></i><i class="step fi-tablet-landscape size-60"></i><i class="step fi-tablet-landscape size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-tablet-landscape" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f3;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-tablet-portrait size-12"></i><i class="step fi-tablet-portrait size-14"></i><i class="step fi-tablet-portrait size-16"></i><i class="step fi-tablet-portrait size-18"></i><i class="step fi-tablet-portrait size-21"></i><i class="step fi-tablet-portrait size-24"></i><i class="step fi-tablet-portrait size-36"></i><i class="step fi-tablet-portrait size-48"></i><i class="step fi-tablet-portrait size-60"></i><i class="step fi-tablet-portrait size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-tablet-portrait" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f4;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-target-two size-12"></i><i class="step fi-target-two size-14"></i><i class="step fi-target-two size-16"></i><i class="step fi-target-two size-18"></i><i class="step fi-target-two size-21"></i><i class="step fi-target-two size-24"></i><i class="step fi-target-two size-36"></i><i class="step fi-target-two size-48"></i><i class="step fi-target-two size-60"></i><i class="step fi-target-two size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-target-two" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f5;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-target size-12"></i><i class="step fi-target size-14"></i><i class="step fi-target size-16"></i><i class="step fi-target size-18"></i><i class="step fi-target size-21"></i><i class="step fi-target size-24"></i><i class="step fi-target size-36"></i><i class="step fi-target size-48"></i><i class="step fi-target size-60"></i><i class="step fi-target size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-target" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f6;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-telephone-accessible size-12"></i><i class="step fi-telephone-accessible size-14"></i><i class="step fi-telephone-accessible size-16"></i><i class="step fi-telephone-accessible size-18"></i><i class="step fi-telephone-accessible size-21"></i><i class="step fi-telephone-accessible size-24"></i><i class="step fi-telephone-accessible size-36"></i><i class="step fi-telephone-accessible size-48"></i><i class="step fi-telephone-accessible size-60"></i><i class="step fi-telephone-accessible size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-telephone-accessible" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f7;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-telephone size-12"></i><i class="step fi-telephone size-14"></i><i class="step fi-telephone size-16"></i><i class="step fi-telephone size-18"></i><i class="step fi-telephone size-21"></i><i class="step fi-telephone size-24"></i><i class="step fi-telephone size-36"></i><i class="step fi-telephone size-48"></i><i class="step fi-telephone size-60"></i><i class="step fi-telephone size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-telephone" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f8;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-text-color size-12"></i><i class="step fi-text-color size-14"></i><i class="step fi-text-color size-16"></i><i class="step fi-text-color size-18"></i><i class="step fi-text-color size-21"></i><i class="step fi-text-color size-24"></i><i class="step fi-text-color size-36"></i><i class="step fi-text-color size-48"></i><i class="step fi-text-color size-60"></i><i class="step fi-text-color size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-text-color" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1f9;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-thumbnails size-12"></i><i class="step fi-thumbnails size-14"></i><i class="step fi-thumbnails size-16"></i><i class="step fi-thumbnails size-18"></i><i class="step fi-thumbnails size-21"></i><i class="step fi-thumbnails size-24"></i><i class="step fi-thumbnails size-36"></i><i class="step fi-thumbnails size-48"></i><i class="step fi-thumbnails size-60"></i><i class="step fi-thumbnails size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-thumbnails" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1fa;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-ticket size-12"></i><i class="step fi-ticket size-14"></i><i class="step fi-ticket size-16"></i><i class="step fi-ticket size-18"></i><i class="step fi-ticket size-21"></i><i class="step fi-ticket size-24"></i><i class="step fi-ticket size-36"></i><i class="step fi-ticket size-48"></i><i class="step fi-ticket size-60"></i><i class="step fi-ticket size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-ticket" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1fb;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torso-business size-12"></i><i class="step fi-torso-business size-14"></i><i class="step fi-torso-business size-16"></i><i class="step fi-torso-business size-18"></i><i class="step fi-torso-business size-21"></i><i class="step fi-torso-business size-24"></i><i class="step fi-torso-business size-36"></i><i class="step fi-torso-business size-48"></i><i class="step fi-torso-business size-60"></i><i class="step fi-torso-business size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torso-business" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1fc;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torso-female size-12"></i><i class="step fi-torso-female size-14"></i><i class="step fi-torso-female size-16"></i><i class="step fi-torso-female size-18"></i><i class="step fi-torso-female size-21"></i><i class="step fi-torso-female size-24"></i><i class="step fi-torso-female size-36"></i><i class="step fi-torso-female size-48"></i><i class="step fi-torso-female size-60"></i><i class="step fi-torso-female size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torso-female" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1fd;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torso size-12"></i><i class="step fi-torso size-14"></i><i class="step fi-torso size-16"></i><i class="step fi-torso size-18"></i><i class="step fi-torso size-21"></i><i class="step fi-torso size-24"></i><i class="step fi-torso size-36"></i><i class="step fi-torso size-48"></i><i class="step fi-torso size-60"></i><i class="step fi-torso size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torso" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1fe;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torsos-all-female size-12"></i><i class="step fi-torsos-all-female size-14"></i><i class="step fi-torsos-all-female size-16"></i><i class="step fi-torsos-all-female size-18"></i><i class="step fi-torsos-all-female size-21"></i><i class="step fi-torsos-all-female size-24"></i><i class="step fi-torsos-all-female size-36"></i><i class="step fi-torsos-all-female size-48"></i><i class="step fi-torsos-all-female size-60"></i><i class="step fi-torsos-all-female size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torsos-all-female" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf1ff;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torsos-all size-12"></i><i class="step fi-torsos-all size-14"></i><i class="step fi-torsos-all size-16"></i><i class="step fi-torsos-all size-18"></i><i class="step fi-torsos-all size-21"></i><i class="step fi-torsos-all size-24"></i><i class="step fi-torsos-all size-36"></i><i class="step fi-torsos-all size-48"></i><i class="step fi-torsos-all size-60"></i><i class="step fi-torsos-all size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torsos-all" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf200;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torsos-female-male size-12"></i><i class="step fi-torsos-female-male size-14"></i><i class="step fi-torsos-female-male size-16"></i><i class="step fi-torsos-female-male size-18"></i><i class="step fi-torsos-female-male size-21"></i><i class="step fi-torsos-female-male size-24"></i><i class="step fi-torsos-female-male size-36"></i><i class="step fi-torsos-female-male size-48"></i><i class="step fi-torsos-female-male size-60"></i><i class="step fi-torsos-female-male size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torsos-female-male" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf201;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torsos-male-female size-12"></i><i class="step fi-torsos-male-female size-14"></i><i class="step fi-torsos-male-female size-16"></i><i class="step fi-torsos-male-female size-18"></i><i class="step fi-torsos-male-female size-21"></i><i class="step fi-torsos-male-female size-24"></i><i class="step fi-torsos-male-female size-36"></i><i class="step fi-torsos-male-female size-48"></i><i class="step fi-torsos-male-female size-60"></i><i class="step fi-torsos-male-female size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torsos-male-female" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf202;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-torsos size-12"></i><i class="step fi-torsos size-14"></i><i class="step fi-torsos size-16"></i><i class="step fi-torsos size-18"></i><i class="step fi-torsos size-21"></i><i class="step fi-torsos size-24"></i><i class="step fi-torsos size-36"></i><i class="step fi-torsos size-48"></i><i class="step fi-torsos size-60"></i><i class="step fi-torsos size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-torsos" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf203;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-trash size-12"></i><i class="step fi-trash size-14"></i><i class="step fi-trash size-16"></i><i class="step fi-trash size-18"></i><i class="step fi-trash size-21"></i><i class="step fi-trash size-24"></i><i class="step fi-trash size-36"></i><i class="step fi-trash size-48"></i><i class="step fi-trash size-60"></i><i class="step fi-trash size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-trash" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf204;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-trees size-12"></i><i class="step fi-trees size-14"></i><i class="step fi-trees size-16"></i><i class="step fi-trees size-18"></i><i class="step fi-trees size-21"></i><i class="step fi-trees size-24"></i><i class="step fi-trees size-36"></i><i class="step fi-trees size-48"></i><i class="step fi-trees size-60"></i><i class="step fi-trees size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-trees" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf205;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-trophy size-12"></i><i class="step fi-trophy size-14"></i><i class="step fi-trophy size-16"></i><i class="step fi-trophy size-18"></i><i class="step fi-trophy size-21"></i><i class="step fi-trophy size-24"></i><i class="step fi-trophy size-36"></i><i class="step fi-trophy size-48"></i><i class="step fi-trophy size-60"></i><i class="step fi-trophy size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-trophy" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf206;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-underline size-12"></i><i class="step fi-underline size-14"></i><i class="step fi-underline size-16"></i><i class="step fi-underline size-18"></i><i class="step fi-underline size-21"></i><i class="step fi-underline size-24"></i><i class="step fi-underline size-36"></i><i class="step fi-underline size-48"></i><i class="step fi-underline size-60"></i><i class="step fi-underline size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-underline" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf207;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-universal-access size-12"></i><i class="step fi-universal-access size-14"></i><i class="step fi-universal-access size-16"></i><i class="step fi-universal-access size-18"></i><i class="step fi-universal-access size-21"></i><i class="step fi-universal-access size-24"></i><i class="step fi-universal-access size-36"></i><i class="step fi-universal-access size-48"></i><i class="step fi-universal-access size-60"></i><i class="step fi-universal-access size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-universal-access" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf208;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-unlink size-12"></i><i class="step fi-unlink size-14"></i><i class="step fi-unlink size-16"></i><i class="step fi-unlink size-18"></i><i class="step fi-unlink size-21"></i><i class="step fi-unlink size-24"></i><i class="step fi-unlink size-36"></i><i class="step fi-unlink size-48"></i><i class="step fi-unlink size-60"></i><i class="step fi-unlink size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-unlink" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf209;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-unlock size-12"></i><i class="step fi-unlock size-14"></i><i class="step fi-unlock size-16"></i><i class="step fi-unlock size-18"></i><i class="step fi-unlock size-21"></i><i class="step fi-unlock size-24"></i><i class="step fi-unlock size-36"></i><i class="step fi-unlock size-48"></i><i class="step fi-unlock size-60"></i><i class="step fi-unlock size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-unlock" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20a;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-upload-cloud size-12"></i><i class="step fi-upload-cloud size-14"></i><i class="step fi-upload-cloud size-16"></i><i class="step fi-upload-cloud size-18"></i><i class="step fi-upload-cloud size-21"></i><i class="step fi-upload-cloud size-24"></i><i class="step fi-upload-cloud size-36"></i><i class="step fi-upload-cloud size-48"></i><i class="step fi-upload-cloud size-60"></i><i class="step fi-upload-cloud size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-upload-cloud" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20b;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-upload size-12"></i><i class="step fi-upload size-14"></i><i class="step fi-upload size-16"></i><i class="step fi-upload size-18"></i><i class="step fi-upload size-21"></i><i class="step fi-upload size-24"></i><i class="step fi-upload size-36"></i><i class="step fi-upload size-48"></i><i class="step fi-upload size-60"></i><i class="step fi-upload size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-upload" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20c;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-usb size-12"></i><i class="step fi-usb size-14"></i><i class="step fi-usb size-16"></i><i class="step fi-usb size-18"></i><i class="step fi-usb size-21"></i><i class="step fi-usb size-24"></i><i class="step fi-usb size-36"></i><i class="step fi-usb size-48"></i><i class="step fi-usb size-60"></i><i class="step fi-usb size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-usb" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20d;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-video size-12"></i><i class="step fi-video size-14"></i><i class="step fi-video size-16"></i><i class="step fi-video size-18"></i><i class="step fi-video size-21"></i><i class="step fi-video size-24"></i><i class="step fi-video size-36"></i><i class="step fi-video size-48"></i><i class="step fi-video size-60"></i><i class="step fi-video size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-video" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20e;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-volume-none size-12"></i><i class="step fi-volume-none size-14"></i><i class="step fi-volume-none size-16"></i><i class="step fi-volume-none size-18"></i><i class="step fi-volume-none size-21"></i><i class="step fi-volume-none size-24"></i><i class="step fi-volume-none size-36"></i><i class="step fi-volume-none size-48"></i><i class="step fi-volume-none size-60"></i><i class="step fi-volume-none size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-volume-none" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf20f;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-volume-strike size-12"></i><i class="step fi-volume-strike size-14"></i><i class="step fi-volume-strike size-16"></i><i class="step fi-volume-strike size-18"></i><i class="step fi-volume-strike size-21"></i><i class="step fi-volume-strike size-24"></i><i class="step fi-volume-strike size-36"></i><i class="step fi-volume-strike size-48"></i><i class="step fi-volume-strike size-60"></i><i class="step fi-volume-strike size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-volume-strike" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf210;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-volume size-12"></i><i class="step fi-volume size-14"></i><i class="step fi-volume size-16"></i><i class="step fi-volume size-18"></i><i class="step fi-volume size-21"></i><i class="step fi-volume size-24"></i><i class="step fi-volume size-36"></i><i class="step fi-volume size-48"></i><i class="step fi-volume size-60"></i><i class="step fi-volume size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-volume" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf211;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-web size-12"></i><i class="step fi-web size-14"></i><i class="step fi-web size-16"></i><i class="step fi-web size-18"></i><i class="step fi-web size-21"></i><i class="step fi-web size-24"></i><i class="step fi-web size-36"></i><i class="step fi-web size-48"></i><i class="step fi-web size-60"></i><i class="step fi-web size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-web" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf212;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-wheelchair size-12"></i><i class="step fi-wheelchair size-14"></i><i class="step fi-wheelchair size-16"></i><i class="step fi-wheelchair size-18"></i><i class="step fi-wheelchair size-21"></i><i class="step fi-wheelchair size-24"></i><i class="step fi-wheelchair size-36"></i><i class="step fi-wheelchair size-48"></i><i class="step fi-wheelchair size-60"></i><i class="step fi-wheelchair size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-wheelchair" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf213;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-widget size-12"></i><i class="step fi-widget size-14"></i><i class="step fi-widget size-16"></i><i class="step fi-widget size-18"></i><i class="step fi-widget size-21"></i><i class="step fi-widget size-24"></i><i class="step fi-widget size-36"></i><i class="step fi-widget size-48"></i><i class="step fi-widget size-60"></i><i class="step fi-widget size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-widget" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf214;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-wrench size-12"></i><i class="step fi-wrench size-14"></i><i class="step fi-wrench size-16"></i><i class="step fi-wrench size-18"></i><i class="step fi-wrench size-21"></i><i class="step fi-wrench size-24"></i><i class="step fi-wrench size-36"></i><i class="step fi-wrench size-48"></i><i class="step fi-wrench size-60"></i><i class="step fi-wrench size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-wrench" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf215;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-x-circle size-12"></i><i class="step fi-x-circle size-14"></i><i class="step fi-x-circle size-16"></i><i class="step fi-x-circle size-18"></i><i class="step fi-x-circle size-21"></i><i class="step fi-x-circle size-24"></i><i class="step fi-x-circle size-36"></i><i class="step fi-x-circle size-48"></i><i class="step fi-x-circle size-60"></i><i class="step fi-x-circle size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-x-circle" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf216;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-x size-12"></i><i class="step fi-x size-14"></i><i class="step fi-x size-16"></i><i class="step fi-x size-18"></i><i class="step fi-x size-21"></i><i class="step fi-x size-24"></i><i class="step fi-x size-36"></i><i class="step fi-x size-48"></i><i class="step fi-x size-60"></i><i class="step fi-x size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-x" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf217;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-yen size-12"></i><i class="step fi-yen size-14"></i><i class="step fi-yen size-16"></i><i class="step fi-yen size-18"></i><i class="step fi-yen size-21"></i><i class="step fi-yen size-24"></i><i class="step fi-yen size-36"></i><i class="step fi-yen size-48"></i><i class="step fi-yen size-60"></i><i class="step fi-yen size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-yen" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf218;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-zoom-in size-12"></i><i class="step fi-zoom-in size-14"></i><i class="step fi-zoom-in size-16"></i><i class="step fi-zoom-in size-18"></i><i class="step fi-zoom-in size-21"></i><i class="step fi-zoom-in size-24"></i><i class="step fi-zoom-in size-36"></i><i class="step fi-zoom-in size-48"></i><i class="step fi-zoom-in size-60"></i><i class="step fi-zoom-in size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-zoom-in" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf219;" />
+ </div>
+ </div>
+
+ <div class="glyph">
+ <div class="preview-glyphs">
+ <i class="step fi-zoom-out size-12"></i><i class="step fi-zoom-out size-14"></i><i class="step fi-zoom-out size-16"></i><i class="step fi-zoom-out size-18"></i><i class="step fi-zoom-out size-21"></i><i class="step fi-zoom-out size-24"></i><i class="step fi-zoom-out size-36"></i><i class="step fi-zoom-out size-48"></i><i class="step fi-zoom-out size-60"></i><i class="step fi-zoom-out size-72"></i>
+ </div>
+ <div class="preview-scale">
+ <span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
+ </div>
+ <div class="usage">
+ <input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fi-zoom-out" />
+ <input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf21a;" />
+ </div>
+ </div>
+
+ </div>
+ </body>
+</html>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-address-book.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-address-book.svg
new file mode 100644
index 0000000..803c41b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-address-book.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M81.195,31.517c1.128,0,2.042-0.897,2.042-1.996V23.61c0-1.102-0.914-2-2.042-2h-4.586v-1.603
+ c0-1.771-1.436-3.207-3.206-3.207H19.97c-1.771,0-3.206,1.435-3.206,3.207v59.986c0,1.766,1.436,3.206,3.206,3.206h53.432
+ c1.77,0,3.206-1.44,3.206-3.206v-1.67h4.586c1.128,0,2.042-0.894,2.042-1.996v-5.912c0-1.102-0.914-2-2.042-2h-4.586v-5.699h4.586
+ c1.128,0,2.042-0.894,2.042-1.991v-5.912c0-1.102-0.914-2-2.042-2h-4.586v-5.699h4.586c1.128,0,2.042-0.897,2.042-1.996v-5.912
+ c0-1.098-0.914-1.996-2.042-1.996h-4.586v-5.695H81.195z M62.391,63.681c0,1.152-0.804,2.088-1.795,2.088H32.75
+ c-0.992,0-1.795-0.935-1.795-2.088v-8.604c0-0.856,0.447-1.625,1.127-1.941l10.9-5.077c-2.583-1.557-4.351-4.689-4.351-8.304
+ c0-5.168,3.599-9.356,8.041-9.356c4.443,0,8.042,4.188,8.042,9.356c0,3.562-1.708,6.655-4.226,8.238l10.789,5.148
+ c0.674,0.325,1.115,1.085,1.115,1.937V63.681z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-alert.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-alert.svg
new file mode 100644
index 0000000..bef63b8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-alert.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M91.17,81.374l0.006-0.004l-0.139-0.24c-0.068-0.128-0.134-0.257-0.216-0.375l-37.69-65.283
+ c-0.611-1.109-1.776-1.87-3.133-1.87c-1.47,0-2.731,0.887-3.285,2.153l-0.004-0.002L9.312,80.529l0.036,0.021
+ c-0.505,0.618-0.82,1.397-0.82,2.257c0,1.982,1.607,3.59,3.588,3.59h0h75.767v0c1.982,0,3.589-1.607,3.589-3.589
+ C91.472,82.297,91.362,81.814,91.17,81.374z M50.035,79.617c-2.874,0-5.201-2.257-5.201-5.13c0-2.874,2.326-5.2,5.201-5.2
+ c2.803,0,5.13,2.325,5.13,5.2C55.166,77.36,52.838,79.617,50.035,79.617z M55.165,34.25v28.299h-0.002
+ c0,0.005,0.002,0.01,0.002,0.016c0,1.173-0.95,2.094-2.094,2.094c-0.005,0-0.009-0.001-0.014-0.001v0.001h-6.093
+ c-1.174,0-2.123-0.921-2.123-2.094c0-0.005,0.002-0.01,0.002-0.016h-0.002V34.326c-0.001-0.026-0.008-0.051-0.008-0.077
+ c0-1.117,0.865-1.996,1.935-2.078v-0.016h6.288v0.001c1.149,0.007,2.074,0.897,2.103,2.039h0.005v0.053V34.25
+ C55.166,34.25,55.165,34.25,55.165,34.25z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-center.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-center.svg
new file mode 100644
index 0000000..0457753
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-center.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.138H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.663,83.113,15.138,81.232,15.138z"/>
+ <path d="M76.224,41.611L76.224,41.611l0-3.143h0c0-1.882-1.525-3.407-3.407-3.407h0H27.183c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.407,3.407,3.407h45.634h0C74.699,45.017,76.224,43.492,76.224,41.611z"/>
+ <path d="M77.81,74.905L77.81,74.905H22.176c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407H77.81h0
+ c1.881,0,3.407-1.525,3.407-3.407h0.015v-3.143h-0.015C81.217,76.431,79.691,74.905,77.81,74.905z"/>
+ <path d="M72.817,58.39c0-1.882-1.525-3.407-3.407-3.407l0,0v0H30.59c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.407,3.407,3.407h38.82v0l0,0c1.881,0,3.407-1.525,3.407-3.407c0,0,0-0.001,0-0.001v-3.141L72.817,58.39z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-justify.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-justify.svg
new file mode 100644
index 0000000..4a10996
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-justify.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.389H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.914,83.113,15.389,81.232,15.389z"/>
+ <path d="M81.232,35.144H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,36.67,83.113,35.144,81.232,35.144z"/>
+ <path d="M81.232,54.899H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,56.425,83.113,54.899,81.232,54.899z"/>
+ <path d="M81.232,74.654H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,76.18,83.113,74.654,81.232,74.654z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-left.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-left.svg
new file mode 100644
index 0000000..705d0a6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-left.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.138H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.663,83.113,15.138,81.232,15.138z"/>
+ <path d="M18.769,45.008h45.634h0c1.881,0,3.407-1.525,3.407-3.407h0v-3.143h0c0-1.882-1.525-3.407-3.407-3.407h0H18.769
+ c-1.882,0-3.407,1.525-3.407,3.407v3.143C15.361,43.483,16.887,45.008,18.769,45.008z"/>
+ <path d="M74.403,74.905L74.403,74.905H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h55.634h0
+ c1.881,0,3.407-1.525,3.407-3.407h0.015v-3.143H77.81C77.81,76.431,76.284,74.905,74.403,74.905z"/>
+ <path d="M18.769,64.94h38.82v0l0,0c1.881,0,3.407-1.525,3.407-3.407c0,0,0-0.001,0-0.001v-3.141l0-0.001
+ c0-1.882-1.525-3.407-3.407-3.407l0,0v0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143C15.361,63.414,16.887,64.94,18.769,64.94z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-right.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-right.svg
new file mode 100644
index 0000000..c2bc676
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-align-right.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.138H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.663,83.113,15.138,81.232,15.138z"/>
+ <path d="M81.232,35.06L81.232,35.06H35.597c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h45.634h0
+ c1.881,0,3.407-1.525,3.407-3.407h0v-3.143h0C84.638,36.586,83.113,35.06,81.232,35.06z"/>
+ <path d="M81.217,74.905L81.217,74.905L81.217,74.905H25.583c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.407,3.407,3.407h55.634h0c1.881,0,3.407-1.525,3.407-3.407h0.015v-3.143h-0.015
+ C84.624,76.431,83.098,74.905,81.217,74.905z"/>
+ <path d="M84.639,58.39c0-1.882-1.525-3.407-3.407-3.407l0,0v0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.407,3.407,3.407h38.82v0l0,0c1.881,0,3.407-1.525,3.407-3.407c0,0,0-0.001,0-0.001v-3.141L84.639,58.39z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-anchor.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-anchor.svg
new file mode 100644
index 0000000..204db43
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-anchor.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.189,67.115l0.007-0.004l-9.393-16.27l-0.009,0.005c-0.268-0.487-0.781-0.822-1.376-0.822
+ c-0.677,0-1.25,0.429-1.474,1.027l-9.158,15.862c-0.219,0.271-0.356,0.611-0.356,0.987c0,0.873,0.706,1.578,1.577,1.578h2.39
+ c-3.983,4.39-9.356,7.487-15.42,8.6v-29.2h9.079c0.871,0,1.578-0.705,1.578-1.578l-0.001-0.008V40.5c0,0,0-0.001,0-0.001
+ c0-0.871-0.706-1.577-1.577-1.577h-0.001h-9.078v-5.36c3.905-1.864,6.611-5.838,6.611-10.454c0-6.401-5.189-11.589-11.589-11.589
+ c-6.4,0-11.589,5.188-11.589,11.589c0,4.617,2.705,8.59,6.611,10.454v5.36h-9.079c0,0,0,0-0.001,0
+ c-0.871,0-1.577,0.706-1.577,1.576h-0.001v6.803h0.001c0.001,0.873,0.706,1.577,1.576,1.577h9.08v29.2
+ c-6.064-1.112-11.437-4.21-15.42-8.6h2.389c0.872,0,1.578-0.705,1.578-1.578c0-0.287-0.083-0.553-0.217-0.785l0.007-0.004
+ l-9.393-16.27l-0.009,0.005c-0.268-0.487-0.781-0.822-1.377-0.822c-0.675,0-1.246,0.427-1.471,1.022l-9.162,15.869
+ c-0.218,0.271-0.354,0.61-0.354,0.985c0,0.873,0.706,1.578,1.577,1.578h4.219C23.835,80.823,36.017,88.482,50,88.482
+ c13.983,0,26.165-7.658,32.611-19.003h4.218c0.872,0,1.577-0.705,1.577-1.578C88.406,67.614,88.324,67.348,88.189,67.115z
+ M50,29.634c-3.604,0-6.526-2.923-6.526-6.524c0-3.604,2.922-6.527,6.526-6.527c3.603,0,6.526,2.923,6.526,6.527
+ C56.526,26.71,53.603,29.634,50,29.634z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-annotate.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-annotate.svg
new file mode 100644
index 0000000..72bcfcb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-annotate.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.488,68.439V31.561c3.232-1.769,5.424-5.199,5.424-9.143c0-5.753-4.664-10.417-10.417-10.417
+ c-3.559,0-6.698,1.788-8.577,4.512H31.083c-1.879-2.724-5.018-4.512-8.577-4.512c-5.753,0-10.417,4.664-10.417,10.417
+ c0,3.944,2.192,7.375,5.424,9.143v36.877c-3.232,1.769-5.424,5.199-5.424,9.143c0,5.753,4.664,10.417,10.417,10.417
+ c4.371,0,8.107-2.695,9.653-6.512h35.682c1.546,3.816,5.282,6.512,9.653,6.512c5.753,0,10.417-4.664,10.417-10.417
+ C87.911,73.638,85.719,70.208,82.488,68.439z M27.488,68.432V31.568c2.054-1.121,3.689-2.912,4.61-5.081h35.806
+ c0.921,2.168,2.556,3.96,4.61,5.081v36.864c-1.379,0.752-2.561,1.813-3.473,3.081H30.961
+ C30.049,70.244,28.866,69.184,27.488,68.432z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-archive.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-archive.svg
new file mode 100644
index 0000000..4fcc82a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-archive.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M89.148,32.927c0.001-0.037,0.011-0.07,0.011-0.107c0-1.023-0.393-1.935-1.016-2.642l0.02-0.011L80.293,16.54
+ c-0.276-1.111-1.281-1.916-2.468-1.914c-0.083,0-0.161,0.016-0.242,0.024v-0.024H22.219v0.004c-0.013,0-0.026-0.004-0.039-0.004
+ c-0.96-0.001-1.759,0.529-2.17,1.315l-0.008-0.005L11.79,30.167l0.015,0.008c-0.596,0.707-0.963,1.619-0.963,2.642
+ c0,0.047,0.012,0.091,0.014,0.138v48.211c-0.002,0.048-0.014,0.093-0.014,0.142c0,2.284,1.817,4.069,4.095,4.066
+ c0.043,0,0.083-0.011,0.125-0.012h69.87c0.043,0.001,0.083,0.012,0.126,0.012c2.283,0,4.1-1.782,4.1-4.062
+ c0-0.036-0.01-0.068-0.011-0.104V32.927z M63.413,57.492L51.022,74.922c-0.226,0.318-0.59,0.505-0.98,0.507c0,0,0,0-0.004,0
+ c-0.386,0-0.751-0.187-0.977-0.503L36.59,57.494c-0.262-0.368-0.299-0.85-0.091-1.251c0.208-0.401,0.62-0.654,1.071-0.654h5.833
+ l0.001-15.654c0-0.667,0.538-1.205,1.203-1.205h10.789c0.665,0,1.204,0.539,1.204,1.204v15.655h5.83
+ c0.453,0,0.867,0.253,1.071,0.652C63.708,56.64,63.674,57.124,63.413,57.492z M18.376,28.733l5.263-9.119h52.67l5.266,9.119H18.376
+ z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-down.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-down.svg
new file mode 100644
index 0000000..53cb1a9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-down.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M21.984,50.868l26.055,36.418c0.471,0.66,1.233,1.049,2.043,1.051c0.006,0,0.006,0,0.006,0
+ c0.815-0.002,1.575-0.396,2.048-1.059l25.887-36.417c0.546-0.767,0.616-1.776,0.183-2.612c-0.426-0.835-1.292-1.361-2.236-1.361
+ H63.787l0.001-32.709c0-1.39-1.125-2.515-2.516-2.515l-22.541,0.001c-1.389-0.001-2.515,1.124-2.516,2.516l0,32.705H24.029
+ c-0.94,0-1.803,0.53-2.237,1.367C21.359,49.089,21.434,50.1,21.984,50.868z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-left.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-left.svg
new file mode 100644
index 0000000..c0c4d72
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-left.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M49.132,21.984L12.714,48.039c-0.66,0.471-1.049,1.233-1.051,2.043c0,0.006,0,0.006,0,0.006
+ c0.002,0.815,0.396,1.575,1.059,2.048L49.14,78.023c0.767,0.546,1.776,0.616,2.612,0.183c0.835-0.426,1.361-1.291,1.361-2.236
+ V63.787l32.709,0.001c1.39,0,2.515-1.125,2.515-2.516l-0.001-22.541c0.001-1.389-1.124-2.515-2.516-2.516l-32.706,0V24.029
+ c0-0.94-0.53-1.803-1.367-2.237C50.911,21.359,49.9,21.434,49.132,21.984z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-right.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-right.svg
new file mode 100644
index 0000000..9da35e9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-right.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50.868,78.016l36.418-26.055c0.66-0.471,1.049-1.233,1.051-2.043c0-0.006,0-0.006,0-0.006
+ c-0.002-0.815-0.396-1.575-1.059-2.048L50.86,21.977c-0.767-0.546-1.776-0.616-2.612-0.183c-0.835,0.426-1.361,1.292-1.361,2.236
+ v12.183l-32.709-0.001c-1.39,0-2.515,1.125-2.515,2.516l0.001,22.541c-0.001,1.389,1.124,2.515,2.516,2.516l32.706,0v12.187
+ c0,0.94,0.53,1.803,1.366,2.237C49.089,78.641,50.1,78.567,50.868,78.016z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-up.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-up.svg
new file mode 100644
index 0000000..8a67d80
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrow-up.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.016,49.132L51.961,12.714c-0.471-0.66-1.233-1.049-2.043-1.051c-0.006,0-0.006,0-0.006,0
+ c-0.815,0.002-1.575,0.396-2.048,1.059L21.977,49.14c-0.546,0.767-0.616,1.776-0.183,2.612c0.426,0.835,1.292,1.361,2.236,1.361
+ h12.183l-0.001,32.709c0,1.39,1.125,2.515,2.516,2.515l22.541-0.001c1.389,0.001,2.515-1.124,2.516-2.517l0-32.705h12.187
+ c0.94,0,1.803-0.53,2.237-1.367C78.641,50.911,78.566,49.9,78.016,49.132z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-compress.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-compress.svg
new file mode 100644
index 0000000..51c2a1e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-compress.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M39.171,88.427l5.103-30.768c0.093-0.558-0.089-1.125-0.489-1.524c-0.002-0.003-0.002-0.003-0.002-0.003
+ c-0.403-0.4-0.971-0.581-1.531-0.486l-30.685,5.186c-0.646,0.108-1.176,0.571-1.375,1.196c-0.202,0.622-0.034,1.308,0.43,1.772
+ l6,5.999L0.514,85.907c-0.685,0.685-0.685,1.793,0,2.479l11.1,11.101c0.686,0.685,1.793,0.685,2.479,0l16.108-16.108l6.002,6.002
+ c0.462,0.462,1.148,0.627,1.774,0.429C38.603,89.61,39.064,89.076,39.171,88.427z"/>
+ </g>
+ <g>
+ <path d="M60.829,11.573l-5.104,30.768c-0.093,0.557,0.09,1.125,0.489,1.524c0.003,0.003,0.003,0.003,0.003,0.003
+ c0.403,0.4,0.972,0.581,1.53,0.486l30.685-5.187c0.647-0.108,1.176-0.571,1.376-1.196c0.202-0.623,0.034-1.308-0.431-1.773
+ l-5.999-5.999l16.108-16.107c0.685-0.686,0.685-1.794,0-2.479L88.386,0.514c-0.685-0.685-1.794-0.685-2.479,0L69.799,16.621
+ l-6.002-6.001c-0.463-0.463-1.15-0.629-1.775-0.429C61.398,10.391,60.937,10.924,60.829,11.573z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-expand.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-expand.svg
new file mode 100644
index 0000000..9da2447
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-expand.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M5.128,67.194L0.024,97.962c-0.093,0.558,0.09,1.125,0.489,1.524c0.002,0.003,0.002,0.003,0.002,0.003
+ c0.403,0.4,0.972,0.581,1.531,0.486l30.685-5.186c0.647-0.108,1.178-0.572,1.376-1.197c0.201-0.622,0.034-1.308-0.431-1.771
+ l-6-5.999l16.109-16.108c0.685-0.685,0.685-1.793,0-2.478L32.684,56.134c-0.685-0.685-1.793-0.685-2.479,0L14.098,72.242
+ L8.096,66.24c-0.464-0.462-1.149-0.627-1.774-0.428C5.697,66.012,5.236,66.545,5.128,67.194z"/>
+ </g>
+ <g>
+ <path d="M94.872,32.806l5.104-30.768c0.093-0.558-0.09-1.125-0.489-1.524c-0.002-0.003-0.002-0.003-0.002-0.003
+ c-0.404-0.399-0.972-0.581-1.531-0.487L67.269,5.21c-0.646,0.109-1.177,0.572-1.377,1.197c-0.2,0.623-0.033,1.308,0.431,1.772
+ l6.001,5.998L56.215,30.286c-0.685,0.686-0.685,1.794,0,2.48l11.102,11.101c0.685,0.685,1.794,0.685,2.479,0l16.107-16.108
+ l6.001,6.001c0.465,0.463,1.15,0.629,1.775,0.43C94.303,33.988,94.765,33.455,94.872,32.806z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-in.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-in.svg
new file mode 100644
index 0000000..819c99e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-in.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M35.995,89.365l4.69-28.272c0.085-0.512-0.082-1.034-0.449-1.401c-0.002-0.002-0.002-0.002-0.002-0.002
+ c-0.37-0.368-0.893-0.535-1.406-0.447L10.63,64.007c-0.594,0.1-1.081,0.525-1.264,1.1c-0.185,0.572-0.031,1.202,0.395,1.628
+ l5.513,5.513L0.473,87.05c-0.63,0.629-0.63,1.647,0,2.277l10.2,10.201c0.63,0.629,1.648,0.629,2.278,0l14.802-14.802l5.515,5.515
+ c0.425,0.425,1.055,0.577,1.63,0.394C35.473,90.452,35.896,89.961,35.995,89.365z"/>
+ </g>
+ <g>
+ <path d="M64.006,10.635l-4.69,28.273c-0.085,0.512,0.083,1.033,0.449,1.4c0.002,0.003,0.002,0.003,0.002,0.003
+ c0.37,0.367,0.893,0.534,1.406,0.447l28.196-4.766c0.594-0.1,1.081-0.525,1.265-1.1c0.185-0.572,0.031-1.202-0.396-1.628
+ l-5.513-5.513l14.802-14.802c0.629-0.629,0.629-1.648,0-2.278l-10.2-10.2c-0.63-0.63-1.648-0.63-2.278,0L72.248,15.274
+ l-5.515-5.515c-0.425-0.425-1.056-0.578-1.63-0.395C64.528,9.549,64.104,10.039,64.006,10.635z"/>
+ </g>
+ <g>
+ <path d="M89.365,64.006l-28.271-4.69c-0.512-0.085-1.035,0.082-1.401,0.449c-0.003,0.003-0.003,0.003-0.003,0.003
+ c-0.368,0.369-0.535,0.892-0.447,1.406l4.765,28.196c0.1,0.594,0.525,1.082,1.099,1.264c0.572,0.185,1.202,0.032,1.629-0.395
+ l5.513-5.513l14.803,14.803c0.629,0.628,1.647,0.628,2.277-0.002l10.201-10.2c0.629-0.629,0.629-1.648,0-2.278L84.727,72.248
+ l5.516-5.515c0.424-0.426,0.577-1.055,0.394-1.63C90.452,64.528,89.961,64.104,89.365,64.006z"/>
+ </g>
+ <g>
+ <path d="M10.635,35.995l28.272,4.69c0.513,0.086,1.034-0.082,1.401-0.449c0.002-0.003,0.002-0.003,0.002-0.003
+ c0.368-0.37,0.535-0.892,0.448-1.406L35.993,10.63c-0.1-0.593-0.525-1.081-1.099-1.264c-0.573-0.186-1.202-0.032-1.629,0.395
+ l-5.513,5.513L12.951,0.473c-0.63-0.63-1.649-0.63-2.278-0.001L0.472,10.673c-0.63,0.63-0.63,1.648,0,2.278l14.801,14.802
+ l-5.515,5.515c-0.424,0.425-0.577,1.056-0.394,1.63C9.549,35.473,10.04,35.897,10.635,35.995z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-out.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-out.svg
new file mode 100644
index 0000000..8c00d5e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-arrows-out.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M4.712,69.854l-4.69,28.273c-0.086,0.512,0.082,1.034,0.449,1.401c0.002,0.003,0.002,0.003,0.002,0.003
+ c0.37,0.368,0.893,0.535,1.406,0.447l28.197-4.765c0.594-0.1,1.081-0.525,1.264-1.1c0.185-0.572,0.031-1.202-0.396-1.628
+ l-5.513-5.513l14.802-14.802c0.63-0.629,0.63-1.647,0-2.277l-10.2-10.201c-0.63-0.629-1.648-0.629-2.278,0L12.954,74.493
+ l-5.515-5.515c-0.425-0.425-1.055-0.577-1.63-0.394C5.234,68.768,4.811,69.258,4.712,69.854z"/>
+ </g>
+ <g>
+ <path d="M95.288,30.146l4.69-28.273c0.085-0.512-0.083-1.034-0.449-1.4C99.527,0.47,99.527,0.47,99.527,0.47
+ c-0.37-0.367-0.893-0.534-1.406-0.447L69.924,4.788c-0.594,0.1-1.081,0.525-1.265,1.1c-0.185,0.572-0.031,1.202,0.396,1.628
+ l5.513,5.513L59.766,27.83c-0.629,0.629-0.629,1.648,0,2.278l10.2,10.201c0.63,0.629,1.648,0.629,2.278,0l14.802-14.802
+ l5.515,5.515c0.425,0.425,1.056,0.578,1.63,0.394C94.766,31.232,95.19,30.742,95.288,30.146z"/>
+ </g>
+ <g>
+ <path d="M69.854,95.288l28.271,4.69c0.512,0.086,1.035-0.082,1.401-0.449c0.002-0.003,0.002-0.003,0.002-0.003
+ c0.368-0.37,0.535-0.892,0.448-1.406l-4.765-28.196c-0.1-0.594-0.525-1.081-1.1-1.265c-0.572-0.185-1.202-0.031-1.628,0.396
+ l-5.513,5.513L72.169,59.765c-0.628-0.628-1.647-0.628-2.277,0.001L59.691,69.967c-0.629,0.629-0.629,1.648,0,2.277l14.802,14.802
+ l-5.515,5.515c-0.425,0.425-0.577,1.055-0.393,1.63C68.768,94.766,69.258,95.19,69.854,95.288z"/>
+ </g>
+ <g>
+ <path d="M30.146,4.712L1.874,0.022C1.361-0.064,0.84,0.104,0.473,0.471C0.47,0.474,0.47,0.474,0.47,0.474
+ C0.103,0.844-0.064,1.366,0.023,1.88l4.766,28.197c0.1,0.593,0.525,1.081,1.099,1.264c0.573,0.186,1.202,0.032,1.629-0.395
+ l5.513-5.513L27.83,40.234c0.63,0.63,1.648,0.63,2.278,0.001l10.201-10.201c0.63-0.63,0.63-1.648,0-2.278L25.507,12.954
+ l5.515-5.515c0.424-0.425,0.577-1.056,0.394-1.63C31.232,5.234,30.742,4.81,30.146,4.712z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asl.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asl.svg
new file mode 100644
index 0000000..c2e5dfe
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asl.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M25.352,26.045c0.347-0.208,0.731-0.37,1.031-0.632c3.378-2.916,7.1-5.305,11.381-6.591
+ c2.212-0.665,4.583-0.822,6.897-1.089c0.424-0.047,1.128,0.387,1.316,0.779c0.189,0.398,0.079,1.195-0.222,1.517
+ c-0.538,0.577-1.262,1.097-2.006,1.345c-2.846,0.951-5.75,1.731-8.589,2.701c-0.673,0.229-1.164,0.968-1.761,1.445
+ c-1.382,1.101-2.778,2.193-4.166,3.287c-0.219,0.174-0.425,0.366-0.637,0.551c0.042,0.076,0.085,0.153,0.127,0.23
+ c0.71-0.299,1.404-0.641,2.133-0.883c2.274-0.773,4.514-1.815,6.856-2.161c2.021-0.3,4.167,0.168,6.248,0.39
+ c0.484,0.055,0.97,0.439,1.381,0.766c1.52,1.196,3.004,2.436,4.511,3.656c0.518,0.42,0.523,0.824,0.133,1.371
+ c-0.926,1.293-2.098,1.699-3.469,0.9c-1.089-0.635-2.065-1.469-3.058-2.254c-0.528-0.418-0.999-0.57-1.722-0.454
+ c-1.379,0.216-2.796,0.175-4.191,0.308c-0.513,0.048-1.091,0.166-1.499,0.451c-1.937,1.373-3.842,2.791-5.715,4.25
+ c-0.352,0.273-0.506,0.807-0.594,1.381c0.188-0.084,0.394-0.143,0.561-0.256c1.53-1.043,3.307-1.186,5.062-1.407
+ c0.559-0.071,1.13-0.071,1.685-0.165c2.269-0.383,4.003,0.707,5.675,2.002c1.375,1.064,2.769,2.104,4.134,3.179
+ c0.803,0.632,1.214,1.458,1.207,2.514c-0.013,1.767,0.097,3.54-0.549,5.243c-0.076,0.199-0.116,0.576-0.008,0.66
+ c1.075,0.823,0.371,1.738,0.089,2.547c-0.599,1.737-1.318,3.428-1.995,5.137c-0.647,1.627-1.637,2.716-3.481,3.239
+ c-4.077,1.161-8.08,2.583-12.104,3.925c-1.645,0.551-3.251,0.766-4.998,0.344c-3.317-0.797-6.583-0.447-9.708,0.938
+ c-1.453,0.646-2.867,1.382-4.349,2.103c-1.701-2.443-2.704-5.113-3.327-7.945c-0.735-3.33-0.78-6.69-0.372-10.061
+ c0.035-0.291,0.299-0.699,0.558-0.803c3.312-1.352,4.841-4.121,5.937-7.281c1.302-3.749,1.923-7.824,4.223-11.121
+ c2.549-3.656,4.515-7.73,7.852-10.85c1.645-1.539,2.97-3.417,4.431-5.148c0.682-0.807,0.996-0.795,1.582,0.094
+ c0.668,1.012,0.507,2.094-0.318,3.133c-1.992,2.516-3.942,5.062-5.896,7.605c-0.205,0.271-0.318,0.61-0.474,0.918
+ C25.219,25.915,25.285,25.978,25.352,26.045z M39.713,54.342c0.811,0,1.543,0.219,1.945-0.646c0.79-1.7,1.992-3.079,3.444-4.241
+ c0.432-0.348,0.389-0.635,0.144-1.1c-0.704-1.348-1.305-2.75-1.996-4.104c-0.194-0.374-0.504-0.747-0.858-0.975
+ c-1.229-0.785-2.48-1.543-3.762-2.234c-0.341-0.186-0.872-0.248-1.231-0.125c-0.973,0.338-1.89,0.834-2.848,1.221
+ c-0.865,0.35-1.766,0.602-2.628,0.953c-2.055,0.836-2.553,2.734-3.158,4.598c-0.405,1.242-0.131,2.152,0.758,3.075
+ c1.176,1.218,2.26,2.532,3.317,3.858c0.374,0.47,0.714,0.496,1.203,0.334C35.93,54.331,37.847,53.971,39.713,54.342z"/>
+ <path d="M74.49,73.967c-0.655,0.49-1.343,0.944-1.957,1.481c-3.015,2.646-6.487,4.538-10.255,5.753
+ c-2.191,0.709-4.569,0.902-6.881,1.139c-1.312,0.136-2.023-1.223-1.2-2.281c0.511-0.652,1.351-1.182,2.15-1.454
+ c2.43-0.824,4.931-1.438,7.363-2.261c0.881-0.299,1.69-0.891,2.445-1.459c1.571-1.191,3.085-2.458,4.618-3.695
+ c0.225-0.182,0.435-0.381,0.529-0.783c-0.837,0.357-1.653,0.771-2.511,1.064c-2.113,0.729-4.203,1.715-6.382,2.002
+ c-2.069,0.274-4.243-0.164-6.362-0.385c-0.479-0.049-0.947-0.461-1.365-0.777c-1.328-1.01-2.632-2.049-3.939-3.086
+ c-1.345-1.068-1.142-2.455,0.542-2.986c0.656-0.207,1.585-0.141,2.18,0.184c1.187,0.65,2.215,1.592,3.347,2.354
+ c0.317,0.217,0.769,0.348,1.151,0.332c1.466-0.06,2.936-0.146,4.391-0.33c0.665-0.081,1.394-0.277,1.933-0.654
+ c1.835-1.279,3.62-2.637,5.375-4.027c0.368-0.291,0.531-0.842,0.692-1.375c-2.368,1.559-5.022,1.568-7.64,1.78
+ c-1.722,0.138-3.213-0.276-4.568-1.384c-1.756-1.439-3.613-2.756-5.358-4.207c-0.414-0.345-0.79-1.022-0.781-1.539
+ c0.033-1.757,0.225-3.513,0.398-5.264c0.057-0.582,0.367-1.139-0.247-1.656c-0.175-0.146-0.18-0.639-0.096-0.922
+ c0.209-0.703,0.522-1.371,0.778-2.059c0.491-1.312,0.975-2.627,1.452-3.949c0.649-1.801,1.736-2.988,3.709-3.551
+ c4.043-1.165,8.02-2.555,12.019-3.873c1.676-0.557,3.299-0.788,5.092-0.312c3.496,0.927,6.889,0.274,10.134-1.2
+ c1.244-0.568,2.443-1.232,3.732-1.887c1.471,1.793,2.239,3.92,2.917,6.08c1.224,3.896,1.276,7.885,0.905,11.908
+ c-0.082,0.898-0.825,1.02-1.374,1.251c-1.989,0.841-3.227,2.423-4.062,4.261c-0.906,2-1.605,4.108-2.261,6.207
+ c-0.919,2.944-1.89,5.848-3.626,8.441c-1.318,1.967-2.508,4.027-3.907,5.933c-1.142,1.556-2.514,2.942-3.776,4.409
+ c-1.347,1.564-2.683,3.138-4.029,4.703c-0.716,0.83-1.061,0.798-1.65-0.145c-0.64-1.025-0.456-2.031,0.413-3.117
+ c1.979-2.482,3.914-4.997,5.849-7.514c0.2-0.259,0.275-0.615,0.409-0.926C74.685,74.116,74.587,74.044,74.49,73.967z M54.765,51.12
+ c0.635,1.527,1.283,3.151,1.998,4.74c0.157,0.352,0.513,0.662,0.851,0.877c1.237,0.773,2.529,1.465,3.75,2.264
+ c0.445,0.292,0.741,0.361,1.247,0.142c1.493-0.655,3.02-1.235,4.544-1.819c1.476-0.56,2.797-1.305,3.38-2.89
+ c0.299-0.813,0.575-1.642,0.788-2.479c0.233-0.914,0.105-1.72-0.615-2.483c-1.28-1.351-2.428-2.819-3.668-4.209
+ c-0.159-0.182-0.572-0.297-0.799-0.225c-2.13,0.676-4.274,0.991-6.516,0.646c-0.408-0.066-1.043,0.256-1.321,0.604
+ C57.123,47.884,55.934,49.55,54.765,51.12z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asterisk.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asterisk.svg
new file mode 100644
index 0000000..6c9c3c7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-asterisk.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.466,60.066c-0.01-0.006-0.022-0.009-0.032-0.015l0.034-0.059l-17.31-9.994l17.39-10.04l-0.005-0.009
+ c0.923-0.57,1.233-1.774,0.687-2.72c-0.012-0.021-0.029-0.038-0.042-0.059l0.011-0.006l-5.52-9.562l-0.007,0.004
+ c-0.56-0.91-1.729-1.225-2.669-0.72l-0.004-0.006L57.578,36.942V16.793h-0.01c-0.033-1.083-0.919-1.953-2.01-1.953
+ c-0.025,0-0.048,0.006-0.073,0.007v-0.013H44.445v0.007c-1.069,0.03-1.926,0.886-1.957,1.952h-0.006v20.115L25.032,26.833
+ l-0.006,0.01c-0.956-0.513-2.151-0.183-2.697,0.764c-0.012,0.021-0.018,0.044-0.03,0.065l-0.01-0.006l-5.52,9.562l0.005,0.003
+ c-0.508,0.94-0.196,2.11,0.712,2.672l-0.002,0.003l0.035,0.02c0.006,0.003,0.01,0.008,0.016,0.011s0.012,0.005,0.018,0.008
+ l17.411,10.052l-17.028,9.832c-0.146,0.044-0.289,0.101-0.426,0.18c-0.961,0.553-1.29,1.781-0.743,2.74l-0.007,0.004l5.711,9.892
+ l0.032-0.019c0.617,0.738,1.689,0.951,2.55,0.455c0.011-0.006,0.019-0.015,0.03-0.021l0.032,0.056l17.369-10.027v19.593
+ c-0.035,0.149-0.058,0.302-0.058,0.461c0,1.108,0.895,2.005,2,2.014v0.007h11.422v-0.037c0.948-0.165,1.67-0.986,1.67-1.98
+ c0-0.012-0.003-0.023-0.004-0.035h0.066V63.056l16.967,9.796c0.112,0.105,0.233,0.202,0.371,0.282
+ c0.959,0.556,2.185,0.227,2.745-0.724l0.005,0.003l5.534-9.587c0.001-0.001,0.002-0.002,0.003-0.004s0.001-0.003,0.002-0.004
+ l0.173-0.299l-0.03-0.018C83.678,61.598,83.327,60.564,82.466,60.066z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-at-sign.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-at-sign.svg
new file mode 100644
index 0000000..c3c3cde
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-at-sign.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M87.5,50.002C87.5,29.293,70.712,12.5,50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c6.668,0,12.918-1.756,18.342-4.809c0.61-0.22,1.049-0.799,1.049-1.486c0-0.622-0.361-1.153-0.882-1.413l0.003-0.004l-6.529-4.002
+ L61.98,75.79c-0.274-0.227-0.621-0.369-1.005-0.369c-0.238,0-0.461,0.056-0.663,0.149l-0.014-0.012
+ C57.115,76.847,53.64,77.561,50,77.561c-15.199,0-27.56-12.362-27.56-27.559c0-15.195,12.362-27.562,27.56-27.562
+ c14.322,0,26.121,10.984,27.434,24.967C77.428,57.419,73.059,63,69.631,63c-1.847,0-3.254-1.23-3.254-3.957
+ c0-0.527,0.176-1.672,0.264-2.111l4.163-19.918l-0.018,0c0.012-0.071,0.042-0.136,0.042-0.21c0-0.734-0.596-1.33-1.33-1.33h-7.23
+ c-0.657,0-1.178,0.485-1.286,1.112l-0.025-0.001l-0.737,3.549c-1.847-3.342-5.629-5.893-10.994-5.893
+ c-10.202,0-19.877,9.764-19.877,21.549c0,8.531,5.101,14.775,13.632,14.775c4.75,0,9.587-2.727,12.665-7.035l0.088,0.527
+ c0.615,3.342,9.843,7.576,15.121,7.576c7.651,0,16.617-5.156,16.617-19.932l-0.022-0.009C87.477,51.13,87.5,50.569,87.5,50.002z
+ M56.615,56.844c-1.935,2.727-5.101,5.805-9.763,5.805c-4.486,0-7.212-3.166-7.212-7.738c0-6.422,5.013-12.754,12.049-12.754
+ c3.958,0,6.245,2.551,7.124,4.486L56.615,56.844z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-background-color.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-background-color.svg
new file mode 100644
index 0000000..7e92774
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-background-color.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon fill-rule="evenodd" clip-rule="evenodd" points="37.808,77.057 34.411,86 67.175,86 63.778,77.057 "/>
+ <polygon fill-rule="evenodd" clip-rule="evenodd" points="40.608,68.316 60.977,68.316 50.793,41.327 "/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M79,14H21c-3.85,0-7,3.15-7,7v58c0,3.85,3.15,7,7,7h2.111l20.812-52.766h0
+ c0.329-1.061,1.307-1.836,2.476-1.836h8.812c1.152,0,2.118,0.753,2.462,1.79h0.018L78.478,86H79c3.85,0,7-3.15,7-7V21
+ C86,17.15,82.85,14,79,14z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-empty.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-empty.svg
new file mode 100644
index 0000000..0f01592
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-empty.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M95.582,41.448h-7.796V24.342h0l0-0.001c0-0.956-0.775-1.731-1.733-1.731H4.418c-0.957,0-1.732,0.775-1.732,1.731l0,0.001
+ h0v51.316h0l0,0.001c0,0.957,0.775,1.731,1.732,1.731h81.635c0.957,0,1.732-0.775,1.732-1.731l0-0.001h0V57.039h7.796
+ c0.957,0,1.732-0.775,1.732-1.732V43.18C97.314,42.223,96.539,41.448,95.582,41.448z M77.829,67.434H12.862V32.785h64.967V67.434z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-full.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-full.svg
new file mode 100644
index 0000000..53ce92e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-full.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M95.582,41.448h-7.796V24.342h0l0-0.001c0-0.956-0.775-1.731-1.733-1.731H4.418c-0.957,0-1.732,0.775-1.732,1.731l0,0.001
+ h0v51.316h0l0,0.001c0,0.957,0.775,1.731,1.732,1.731h81.635c0.957,0,1.732-0.775,1.732-1.731l0-0.001h0V57.039h7.796
+ c0.957,0,1.732-0.775,1.732-1.732V43.18C97.314,42.223,96.539,41.448,95.582,41.448z M77.829,67.434H12.862V32.785h64.967V67.434z"
+ />
+ <rect x="17.84" y="37.382" width="55.01" height="25.074"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-half.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-half.svg
new file mode 100644
index 0000000..43014ec
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-battery-half.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M95.582,41.448h-7.796V24.342h0l0-0.001c0-0.956-0.775-1.731-1.733-1.731H4.418c-0.957,0-1.732,0.775-1.732,1.731l0,0.001
+ h0v51.316h0l0,0.001c0,0.957,0.775,1.731,1.732,1.731h81.635c0.957,0,1.732-0.775,1.732-1.731l0-0.001h0V57.039h7.796
+ c0.957,0,1.732-0.775,1.732-1.732V43.18C97.314,42.223,96.539,41.448,95.582,41.448z M77.829,67.434H12.862V32.785h64.967V67.434z"
+ />
+ <polygon points="56.581,37.635 17.774,37.635 17.774,62.365 46.879,62.365 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin-circle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin-circle.svg
new file mode 100644
index 0000000..19e7b3b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin-circle.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="g99">
+ <path fill="#231F20" d="M49.805,38.076l-2.049,8.215c2.323,0.579,9.483,2.941,10.643-1.708
+ C59.608,39.736,52.128,38.655,49.805,38.076z"/>
+ <path fill="#231F20" d="M46.723,50.437l-2.26,9.058c2.789,0.693,11.392,3.455,12.664-1.655
+ C58.456,52.512,49.512,51.133,46.723,50.437z"/>
+ <path fill="#231F20" d="M59.067,13.621C38.981,8.612,18.633,20.84,13.626,40.932c-5.011,20.089,7.216,40.438,27.3,45.447
+ c20.092,5.009,40.44-7.217,45.449-27.307C91.384,38.981,79.158,18.629,59.067,13.621z M66.529,44.658
+ c-0.541,3.653-2.565,5.422-5.254,6.041c3.691,1.921,5.57,4.869,3.78,9.979c-2.22,6.345-7.497,6.881-14.512,5.553l-1.703,6.824
+ l-4.115-1.025l1.68-6.733c-1.066-0.264-2.156-0.546-3.279-0.85l-1.686,6.764l-4.11-1.026l1.703-6.836
+ c-0.961-0.246-1.937-0.508-2.933-0.757l-5.354-1.336l2.042-4.709c0,0,3.032,0.807,2.991,0.747c1.165,0.289,1.681-0.471,1.885-0.978
+ l2.691-10.787c0.151,0.037,0.298,0.073,0.434,0.108c-0.164-0.065-0.313-0.108-0.427-0.137l1.919-7.701
+ c0.05-0.874-0.251-1.976-1.917-2.392c0.065-0.044-2.988-0.743-2.988-0.743l1.095-4.395l5.675,1.417l-0.005,0.021
+ c0.853,0.212,1.732,0.413,2.628,0.617l1.686-6.757l4.112,1.025l-1.652,6.625c1.104,0.252,2.215,0.506,3.297,0.775l1.641-6.581
+ l4.114,1.025l-1.685,6.76C63.476,36.985,67.275,39.667,66.529,44.658z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin.svg
new file mode 100644
index 0000000..2fb56e0
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bitcoin.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M66.237,47.445c3.667-1.869,5.959-5.162,5.421-10.644c-0.723-7.494-7.193-10.003-15.36-10.715l-0.004-9.058
+ c0.002-0.029,0.017-0.054,0.017-0.084c0-0.691-0.56-1.25-1.251-1.251h0h0h-3.812h0h0h-0.001v0c-0.69,0.001-1.249,0.56-1.249,1.25
+ l0,0h-0.029l0.005,8.872c-1.664,0-3.364,0.033-5.052,0.068l-0.003-8.83c0.003-0.038,0.022-0.071,0.022-0.11
+ c0-0.691-0.56-1.25-1.251-1.251h0h0h-3.812h0h0h-0.001v0c-0.69,0.001-1.249,0.56-1.249,1.25c0,0.001,0.001,0.002,0.001,0.003
+ h-0.031l0.002,9.143c-1.37,0.028-2.715,0.057-4.027,0.057l-0.001-0.033h-8.726v0.013c-0.691,0-1.251,0.56-1.251,1.251v4.226
+ c0,0.691,0.56,1.251,1.251,1.251c0.002,0,0.003-0.001,0.005-0.001v0.019c0,0,4.672-0.091,4.594-0.008
+ c2.562,0.001,3.397,1.488,3.64,2.771l0.005,11.843l0.001,0.045l0.005,16.587c-0.112,0.806-0.586,2.093-2.376,2.096
+ c0.081,0.071-4.599-0.001-4.599-0.001l-0.001,0.006c-0.008,0-0.014-0.005-0.022-0.005c-0.601,0-1.079,0.432-1.2,0.997l-0.051-0.003
+ l-1.152,5.169l0.027,0.005c-0.005,0.046-0.027,0.086-0.027,0.134c0,0.664,0.522,1.195,1.176,1.236l-0.003,0.019l8.233-0.003
+ c1.532,0,3.04,0.025,4.52,0.034l0.007,9.262h0.003c0,0.69,0.56,1.25,1.251,1.25l0,0l0,0h3.812l0,0l0,0h0.001
+ c0.69-0.001,1.249-0.561,1.249-1.251l0,0h0.002l-0.004-9.149c1.735,0.035,3.414,0.048,5.054,0.044l0.002,9.106h0.003
+ c0.001,0.69,0.56,1.25,1.25,1.25l0,0l0,0h3.812l0,0l0,0h0.001c0.69-0.001,1.249-0.561,1.249-1.251c0,0,0-0.001,0-0.001l0.008,0
+ l-0.002-9.247c10.635-0.615,18.079-3.297,18.999-13.286C76.06,52.479,72.275,48.891,66.237,47.445z M45.072,33.32
+ c3.571-0.002,14.789-1.142,14.793,6.312c0.001,7.148-11.218,6.318-14.789,6.32L45.072,33.32z M45.083,66.255L45.08,52.326
+ c4.288,0,17.733-1.238,17.736,6.955C62.822,67.137,49.371,66.248,45.083,66.255z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-blind.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-blind.svg
new file mode 100644
index 0000000..a77a6e7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-blind.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle fill="#231F20" cx="41.53" cy="19.773" r="7.152"/>
+ <path fill="#231F20" d="M83.162,84.562l0.01-0.006l-20.92-36.234c0.359-0.495,0.577-1.098,0.577-1.756
+ c0-1.263-0.782-2.339-1.887-2.783L54.907,40.3l-9.159-9.159c-1.311-1.614-3.31-2.647-5.552-2.647c-2.026,0-3.851,0.846-5.152,2.199
+ L24.412,41.324l0.012,0.012c-0.169,0.134-0.285,0.332-0.285,0.564c0,0.056,0.02,0.104,0.032,0.156h-0.029v11.975
+ c0,0.009-0.003,0.017-0.003,0.025c0,1.658,1.344,3.003,3.003,3.003s3.002-1.345,3.002-3.003c0-0.008-0.002-0.016-0.002-0.024
+ v-10.01l3.649-3.649V59.18h0.001l-6.954,12.044l-8.891,8.891l0.033,0.033c-0.819,0.764-1.339,1.843-1.339,3.052
+ c0,2.309,1.872,4.18,4.181,4.18c1.317,0,2.476-0.621,3.243-1.571l9.596-9.596l-0.037-0.037l8.096-14.024l7.104,7.104l9.232,15.99
+ l0.036-0.021c0.715,1.278,2.066,2.153,3.635,2.153c2.309,0,4.181-1.871,4.181-4.18c0-0.915-0.302-1.754-0.8-2.443l-9.627-16.674
+ l-0.012,0.007l-8.679-8.678V40.609l4.451,4.451l-0.001,0.002l0.007,0.004l0.025,0.025l0.007-0.007l6.847,3.954
+ c0.054,0.037,0.113,0.064,0.169,0.098l0.028,0.016l0-0.001c0.443,0.258,0.952,0.417,1.502,0.417c0.189,0,0.372-0.022,0.552-0.056
+ l20.816,36.054c0.013,0.032,0.034,0.057,0.05,0.087l0.007,0.012l0.001,0c0.189,0.351,0.552,0.598,0.982,0.598
+ c0.621,0,1.125-0.496,1.125-1.109C83.359,84.932,83.276,84.736,83.162,84.562z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bluetooth.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bluetooth.svg
new file mode 100644
index 0000000..3013762
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bluetooth.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M71.782,64.059L57.807,50.085l14.011-14.011c0.164-0.141,0.314-0.291,0.455-0.455l0.013-0.013l-0.001-0.001
+ c0.632-0.742,1.028-1.691,1.028-2.742c0-1.307-0.603-2.461-1.531-3.241L52.156,9.995c-0.779-0.978-1.965-1.617-3.312-1.617
+ c-2.347,0-4.25,1.903-4.25,4.25c0,0.407,0.076,0.793,0.183,1.167v23.258L34.052,26.329c-0.777-0.842-1.879-1.377-3.115-1.377
+ c-2.347,0-4.25,1.903-4.25,4.25c0,1.238,0.538,2.342,1.383,3.119l16.706,16.706v2.115L27.953,67.966
+ c-0.013,0.012-0.025,0.025-0.038,0.038l-0.032,0.032l0.003,0.003c-0.739,0.765-1.199,1.802-1.199,2.949
+ c0,2.347,1.903,4.25,4.25,4.25c1.289,0,2.429-0.586,3.209-1.491l10.63-10.63v24.099c-0.002,0.053-0.016,0.102-0.016,0.156
+ s0.014,0.103,0.016,0.156v0.022h0.002c0.095,2.262,1.945,4.072,4.232,4.072c1.259,0,2.378-0.558,3.156-1.428l0.004,0.004
+ l19.862-19.863c0.021-0.021,0.043-0.042,0.064-0.064l0.19-0.19l-0.018-0.018c0.642-0.744,1.045-1.702,1.045-2.762
+ C73.312,65.993,72.71,64.839,71.782,64.059z M63.071,67.322l-9.828,9.828V57.494L63.071,67.322z M53.243,42.675V23.057l9.809,9.809
+ L53.243,42.675z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bold.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bold.svg
new file mode 100644
index 0000000..87238c7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bold.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M62.73,49.109c5.347-1.103,9.76-5.94,9.76-12.985c0-7.553-5.517-14.428-16.295-14.428H29.011
+ c-1.438,0-2.604,1.166-2.604,2.604v51.399c0,1.438,1.166,2.604,2.604,2.604h28.118c10.863,0,16.464-6.79,16.464-15.361
+ C73.594,55.899,68.841,50.042,62.73,49.109z M38.458,32.305h15.107c4.074,0,6.62,2.461,6.62,5.94c0,3.649-2.546,5.941-6.62,5.941
+ H38.458V32.305z M54.073,67.695H38.458v-12.9h15.616c4.668,0,7.214,2.886,7.214,6.45C61.288,65.319,58.572,67.695,54.073,67.695z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book-bookmark.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book-bookmark.svg
new file mode 100644
index 0000000..8d452be
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book-bookmark.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.063,22.284h-0.006c-0.029-0.874-0.734-1.573-1.612-1.589v-0.003h-3.36l-0.001,60.404l0.001,0.01
+ c0,0.9-0.721,1.627-1.617,1.644v0.005l-50.906-0.002c-0.816,0-1.488-0.595-1.619-1.375v-3.602h47.405v-0.003
+ c0.011,0,0.021,0.003,0.031,0.003c0.91,0,1.646-0.735,1.646-1.646c0-0.006-0.002-0.012-0.002-0.012l0.002-62.202
+ c0-0.91-0.736-1.647-1.646-1.646c-0.01,0-0.02,0.003-0.03,0.003v-0.004h-5.756v13.022v16.291v5.639
+ c0,0.434-0.353,0.785-0.787,0.785c-0.228,0-0.429-0.101-0.573-0.255l-5.667-5.667h-0.019c-0.126-0.145-0.306-0.241-0.513-0.241
+ c-0.207,0-0.387,0.096-0.513,0.241h-0.019l-5.709,5.709h-0.009c-0.14,0.13-0.325,0.214-0.532,0.214
+ c-0.434,0-0.786-0.352-0.786-0.785v-5.639V25.292V12.27l-29.883,0c-0.91,0-1.646,0.736-1.646,1.646
+ c0,0.021,0.006,0.042,0.006,0.063l0,59.237v12.807c-0.001,0.02-0.006,0.039-0.006,0.059s0.005,0.039,0.006,0.059v0.076h0.008
+ c0.07,0.845,0.769,1.511,1.632,1.511v0.001l60.833,0.002h0.029v-0.003c0.896-0.016,1.617-0.743,1.617-1.643l-0.001-0.01
+ L82.063,22.284z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book.svg
new file mode 100644
index 0000000..cdfea0a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-book.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.063,22.284h-0.006c-0.029-0.874-0.734-1.573-1.612-1.589v-0.003h-3.36l-0.001,60.404l0.001,0.01
+ c0,0.9-0.721,1.627-1.617,1.644v0.005l-50.906-0.002c-0.816,0-1.488-0.595-1.619-1.375v-3.602h47.405v-0.003
+ c0.011,0,0.021,0.003,0.031,0.003c0.91,0,1.646-0.735,1.646-1.646c0-0.006-0.002-0.012-0.002-0.012l0.002-62.202
+ c0-0.91-0.736-1.647-1.646-1.646c-0.01,0-0.02,0.003-0.03,0.003v-0.004L19.583,12.27c-0.91,0-1.646,0.736-1.646,1.646
+ c0,0.021,0.006,0.042,0.006,0.063l0,59.237v12.807c-0.001,0.02-0.006,0.039-0.006,0.059s0.005,0.039,0.006,0.059v0.076h0.008
+ c0.07,0.845,0.769,1.511,1.632,1.511v0.001l60.833,0.002h0.029v-0.003c0.896-0.016,1.617-0.743,1.617-1.643l-0.001-0.01
+ L82.063,22.284z M22.916,23.872c0-0.908,0.736-1.646,1.646-1.646h40.84c0.909,0,1.646,0.738,1.646,1.646h0l-0.001,12.361l0,0.002
+ c0,0.91-0.737,1.646-1.646,1.646h0H24.562c-0.909,0-1.646-0.736-1.646-1.646l0.001-12.354
+ C22.917,23.878,22.916,23.875,22.916,23.872z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bookmark.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bookmark.svg
new file mode 100644
index 0000000..d2ca515
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-bookmark.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M68.312,13.111H31.687c-1.661,0-3.007,1.346-3.007,3.007v6.743v45.917v15.897c0,1.224,0.992,2.215,2.216,2.215
+ c0.585,0,1.113-0.231,1.509-0.602h0.014l16.094-16.094h0.035c0.355-0.414,0.876-0.682,1.465-0.682s1.109,0.268,1.465,0.682h0.035
+ l15.918,15.918c0.406,0.472,1.001,0.777,1.673,0.777c1.224,0,2.216-0.992,2.216-2.215V68.777V22.861v-6.743
+ C71.32,14.457,69.973,13.111,68.312,13.111z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-braille.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-braille.svg
new file mode 100644
index 0000000..769b639
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-braille.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle cx="31.102" cy="23.979" r="6.978"/>
+ <circle cx="68.898" cy="23.979" r="6.978"/>
+ <circle cx="31.102" cy="50" r="6.978"/>
+ <circle cx="68.898" cy="50" r="6.978"/>
+ <circle cx="31.102" cy="76.02" r="6.978"/>
+ <circle cx="68.898" cy="76.02" r="6.978"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-new.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-new.svg
new file mode 100644
index 0000000..8c1939f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-new.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.558,49.96c0-0.885-0.435-1.663-1.097-2.151l0.014-0.024l-9.324-5.383l5.367-9.296l-0.018-0.011
+ c0.328-0.752,0.315-1.643-0.127-2.408c-0.443-0.766-1.208-1.223-2.025-1.314v-0.026H70.58V18.61h-0.022
+ c-0.092-0.816-0.549-1.58-1.314-2.022c-0.767-0.443-1.658-0.456-2.412-0.125l-0.013-0.023l-9.481,5.474l-5.25-9.094l-0.019,0.011
+ c-0.488-0.66-1.265-1.094-2.149-1.094c-0.885,0-1.664,0.435-2.151,1.097l-0.024-0.014l-5.337,9.244l-9.19-5.306l-0.011,0.019
+ c-0.753-0.328-1.643-0.315-2.408,0.127c-0.767,0.442-1.223,1.208-1.315,2.025h-0.027v10.674H18.845v0.021
+ c-0.816,0.092-1.58,0.549-2.022,1.314c-0.442,0.766-0.455,1.657-0.126,2.41l-0.023,0.014l5.246,9.087l-9.394,5.424l0.011,0.019
+ c-0.66,0.488-1.094,1.265-1.094,2.149c0,0.885,0.435,1.664,1.097,2.151l-0.014,0.024l9.324,5.383l-5.367,9.296l0.018,0.01
+ c-0.328,0.753-0.315,1.643,0.127,2.408c0.443,0.766,1.208,1.223,2.025,1.314v0.027H29.42V81.39h0.022
+ c0.092,0.816,0.549,1.58,1.314,2.022c0.767,0.443,1.659,0.455,2.412,0.125l0.013,0.023l9.481-5.474l5.25,9.094l0.019-0.011
+ c0.488,0.66,1.265,1.094,2.149,1.094c0.885,0,1.664-0.435,2.151-1.096l0.023,0.013l5.337-9.244l9.191,5.306l0.011-0.019
+ c0.753,0.328,1.643,0.315,2.408-0.127c0.767-0.442,1.223-1.208,1.315-2.025h0.027V70.398h10.613v-0.021
+ c0.816-0.092,1.58-0.549,2.022-1.314c0.442-0.766,0.455-1.658,0.126-2.411l0.023-0.013l-5.246-9.087l9.394-5.424l-0.011-0.019
+ C88.124,51.622,88.558,50.844,88.558,49.96z M43.715,61.355l-9.846-4.35l4.345,7.525l-2.456,1.418l-6.662-11.537l2.525-1.459
+ l9.53,4.162l-4.185-7.248l2.457-1.418l6.66,11.537L43.715,61.355z M48.367,58.669l-6.661-11.538l8.165-4.713l1.248,2.162
+ l-5.709,3.295l1.398,2.422l5.587-3.225l1.248,2.16l-5.587,3.227l1.518,2.629l5.709-3.295l1.248,2.162L48.367,58.669z
+ M67.273,47.754L60.675,41l2.567,9.08l-2.611,1.508l-9.965-9.629l2.75-1.588l6.838,7.168l-2.617-9.605l1.92-1.108l6.993,7.079
+ l-2.79-9.506l2.75-1.588l3.375,13.436L67.273,47.754z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-sale.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-sale.svg
new file mode 100644
index 0000000..88d5736
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst-sale.svg
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon points="44.105,55.641 47.703,53.562 43.037,49.637 "/>
+ <path d="M88.558,49.96c0-0.885-0.435-1.663-1.097-2.151l0.014-0.024l-9.324-5.383l5.367-9.296l-0.018-0.011
+ c0.328-0.752,0.315-1.643-0.127-2.408c-0.443-0.766-1.208-1.223-2.025-1.314v-0.026H70.58V18.61h-0.022
+ c-0.092-0.816-0.549-1.58-1.314-2.022c-0.767-0.443-1.658-0.456-2.412-0.125l-0.013-0.023l-9.481,5.474l-5.25-9.094l-0.019,0.011
+ c-0.488-0.66-1.265-1.094-2.149-1.094c-0.885,0-1.664,0.435-2.151,1.097l-0.024-0.014l-5.337,9.244l-9.19-5.306l-0.011,0.019
+ c-0.753-0.328-1.643-0.315-2.408,0.127c-0.767,0.442-1.223,1.208-1.315,2.025h-0.027v10.674H18.845v0.021
+ c-0.816,0.092-1.58,0.549-2.022,1.314c-0.442,0.766-0.455,1.657-0.126,2.41l-0.023,0.014l5.246,9.087l-9.394,5.424l0.011,0.019
+ c-0.66,0.488-1.094,1.265-1.094,2.149c0,0.885,0.435,1.664,1.097,2.151l-0.014,0.024l9.324,5.383l-5.367,9.296l0.018,0.01
+ c-0.328,0.753-0.315,1.643,0.127,2.408c0.443,0.766,1.208,1.223,2.025,1.314v0.027H29.42V81.39h0.022
+ c0.092,0.816,0.549,1.58,1.314,2.022c0.767,0.443,1.659,0.455,2.412,0.125l0.013,0.023l9.481-5.474l5.25,9.094l0.019-0.011
+ c0.488,0.66,1.265,1.094,2.149,1.094c0.885,0,1.664-0.435,2.151-1.096l0.023,0.013l5.337-9.244l9.191,5.306l0.011-0.019
+ c0.753,0.328,1.643,0.315,2.408-0.127c0.767-0.442,1.224-1.208,1.315-2.025h0.027V70.398h10.613v-0.021
+ c0.816-0.092,1.58-0.549,2.022-1.314c0.442-0.766,0.455-1.657,0.126-2.41l0.023-0.013l-5.246-9.087l9.394-5.424l-0.011-0.019
+ C88.124,51.622,88.558,50.844,88.558,49.96z M37.537,65.197c-2.23,1.288-4.252,1.464-5.971,1.002l0.241-2.697
+ c1.302,0.377,2.985,0.375,4.575-0.544c1.367-0.789,1.658-1.765,1.269-2.438c-1.159-2.006-6.992,3.23-9.499-1.111
+ c-1.108-1.92-0.367-4.471,2.35-6.039c1.833-1.059,3.675-1.383,5.426-0.988l-0.309,2.623c-1.433-0.324-2.908-0.004-4.084,0.674
+ c-1.038,0.6-1.367,1.389-0.967,2.082c1.049,1.816,6.965-3.236,9.451,1.069C41.238,60.939,40.635,63.41,37.537,65.197z
+ M51.48,56.871l-1.854-1.535l-4.947,2.856l0.401,2.374l-2.785,1.607L40.08,48.07l3.079-1.777l11.106,8.971L51.48,56.871z
+ M55.233,54.705l-6.661-11.538l2.474-1.429l5.413,9.375l4.878-2.816l1.249,2.163L55.233,54.705z M64.245,49.502l-6.661-11.537
+ l8.164-4.715l1.248,2.162l-5.707,3.296l1.398,2.422l5.586-3.226l1.248,2.162l-5.586,3.225l1.518,2.63l5.708-3.296l1.249,2.162
+ L64.245,49.502z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst.svg
new file mode 100644
index 0000000..1da7b9d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-burst.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.558,49.96c0-0.885-0.435-1.663-1.097-2.151l0.014-0.024l-9.324-5.383l5.367-9.296l-0.018-0.011
+ c0.328-0.752,0.315-1.643-0.127-2.408c-0.443-0.766-1.208-1.223-2.025-1.314v-0.026H70.58V18.61h-0.022
+ c-0.092-0.816-0.549-1.58-1.314-2.022c-0.767-0.443-1.658-0.456-2.412-0.125l-0.013-0.023l-9.481,5.474l-5.25-9.094l-0.019,0.011
+ c-0.488-0.66-1.265-1.094-2.149-1.094c-0.885,0-1.664,0.435-2.151,1.097l-0.024-0.014l-5.337,9.244l-9.19-5.306l-0.011,0.019
+ c-0.753-0.328-1.643-0.315-2.408,0.127c-0.767,0.442-1.223,1.208-1.315,2.025h-0.027v10.674H18.845v0.021
+ c-0.816,0.092-1.58,0.549-2.022,1.314c-0.442,0.766-0.455,1.657-0.126,2.41l-0.023,0.014l5.246,9.087l-9.394,5.424l0.011,0.019
+ c-0.66,0.488-1.094,1.265-1.094,2.149c0,0.885,0.435,1.664,1.097,2.151l-0.014,0.024l9.324,5.383l-5.367,9.296l0.019,0.011
+ c-0.328,0.753-0.315,1.643,0.127,2.408c0.443,0.766,1.208,1.223,2.025,1.314v0.027H29.42V81.39h0.022
+ c0.092,0.816,0.549,1.58,1.314,2.022c0.767,0.443,1.658,0.455,2.412,0.125l0.013,0.023l9.481-5.474l5.25,9.094l0.019-0.011
+ c0.488,0.66,1.265,1.094,2.149,1.094c0.885,0,1.664-0.435,2.151-1.096l0.023,0.013l5.337-9.244l9.191,5.306l0.011-0.019
+ c0.753,0.328,1.643,0.315,2.408-0.127c0.767-0.442,1.223-1.208,1.315-2.025h0.027V70.398h10.613v-0.021
+ c0.816-0.092,1.58-0.549,2.022-1.314c0.442-0.766,0.455-1.658,0.126-2.411l0.023-0.013l-5.246-9.087l9.394-5.424l-0.011-0.019
+ C88.124,51.622,88.558,50.844,88.558,49.96z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-calendar.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-calendar.svg
new file mode 100644
index 0000000..3b11eab
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-calendar.svg
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.583,39.494H19.417c-0.699,0-1.266,0.565-1.266,1.264v43.916c0,0.698,0.567,1.264,1.266,1.264h61.165
+ c0.703,0,1.267-0.566,1.267-1.264V40.758C81.849,40.059,81.285,39.494,80.583,39.494z M39.373,76.679
+ c-2.111,0-4.443-0.424-6.243-1.136c-0.271-0.107-0.437-0.385-0.396-0.674l0.59-4.294c0.024-0.19,0.136-0.358,0.3-0.456
+ c0.17-0.099,0.372-0.116,0.548-0.049c1.979,0.747,3.643,1.053,5.744,1.053c2.202,0,3.736-1.04,3.736-2.528
+ c0-1.847-0.891-2.835-5.762-3.113c-0.335-0.019-0.595-0.296-0.595-0.631v-4.293c0-0.332,0.255-0.608,0.585-0.632
+ c4.195-0.296,4.68-1.586,4.68-2.53c0-0.639,0-1.709-2.84-1.709c-1.519,0-3.132,0.414-4.792,1.226
+ c-0.184,0.087-0.398,0.083-0.574-0.009c-0.181-0.096-0.303-0.272-0.33-0.472l-0.588-4.292c-0.04-0.275,0.109-0.543,0.359-0.661
+ c1.933-0.894,4.372-1.347,7.254-1.347c5.137,0,8.589,2.386,8.589,5.937c0,2.663-1.377,4.623-4.202,5.955
+ c2.425,0.935,4.903,2.632,4.903,6.222C50.339,73.368,46.037,76.679,39.373,76.679z M66.091,75.656c0,0.349-0.284,0.632-0.633,0.632
+ h-5.227c-0.351,0-0.633-0.283-0.633-0.632V58.434l-3.435,1.31c-0.184,0.068-0.383,0.052-0.548-0.048
+ c-0.167-0.097-0.279-0.266-0.303-0.457l-0.585-4.294c-0.037-0.269,0.102-0.532,0.346-0.651l7.493-3.706
+ c0.088-0.042,0.184-0.065,0.282-0.065h2.611c0.349,0,0.633,0.283,0.633,0.633V75.656z"/>
+ <g>
+ <path d="M80.583,19.72h-6.519v3.051c0,3.235-1.845,6.69-7.03,6.69c-5.185,0-7.031-3.455-7.031-6.69V19.72H40.08v3.051
+ c0,3.235-1.845,6.69-7.03,6.69c-5.186,0-7.036-3.455-7.036-6.69V19.72h-6.597c-0.699,0-1.266,0.565-1.266,1.264v12.859
+ c0,0.7,0.567,1.266,1.266,1.266h61.165c0.703,0,1.267-0.566,1.267-1.266V20.984C81.849,20.285,81.285,19.72,80.583,19.72z"/>
+ <path d="M33.05,25.376c2.095,0,2.946-0.755,2.946-2.606V19.72v-3.05c0-1.853-0.851-2.607-2.946-2.607
+ c-2.101,0-2.952,0.755-2.952,2.607v3.05v3.051C30.098,24.622,30.949,25.376,33.05,25.376z"/>
+ <path d="M67.033,25.376c2.095,0,2.946-0.755,2.946-2.606V19.72v-3.05c0-1.853-0.851-2.607-2.946-2.607
+ c-2.101,0-2.946,0.755-2.946,2.607v3.05v3.051C64.086,24.622,64.932,25.376,67.033,25.376z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-camera.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-camera.svg
new file mode 100644
index 0000000..d787172
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-camera.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle cx="50.041" cy="53.256" r="9.513"/>
+ <path d="M86.778,24.2v-0.037H70.111v-2.792c0-2.056-1.667-3.722-3.722-3.722H33.611c-2.056,0-3.723,1.666-3.723,3.722v2.792H13.221
+ V24.2c-2.056,0-3.721,1.666-3.721,3.722v50.669c0,2.056,1.665,3.722,3.721,3.722v0.037h73.557v-0.037
+ c2.055,0,3.722-1.667,3.722-3.722V27.922C90.5,25.866,88.833,24.2,86.778,24.2z M50.247,72.542
+ c-10.651,0-19.286-8.634-19.286-19.286c0-10.651,8.635-19.286,19.286-19.286c10.652,0,19.287,8.635,19.287,19.286
+ C69.535,63.908,60.899,72.542,50.247,72.542z M85.513,39.145H70.773v-9.957h14.739V39.145z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-check.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-check.svg
new file mode 100644
index 0000000..5179421
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-check.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M88.04,30.319L75.124,17.401c-0.454-0.453-1.067-0.709-1.71-0.709c-0.642,0-1.256,0.256-1.709,0.709L37.392,51.714
+ l-9.094-9.093c-0.945-0.944-2.474-0.944-3.419,0L11.96,55.539c-0.453,0.453-0.709,1.068-0.709,1.709c0,0.641,0.256,1.256,0.709,1.71
+ L35.607,82.6c0.453,0.453,1.067,0.708,1.709,0.708c0.029,0,0.055-0.016,0.083-0.016c0.024,0,0.05,0.014,0.075,0.014
+ c0.621,0,1.236-0.236,1.709-0.708L88.04,33.738C88.985,32.794,88.985,31.264,88.04,30.319z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-checkbox.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-checkbox.svg
new file mode 100644
index 0000000..d780b7a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-checkbox.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M92.038,24.333l-8.62-8.622c-0.303-0.302-0.712-0.473-1.141-0.473c-0.428,0-0.838,0.171-1.141,0.473
+ L49.987,46.86l-6.07-6.068c-0.63-0.63-1.651-0.63-2.282,0l-8.622,8.622c-0.303,0.302-0.473,0.713-0.473,1.141
+ c0,0.427,0.17,0.838,0.473,1.141l15.782,15.778c0.302,0.302,0.712,0.473,1.141,0.473c0.019,0,0.037-0.01,0.056-0.01
+ c0.016,0,0.033,0.009,0.05,0.009c0.414,0,0.825-0.158,1.141-0.473l40.855-40.857C92.668,25.984,92.668,24.963,92.038,24.333z"/>
+ <g>
+ <path d="M72.022,53.625v21.159H27.978V30.74h31.06l9.979-9.978H23.193v0.007c-0.023,0-0.044-0.007-0.068-0.007
+ c-2.788,0-5.045,2.229-5.113,5H18v54h0.013c0.067,2.728,2.259,4.92,4.987,4.987v0.013h0.125l0.001,0c0,0,0,0,0,0h53.748l0.001,0
+ c0,0,0,0,0,0H77v-0.013c2.729-0.067,4.92-2.259,4.987-4.987H82V43.647L72.022,53.625z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-notes.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-notes.svg
new file mode 100644
index 0000000..1ce072b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-notes.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.761,17.26h-0.019c0.001-0.049,0.015-0.095,0.015-0.145c0-2.893-2.346-5.245-5.241-5.245
+ c-0.04,0-0.076,0.011-0.116,0.012H60.842V8.48h0l0-0.002c0-0.881-0.714-1.593-1.593-1.595V6.875H40.8v0.006
+ c-0.015,0-0.028-0.004-0.043-0.004c-0.88,0-1.594,0.713-1.594,1.594c0,0.01,0.003,0.02,0.003,0.03v3.38H24.501
+ c-0.007,0-0.013-0.002-0.02-0.002c-2.893,0-5.242,2.354-5.242,5.243c0,0.047,0.013,0.09,0.014,0.137h-0.014v70.572h0.003
+ c0,0.009-0.003,0.018-0.003,0.027c0,2.895,2.35,5.238,5.243,5.238c0.078,0,0.151-0.02,0.229-0.023v0.021h50.5
+ c0.098,0.005,0.191,0.029,0.29,0.029c2.894,0,5.239-2.348,5.239-5.238c0-0.019-0.005-0.036-0.005-0.055h0.028V17.26z
+ M70.822,83.185H29.178V21.809h4.997v3.069c-0.002,0.033-0.01,0.063-0.01,0.097c0,0.998,0.81,1.814,1.814,1.814
+ c0.005,0,0.009-0.001,0.014-0.001v0.008h28.027c1.005-0.002,1.813-0.816,1.813-1.813c0-0.015-0.004-0.029-0.004-0.044v-3.13h4.992
+ V83.185z"/>
+ <path d="M39.15,41.119c0-0.658-0.537-1.195-1.198-1.195c-0.031,0-0.058,0.015-0.088,0.018v-0.018h-2.502
+ c-0.661,0-1.199,0.539-1.199,1.197v2.595h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h2.502v-0.018
+ c0.03,0.002,0.056,0.018,0.086,0.018c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595H39.15L39.15,41.119z"/>
+ <path d="M65.831,41.119c0-0.658-0.537-1.195-1.198-1.195c-0.001,0-0.001,0-0.002,0H45.337c-0.661,0-1.199,0.539-1.199,1.197v2.595
+ h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h19.294c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595h-0.001L65.831,41.119z"/>
+ <path d="M39.15,51.094c0-0.658-0.537-1.195-1.198-1.195c-0.031,0-0.058,0.015-0.088,0.018v-0.018h-2.502
+ c-0.661,0-1.199,0.539-1.199,1.197v2.595h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h2.502v-0.018
+ c0.03,0.002,0.056,0.018,0.086,0.018c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595H39.15L39.15,51.094z"/>
+ <path d="M65.831,51.094c0-0.658-0.537-1.195-1.198-1.195c-0.001,0-0.001,0-0.002,0H45.337c-0.661,0-1.199,0.539-1.199,1.197v2.595
+ h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h19.294c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595h-0.001L65.831,51.094z"/>
+ <path d="M39.15,61.069c0-0.658-0.537-1.195-1.198-1.195c-0.031,0-0.058,0.015-0.088,0.018v-0.018h-2.502
+ c-0.661,0-1.199,0.539-1.199,1.197v2.595h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h2.502v-0.018
+ c0.03,0.002,0.056,0.018,0.086,0.018c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595H39.15L39.15,61.069z"/>
+ <path d="M65.831,61.069c0-0.658-0.537-1.195-1.198-1.195c-0.001,0-0.001,0-0.002,0H45.337c-0.661,0-1.199,0.539-1.199,1.197v2.595
+ h0l0,0.002c0,0.656,0.537,1.193,1.199,1.193h0.001h19.294c0.663,0,1.2-0.537,1.2-1.193l0-0.002h0v-2.595h-0.001L65.831,61.069z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-pencil.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-pencil.svg
new file mode 100644
index 0000000..0292f51
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard-pencil.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M87.969,43.045l-8.253-8.25c-0.478-0.481-1.26-0.481-1.738,0l-22.583,22.58l0.045,0.045l-0.072-0.02l-3.091,11.534
+ l0.009,0.002c-0.14,0.425-0.053,0.908,0.286,1.249c0.376,0.379,0.929,0.451,1.383,0.237l0.002,0.009l11.415-3.059l-0.007-0.027
+ l0.019,0.019l22.584-22.583C88.447,44.304,88.447,43.521,87.969,43.045z M56.035,66.697l1.836-6.846l5.012,5.012L56.035,66.697z"/>
+ <path d="M71.967,73.23L71.967,73.23l-7.484,0v0c0,0-0.001,0-0.001,0c-0.68,0.003-1.225,0.548-1.228,1.229l0.002,0.012v8.715H21.612
+ V21.809h4.997v3.069c-0.002,0.033-0.01,0.063-0.01,0.097c0,0.998,0.81,1.814,1.814,1.814c0.005,0,0.009-0.001,0.014-0.001v0.008
+ h28.027c1.005-0.002,1.813-0.816,1.813-1.813c0-0.015-0.004-0.029-0.004-0.044v-3.13h4.992v8.718l-0.002,0.012
+ c0.002,0.682,0.546,1.227,1.228,1.229h7.484h0.001c0.68-0.003,1.225-0.547,1.228-1.228h0V17.26h-0.019
+ c0.001-0.049,0.015-0.095,0.015-0.145c0-2.893-2.346-5.245-5.241-5.245c-0.04,0-0.076,0.011-0.116,0.012H53.276V8.48h0l0-0.002
+ c0-0.881-0.714-1.593-1.593-1.595V6.875h-18.45v0.006c-0.015,0-0.028-0.004-0.043-0.004c-0.88,0-1.594,0.713-1.594,1.594
+ c0,0.01,0.003,0.02,0.003,0.03v3.38H16.935c-0.007,0-0.013-0.002-0.02-0.002c-2.893,0-5.242,2.354-5.242,5.243
+ c0,0.047,0.013,0.09,0.014,0.137h-0.014v70.572h0.003c0,0.009-0.003,0.018-0.003,0.027c0,2.895,2.35,5.238,5.243,5.238
+ c0.078,0,0.151-0.02,0.229-0.023v0.021h50.5c0.098,0.005,0.191,0.029,0.29,0.029c2.894,0,5.239-2.348,5.239-5.238
+ c0-0.019-0.005-0.036-0.005-0.055h0.028V74.458h0l0,0C73.193,73.776,72.649,73.232,71.967,73.23z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard.svg
new file mode 100644
index 0000000..6bc4b0f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clipboard.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.761,17.26h-0.019c0.001-0.049,0.015-0.095,0.015-0.145c0-2.893-2.346-5.245-5.241-5.245
+ c-0.04,0-0.076,0.011-0.116,0.012H60.842V8.48h0l0-0.002c0-0.881-0.714-1.593-1.593-1.595V6.875H40.8v0.006
+ c-0.015,0-0.028-0.004-0.043-0.004c-0.88,0-1.594,0.713-1.594,1.594c0,0.01,0.003,0.02,0.003,0.03v3.38H24.501
+ c-0.007,0-0.013-0.002-0.02-0.002c-2.893,0-5.242,2.354-5.242,5.243c0,0.047,0.013,0.09,0.014,0.137h-0.014v70.572h0.003
+ c0,0.009-0.003,0.018-0.003,0.027c0,2.895,2.35,5.238,5.243,5.238c0.078,0,0.151-0.02,0.229-0.023v0.021h50.5
+ c0.098,0.005,0.191,0.029,0.29,0.029c2.894,0,5.239-2.348,5.239-5.238c0-0.019-0.005-0.036-0.005-0.055h0.028V17.26z
+ M70.822,83.185H29.178V21.809h4.997v3.069c-0.002,0.033-0.01,0.063-0.01,0.097c0,0.998,0.81,1.814,1.814,1.814
+ c0.005,0,0.009-0.001,0.014-0.001v0.008h28.027c1.005-0.002,1.813-0.816,1.813-1.813c0-0.015-0.004-0.029-0.004-0.044v-3.13h4.992
+ V83.185z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clock.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clock.svg
new file mode 100644
index 0000000..11478e1
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-clock.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M50,22.44c15.198,0,27.56,12.367,27.56,27.562c0,15.197-12.362,27.559-27.56,27.559
+ c-15.199,0-27.561-12.362-27.561-27.559C22.439,34.806,34.801,22.44,50,22.44 M50,12.5c-20.712,0-37.5,16.792-37.5,37.502
+ C12.5,70.712,29.288,87.5,50,87.5c20.712,0,37.5-16.788,37.5-37.498C87.5,29.292,70.712,12.5,50,12.5L50,12.5z"/>
+ </g>
+ <path fill="#231F20" d="M69.195,36.068l-3.897-3.902c-0.743-0.747-2.077-0.729-2.791,0L50.022,44.654l-6.863-6.863
+ c-0.743-0.743-2.046-0.743-2.789,0l-3.892,3.893c-0.372,0.364-0.585,0.873-0.585,1.402c0,0.525,0.204,1.025,0.578,1.394
+ l12.133,12.133c0.374,0.374,0.869,0.578,1.396,0.578c0.027,0,0.051,0,0.078,0c0.517-0.009,1-0.213,1.364-0.578l17.754-17.754
+ C69.965,38.087,69.965,36.835,69.195,36.068z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-closed-caption.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-closed-caption.svg
new file mode 100644
index 0000000..c0bbf57
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-closed-caption.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path fill="#231F20" d="M81.615,28.882l-31.178-6.257c-0.287-0.059-0.586-0.059-0.875,0l-31.176,6.257
+ c-1.026,0.208-1.764,1.101-1.764,2.136v18.379v1.208v18.379c0,1.036,0.738,1.928,1.764,2.135l31.176,6.254
+ c0.289,0.062,0.588,0.062,0.875,0l31.178-6.254c1.025-0.207,1.764-1.099,1.764-2.135V50.605v-1.208V31.018
+ C83.379,29.983,82.64,29.09,81.615,28.882z M45.643,58.113c-2.142,4.72-5.503,7.108-9.991,7.108
+ c-7.493,0-12.525-6.117-12.525-15.219c0-9.107,5.033-15.225,12.525-15.225c4.462,0,7.803,2.264,9.936,6.729
+ c0.191,0.396,0.21,0.854,0.055,1.265c-0.151,0.417-0.467,0.75-0.874,0.929l-3.621,1.616c-0.827,0.368-1.815,0.006-2.191-0.821
+ c-0.54-1.172-1.552-2.576-3.305-2.576c-2.774,0-4.709,3.324-4.709,8.084c0,4.758,1.935,8.08,4.709,8.08
+ c1.986,0,2.942-1.953,3.263-2.792c0.159-0.421,0.485-0.764,0.904-0.934c0.421-0.182,0.894-0.173,1.309,0.005l3.663,1.576
+ c0.407,0.172,0.725,0.5,0.885,0.912C45.837,57.258,45.824,57.711,45.643,58.113z M76.726,58.113
+ c-2.142,4.72-5.501,7.108-9.991,7.108c-7.493,0-12.525-6.117-12.525-15.219c0-9.107,5.033-15.225,12.525-15.225
+ c4.462,0,7.803,2.264,9.936,6.729c0.191,0.396,0.209,0.854,0.055,1.265c-0.151,0.417-0.467,0.75-0.874,0.929l-3.621,1.616
+ c-0.827,0.368-1.814,0.006-2.191-0.821c-0.54-1.172-1.552-2.576-3.305-2.576c-2.774,0-4.71,3.324-4.71,8.084
+ c0,4.758,1.935,8.08,4.71,8.08c1.986,0,2.942-1.953,3.263-2.792c0.159-0.421,0.486-0.764,0.904-0.934
+ c0.421-0.182,0.894-0.173,1.309,0.005l3.663,1.576c0.407,0.172,0.726,0.5,0.885,0.912C76.921,57.258,76.908,57.711,76.726,58.113z"
+ />
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-cloud.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-cloud.svg
new file mode 100644
index 0000000..aeb6785
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-cloud.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M79.437,47.349c-3.51-12.982-14.464-22.083-27.134-22.083c-8.835,0-17.065,4.454-22.414,12.018
+ c-1.485-0.339-2.987-0.514-4.501-0.514c-11.889,0-21.563,10.539-21.563,23.498c0,4.647,1.251,9.148,3.612,13.018
+ c0.555,0.906,1.49,1.449,2.49,1.449h80.84c0.947,0,1.836-0.485,2.403-1.315c1.964-2.876,3.004-6.255,3.004-9.767
+ C96.175,53.995,88.36,46.18,79.437,47.349z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-minus.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-minus.svg
new file mode 100644
index 0000000..d29afac
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-minus.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M63.185,55.07c-0.956,0-1.73-0.774-1.73-1.73c0,0,0-0.001,0-0.001V36.446l0-0.001c0-0.956,0.774-1.73,1.73-1.73h17.962
+ V16.936h-0.034c-0.172-1.703-1.592-3.036-3.34-3.036H7.429v0.009c-1.705,0.047-3.079,1.355-3.247,3.027H4.147v56.342h0.068
+ c0.305,1.512,1.622,2.65,3.214,2.694v0.009h11.564v6.744c0,1.864,1.51,3.374,3.374,3.374c1.165,0,2.193-0.591,2.799-1.49
+ l8.628-8.628h43.98c1.634,0,2.995-1.161,3.306-2.703h0.068V55.07H63.185z"/>
+ </g>
+ <g>
+ <path d="M94.123,39.702h-25.95c-0.956,0-1.731,0.774-1.731,1.73v6.92c0,0.956,0.774,1.73,1.731,1.73h25.95
+ c0.956,0,1.73-0.774,1.73-1.73v-6.92C95.853,40.476,95.079,39.702,94.123,39.702z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-quotes.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-quotes.svg
new file mode 100644
index 0000000..d479297
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-quotes.svg
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.466,16.936c-0.172-1.703-1.592-3.036-3.34-3.036H14.781v0.009c-1.705,0.047-3.079,1.355-3.247,3.027H11.5v56.342h0.068
+ c0.305,1.512,1.622,2.65,3.214,2.694v0.009h11.564v6.744c0,1.864,1.51,3.374,3.373,3.374c1.166,0,2.194-0.592,2.8-1.492
+ l8.627-8.627h43.98c1.634,0,2.995-1.161,3.306-2.703H88.5V16.936H88.466z M28.399,50.662c-3.055,0-5.787-2.405-5.787-6.632
+ c0-4.878,2.667-9.234,6.699-12.095l0.014,0.012c0.099-0.05,0.206-0.085,0.324-0.085c0.164,0,0.308,0.064,0.43,0.156l0.008-0.007
+ l2.703,1.706l-0.016,0.015c0.192,0.131,0.325,0.34,0.325,0.59c0,0.277-0.161,0.511-0.39,0.633l0.002,0.002
+ c-0.015,0.008-0.031,0.02-0.046,0.028c-0.004,0.002-0.007,0.005-0.012,0.007c-2.065,1.124-4.26,3.726-4.839,6.046
+ c0.26-0.13,0.78-0.195,1.301-0.195c2.471,0,4.421,1.885,4.421,4.681C33.537,48.321,31.195,50.662,28.399,50.662z M41.632,50.662
+ c-3.055,0-5.787-2.405-5.787-6.632c0-4.878,2.667-9.234,6.699-12.095l0.014,0.012c0.099-0.05,0.206-0.085,0.324-0.085
+ c0.164,0,0.308,0.064,0.43,0.156l0.008-0.007l2.703,1.706l-0.016,0.015c0.192,0.131,0.325,0.34,0.325,0.59
+ c0,0.277-0.161,0.511-0.39,0.633l0.002,0.002c-0.015,0.008-0.031,0.02-0.046,0.028c-0.004,0.002-0.007,0.005-0.012,0.007
+ c-2.065,1.124-4.26,3.726-4.839,6.046c0.26-0.13,0.78-0.195,1.301-0.195c2.471,0,4.421,1.885,4.421,4.681
+ C46.769,48.321,44.428,50.662,41.632,50.662z M57.456,57.849l-0.014-0.012c-0.099,0.05-0.206,0.085-0.324,0.085
+ c-0.164,0-0.308-0.064-0.43-0.156l-0.008,0.007l-2.703-1.706l0.016-0.015c-0.192-0.131-0.325-0.34-0.325-0.59
+ c0-0.277,0.161-0.511,0.39-0.633l-0.002-0.002c0.015-0.008,0.031-0.02,0.046-0.028c0.004-0.002,0.007-0.005,0.012-0.007
+ c2.065-1.124,4.26-3.726,4.839-6.046c-0.26,0.13-0.78,0.195-1.301,0.195c-2.471,0-4.421-1.885-4.421-4.681
+ c0-2.797,2.342-5.137,5.138-5.137c3.055,0,5.787,2.405,5.787,6.632C64.155,50.632,61.488,54.988,57.456,57.849z M70.689,57.849
+ l-0.014-0.012c-0.099,0.05-0.206,0.085-0.324,0.085c-0.164,0-0.308-0.064-0.43-0.156l-0.008,0.007l-2.703-1.706l0.016-0.015
+ c-0.192-0.131-0.325-0.34-0.325-0.59c0-0.277,0.161-0.511,0.39-0.633l-0.002-0.002c0.015-0.008,0.031-0.02,0.046-0.028
+ c0.004-0.002,0.007-0.005,0.012-0.007c2.065-1.124,4.26-3.726,4.839-6.046c-0.26,0.13-0.78,0.195-1.301,0.195
+ c-2.471,0-4.421-1.885-4.421-4.681c0-2.797,2.342-5.137,5.138-5.137c3.055,0,5.787,2.405,5.787,6.632
+ C77.388,50.632,74.721,54.988,70.689,57.849z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-video.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-video.svg
new file mode 100644
index 0000000..d4d6e34
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment-video.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.466,16.936c-0.172-1.703-1.592-3.036-3.34-3.036H14.781v0.009c-1.705,0.047-3.078,1.355-3.247,3.027H11.5v56.342h0.068
+ c0.305,1.512,1.622,2.649,3.213,2.694v0.009h11.565v6.744c0,1.864,1.51,3.374,3.374,3.374c1.166,0,2.193-0.591,2.799-1.491
+ l8.628-8.628h43.98c1.634,0,2.995-1.161,3.306-2.703H88.5V16.936H88.466z M70.974,57.175l-12.694-6.003v5.653
+ c0,1.335-1.093,2.426-2.428,2.426H34.374c-1.334,0-2.427-1.091-2.427-2.426V33.39c0-1.335,1.093-2.425,2.427-2.425h21.478
+ c1.334,0,2.428,1.09,2.428,2.425v5.503l12.694-5.948V57.175z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment.svg
new file mode 100644
index 0000000..c4620e0
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comment.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.466,16.936c-0.172-1.703-1.592-3.036-3.34-3.036H14.781v0.009c-1.705,0.047-3.079,1.355-3.247,3.027H11.5v56.342h0.068
+ c0.305,1.512,1.622,2.65,3.214,2.694v0.009h11.564v6.744c0,1.864,1.51,3.374,3.374,3.374c1.165,0,2.192-0.591,2.798-1.49
+ l8.629-8.629h43.979c1.634,0,2.995-1.161,3.306-2.703H88.5V16.936H88.466z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comments.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comments.svg
new file mode 100644
index 0000000..737e427
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-comments.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.974,17.838c-0.127-1.257-1.16-2.241-2.443-2.277v-0.007H39.624c-1.315,0-2.384,1.004-2.513,2.284h-0.026v13.139h22.342
+ c1.174,0,2.127,0.896,2.243,2.039h0.023v29.232h11.009l6.488,6.487c0.456,0.677,1.229,1.122,2.106,1.122
+ c1.402,0,2.538-1.136,2.538-2.537v-5.072h8.698V62.24c1.197-0.033,2.188-0.889,2.417-2.027H95V17.838H94.974z"/>
+ <path d="M54.44,35.964H7.204v0.006c-1.144,0.031-2.067,0.91-2.181,2.033H5v37.835h0.046c0.205,1.015,1.09,1.779,2.158,1.809v0.006
+ h7.765v4.529c0,1.25,1.015,2.265,2.266,2.265c0.783,0,1.474-0.398,1.88-1.002l5.792-5.792H54.44c1.096,0,2.011-0.78,2.22-1.815
+ h0.045V38.003h-0.023C56.568,36.859,55.614,35.964,54.44,35.964z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-compass.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-compass.svg
new file mode 100644
index 0000000..f343227
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-compass.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M50,77.56c-15.199,0-27.56-12.362-27.56-27.558
+ C22.44,34.807,34.801,22.44,50,22.44c15.198,0,27.56,12.367,27.56,27.562C77.56,65.198,65.198,77.56,50,77.56z"/>
+ <path fill="#231F20" d="M64.674,32.69L45.129,44.338c-0.267,0.156-0.488,0.379-0.646,0.641L32.69,64.67
+ c-0.442,0.737-0.32,1.684,0.291,2.285l0.078,0.078c0.359,0.354,0.833,0.539,1.311,0.539c0.328,0,0.66-0.088,0.956-0.268
+ l19.69-11.789c0.262-0.16,0.485-0.383,0.641-0.645l11.648-19.545c0.437-0.729,0.245-1.738-0.349-2.345
+ C66.354,32.37,65.41,32.244,64.674,32.69z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-contrast.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-contrast.svg
new file mode 100644
index 0000000..f345f19
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-contrast.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5c20.712,0,37.5-16.788,37.5-37.498
+ C87.5,29.293,70.712,12.5,50,12.5z M50.124,22.443C65.265,22.51,77.56,34.848,77.56,50.002c0,15.155-12.295,27.488-27.436,27.555
+ V22.443z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-credit-card.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-credit-card.svg
new file mode 100644
index 0000000..65257f6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-credit-card.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.941,26.224c0-1.469-1.191-2.659-2.66-2.659c-0.036,0-0.07,0.009-0.106,0.011H15.949
+ c-0.078-0.007-0.153-0.023-0.233-0.023c-1.467,0-2.658,1.19-2.658,2.659c0,0.124,0.02,0.243,0.037,0.363v7.009h73.846v-7.243H86.93
+ C86.931,26.3,86.941,26.263,86.941,26.224z"/>
+ <path d="M13.095,73.78L13.095,73.78c0.001,0.003,0,0.006,0,0.01c0,1.468,1.191,2.658,2.659,2.658c0.056,0,0.109-0.013,0.164-0.017
+ v0.002h68.459v-0.02c1.419-0.051,2.554-1.205,2.563-2.633h0.002V43.582H13.095V73.78z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crop.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crop.svg
new file mode 100644
index 0000000..07e9d2f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crop.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.231,71.062c0,0-0.001,0-0.001,0h-7.263V23.959h-0.051c0.003-0.07,0.021-0.135,0.021-0.206
+ c0-2.635-2.137-4.772-4.772-4.772l0,0H28.99v-7.068h0c0-1.487-1.205-2.692-2.693-2.693h-4.571c-1.488,0-2.693,1.205-2.693,2.693
+ c0,0,0,0,0,0.001v7.067h-7.263c0,0-0.001,0-0.001,0c-1.487,0-2.692,1.205-2.693,2.693v4.571c0,1.488,1.205,2.693,2.693,2.693
+ c0,0,0.001,0,0.001,0h7.263v47.103h0.052c-0.003,0.07-0.021,0.135-0.021,0.206c0,2.635,2.137,4.772,4.772,4.772l0,0H71.01v7.068
+ c0,1.487,1.205,2.692,2.693,2.693h4.571c1.488,0,2.693-1.205,2.693-2.693v-7.068h7.263c0,0,0,0,0.001,0
+ c1.487,0,2.692-1.205,2.693-2.693v-4.571C90.923,72.267,89.719,71.062,88.231,71.062z M28.99,71.063V28.937h42.02v42.125H28.99z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crown.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crown.svg
new file mode 100644
index 0000000..f1f24a7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-crown.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M84.01,79.998L84.01,79.998c-0.001-1.679-1.362-3.043-3.042-3.043H19.033h0
+ c-1.68,0-3.042,1.364-3.042,3.043h0v3.871h0l0,0c0,1.681,1.362,3.042,3.042,3.042h0h61.935c1.681,0,3.042-1.361,3.042-3.042l0,0h0
+ V79.998z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M24.619,38.433l-0.017-0.017L24.6,38.418c-0.572-0.491-1.306-0.798-2.118-0.798
+ c-1.779,0-3.219,1.424-3.26,3.193h-0.08v29.238h0.103c0.155,1.659,1.536,2.965,3.237,2.965c0.012,0,0.024-0.003,0.036-0.004v0.004
+ h54.963V72.94c0.013,0,0.024,0.004,0.037,0.004c1.675,0,3.041-1.268,3.229-2.893h0.037v-0.37l0-0.005c0,0,0-0.003,0-0.005V41.42
+ c0.046-0.219,0.073-0.446,0.073-0.679c0-1.803-1.463-3.266-3.267-3.266c-0.776,0-1.479,0.282-2.04,0.733l-0.009-0.009l-0.091,0.091
+ c-0.112,0.097-0.215,0.201-0.312,0.312l-6.881,6.881L52.405,29.631l-0.031,0.031c-0.596-0.633-1.435-1.033-2.373-1.033
+ c-0.94,0-1.781,0.402-2.377,1.037l-0.035-0.035L31.702,45.516l-6.766-6.767C24.837,38.637,24.732,38.532,24.619,38.433z
+ M72.973,46.827v0.095h-0.095L72.973,46.827z"/>
+ <circle fill-rule="evenodd" clip-rule="evenodd" cx="22.348" cy="27.13" r="6.042"/>
+ <circle fill-rule="evenodd" clip-rule="evenodd" cx="77.348" cy="27.13" r="6.042"/>
+ <circle fill-rule="evenodd" clip-rule="evenodd" cx="50.348" cy="19.13" r="6.042"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-css3.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-css3.svg
new file mode 100644
index 0000000..4972fc3
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-css3.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M18.258,14.29l5.951,64.477L50,85.71l25.79-6.943l5.953-64.477H18.258z M68.96,35.187l-18.983,8.116
+ l-0.046,0.019h0.046H68.29l-2.1,24.146l-16.184,4.725l-0.029-0.009v0.009l-16.272-4.812l-1.05-12.16h0.028h8.02h0.029l0.525,6.299
+ l8.646,2.183l0.074-0.021v0.01l8.952-2.521l0.613-10.148l-9.565-0.029L32.13,50.934l-0.612-7.611l18.459-7.688l1.076-0.447h-1.076
+ H30.818L29.855,27.4h20.122h19.771L68.96,35.187z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-database.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-database.svg
new file mode 100644
index 0000000..749397c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-database.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M32.948,24.348h-0.011c-0.057-2.327-1.971-4.133-4.3-4.165v-0.006h-15.69v0.011c-2.307,0.057-4.067,1.852-4.119,4.161
+ h-0.01v51.2h0.008c0.043,2.3,1.838,4.089,4.121,4.178v0.097h15.69v0c2.401-0.001,4.311-1.875,4.311-4.274c0,0,0-0.001,0-0.001h0
+ V24.348z M20.882,74.836c-3.443,0-6.233-2.792-6.233-6.234c0-3.443,2.791-6.234,6.233-6.234c3.444,0,6.235,2.791,6.235,6.234
+ C27.117,72.045,24.326,74.836,20.882,74.836z M27.96,52.426H13.805V25.164H27.96V52.426z"/>
+ </g>
+ <g>
+ <path d="M62.065,24.348h-0.011c-0.057-2.327-1.971-4.133-4.3-4.165v-0.006h-15.69v0.011c-2.307,0.057-4.067,1.852-4.119,4.161
+ h-0.01v51.2h0.008c0.043,2.3,1.838,4.089,4.121,4.178v0.097h15.69v0c2.401-0.001,4.311-1.875,4.311-4.274c0,0,0-0.001,0-0.001h0
+ V24.348z M49.999,74.836c-3.443,0-6.233-2.792-6.233-6.234c0-3.443,2.791-6.234,6.233-6.234c3.444,0,6.235,2.791,6.235,6.234
+ C56.234,72.045,53.443,74.836,49.999,74.836z M57.077,52.426H42.923V25.164h14.155V52.426z"/>
+ </g>
+ <g>
+ <path d="M91.182,24.348h-0.011c-0.057-2.327-1.971-4.133-4.3-4.165v-0.006h-15.69v0.011c-2.307,0.057-4.067,1.852-4.119,4.161
+ h-0.01v51.2h0.008c0.043,2.3,1.838,4.089,4.121,4.178v0.097h15.69v0c2.401-0.001,4.311-1.875,4.311-4.274c0,0,0-0.001,0-0.001h0
+ V24.348z M79.117,74.836c-3.443,0-6.233-2.792-6.233-6.234c0-3.443,2.791-6.234,6.233-6.234c3.444,0,6.235,2.791,6.235,6.234
+ C85.352,72.045,82.56,74.836,79.117,74.836z M86.195,52.426H72.04V25.164h14.155V52.426z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-five.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-five.svg
new file mode 100644
index 0000000..6269b38
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-five.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M32.99,73.676c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.15-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035
+ C40.025,70.527,36.875,73.676,32.99,73.676z M32.99,40.07c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.15-7.035,7.034-7.035
+ c3.885,0,7.035,3.15,7.035,7.035C40.025,36.921,36.875,40.07,32.99,40.07z M50,57.035c-3.885,0-7.034-3.148-7.034-7.034
+ c0-3.885,3.149-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035C57.034,53.886,53.885,57.035,50,57.035z M67.009,73.979
+ c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036
+ C74.044,70.83,70.894,73.979,67.009,73.979z M67.009,40.07c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036
+ c3.885,0,7.035,3.149,7.035,7.036C74.044,36.921,70.894,40.07,67.009,40.07z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-four.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-four.svg
new file mode 100644
index 0000000..1caa06a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-four.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M32.99,73.676c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035
+ C40.025,70.527,36.875,73.676,32.99,73.676z M32.99,40.07c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035
+ c3.885,0,7.035,3.15,7.035,7.035C40.025,36.921,36.875,40.07,32.99,40.07z M67.009,73.979c-3.885,0-7.034-3.148-7.034-7.033
+ c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036C74.044,70.83,70.894,73.979,67.009,73.979z M67.009,40.07
+ c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036
+ C74.044,36.921,70.894,40.07,67.009,40.07z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-one.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-one.svg
new file mode 100644
index 0000000..bd92b52
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-one.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M50,57.621c-4.21,0-7.621-3.411-7.621-7.62s3.412-7.621,7.621-7.621c4.208,0,7.621,3.412,7.621,7.621S54.209,57.621,50,57.621z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-six.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-six.svg
new file mode 100644
index 0000000..218e4c4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-six.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M32.99,73.676c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035
+ C40.025,70.527,36.875,73.676,32.99,73.676z M32.99,57.035c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035
+ c3.885,0,7.035,3.15,7.035,7.035C40.025,53.886,36.875,57.035,32.99,57.035z M32.99,40.07c-3.885,0-7.034-3.148-7.034-7.034
+ c0-3.885,3.149-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035C40.025,36.921,36.875,40.07,32.99,40.07z M67.009,73.979
+ c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036
+ C74.044,70.83,70.894,73.979,67.009,73.979z M67.01,57.035c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035
+ c3.885,0,7.035,3.15,7.035,7.035C74.044,53.886,70.895,57.035,67.01,57.035z M67.009,40.07c-3.885,0-7.034-3.148-7.034-7.033
+ c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036C74.044,36.921,70.894,40.07,67.009,40.07z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-three.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-three.svg
new file mode 100644
index 0000000..9a2ca59
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-three.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M32.99,40.07c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.15-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035
+ C40.025,36.921,36.875,40.07,32.99,40.07z M49.999,57.035c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036
+ c3.885,0,7.035,3.149,7.035,7.036C57.034,53.886,53.885,57.035,49.999,57.035z M67.009,73.979c-3.885,0-7.034-3.148-7.034-7.033
+ c0-3.887,3.149-7.036,7.034-7.036c3.885,0,7.035,3.149,7.035,7.036C74.044,70.83,70.894,73.979,67.009,73.979z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-two.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-two.svg
new file mode 100644
index 0000000..1fac170
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-die-two.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.921,23.292c-0.092-3.956-3.264-7.145-7.213-7.264v-0.011H23.292v0.008c-3.974,0.092-7.174,3.293-7.267,7.267h-0.009
+ v53.416h0.009c0.091,3.974,3.292,7.175,7.267,7.267v0.008h53.416v-0.009c3.975-0.092,7.176-3.292,7.267-7.267h0.009V23.292H83.921z
+ M32.99,40.07c-3.885,0-7.034-3.148-7.034-7.034c0-3.885,3.149-7.035,7.034-7.035c3.885,0,7.035,3.15,7.035,7.035
+ C40.025,36.921,36.875,40.07,32.99,40.07z M67.009,73.978c-3.885,0-7.034-3.148-7.034-7.033c0-3.887,3.149-7.036,7.034-7.036
+ c3.885,0,7.035,3.149,7.035,7.036C74.044,70.83,70.894,73.978,67.009,73.978z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dislike.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dislike.svg
new file mode 100644
index 0000000..9a185d8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dislike.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.533,29.788h-0.006c0-0.323-0.124-0.646-0.369-0.894l0.003-0.003l-9.764-9.764l-0.024,0.024
+ c-0.281-0.23-0.626-0.318-0.967-0.272H35.304c-0.073-0.006-0.143-0.022-0.218-0.022c-1.356,0-2.453,1.067-2.523,2.406h-0.008v0.082
+ c0,0.017-0.005,0.032-0.005,0.048s0.005,0.032,0.005,0.048v8.346h0v28.152h0.001c0,0.003-0.001,0.006-0.001,0.009
+ c0,1.401,1.136,2.537,2.537,2.537c0.047,0,0.09-0.011,0.136-0.014h9.931c0.15,0.244,0.334,0.453,0.536,0.637l0.109,0.188v0.109
+ h0.063l9.709,16.816l0.025-0.014c0.99,1.753,2.847,2.936,4.98,2.936c3.171,0,5.742-2.607,5.742-5.825h0.058v-3.257v-0.106V60.471
+ h13.684v-0.019c1.361-0.04,2.452-1.145,2.461-2.513h0.008V29.788z"/>
+ <path d="M27.407,25.873L27.407,25.873c-0.001-0.003,0-0.006,0-0.009c0-1.401-1.136-2.536-2.537-2.536
+ c-0.047,0-0.091,0.011-0.137,0.014l-4.798,0v0.018c-1.361,0.04-2.452,1.145-2.461,2.513h-0.008v27.502h0.043
+ c0.12,1.257,1.147,2.243,2.426,2.287v0.022l4.971,0l0,0l0,0h0l0,0c1.4,0,2.536-1.136,2.536-2.537c0-0.12-0.019-0.234-0.035-0.35
+ V25.873z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar-bill.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar-bill.svg
new file mode 100644
index 0000000..03cb2b9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar-bill.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M93.681,30.128h-0.045c0-2.135-1.73-3.866-3.865-3.865l0,0v0H10.185c-2.135,0-3.866,1.731-3.866,3.865h0v39.744h0l0,0.001
+ c0,2.135,1.731,3.865,3.866,3.865H89.77v0l0.001,0c2.135,0.001,3.866-1.73,3.865-3.864l0-0.001l0.045,0V30.128z M78.704,35.474
+ v-3.431c0-0.438,0.354-0.793,0.793-0.793c0.031,0,0.058,0.014,0.088,0.018V31.25h8.271v0.006c0.011,0,0.02-0.006,0.031-0.006
+ c0.438,0,0.793,0.355,0.793,0.793v8.417h0c0,0.438-0.356,0.793-0.793,0.793c-0.011,0-0.02-0.006-0.031-0.006v0.006h-3.37l0,0
+ c-0.439,0-0.793-0.355-0.793-0.793h0v-4.194h-4.107v-0.018c-0.03,0.003-0.057,0.018-0.088,0.018
+ C79.058,36.267,78.704,35.912,78.704,35.474L78.704,35.474L78.704,35.474z M21.296,64.526v3.431c0,0.438-0.354,0.793-0.793,0.793
+ c-0.031,0-0.058-0.014-0.088-0.018v0.017h-8.271v-0.006c-0.011,0-0.02,0.006-0.031,0.006c-0.438,0-0.793-0.355-0.793-0.793v-8.418
+ h0c0-0.438,0.356-0.793,0.793-0.793c0.011,0,0.02,0.006,0.031,0.006v-0.006h3.37l0.001,0c0.439,0,0.793,0.355,0.793,0.793h0v4.194
+ h4.107v0.018c0.03-0.003,0.057-0.018,0.088-0.018C20.942,63.733,21.296,64.088,21.296,64.526L21.296,64.526L21.296,64.526z
+ M21.31,32.074v3.37l0,0.001c0,0.438-0.355,0.793-0.793,0.793v0h-4.194v4.107h-0.018c0.003,0.03,0.018,0.057,0.018,0.088
+ c0,0.438-0.355,0.793-0.793,0.793l0,0v0H12.1c-0.438,0-0.793-0.354-0.793-0.793c0-0.031,0.014-0.058,0.018-0.088h-0.017v-8.271
+ h0.006c0-0.011-0.006-0.02-0.006-0.031c0-0.438,0.355-0.793,0.793-0.793h8.418c0.438,0,0.793,0.355,0.793,0.793
+ c0,0.011-0.006,0.02-0.006,0.031H21.31z M50,68.75c-10.356,0-18.75-8.394-18.75-18.749c0-10.354,8.394-18.751,18.75-18.751
+ c10.356,0,18.75,8.396,18.75,18.751C68.75,60.356,60.356,68.75,50,68.75z M88.693,59.656v8.271h-0.006
+ c0,0.011,0.006,0.02,0.006,0.031c0,0.438-0.355,0.793-0.793,0.793h-8.418c-0.438,0-0.793-0.356-0.793-0.793
+ c0-0.011,0.006-0.02,0.006-0.031h-0.006v-3.37l0-0.001c0-0.438,0.355-0.793,0.793-0.793v0h4.194v-4.107h0.018
+ c-0.003-0.03-0.018-0.057-0.018-0.088c0-0.438,0.355-0.793,0.793-0.793h0H87.9c0.438,0,0.793,0.354,0.793,0.793
+ c0,0.031-0.014,0.058-0.018,0.088H88.693z"/>
+ <path d="M50,36.22c-7.599,0-13.78,6.184-13.78,13.781c0,2.91,0.912,5.607,2.457,7.834v-0.096c0-0.617,0.322-1.169,0.812-1.398
+ l5.64-2.627l2.212-1.03c-0.999-0.602-1.82-1.537-2.374-2.673c-0.479-0.978-0.761-2.103-0.761-3.31c0-0.694,0.116-1.351,0.284-1.981
+ c0.729-2.749,2.906-4.76,5.509-4.76c2.653,0,4.863,2.085,5.55,4.915c0.141,0.584,0.242,1.189,0.242,1.826
+ c0,1.136-0.253,2.197-0.679,3.136c-0.536,1.182-1.355,2.163-2.364,2.799l2.31,1.102l5.462,2.605
+ c0.485,0.234,0.802,0.782,0.802,1.396v0.095c1.545-2.227,2.457-4.924,2.457-7.834C63.78,42.403,57.599,36.22,50,36.22z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar.svg
new file mode 100644
index 0000000..686a3a9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-dollar.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M54.284,44.798V34.688c3.297,0.807,6.52,2.344,9.157,4.762l0.011-0.015c0.197,0.157,0.436,0.265,0.708,0.265
+ c0.358,0,0.665-0.173,0.877-0.428l0.015,0.003l4.262-6.008l-0.01-0.005c0.175-0.202,0.291-0.458,0.291-0.746
+ c0-0.34-0.153-0.638-0.387-0.849c-3.953-3.651-9-5.843-14.924-6.502v-5.806h-0.001c0-0.637-0.516-1.153-1.153-1.153h-4.578
+ c-0.637,0-1.153,0.516-1.153,1.153v5.659c-9.89,1.025-15.75,7.326-15.75,14.725c0,9.963,8.205,12.82,15.75,14.652v11.354
+ c-4.845-0.868-8.827-3.379-11.536-6.19c-0.019-0.021-0.039-0.039-0.06-0.058c-0.016-0.017-0.036-0.034-0.052-0.051l-0.008,0.011
+ c-0.199-0.162-0.442-0.273-0.719-0.273c-0.436,0-0.802,0.251-0.998,0.608l-0.014-0.002l-4.125,6.124l0.005,0.01
+ c-0.176,0.202-0.292,0.458-0.292,0.748c0,0.367,0.182,0.679,0.448,0.89l-0.011,0.016c4.029,4.029,9.67,6.959,17.362,7.619v5.44
+ c0,0.637,0.516,1.153,1.153,1.153h0h4.578c0.637,0,1.153-0.517,1.153-1.153h0.001V75.2c10.769-1.1,16.117-7.398,16.117-15.531
+ C70.401,49.634,61.903,46.702,54.284,44.798z M47.398,43.112c-3.003-0.951-5.055-2.051-5.055-4.176c0-2.49,1.832-4.248,5.055-4.688
+ V43.112z M54.284,65.896v-9.816c3.224,1.025,5.495,2.199,5.495,4.615C59.779,63.04,58.02,65.163,54.284,65.896z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-download.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-download.svg
new file mode 100644
index 0000000..121a21f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-download.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84.514,49.615H67.009c-2.133,0-4.025,1.374-4.679,3.406c-1.734,5.375-6.691,8.983-12.329,8.983
+ c-5.64,0-10.595-3.608-12.329-8.983c-0.656-2.032-2.546-3.406-4.681-3.406H15.486c-2.716,0-4.919,2.2-4.919,4.919v28.054
+ c0,2.714,2.203,4.917,4.919,4.917h69.028c2.719,0,4.919-2.203,4.919-4.917V54.534C89.433,51.815,87.233,49.615,84.514,49.615z"/>
+ <path d="M48.968,52.237c0.247,0.346,0.651,0.553,1.076,0.553h0.003c0.428,0,0.826-0.207,1.076-0.558l13.604-19.133
+ c0.286-0.404,0.321-0.932,0.096-1.374c-0.225-0.442-0.682-0.716-1.177-0.716h-6.399V13.821c0-0.735-0.593-1.326-1.323-1.326H44.078
+ c-0.732,0-1.323,0.591-1.323,1.326v17.188h-6.404c-0.495,0-0.949,0.279-1.174,0.716c-0.229,0.442-0.19,0.97,0.098,1.374
+ L48.968,52.237z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eject.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eject.svg
new file mode 100644
index 0000000..095eb2e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eject.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M15.194,59.995L15.194,59.995l69.732-0.074l0-0.014c1.316-0.073,2.363-1.155,2.361-2.489
+ c-0.001-0.722-0.312-1.367-0.802-1.823L51.834,21.02l-0.004,0.004c-0.459-0.542-1.136-0.892-1.902-0.892
+ c-0.833,0.001-1.566,0.414-2.02,1.041L13.448,55.708c-0.466,0.455-0.757,1.087-0.756,1.79
+ C12.693,58.879,13.813,59.997,15.194,59.995z"/>
+ <path d="M87.308,77.253l-0.01-9.803l0-0.05h-0.005c-0.029-1.378-1.15-2.486-2.534-2.485l0-0.006l-69.751,0.074l0,0.042
+ c-1.286,0.125-2.295,1.198-2.293,2.516c0,0.033,0.008,0.063,0.01,0.096l0.01,9.477c-0.006,0.074-0.022,0.145-0.022,0.22
+ c0.001,1.322,1.018,2.395,2.311,2.511v0.023l69.751-0.074h0c1.401-0.001,2.535-1.138,2.534-2.539
+ C87.309,77.255,87.308,77.254,87.308,77.253z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-elevator.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-elevator.svg
new file mode 100644
index 0000000..e0de3ab
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-elevator.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M77.741,10.79c-0.001,0-0.001,0-0.002,0v0H4.36v0c-1.391,0.001-2.519,1.129-2.519,2.521V86.69
+ c0,1.391,1.128,2.52,2.519,2.521l0,0h0.001c0,0,0,0,0.001,0s0,0,0.001,0h73.376l0,0c0.001,0,0.001,0,0.002,0
+ c1.393,0,2.521-1.129,2.521-2.521V13.311C80.262,11.918,79.134,10.79,77.741,10.79z M11.862,20.809h58.381V79.19H11.862V20.809z"/>
+ <path fill="#231F20" d="M97.524,63.966h-2.882l0-7.737c0-0.33-0.266-0.596-0.595-0.596h-5.333c-0.329,0-0.595,0.266-0.595,0.596
+ v7.736h-2.883c-0.223,0.001-0.427,0.126-0.529,0.324c-0.103,0.197-0.085,0.437,0.045,0.618l6.164,8.616
+ c0.111,0.156,0.292,0.248,0.483,0.248c0.001,0,0.001,0,0.001,0c0.193,0,0.373-0.094,0.484-0.25l6.125-8.615
+ c0.129-0.182,0.146-0.421,0.043-0.619C97.952,64.09,97.747,63.965,97.524,63.966z"/>
+ <path fill="#231F20" d="M85.276,36.035h2.882l0,7.737c0,0.329,0.267,0.595,0.596,0.596l5.333-0.001
+ c0.329,0,0.596-0.266,0.595-0.595v-7.737h2.883c0.223,0,0.427-0.125,0.529-0.323s0.085-0.438-0.045-0.618l-6.164-8.615
+ c-0.112-0.157-0.292-0.25-0.483-0.25c-0.001,0-0.001,0-0.001,0c-0.193,0.002-0.373,0.094-0.485,0.252l-6.124,8.614
+ c-0.129,0.181-0.146,0.42-0.044,0.618C84.848,35.91,85.053,36.035,85.276,36.035z"/>
+ <circle fill="#231F20" cx="27.998" cy="31.993" r="4.955"/>
+ <path fill="#231F20" d="M37.38,38.28v-0.024H19.628v0.017c-1.283,0-2.323,1.036-2.332,2.316h-0.002v14.04h0.023
+ c-0.001,0.535,0.202,1.07,0.61,1.478c0.813,0.814,2.133,0.814,2.947,0c0.407-0.408,0.61-0.943,0.609-1.478h0.005v-9.699v-0.103
+ h0.006c0.015-0.354,0.302-0.638,0.66-0.638c0.358,0,0.646,0.283,0.661,0.638h0.006v0.103v6.254v19.344
+ c0.002,1.345,1.091,2.434,2.437,2.434c1.345,0,2.437-1.091,2.437-2.437V57.584h0.018c0-0.373,0.302-0.675,0.675-0.675
+ s0.675,0.302,0.675,0.675h0.017v12.941c0,1.346,1.092,2.437,2.437,2.437c1.346,0,2.437-1.091,2.437-2.437V57.584v-6.399v-6.254
+ v-0.103c0-0.369,0.298-0.667,0.666-0.667c0.367,0,0.665,0.298,0.665,0.667v0.103v9.699h0.023c-0.001,0.535,0.202,1.07,0.61,1.478
+ c0.814,0.814,2.133,0.814,2.947,0c0.408-0.408,0.611-0.943,0.61-1.478h0.004v-14.04C39.477,39.383,38.556,38.401,37.38,38.28z"/>
+ <circle fill="#231F20" cx="53.331" cy="31.993" r="4.955"/>
+ <path fill="#231F20" d="M62.713,38.28v-0.024H44.961v0.017c-1.283,0-2.323,1.036-2.332,2.316h-0.002v14.04h0.023
+ c-0.001,0.535,0.202,1.07,0.61,1.478c0.813,0.814,2.133,0.814,2.947,0c0.407-0.408,0.61-0.943,0.609-1.478h0.005v-9.699v-0.103
+ h0.006c0.015-0.354,0.302-0.638,0.66-0.638c0.358,0,0.646,0.283,0.661,0.638h0.006v0.103v6.254v19.344
+ c0.002,1.345,1.091,2.434,2.437,2.434c1.345,0,2.437-1.091,2.437-2.437V57.584h0.018c0-0.373,0.302-0.675,0.675-0.675
+ s0.675,0.302,0.675,0.675h0.017v12.941c0,1.346,1.092,2.437,2.437,2.437c1.346,0,2.437-1.091,2.437-2.437V57.584v-6.399v-6.254
+ v-0.103c0-0.369,0.298-0.667,0.666-0.667c0.367,0,0.665,0.298,0.665,0.667v0.103v9.699h0.023c-0.001,0.535,0.202,1.07,0.61,1.478
+ c0.814,0.814,2.133,0.814,2.947,0c0.408-0.408,0.611-0.943,0.61-1.478h0.004v-14.04C64.809,39.383,63.889,38.401,62.713,38.28z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-euro.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-euro.svg
new file mode 100644
index 0000000..21953e0
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-euro.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M77.024,63.084c-0.029-0.016-0.061-0.016-0.09-0.03l0.005-0.012l-7.807-3.746l-0.002,0.016
+ c-0.532-0.238-1.166-0.056-1.464,0.46c-0.026,0.045-0.028,0.094-0.047,0.141c-2.274,4.302-7.07,7.714-12.505,7.714
+ c-6.761,0-12.154-3.461-14.891-8.934h19.604c0.025,0.002,0.047,0.015,0.073,0.015c0.637,0,1.153-0.516,1.153-1.153v-4.062
+ c0-0.622-0.494-1.12-1.11-1.145v-0.014H38.293c-0.081-0.725-0.081-1.529-0.081-2.334c0-0.885,0-1.689,0.161-2.576h21.513
+ c0.005,0,0.009,0.003,0.015,0.003s0.009-0.003,0.015-0.003h0.029v-0.006c0.616-0.024,1.11-0.523,1.11-1.145v-4.062
+ c0-0.637-0.516-1.153-1.153-1.153c-0.015,0-0.028,0.008-0.044,0.009H40.305c2.817-5.312,8.21-8.693,14.81-8.693
+ c5.474,0,10.303,3.461,12.557,7.807l0.011-0.005c0.303,0.5,0.923,0.677,1.448,0.442l0.002,0.016l7.807-3.746l-0.005-0.012
+ c0.029-0.014,0.062-0.014,0.09-0.03c0.523-0.302,0.705-0.949,0.452-1.486l0.015-0.007c-0.013-0.023-0.028-0.046-0.041-0.069
+ c-0.002-0.004-0.002-0.009-0.005-0.013c-0.003-0.005-0.008-0.007-0.01-0.012C73.642,28.531,66.813,22.23,55.115,22.23
+ c-13.12,0-23.744,7.324-27.366,18.836h-4.142c-0.015,0-0.028-0.009-0.044-0.009c-0.637,0-1.153,0.516-1.153,1.153v4.062
+ c0,0.637,0.516,1.153,1.153,1.153c0.005,0,0.009-0.003,0.015-0.003h2.964c-0.081,0.887-0.081,1.691-0.081,2.576
+ c0,0.805,0,1.609,0.081,2.334h-2.978v0.005c-0.637,0-1.153,0.516-1.153,1.153v4.062c0,0.637,0.516,1.153,1.153,1.153
+ c0.026,0,0.047-0.013,0.073-0.015h4.032C31.21,70.363,41.915,77.77,55.115,77.77c11.679,0,18.505-6.44,22.303-13.078
+ c0.008-0.012,0.021-0.019,0.028-0.032c0.006-0.011,0.006-0.024,0.012-0.035c0.011-0.019,0.023-0.037,0.034-0.056l-0.013-0.006
+ C77.727,64.027,77.545,63.385,77.024,63.084z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eye.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eye.svg
new file mode 100644
index 0000000..56732d7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-eye.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84.448,47.672L67.712,30.936l-0.116,0.116c-4.632-4.325-10.847-6.977-17.685-6.977c-7.679,0-14.575,3.341-19.322,8.646
+ L15.013,48.298l0.012,0.012c-0.414,0.472-0.673,1.083-0.673,1.76c0,0.844,0.398,1.588,1.009,2.079l16.896,16.895l0.035-0.035
+ c4.625,4.289,10.815,6.915,17.62,6.915c7.67,0,14.559-3.333,19.305-8.627l0.062,0.062l15.479-15.479
+ c0.065-0.059,0.126-0.12,0.185-0.185l0.001-0.001v0c0.431-0.476,0.7-1.1,0.7-1.792C85.645,48.972,85.169,48.153,84.448,47.672z
+ M49.912,67.567c-9.702,0-17.567-7.865-17.567-17.567c0-9.701,7.865-17.566,17.567-17.566c9.702,0,17.568,7.865,17.568,17.566
+ C67.48,59.702,59.614,67.567,49.912,67.567z"/>
+ <circle cx="49.99" cy="50.077" r="8.512"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-fast-forward.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-fast-forward.svg
new file mode 100644
index 0000000..a95fbac
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-fast-forward.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.346,49.976c0-0.702-0.422-1.303-1.026-1.57l0.017-0.03l-37.39-21.588c-0.31-0.307-0.736-0.497-1.207-0.497
+ c-0.932,0-1.686,0.743-1.713,1.669h-0.005v15.249L16.58,26.788c-0.31-0.307-0.736-0.497-1.207-0.497
+ c-0.932,0-1.687,0.743-1.713,1.669h-0.005v44.031c0,0.949,0.77,1.718,1.718,1.718c0.483,0,0.918-0.2,1.23-0.521l28.42-16.408
+ v15.212c0,0.949,0.769,1.718,1.718,1.718c0.483,0,0.918-0.2,1.23-0.521l37.545-21.677l-0.031-0.054
+ C85.997,51.16,86.346,50.611,86.346,49.976z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female-symbol.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female-symbol.svg
new file mode 100644
index 0000000..e21bccc
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female-symbol.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M68.507,55.658c10.221-10.221,10.221-26.793,0-37.016c-10.222-10.221-26.793-10.221-37.015,0
+ c-10.222,10.223-10.222,26.795,0,37.016c3.807,3.807,8.495,6.193,13.408,7.165v8.09h-5.299v0c-0.395,0-0.791,0.151-1.092,0.453
+ c-0.301,0.302-0.452,0.697-0.452,1.092h0v6.886h0c0,0.852,0.692,1.543,1.544,1.544c0.002,0,0.003,0,0.005,0h5.294v6.592h0
+ c0,0.753,0.54,1.379,1.254,1.515v0.029h0.289c0,0,0,0,0.001,0s0,0,0.001,0h6.884c0.001,0,0.001,0,0.002,0
+ c0.852,0,1.544-0.691,1.544-1.544h0.001v-6.592h5.52c0.001,0,0.002,0,0.003,0c0.853,0,1.544-0.691,1.544-1.544v-6.886
+ c0-0.395-0.151-0.791-0.452-1.092c-0.302-0.302-0.697-0.453-1.092-0.453v0h-5.522v-8.048
+ C59.87,61.923,64.643,59.522,68.507,55.658z M50,53.349c-8.946,0-16.199-7.252-16.198-16.198c0-8.946,7.252-16.199,16.199-16.199
+ c8.946,0,16.199,7.252,16.198,16.198C66.198,46.096,58.946,53.349,50,53.349z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female.svg
new file mode 100644
index 0000000..ea6985e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-female.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle fill="#231F20" cx="49.244" cy="20.203" r="8.2"/>
+ <path fill="#231F20" d="M72.147,54.101l-5.47-20.414c-0.003-0.016-0.009-0.031-0.013-0.047l-0.096-0.359l-0.014,0.004
+ c-0.499-1.556-1.94-2.69-3.662-2.69c-0.013,0-0.026,0.004-0.039,0.004v-0.071H37.108v0.067c-1.722,0-3.163,1.134-3.662,2.69
+ l-0.014-0.004l-0.096,0.358c-0.004,0.017-0.01,0.032-0.013,0.049l-5.47,20.413l0.052,0.014c-0.025,0.169-0.052,0.337-0.052,0.513
+ c0,1.924,1.56,3.485,3.485,3.485c1.474,0,2.727-0.919,3.236-2.212l0.024,0.006l4.013-14.974v0.057h0.031
+ c0.11-0.493,0.529-0.869,1.054-0.869c0.526,0,0.945,0.377,1.055,0.869h0.033v0.161c0.002,0.025,0.014,0.046,0.014,0.071
+ s-0.013,0.046-0.014,0.071v0.153L34.36,65.424c-0.104,0.211-0.167,0.442-0.184,0.688l-0.014,0.051l0.008,0.002
+ c-0.001,0.027-0.008,0.053-0.008,0.081c0,1.033,0.838,1.87,1.871,1.87h4.751v15.849c0,2.226,1.805,4.032,4.032,4.032
+ c2.227,0,4.032-1.805,4.032-4.032l0-15.849h2.293v15.849c0,2.226,1.806,4.032,4.033,4.032c2.227,0,4.032-1.805,4.032-4.032V68.116
+ h4.765c1.033,0,1.871-0.837,1.871-1.87c0-0.028-0.007-0.054-0.008-0.081l0.008-0.002l-0.014-0.051
+ c-0.018-0.246-0.081-0.477-0.184-0.688L59.24,41.52l0.021-0.006c-0.027-0.095-0.059-0.188-0.059-0.291
+ c0-0.608,0.493-1.102,1.102-1.102c0.518,0,0.932,0.365,1.05,0.847l0.042-0.011l4.006,14.951l0.024-0.006
+ c0.509,1.293,1.762,2.212,3.236,2.212c1.925,0,3.485-1.561,3.485-3.485c0-0.176-0.027-0.344-0.052-0.513L72.147,54.101z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-filter.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-filter.svg
new file mode 100644
index 0000000..9baa0da
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-filter.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M90,22.292c0-3.508-2.781-6.359-6.258-6.488v-0.012H16.848v0.018c-0.116-0.006-0.231-0.018-0.348-0.018
+ c-3.59,0-6.5,2.91-6.5,6.5c0,2.045,0.946,3.867,2.423,5.059l30.14,30.139l-0.001,18.599v0.154h0.015
+ c0.054,1.204,0.727,2.236,1.713,2.8l-0.009,0.016l7.872,4.545c0.066,0.046,0.139,0.079,0.208,0.12l0.028,0.016l0-0.001
+ c0.502,0.29,1.078,0.469,1.7,0.469c1.887,0,3.417-1.529,3.416-3.416c0-0.09-0.02-0.175-0.026-0.263h0.026l0-23.011l30.417-30.416
+ l-0.03-0.03C89.185,25.884,90,24.185,90,22.292z M32.249,28.792h0.014l0.001,0.015L32.249,28.792z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-first-aid.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-first-aid.svg
new file mode 100644
index 0000000..60946ec
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-first-aid.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M29.365,27.367h6.146v-5.15h28.776v5.258h6.145V18.43h-0.002c-0.012-1.36-1.115-2.462-2.477-2.466v0H31.844v0
+ c-0.002,0-0.004,0-0.005,0c-1.374,0-2.487,1.115-2.487,2.488c0,0.045,0.011,0.086,0.013,0.131V27.367z"/>
+ <path d="M24.772,84.037h50.436V32.838H24.772V84.037z M34.757,54.851c0-0.408,0.361-0.768,0.768-0.768l10.235,0.001l0-10.235
+ c0-0.424,0.344-0.768,0.768-0.768h7.17c0.424,0,0.768,0.344,0.768,0.769l0,10.234l10.236,0c0.424,0,0.768,0.344,0.768,0.768l0,7.17
+ c0,0.212-0.086,0.404-0.225,0.543c-0.139,0.139-0.331,0.225-0.543,0.225l-10.236,0v10.236c0,0.204-0.081,0.399-0.224,0.542
+ c-0.144,0.144-0.34,0.226-0.544,0.226h-7.169c-0.204,0-0.399-0.081-0.543-0.225c-0.144-0.144-0.225-0.339-0.225-0.543V62.789
+ H35.525c-0.204,0-0.399-0.081-0.543-0.225c-0.144-0.144-0.225-0.339-0.225-0.543L34.757,54.851z"/>
+ <path d="M13.835,32.839c-2.207,0-3.998,1.787-3.998,3.996c0,0.053,0.013,0.102,0.016,0.154v42.94
+ c-0.001,0.035-0.01,0.067-0.01,0.102c0,2.203,1.789,3.995,3.993,3.998v0.008h5.959V32.838L13.835,32.839L13.835,32.839z"/>
+ <path d="M90.16,80.006V36.814h-0.019c-0.012-2.195-1.795-3.977-3.995-3.977h-5.959v51.199h5.943v-0.003
+ c0.012,0,0.023,0.003,0.035,0.003c2.208,0,3.998-1.789,3.998-3.998C90.163,80.028,90.16,80.017,90.16,80.006z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-flag.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-flag.svg
new file mode 100644
index 0000000..061bdcc
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-flag.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84.772,23.937c-0.21,0-0.41,0.043-0.593,0.118v-0.009c-3.37,1.756-7.191,2.764-11.253,2.764
+ c-7.52,0-14.244-3.401-18.724-8.747c-4.048-3.82-9.5-6.167-15.504-6.167c-5.782,0-11.054,2.174-15.052,5.745
+ c-0.842-1.774-2.635-3.009-4.729-3.009c-2.898,0-5.248,2.349-5.248,5.247v62.974c0,2.898,2.35,5.248,5.248,5.248
+ c2.898,0,5.248-2.35,5.248-5.248V54.497c3.302-1.668,7.031-2.614,10.984-2.614c7.53,0,14.261,3.41,18.741,8.767
+ c4.045,3.809,9.492,6.146,15.487,6.146c6.49,0,12.328-2.747,16.451-7.128c0.308-0.285,0.504-0.689,0.504-1.142V25.496
+ C86.331,24.635,85.633,23.937,84.772,23.937z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-add.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-add.svg
new file mode 100644
index 0000000..1391da8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-add.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.016,24.091H49.313c-1.979-2.37-4.013-4.865-4.541-5.624c-0.511-1.071-1.607-1.808-2.875-1.808H27.367
+ c-0.964,0-1.875,0.435-2.479,1.185l-5.021,6.247h-5.884c-3.021,0-5.484,2.46-5.484,5.484v48.284c0,3.024,2.463,5.482,5.484,5.482
+ h72.032c3.021,0,5.484-2.458,5.484-5.482V29.575C91.5,26.55,89.036,24.091,86.016,24.091z M81.543,63.286
+ c0,0.182-0.074,0.346-0.195,0.465c-0.119,0.12-0.283,0.194-0.464,0.194h-8.779v8.78c0,0.174-0.07,0.341-0.193,0.466
+ c-0.124,0.122-0.291,0.193-0.465,0.193h-6.15c-0.175,0-0.342-0.07-0.466-0.193c-0.124-0.125-0.192-0.292-0.192-0.466v-8.78h-8.78
+ c-0.174,0-0.342-0.07-0.465-0.194c-0.124-0.123-0.193-0.29-0.193-0.465v-6.149c0.001-0.351,0.309-0.659,0.658-0.659l8.779,0l0-8.78
+ c0-0.363,0.294-0.658,0.659-0.658l6.15,0.001c0.364,0,0.659,0.293,0.659,0.658v8.778h8.78c0.364,0,0.659,0.294,0.659,0.659
+ L81.543,63.286z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-lock.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-lock.svg
new file mode 100644
index 0000000..271ef81
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder-lock.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M69.499,52.139c-1.84,0-3.336,1.495-3.336,3.332v2.921h6.672v-2.921c0-0.006,0-0.013,0-0.02h-0.001
+ c0-0.004,0.001-0.007,0.001-0.011C72.817,53.617,71.328,52.139,69.499,52.139z"/>
+ <path d="M86.016,24.091H49.313c-1.979-2.37-4.013-4.865-4.54-5.624c-0.511-1.071-1.608-1.808-2.874-1.808H27.367
+ c-0.963,0-1.875,0.435-2.478,1.185l-5.021,6.247h-5.885c-3.021,0-5.484,2.46-5.484,5.484v48.284c0,3.024,2.463,5.482,5.484,5.482
+ h72.032c3.021,0,5.484-2.458,5.484-5.482V29.575C91.5,26.55,89.036,24.091,86.016,24.091z M81.543,72.488
+ c0,0.497-0.401,0.897-0.898,0.897H58.67c-0.496,0-0.897-0.4-0.897-0.897V59.289c0-0.496,0.401-0.897,0.897-0.897h1.271h1.442
+ v-2.921c0-4.473,3.64-8.114,8.115-8.114c4.476,0,8.116,3.641,8.116,8.114c0,0.011,0,0.024-0.001,0.037v2.884h1.76h1.271
+ c0.496,0,0.898,0.401,0.898,0.897V72.488z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder.svg
new file mode 100644
index 0000000..eef46f3
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-folder.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.016,24.09H49.314c-1.979-2.369-4.013-4.865-4.541-5.623c-0.511-1.071-1.607-1.808-2.875-1.808H27.367
+ c-0.964,0-1.875,0.436-2.479,1.185l-5.021,6.247h-5.884c-3.021,0-5.484,2.46-5.484,5.484v48.285c0,3.024,2.463,5.482,5.484,5.482
+ h72.032c3.021,0,5.484-2.458,5.484-5.482V29.574C91.5,26.55,89.036,24.09,86.016,24.09z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foot.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foot.svg
new file mode 100644
index 0000000..65a5299
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foot.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle cx="28.549" cy="35.885" r="4.342"/>
+ <circle cx="65.794" cy="15.531" r="8.767"/>
+ <circle cx="47.712" cy="18.329" r="5.469"/>
+ <path d="M72.903,74.043c-1.387-2.237-2.202-4.867-2.202-7.693c0-2.464,0.616-4.782,1.692-6.82l-0.034-0.051
+ c2.168-3.252,3.436-7.155,3.436-11.356c0-11.326-9.182-20.507-20.507-20.507c-11.326,0-20.507,9.181-20.507,20.507
+ c0,2.212,0.36,4.338,1.009,6.335c0.436,1.792,1.139,3.475,2.068,5.011l-0.096,0.055l14.854,25.729
+ c1.568,4.64,5.947,7.984,11.115,7.984c6.484,0,11.743-5.256,11.743-11.741c0-2.813-0.992-5.394-2.643-7.416L72.903,74.043z"/>
+ <circle cx="36.161" cy="26.693" r="4.342"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foundation.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foundation.svg
new file mode 100644
index 0000000..9926d04
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-foundation.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M78.682,76.043l-2.949-1.574c-0.217-0.116-0.484-0.035-0.598,0.181l-1.189,2.215
+ c-0.055,0.104-0.067,0.227-0.034,0.338c0.036,0.112,0.113,0.206,0.215,0.263l2.951,1.571c0.066,0.036,0.138,0.053,0.207,0.053
+ c0.159,0,0.311-0.085,0.391-0.234l1.189-2.214c0.055-0.104,0.066-0.224,0.034-0.337C78.863,76.192,78.787,76.096,78.682,76.043z"/>
+ <path fill="#231F20" d="M78.76,23.487l-2.983-1.747c-0.213-0.125-0.483-0.053-0.604,0.155l-1.277,2.167
+ c-0.061,0.101-0.077,0.22-0.049,0.334c0.031,0.115,0.105,0.213,0.206,0.271l2.983,1.745c0.07,0.041,0.147,0.06,0.224,0.06
+ c0.152,0,0.298-0.076,0.381-0.216l1.276-2.166c0.06-0.101,0.078-0.223,0.048-0.334C78.935,23.642,78.86,23.547,78.76,23.487z"/>
+ <path fill="#231F20" d="M72.785,72.897l-3.344-1.809V21.964l1.628,0.957c0.069,0.039,0.147,0.06,0.223,0.06
+ c0.151,0,0.296-0.08,0.381-0.219l1.276-2.166c0.062-0.102,0.078-0.221,0.049-0.335c-0.031-0.114-0.104-0.212-0.206-0.272
+ l-1.216-0.712l-1.373-0.945c-0.614-0.332-1.331-0.211-1.819,0.228l-12.062,6.551L44.128,18.49c-0.001-0.002-0.005,0-0.005,0
+ c-0.029-0.016-0.055-0.036-0.087-0.051c-0.136-0.062-0.288-0.059-0.434-0.089c-0.136-0.027-0.261-0.081-0.401-0.081
+ c-0.141,0-0.264,0.054-0.401,0.082c-0.143,0.029-0.295,0.025-0.426,0.088c-0.026,0.012-0.046,0.031-0.07,0.042
+ c-0.007,0.007-0.017,0.003-0.023,0.009l-12.193,6.621L17.894,18.49c-0.539-0.292-1.206-0.309-1.755-0.051
+ c-0.552,0.262-0.893,0.757-0.893,1.294v53.523c0,0.504,0.3,0.975,0.797,1.245l13.118,7.126c0.003,0.002,0.009,0.002,0.014,0.005
+ c0.03,0.015,0.054,0.03,0.083,0.045c0.254,0.12,0.541,0.181,0.829,0.181c0.287,0,0.575-0.06,0.831-0.181
+ c0.023-0.011,0.043-0.03,0.067-0.043c0.008-0.005,0.019-0.002,0.027-0.007l12.191-6.625l12.191,6.625
+ c0.004,0.002,0.011,0.002,0.017,0.005c0.026,0.015,0.05,0.03,0.079,0.045c0.256,0.12,0.544,0.181,0.831,0.181
+ c0.289,0,0.577-0.06,0.831-0.181c0.026-0.011,0.042-0.03,0.068-0.043c0.008-0.005,0.018-0.002,0.028-0.007l12.13-6.591l0.949,0.404
+ l0.85,0.452c0.067,0.037,0.139,0.051,0.208,0.051c0.158,0,0.312-0.082,0.391-0.23l1.189-2.216
+ C73.079,73.282,72.999,73.014,72.785,72.897z M30.045,78.591l-11.351-6.146V22.42l11.351,6.146V78.591z M56.281,78.519
+ l-13.078-7.086V21.439l13.078,7.119V78.519z"/>
+ <path fill="#231F20" d="M84.312,56.317h-2.521c-0.242,0-0.44,0.198-0.44,0.442v5.255c0,0.243,0.198,0.44,0.44,0.44h2.521
+ c0.244,0,0.442-0.197,0.442-0.44v-5.255C84.753,56.515,84.556,56.317,84.312,56.317z"/>
+ <path fill="#231F20" d="M84.312,77.338h-2.521c-0.079,0-0.157,0.023-0.225,0.064l-0.37,0.221c-0.068,0.043-0.125,0.101-0.162,0.17
+ l-1.189,2.217c-0.055,0.104-0.066,0.227-0.032,0.338c0.034,0.113,0.112,0.207,0.215,0.262l1.556,0.828
+ c0.416,0.223,0.883,0.346,1.313,0.346c0.898,0,1.855-0.538,1.855-2.051V77.78C84.753,77.538,84.556,77.338,84.312,77.338z"/>
+ <path fill="#231F20" d="M83.464,26.242l-1.722-1.011c-0.212-0.122-0.481-0.053-0.605,0.159l-1.276,2.164
+ c-0.06,0.1-0.078,0.222-0.047,0.334c0.027,0.114,0.102,0.213,0.204,0.271l1.333,0.778v1.541c0,0.243,0.198,0.441,0.44,0.441h2.521
+ c0.244,0,0.442-0.198,0.442-0.441v-1.877C84.753,27.031,83.519,26.275,83.464,26.242z"/>
+ <path fill="#231F20" d="M84.312,35.293h-2.521c-0.242,0-0.44,0.199-0.44,0.443v5.256c0,0.244,0.198,0.442,0.44,0.442h2.521
+ c0.244,0,0.442-0.198,0.442-0.442v-5.256C84.753,35.492,84.556,35.293,84.312,35.293z"/>
+ <path fill="#231F20" d="M84.312,66.83h-2.521c-0.242,0-0.44,0.197-0.44,0.44v5.257c0,0.244,0.198,0.442,0.44,0.442h2.521
+ c0.244,0,0.442-0.198,0.442-0.442V67.27C84.753,67.027,84.556,66.83,84.312,66.83z"/>
+ <path fill="#231F20" d="M84.312,45.805h-2.521c-0.242,0-0.44,0.198-0.44,0.442v5.255c0,0.243,0.198,0.442,0.44,0.442h2.521
+ c0.244,0,0.442-0.199,0.442-0.442v-5.255C84.753,46.004,84.556,45.805,84.312,45.805z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-bar.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-bar.svg
new file mode 100644
index 0000000..7f0226f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-bar.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M46.05,60.163H31.923c-0.836,0-1.513,0.677-1.513,1.513v21.934c0,0.836,0.677,1.513,1.513,1.513H46.05
+ c0.836,0,1.512-0.677,1.512-1.513V61.675C47.562,60.839,46.885,60.163,46.05,60.163z"/>
+ </g>
+ <g>
+ <path d="M68.077,14.878H53.95c-0.836,0-1.513,0.677-1.513,1.513v67.218c0,0.836,0.677,1.513,1.513,1.513h14.127
+ c0.836,0,1.513-0.677,1.513-1.513V16.391C69.59,15.555,68.913,14.878,68.077,14.878z"/>
+ </g>
+ <g>
+ <path d="M90.217,35.299H76.09c-0.836,0-1.513,0.677-1.513,1.513v46.797c0,0.836,0.677,1.513,1.513,1.513h14.126
+ c0.836,0,1.513-0.677,1.513-1.513V36.812C91.729,35.977,91.052,35.299,90.217,35.299z"/>
+ </g>
+ <g>
+ <path d="M23.91,35.299H9.783c-0.836,0-1.513,0.677-1.513,1.513v46.797c0,0.836,0.677,1.513,1.513,1.513H23.91
+ c0.836,0,1.513-0.677,1.513-1.513V36.812C25.423,35.977,24.746,35.299,23.91,35.299z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-horizontal.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-horizontal.svg
new file mode 100644
index 0000000..65edd64
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-horizontal.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M86.304,40.985H13.696c-0.836,0-1.513,0.677-1.513,1.513v15.127c0,0.836,0.677,1.513,1.513,1.513h72.608
+ c0.836,0,1.513-0.677,1.513-1.513V42.497C87.817,41.662,87.14,40.985,86.304,40.985z"/>
+ </g>
+ <g>
+ <path d="M56.261,17.848v-0.053H13.696c-0.836,0-1.513,0.677-1.513,1.513v15.127c0,0.836,0.677,1.513,1.513,1.513h42.565v-0.053
+ c0.652-0.169,1.135-0.755,1.135-1.459V19.307C57.396,18.603,56.913,18.017,56.261,17.848z"/>
+ </g>
+ <g>
+ <path d="M65.883,64.053H13.696c-0.836,0-1.513,0.677-1.513,1.513v15.127c0,0.836,0.677,1.513,1.513,1.513h52.187
+ c0.836,0,1.513-0.677,1.513-1.513V65.566C67.396,64.73,66.719,64.053,65.883,64.053z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-pie.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-pie.svg
new file mode 100644
index 0000000..c9484b8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-pie.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M54.193,12.87c-0.731,0-1.325,0.594-1.325,1.326c0,0.068,0.029,0.127,0.039,0.193h-0.039v31.438
+ c0,0.732,0.594,1.326,1.325,1.326H85.63v-0.039c0.066,0.01,0.125,0.039,0.194,0.039c0.731,0,1.325-0.594,1.325-1.326
+ C86.961,27.707,72.313,13.059,54.193,12.87z"/>
+ </g>
+ <g>
+ <path d="M79.485,53.46c0-0.732-0.593-1.326-1.325-1.326H49.261c-0.732,0-1.325-0.594-1.325-1.326V22.015h-0.039
+ c0.01-0.066,0.039-0.125,0.039-0.193c0-0.733-0.594-1.326-1.326-1.326c-0.032,0-0.058,0.016-0.089,0.018v-0.009
+ c-0.118-0.001-0.235-0.009-0.353-0.009c-18.4,0-33.317,14.917-33.317,33.317c0,18.4,14.917,33.317,33.317,33.317
+ s33.317-14.917,33.317-33.317c0-0.106-0.005-0.211-0.007-0.318C79.478,53.482,79.485,53.472,79.485,53.46z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-trend.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-trend.svg
new file mode 100644
index 0000000..bf75b9e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-graph-trend.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M85.088,80.271c2.715,0,4.912-2.2,4.912-4.917V24.645c0-2.717-2.197-4.917-4.912-4.917H14.912
+ c-2.714,0-4.912,2.2-4.912,4.917v50.709c0,2.717,2.197,4.917,4.912,4.917H85.088z M80.175,70.443h-60.35V29.556h60.35V70.443z"/>
+ </g>
+ <g>
+ <g>
+ <path d="M41.564,65.897c-0.927,0-1.819-0.37-2.481-1.029l-4.896-4.897l-5.96,4.932c-1.5,1.242-3.708,1.024-4.942-0.466
+ c-1.234-1.495-1.026-3.71,0.466-4.941l8.424-6.969c1.394-1.156,3.434-1.06,4.719,0.223l4.072,4.075l8.979-13.989
+ c0.69-1.07,1.874-1.688,3.181-1.602c1.272,0.082,2.4,0.846,2.945,2.002l5.299,11.206L71.602,36.45
+ c0.96-1.688,3.099-2.266,4.787-1.318c1.683,0.963,2.273,3.102,1.315,4.79L64.133,63.784c-0.646,1.135-1.901,1.82-3.183,1.769
+ c-1.31-0.046-2.481-0.821-3.041-2.008l-5.479-11.591L44.516,64.28c-0.573,0.897-1.521,1.48-2.577,1.597
+ C41.815,65.887,41.688,65.897,41.564,65.897z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-guide-dog.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-guide-dog.svg
new file mode 100644
index 0000000..c20f008
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-guide-dog.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M39.818,24.963L51.575,36.72c0.033,0.035,0.067,0.069,0.102,0.102l0.095,0.095l0.009-0.009
+ c0.35,0.285,0.791,0.464,1.279,0.464c1.123,0,2.034-0.911,2.034-2.035c0-0.733-0.391-1.37-0.973-1.728l-11.7-11.699
+ c-0.373-0.425-0.913-0.698-1.523-0.698c-1.123,0-2.034,0.911-2.034,2.034C38.864,23.971,39.246,24.604,39.818,24.963z"/>
+ <path d="M53.059,65.729V40.69h-26.9c-0.147,0-0.29,0.037-0.432,0.091L14.76,34.45l-0.009,0.015
+ c-0.354-0.183-0.749-0.296-1.175-0.296c-1.421,0-2.573,1.152-2.573,2.572c0,0.909,0.474,1.704,1.185,2.162l-0.019,0.033
+ l11.112,6.416c-0.429,1.868-0.685,4.162-0.685,6.651c0,5.261,1.133,9.669,2.664,10.936L18.996,73.79
+ c-0.464,0.595-0.751,1.333-0.751,2.146c0,1.939,1.572,3.512,3.512,3.512c1.134,0,2.132-0.547,2.774-1.382l0.06,0.035l7.327-12.691
+ L39.245,78.1l0.06-0.034c0.642,0.835,1.64,1.382,2.774,1.382c1.94,0,3.512-1.572,3.512-3.512c0-0.812-0.287-1.551-0.751-2.146
+ l-4.732-8.195c2.467,0.142,5.146,0.22,7.951,0.22C49.78,65.815,51.452,65.785,53.059,65.729z"/>
+ <path d="M70.685,63.13c1.151-0.649,2.112-3.049,2.597-6.305L57.059,40.602v22.686L50.995,73.79
+ c-0.464,0.595-0.751,1.333-0.751,2.146c0,1.939,1.572,3.512,3.512,3.512c1.134,0,2.132-0.547,2.774-1.382l0.06,0.035l7.327-12.691
+ L71.245,78.1l0.06-0.034c0.642,0.835,1.64,1.382,2.774,1.382c1.94,0,3.512-1.572,3.512-3.512c0-0.812-0.287-1.551-0.751-2.146
+ L70.685,63.13z"/>
+ <path d="M88.997,41.676c0-0.83-0.409-1.56-1.031-2.015l-3.906-3.906V31.69c0-1.528-0.879-2.837-2.151-3.49l-5.054-2.918
+ l-0.014,0.024c-0.425-0.252-0.898-0.426-1.406-0.503l-2.454-4.25l-5.098,8.83l-8.193,8.192l13.919,13.919
+ c-0.016-1.062-0.069-2.091-0.17-3.058l2.746-2.746h7.875h2v-0.027l2.174-2.174l-0.01-0.01
+ C88.698,43.023,88.997,42.386,88.997,41.676z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-hearing-aid.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-hearing-aid.svg
new file mode 100644
index 0000000..3298723
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-hearing-aid.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M47.484,28.548c-11.263,0-20.424,9.236-20.424,20.586c0,1.848,1.489,3.349,3.319,3.349c1.833,0,3.323-1.501,3.323-3.349
+ c0-7.654,6.182-13.887,13.782-13.887c7.598,0,13.777,6.232,13.777,13.887c0,1.615-0.271,3.192-0.729,4.521
+ c-0.872,1.553-2.828,4.861-4.005,6.305c-0.231,0.281-0.462,0.549-0.694,0.811c-1.647,1.898-3.704,4.261-3.559,9.344
+ c0.092,3.171,0.146,6.25-0.061,7.299l-0.062,0.355c-0.151,0.877-0.338,1.963-4.407,2.105c-0.887,0.033-1.71,0.411-2.315,1.064
+ c-0.606,0.648-0.922,1.502-0.891,2.398c0.064,1.812,1.522,3.23,3.318,3.23h0.099h0.019c6.288-0.217,9.894-2.797,10.757-7.844
+ c0.294-1.482,0.339-3.547,0.189-8.807c-0.07-2.453,0.55-3.166,1.912-4.732c0.273-0.312,0.551-0.627,0.824-0.965
+ c1.946-2.379,4.73-7.389,4.754-7.432c0.081-0.148,0.155-0.305,0.223-0.475c0.847-2.294,1.276-4.711,1.276-7.18
+ C67.907,37.784,58.745,28.548,47.484,28.548z"/>
+ <path d="M52.169,49.685c0,1.537,1.245,2.798,2.775,2.798c1.53,0,2.776-1.261,2.776-2.798c0-5.689-4.594-10.319-10.237-10.319
+ c-5.648,0-10.24,4.63-10.24,10.319c0,1.537,1.244,2.798,2.773,2.798c1.531,0,2.776-1.261,2.776-2.798
+ c0-2.604,2.103-4.721,4.69-4.721C50.066,44.964,52.169,47.081,52.169,49.685z"/>
+ <path d="M33.252,59.843L19.534,73.665c-0.583,0.586-0.902,1.361-0.902,2.193c0,0.828,0.319,1.604,0.903,2.193
+ c0.58,0.584,1.355,0.91,2.177,0.91c0.821,0,1.592-0.326,2.175-0.912l13.718-13.824c0.582-0.586,0.9-1.363,0.9-2.192
+ c0-0.833-0.318-1.604-0.899-2.188C36.439,58.663,34.411,58.665,33.252,59.843z"/>
+ <path d="M59.111,22.296c-0.017,0-0.032,0.004-0.048,0.005v-0.005h-1.294v0.029c-0.63,0.074-1.123,0.585-1.139,1.232h-0.006v2.301
+ h0.031c0.073,0.586,0.526,1.038,1.113,1.107v0.029h1.294v-0.021c0.016,0,0.032,0.005,0.048,0.005c4.775,0,8.656,3.862,8.705,8.617
+ h-0.011v1.295h0.03c0.075,0.632,0.588,1.127,1.235,1.14v0.005h2.299v-0.031c0.587-0.072,1.038-0.525,1.108-1.114h0.03v-1.295
+ h-0.005C72.453,28.257,66.466,22.296,59.111,22.296z"/>
+ <path d="M81.365,35.597c-0.049-12.23-10.012-22.164-22.254-22.164c-0.017,0-0.032,0.004-0.048,0.005v-0.005h-1.294v0.029
+ c-0.632,0.074-1.128,0.587-1.14,1.237h-0.005v2.298h0.03c0.072,0.586,0.526,1.038,1.114,1.107v0.029h1.294v-0.02
+ c0.016,0,0.032,0.005,0.048,0.005c9.661,0,17.519,7.832,17.568,17.478h-0.01v1.295h0.03c0.075,0.631,0.586,1.124,1.232,1.139v0.006
+ h2.302v-0.031c0.585-0.074,1.036-0.526,1.105-1.113h0.03v-1.295H81.365z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-heart.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-heart.svg
new file mode 100644
index 0000000..3f90c02
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-heart.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M67.607,13.462c-7.009,0-13.433,3.238-17.607,8.674c-4.174-5.437-10.598-8.674-17.61-8.674
+ c-12.266,0-22.283,10.013-22.33,22.32c-0.046,13.245,6.359,21.054,11.507,27.331l1.104,1.349
+ c6.095,7.515,24.992,21.013,25.792,21.584c0.458,0.328,1,0.492,1.538,0.492c0.539,0,1.08-0.165,1.539-0.492
+ c0.8-0.571,19.697-14.069,25.792-21.584l1.103-1.349c5.147-6.277,11.553-14.086,11.507-27.331
+ C89.894,23.475,79.876,13.462,67.607,13.462z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-home.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-home.svg
new file mode 100644
index 0000000..94b0b9b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-home.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M83.505,37.85L51.013,12.688c-0.915-0.707-2.197-0.698-3.1,0.025L16.46,37.874c-0.592,0.474-0.939,1.195-0.939,1.956v45.5
+ c0,1.385,1.121,2.505,2.505,2.505h18.697c1.382,0,2.505-1.121,2.505-2.505V57.471h21.54V85.33c0,1.385,1.123,2.505,2.505,2.505h18.7
+ c1.382,0,2.505-1.121,2.505-2.505v-45.5C84.479,39.055,84.119,38.324,83.505,37.85z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-html5.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-html5.svg
new file mode 100644
index 0000000..8ca1961
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-html5.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M20.706,16.778l5.332,59.802l23.926,6.643l23.993-6.651l5.337-59.793H20.706z M68.172,30.97l-0.334,3.718l-0.147,1.648
+ h-0.023H50h-0.025H39.624l0.67,7.511h9.68H50h15.047h1.977l-0.179,1.97l-1.724,19.311l-0.11,1.238L50,70.526v0l-0.034,0.011
+ l-15.024-4.171l-1.027-11.517h3.393h3.969l0.522,5.851l8.168,2.205l0.007-0.002v-0.001l8.181-2.208l0.851-9.512H50h-0.025H33.586
+ L31.784,30.97l-0.175-1.969h18.366H50h18.348L68.172,30.97z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-less.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-less.svg
new file mode 100644
index 0000000..f3f1ff9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-less.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.138H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.663,83.113,15.138,81.232,15.138z"/>
+ <path d="M81.232,74.905H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,76.431,83.113,74.905,81.232,74.905z"/>
+ <path d="M84.639,58.39c0-1.882-1.525-3.407-3.407-3.407h0h0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.406,3.407,3.406h38.82h0c1.881,0,3.407-1.525,3.407-3.406l0-0.001v-3.141L84.639,58.39z"/>
+ <path d="M84.639,38.577c0-1.882-1.525-3.407-3.407-3.407h0h0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.406,3.407,3.406h38.82h0c1.881,0,3.407-1.525,3.407-3.406c0,0,0-0.001,0-0.001v-3.141L84.639,38.577z"/>
+ <path d="M15.361,50.008c0,0.232,0.14,0.431,0.34,0.519l-0.006,0.011l12.376,7.146c0.103,0.101,0.243,0.164,0.398,0.164
+ c0.308,0,0.556-0.247,0.565-0.553h0.003V42.722c0-0.314-0.255-0.569-0.569-0.569c-0.159,0-0.302,0.066-0.406,0.172L15.636,49.5
+ l0.014,0.024C15.481,49.622,15.361,49.798,15.361,50.008z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-more.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-more.svg
new file mode 100644
index 0000000..83bbe80
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-indent-more.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.232,15.138H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,16.663,83.113,15.138,81.232,15.138z"/>
+ <path d="M81.232,74.905H18.769c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C84.639,76.431,83.113,74.905,81.232,74.905z"/>
+ <path d="M84.639,58.39c0-1.882-1.525-3.407-3.407-3.407h0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.406,3.407,3.406h38.82h0c1.881,0,3.407-1.525,3.407-3.406l0-0.001v-3.141L84.639,58.39z"/>
+ <path d="M84.639,38.577c0-1.882-1.525-3.407-3.407-3.407h0h-38.82c-1.882,0-3.407,1.525-3.407,3.407v3.143
+ c0,1.881,1.525,3.406,3.407,3.406h38.82h0c1.881,0,3.407-1.525,3.407-3.406c0,0,0-0.001,0-0.001v-3.141L84.639,38.577z"/>
+ <path d="M15.93,57.847c0.159,0,0.302-0.066,0.406-0.172L28.763,50.5l-0.014-0.024c0.169-0.098,0.289-0.274,0.289-0.484
+ c0-0.232-0.14-0.431-0.34-0.519l0.006-0.01l-12.376-7.146c-0.103-0.101-0.243-0.164-0.398-0.164c-0.308,0-0.556,0.247-0.565,0.553
+ h-0.003v14.573C15.361,57.593,15.616,57.847,15.93,57.847z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-info.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-info.svg
new file mode 100644
index 0000000..94ad406
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-info.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M53.826,70.86c0,0.72-0.584,1.304-1.304,1.304h-5.044
+ c-0.72,0-1.304-0.583-1.304-1.304V46.642c0-0.72,0.584-1.304,1.304-1.304h5.044c0.72,0,1.304,0.583,1.304,1.304V70.86z
+ M49.969,39.933c-2.47,0-4.518-2.048-4.518-4.579c0-2.53,2.048-4.518,4.518-4.518c2.531,0,4.579,1.987,4.579,4.518
+ C54.549,37.885,52.5,39.933,49.969,39.933z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-italic.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-italic.svg
new file mode 100644
index 0000000..5efc8d4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-italic.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M60.571,24.301c0-1.438-1.166-2.604-2.604-2.604h-4.594c-1.39,0-2.515,1.092-2.59,2.463l-0.014-0.001L39.493,75.137
+ c-0.005,0.022-0.01,0.044-0.015,0.066l-0.011,0.048l0.006,0c-0.026,0.146-0.045,0.295-0.045,0.449c0,1.371,1.062,2.482,2.406,2.584
+ v0.02h4.792c1.346,0,2.441-1.025,2.577-2.336l0.013,0.001l11.257-50.972l-0.008-0.001C60.527,24.773,60.571,24.543,60.571,24.301z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-key.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-key.svg
new file mode 100644
index 0000000..c434a69
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-key.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M93.481,44.925c-0.042-0.42-0.216-0.83-0.538-1.152c-0.372-0.371-0.858-0.557-1.344-0.557h-5.166h-2.315H52.128
+ c-2.601-9.968-11.654-17.354-22.426-17.354C16.907,25.862,6.5,36.269,6.5,49.064c0,12.798,10.407,23.202,23.202,23.202
+ c11.445,0,20.953-8.332,22.84-19.242h8.79v5.034v4.524v2.959h0.014c0.072,0.981,0.884,1.758,1.886,1.758
+ c0.026,0,0.049-0.006,0.075-0.007v0.011h6.1V67.3c1.002,0.001,1.814-0.776,1.886-1.758h0.016v-7.483h0v-5.034h4.979v15.357l0,0
+ v3.996h0.015c0.075,0.982,0.885,1.758,1.887,1.76c0.007,0,0.014-0.002,0.021-0.002h6.112c0.007,0,0.014,0.002,0.021,0.002
+ c1.001-0.002,1.812-0.778,1.887-1.76h0.015v-7.482h0V53.024h0.189h5.166v-0.002c0.486,0,0.972-0.186,1.344-0.558
+ c0.37-0.372,0.555-0.857,0.556-1.343H93.5v-6.197H93.481z M29.702,62.532c-7.338,0-13.308-5.974-13.308-13.311
+ c0-7.338,5.97-13.311,13.308-13.311c7.337,0,13.304,5.973,13.304,13.311C43.007,56.559,37.039,62.532,29.702,62.532z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-laptop.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-laptop.svg
new file mode 100644
index 0000000..62cd20b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-laptop.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M14.022,67.699h71.957c2.747,0,4.976-2.229,4.976-4.977V18.628c0-2.75-2.229-4.976-4.976-4.976H14.022
+ c-2.747,0-4.976,2.226-4.976,4.976v44.094C9.045,65.47,11.274,67.699,14.022,67.699z M18.998,23.604h62.005v34.142H18.998V23.604z"
+ />
+ <path fill="#231F20" d="M95.325,72.686H4.675c-1.267,0-2.294,1.027-2.294,2.294v5.555c0,0.58,0.218,1.135,0.609,1.559l3.25,3.518
+ c0.433,0.466,1.045,0.735,1.684,0.735h83.915c0.612,0,1.198-0.245,1.631-0.681l3.485-3.519c0.424-0.43,0.664-1.01,0.664-1.613
+ V74.98C97.619,73.714,96.591,72.686,95.325,72.686z M58.669,80.655c0,0.28-0.185,0.507-0.415,0.507H41.746
+ c-0.23,0-0.415-0.227-0.415-0.507v-2.264c0-0.28,0.185-0.504,0.415-0.504h16.508c0.23,0,0.415,0.224,0.415,0.504V80.655z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-layout.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-layout.svg
new file mode 100644
index 0000000..41be56a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-layout.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <rect x="27.725" y="30.515" fill="#231F20" width="44.55" height="23.113"/>
+ <rect x="28.793" y="58.615" fill="#231F20" width="11.074" height="10.87"/>
+ <rect x="60.915" y="58.615" fill="#231F20" width="11.074" height="10.87"/>
+ <rect x="44.854" y="58.615" fill="#231F20" width="11.074" height="10.87"/>
+ <path fill="#231F20" d="M82.69,15.588L82.69,15.588H17.311h-0.001c-2.491,0-4.512,2.02-4.512,4.512h-0.001v60.067h0.028
+ c0.14,2.366,2.085,4.246,4.485,4.246h0h0H82.69c2.401,0,4.344-1.88,4.484-4.246h0.027V20.1
+ C87.202,17.607,85.182,15.588,82.69,15.588z M77.262,74.473H22.738V25.527h54.525V74.473z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lightbulb.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lightbulb.svg
new file mode 100644
index 0000000..401f603
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lightbulb.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.302,18.915L80.302,18.915l0.042-0.042l-0.008-0.008c0.523-0.57,0.518-1.451-0.033-2.003l0,0l-2.053-2.053l0,0l0,0
+ c-0.552-0.551-1.433-0.556-2.003-0.033l-0.009-0.009l-8.842,8.843c-0.567,0.566-0.567,1.486,0,2.053h0l2.053,2.054l0.001,0
+ c0.567,0.567,1.486,0.567,2.053,0L80.302,18.915L80.302,18.915z"/>
+ <path d="M48.548,19.274v0.001h2.903v-0.001c0.782,0,1.415-0.619,1.446-1.393h0.006V5.378c0-0.802-0.65-1.452-1.452-1.452V3.924
+ h-2.903v0.001c-0.802,0-1.452,0.65-1.452,1.452v12.504h0.006C47.134,18.655,47.766,19.274,48.548,19.274z"/>
+ <path d="M91.613,39.997c0-0.783-0.619-1.415-1.393-1.446v-0.006H77.716c-0.802,0-1.452,0.649-1.452,1.452h0V42.9h0
+ c0,0.803,0.65,1.453,1.452,1.453H90.22v-0.006c0.774-0.032,1.393-0.665,1.393-1.447h0L91.613,39.997L91.613,39.997z"/>
+ <path d="M50,24.201c-11.756,0-21.285,9.529-21.285,21.285c0,4.608,1.479,8.862,3.968,12.346h-0.008
+ c3.174,4.952,5.157,11.512,5.303,18.739c0.255,0.419,0.711,0.703,1.237,0.703c0.056,0,0.109-0.01,0.163-0.017v0.017H60.55v-0.017
+ c0.054,0.006,0.107,0.017,0.162,0.017c0.575,0,1.067-0.337,1.303-0.822c0.175-7.584,2.371-14.429,5.843-19.439
+ c2.154-3.324,3.427-7.27,3.427-11.526C71.285,33.73,61.756,24.201,50,24.201z"/>
+ <path d="M60.712,89.788c-0.056,0-0.108,0.01-0.162,0.017v-0.017H39.378v0.017c-0.054-0.006-0.107-0.017-0.163-0.017
+ c-0.801,0-1.452,0.649-1.452,1.452v3.384c0,0.802,0.65,1.452,1.452,1.452c0.056,0,0.109-0.01,0.163-0.017v0.017H60.55V96.06
+ c0.054,0.006,0.107,0.016,0.162,0.016c0.802,0,1.452-0.65,1.452-1.452V91.24C62.164,90.437,61.514,89.788,60.712,89.788z"/>
+ <path d="M60.712,80.348c-0.056,0-0.108,0.01-0.162,0.017v-0.017H39.378v0.017c-0.054-0.006-0.107-0.017-0.163-0.017
+ c-0.784,0-1.42,0.624-1.447,1.403c-0.002,0.019-0.003,0.038-0.005,0.057v3.376c0,0.802,0.65,1.452,1.452,1.452
+ c0.056,0,0.109-0.01,0.163-0.017v0.017H60.55V86.62c0.054,0.006,0.107,0.017,0.162,0.017c0.802,0,1.452-0.65,1.452-1.452V81.8
+ C62.164,80.997,61.514,80.348,60.712,80.348z"/>
+ <path d="M22.344,39.685v-0.006H9.839c-0.802,0-1.452,0.65-1.452,1.451v2.904c0,0.801,0.65,1.451,1.452,1.451h12.505V45.48
+ c0.773-0.032,1.393-0.665,1.393-1.445h0V41.13h0C23.736,40.35,23.117,39.717,22.344,39.685z"/>
+ <path d="M20.199,18.415l8.842,8.843l0.009-0.009c0.569,0.523,1.45,0.519,2.002-0.033l0.001,0l2.053-2.054h0
+ c0.552-0.552,0.556-1.434,0.033-2.003l0.009-0.009l-8.843-8.842c-0.566-0.566-1.486-0.566-2.053,0l0,0l0,0l-2.053,2.053l0,0
+ C19.632,16.929,19.632,17.848,20.199,18.415z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-like.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-like.svg
new file mode 100644
index 0000000..5639e62
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-like.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.488,74.334c0-0.12-0.019-0.234-0.035-0.35V47.06h-0.001c0-0.003,0.001-0.006,0.001-0.009
+ c0-1.401-1.136-2.536-2.537-2.536c-0.047,0-0.09,0.011-0.136,0.014l-4.799,0v0.018c-1.361,0.04-2.452,1.145-2.461,2.513h-0.008
+ v27.502h0.043c0.12,1.257,1.147,2.243,2.426,2.287v0.022l4.971,0l0,0l0,0h0l0,0C81.352,76.871,82.488,75.735,82.488,74.334z"/>
+ <path d="M67.49,78.554v-8.341h0V42.061H67.49c0-0.003,0.001-0.006,0.001-0.009c0-1.401-1.136-2.536-2.537-2.536
+ c-0.046,0-0.09,0.011-0.136,0.014h-9.932c-0.15-0.244-0.334-0.453-0.536-0.637L44.47,21.778l-0.025,0.015
+ c-0.99-1.753-2.848-2.936-4.98-2.936c-3.171,0-5.742,2.608-5.742,5.825c0,0,0,0,0,0h-0.058v3.257v0.105v11.485H19.981v0.018
+ c-1.361,0.04-2.452,1.145-2.461,2.513h-0.008v28.152h0.006c0,0.323,0.124,0.646,0.368,0.894l-0.003,0.003l9.764,9.764l0.024-0.024
+ c0.281,0.231,0.626,0.318,0.967,0.272h36.103c0.073,0.006,0.143,0.022,0.217,0.022c1.355,0,2.454-1.066,2.523-2.405h0.008V78.66
+ c0-0.018,0.005-0.035,0.005-0.053S67.491,78.572,67.49,78.554z M20.505,70.212l0.042,0.047l-0.047-0.047H20.505z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-link.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-link.svg
new file mode 100644
index 0000000..b5583cd
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-link.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.663,21.338c-7.552-7.552-19.648-7.79-27.486-0.713l-0.019-0.019L41.06,30.703c-1.831,1.831-3.216,3.936-4.187,6.176
+ c-1.937,0.841-3.775,1.983-5.419,3.468l-0.019-0.019L21.338,50.425c-7.797,7.797-7.797,20.439,0,28.237
+ c7.797,7.798,20.439,7.798,28.237,0l10.098-10.098l-0.019-0.019c1.484-1.644,2.627-3.482,3.467-5.419
+ c2.24-0.971,4.345-2.356,6.176-4.187l10.098-10.098l-0.019-0.019C86.452,40.985,86.214,28.889,78.663,21.338z M42.761,71.487
+ l-0.001,0.001c-3.935,3.935-10.314,3.935-14.248,0c-3.935-3.935-3.935-10.314,0-14.248l0.001-0.001l7.367-7.367
+ c0.865,3.321,2.579,6.466,5.18,9.068c2.602,2.602,5.747,4.315,9.067,5.181L42.761,71.487z M48.234,51.766
+ c-1.796-1.796-2.763-4.102-2.919-6.452c2.35,0.156,4.655,1.123,6.452,2.919c1.796,1.796,2.764,4.102,2.919,6.452
+ C52.336,54.528,50.03,53.562,48.234,51.766z M72.109,42.139l-0.619,0.619l-0.001,0.001l-0.001,0l-7.369,7.369
+ c-0.865-3.321-2.578-6.466-5.179-9.068c-2.602-2.602-5.748-4.314-9.069-5.18l7.369-7.369c0,0,0,0,0.001-0.001l0.001-0.001
+ l0.619-0.619l0.029,0.028c3.959-3.329,9.874-3.134,13.6,0.591s3.921,9.642,0.591,13.6L72.109,42.139z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-bullet.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-bullet.svg
new file mode 100644
index 0000000..deeb774
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-bullet.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.721,20.13H26.258c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C92.128,21.655,90.602,20.13,88.721,20.13z"/>
+ <path d="M88.721,45.022H26.258c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C92.128,46.547,90.602,45.022,88.721,45.022z"/>
+ <path d="M88.721,69.913H26.258c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407V73.32C92.128,71.439,90.602,69.913,88.721,69.913z"/>
+ <circle cx="12.856" cy="25.108" r="4.984"/>
+ <circle cx="12.856" cy="49.002" r="4.984"/>
+ <circle cx="12.856" cy="74.891" r="4.984"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-number.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-number.svg
new file mode 100644
index 0000000..f81ae89
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-number.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon points="14.427,22.495 14.427,30.242 16.7,30.242 16.7,19.566 14.715,19.566 11.354,22.943 12.65,24.304 "/>
+ <path d="M12.828,46.423c0.88,0,1.729,0.448,1.729,1.393c0,1.312-1.28,2.401-5.65,5.634v1.793h8.035v-2.001h-4.354
+ c2.77-2.017,4.274-3.601,4.274-5.426c0-2.129-1.792-3.41-4.082-3.41c-1.489,0-3.073,0.544-4.114,1.745l1.296,1.505
+ C10.683,46.903,11.611,46.423,12.828,46.423z"/>
+ <path d="M14.604,74.736c1.184-0.208,2.337-1.088,2.337-2.433c0-1.776-1.537-2.897-4.034-2.897c-1.873,0-3.217,0.72-4.082,1.697
+ l1.136,1.424c0.752-0.72,1.681-1.104,2.721-1.104c1.104,0,1.985,0.416,1.985,1.264c0,0.785-0.8,1.137-1.985,1.137
+ c-0.4,0-1.137,0-1.329-0.016v2.049c0.16-0.016,0.88-0.032,1.329-0.032c1.489,0,2.145,0.384,2.145,1.233
+ c0,0.8-0.721,1.36-2.017,1.36c-1.041,0-2.209-0.448-2.929-1.216l-1.2,1.521c0.784,0.96,2.257,1.712,4.209,1.712
+ c2.561,0,4.21-1.296,4.21-3.137C17.102,75.696,15.693,74.848,14.604,74.736z"/>
+ <path d="M87.926,19.889H25.462c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C91.333,21.415,89.807,19.889,87.926,19.889z"/>
+ <path d="M87.926,44.781H25.462c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407v-3.143C91.333,46.306,89.807,44.781,87.926,44.781z"/>
+ <path d="M87.926,69.673H25.462c-1.882,0-3.407,1.525-3.407,3.407v3.143c0,1.881,1.525,3.407,3.407,3.407h62.463
+ c1.881,0,3.407-1.525,3.407-3.407V73.08C91.333,71.198,89.807,69.673,87.926,69.673z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-thumbnails.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-thumbnails.svg
new file mode 100644
index 0000000..e5ef93f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list-thumbnails.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.182,67.457L80.182,67.457l-35.4-0.001v0.001c-0.003,0-0.006-0.001-0.009-0.001c-1.253,0-2.269,1.017-2.269,2.269
+ c0,0.042,0.01,0.08,0.012,0.121V80.18h0.011c0,1.248,1.008,2.26,2.254,2.268v0.001h35.4v-0.002c1.246-0.008,2.254-1.02,2.254-2.268
+ l0-10.354c0.002-0.034,0.01-0.067,0.01-0.101C82.446,68.474,81.433,67.46,80.182,67.457z"/>
+ <path d="M30.278,67.454L30.278,67.454H19.823l0,0h-0.001c-1.253,0-2.269,1.017-2.269,2.269l0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.268,2.269h0.001l0,0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V69.723h0l0,0
+ C32.547,68.471,31.531,67.454,30.278,67.454z"/>
+ <path d="M80.182,42.467L80.182,42.467l-35.4-0.001v0.001c-0.003,0-0.006-0.001-0.009-0.001c-1.253,0-2.269,1.017-2.269,2.269
+ c0,0.042,0.01,0.08,0.012,0.121V55.19h0.011c0,1.248,1.008,2.26,2.254,2.268v0.001h35.4v-0.002c1.246-0.008,2.254-1.02,2.254-2.268
+ l0-10.354c0.002-0.034,0.01-0.067,0.01-0.101C82.446,43.484,81.433,42.47,80.182,42.467z"/>
+ <path d="M30.278,42.464L30.278,42.464H19.823v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269l0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.268,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V44.733h0l0,0
+ C32.547,43.481,31.531,42.464,30.278,42.464z"/>
+ <path d="M42.516,30.276h0.011c0,1.248,1.008,2.26,2.254,2.268v0.001h35.4v-0.002c1.246-0.008,2.254-1.02,2.254-2.268l0-10.354
+ c0.002-0.034,0.01-0.067,0.01-0.101c0-1.251-1.013-2.265-2.264-2.268v-0.001h-35.4v0.001c-0.003,0-0.006-0.001-0.009-0.001
+ c-1.253,0-2.269,1.017-2.269,2.269c0,0.042,0.01,0.08,0.012,0.121V30.276z"/>
+ <path d="M30.278,17.551L30.278,17.551H19.823v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269l0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.268,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V19.82h0l0,0
+ C32.547,18.567,31.531,17.551,30.278,17.551z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list.svg
new file mode 100644
index 0000000..c29a5dc
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-list.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M17.563,30.277h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.018,2.259-2.268h0.01
+ l0-10.459h0c-0.002-1.251-1.017-2.265-2.269-2.265l0,0H19.821v0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269
+ c0,0.039,0.01,0.076,0.012,0.115L17.563,30.277z"/>
+ <path d="M80.179,42.504L80.179,42.504H19.821v0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269c0,0.039,0.01,0.076,0.012,0.115
+ l0,10.34h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.018,2.259-2.268h0.01l0-10.459h0
+ C82.446,43.518,81.431,42.504,80.179,42.504z"/>
+ <path d="M80.179,67.454L80.179,67.454H19.821l0,0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269c0,0.039,0.01,0.076,0.012,0.115
+ l0,10.34h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.019,2.259-2.269h0.01l0-10.459h0
+ C82.446,68.468,81.431,67.454,80.179,67.454z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lock.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lock.svg
new file mode 100644
index 0000000..4d8b601
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-lock.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M82.105,44.218h-3.713h-5.145v-8.431c0.003-0.036,0.003-0.071,0.003-0.102c0-13.073-10.636-23.71-23.713-23.71
+ c-13.073,0-23.71,10.637-23.71,23.71v8.533h-4.218h-3.713c-1.449,0-2.621,1.172-2.621,2.621v38.565c0,1.448,1.172,2.621,2.621,2.621
+ h64.21c1.449,0,2.621-1.172,2.621-2.621V46.839C84.726,45.391,83.554,44.218,82.105,44.218z M39.791,35.685
+ c0-5.375,4.371-9.741,9.746-9.741c5.341,0,9.695,4.32,9.747,9.649c0,0.01-0.003,0.021-0.003,0.031h0.003c0,0.021,0,0.041,0,0.061
+ v8.533H39.791V35.685z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-loop.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-loop.svg
new file mode 100644
index 0000000..bced6ad
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-loop.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.729,23.57c-0.007-0.562-0.32-1.084-0.825-1.337c-0.503-0.259-1.107-0.212-1.568,0.114l-5.944,4.262l-0.468,0.336
+ c-6.405-6.391-15.196-10.389-24.938-10.389c-13.284,0-24.878,7.354-30.941,18.201l0.024,0.013
+ c-0.548,1.183-0.124,2.607,1.026,3.271c0.001,0,0.001,0,0.002,0.001l8.136,4.697c1.218,0.704,2.777,0.287,3.48-0.932
+ c0.006-0.011,0.009-0.023,0.015-0.034c3.591-6.404,10.438-10.747,18.289-10.747c4.879,0,9.352,1.696,12.914,4.5l-1.001,0.719
+ l-5.948,4.262c-0.455,0.327-0.696,0.89-0.611,1.447c0.081,0.558,0.471,1.028,1.008,1.208l25.447,8.669
+ c0.461,0.162,0.966,0.084,1.367-0.203c0.399-0.29,0.629-0.746,0.627-1.23L83.729,23.57z"/>
+ <path d="M79.904,61.958c0,0-0.001,0-0.002-0.001l-8.136-4.697c-1.218-0.704-2.777-0.287-3.48,0.932
+ c-0.006,0.011-0.009,0.023-0.015,0.034c-3.591,6.404-10.438,10.747-18.289,10.747c-4.879,0-9.352-1.696-12.914-4.5l1.001-0.719
+ l5.948-4.262c0.455-0.327,0.696-0.89,0.611-1.447c-0.081-0.558-0.471-1.028-1.008-1.208l-25.447-8.669
+ c-0.461-0.162-0.966-0.084-1.367,0.203c-0.399,0.29-0.629,0.746-0.627,1.23l0.092,26.828c0.007,0.562,0.32,1.084,0.825,1.337
+ c0.503,0.259,1.107,0.212,1.568-0.114l5.944-4.262l0.468-0.336c6.405,6.391,15.196,10.389,24.938,10.389
+ c13.284,0,24.878-7.354,30.941-18.201L80.93,65.23C81.478,64.046,81.055,62.623,79.904,61.958z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-magnifying-glass.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-magnifying-glass.svg
new file mode 100644
index 0000000..d4a4e3c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-magnifying-glass.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M56.774,10.391c-17.679,0-32.001,14.329-32.001,32c0,6.044,1.676,11.695,4.588,16.517L13.846,74.423l0.054,0.054
+ c-1.656,1.585-2.673,3.835-2.673,6.378c-0.001,4.913,3.913,8.755,8.821,8.754c2.507-0.001,4.749-1.004,6.349-2.636l0.039,0.039
+ l16.008-16.009c4.312,2.163,9.176,3.388,14.33,3.388c17.68,0,31.999-14.327,31.999-32C88.773,24.72,74.453,10.391,56.774,10.391z
+ M56.968,61.808c-11.05,0-20.001-8.954-20.001-20c0-11.044,8.951-20,20.001-20c11.05,0,19.999,8.955,19.999,20
+ C76.968,52.854,68.018,61.808,56.968,61.808z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mail.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mail.svg
new file mode 100644
index 0000000..da03bd7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mail.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M85.944,20.189H14.056c-1.41,0-2.556,1.147-2.556,2.557v5.144c0,0.237,0.257,0.509,0.467,0.619
+ l37.786,21.583c0.098,0.057,0.208,0.083,0.318,0.083c0.112,0,0.225-0.029,0.324-0.088L87.039,28.53
+ c0.206-0.115,0.752-0.419,0.957-0.559c0.248-0.169,0.504-0.322,0.504-0.625v-4.601C88.5,21.336,87.354,20.189,85.944,20.189z"/>
+ <path fill="#231F20" d="M88.181,35.646c-0.2-0.116-0.444-0.111-0.645,0.004L66.799,47.851c-0.166,0.096-0.281,0.266-0.309,0.458
+ c-0.025,0.191,0.035,0.386,0.164,0.527l20.74,22.357c0.123,0.133,0.291,0.204,0.467,0.204c0.079,0,0.159-0.015,0.234-0.043
+ c0.245-0.097,0.405-0.332,0.405-0.596V36.201C88.5,35.971,88.379,35.76,88.181,35.646z"/>
+ <path fill="#231F20" d="M60.823,51.948c-0.204-0.221-0.532-0.27-0.791-0.118l-8.312,4.891c-0.976,0.574-2.226,0.579-3.208,0.021
+ l-7.315-4.179c-0.242-0.137-0.547-0.104-0.751,0.086L12.668,78.415c-0.148,0.138-0.222,0.337-0.2,0.538
+ c0.022,0.201,0.139,0.381,0.314,0.482c0.432,0.254,0.849,0.375,1.273,0.375h71.153c0.255,0,0.485-0.151,0.585-0.385
+ c0.102-0.232,0.056-0.503-0.118-0.689L60.823,51.948z"/>
+ <path fill="#231F20" d="M34.334,49.601c0.15-0.137,0.225-0.339,0.203-0.54c-0.022-0.202-0.142-0.381-0.318-0.483L12.453,36.146
+ c-0.194-0.112-0.439-0.11-0.637,0.004c-0.196,0.114-0.316,0.325-0.316,0.552v32.62c0,0.253,0.15,0.483,0.382,0.584
+ c0.082,0.037,0.169,0.055,0.257,0.055c0.157,0,0.314-0.059,0.434-0.171L34.334,49.601z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-female.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-female.svg
new file mode 100644
index 0000000..d9f8eee
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-female.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <circle fill="#231F20" cx="22.336" cy="19.721" r="8.272"/>
+ <path fill="#231F20" d="M37.999,30.217v-0.04H8.363v0.027c-2.142,0-3.878,1.729-3.894,3.867H4.466v23.439h0.039
+ c-0.002,0.893,0.337,1.786,1.018,2.467c1.358,1.359,3.56,1.359,4.919,0c0.68-0.681,1.019-1.574,1.017-2.467h0.008V41.32v-0.172
+ h0.009c0.025-0.592,0.505-1.064,1.101-1.064c0.598,0,1.078,0.473,1.103,1.064h0.009v0.172v10.44v32.293
+ c0.003,2.245,1.822,4.063,4.068,4.063c2.246,0,4.068-1.821,4.068-4.068V62.444h0.03c0-0.623,0.504-1.128,1.126-1.128
+ c0.622,0,1.127,0.505,1.127,1.128h0.029v21.604c0,2.247,1.823,4.068,4.069,4.068c2.247,0,4.068-1.821,4.068-4.068V62.444V51.76
+ V41.32v-0.172c0-0.615,0.497-1.112,1.112-1.112c0.613,0,1.11,0.497,1.11,1.112v0.172v16.191h0.038
+ c-0.002,0.893,0.337,1.786,1.018,2.467c1.359,1.359,3.561,1.359,4.92,0c0.681-0.681,1.02-1.574,1.018-2.467h0.007V34.072
+ C41.499,32.057,39.962,30.418,37.999,30.217z"/>
+ </g>
+ <g>
+ <circle fill="#231F20" cx="72.297" cy="19.768" r="8.32"/>
+ <path fill="#231F20" d="M95.534,54.161l-5.55-20.712c-0.003-0.016-0.009-0.032-0.013-0.048l-0.098-0.365l-0.014,0.004
+ c-0.506-1.579-1.968-2.729-3.715-2.729c-0.014,0-0.026,0.004-0.04,0.004v-0.072h-26.12v0.068c-1.747,0-3.209,1.151-3.715,2.729
+ l-0.014-0.004L56.157,33.4c-0.004,0.017-0.01,0.033-0.013,0.05l-5.55,20.711l0.052,0.014c-0.025,0.171-0.052,0.342-0.052,0.52
+ c0,1.952,1.583,3.536,3.536,3.536c1.495,0,2.767-0.932,3.283-2.244l0.025,0.007l4.071-15.193v0.057h0.032
+ c0.111-0.5,0.536-0.882,1.07-0.882c0.534,0,0.959,0.382,1.07,0.882h0.033v0.164c0.002,0.025,0.015,0.047,0.015,0.072
+ c0,0.025-0.013,0.047-0.015,0.072v0.155l-6.518,24.326c-0.105,0.214-0.169,0.449-0.187,0.698l-0.014,0.051l0.008,0.002
+ c-0.001,0.028-0.008,0.054-0.008,0.082c0,1.048,0.85,1.897,1.898,1.897h4.82v16.08c0,2.259,1.831,4.09,4.091,4.09
+ c2.259,0,4.091-1.832,4.091-4.09l0-16.08h2.326v16.08c0,2.259,1.832,4.09,4.091,4.09c2.26,0,4.091-1.832,4.091-4.09v-16.08h4.835
+ c1.048,0,1.898-0.849,1.898-1.897c0-0.028-0.007-0.055-0.008-0.082l0.008-0.002l-0.014-0.051
+ c-0.018-0.249-0.082-0.484-0.187-0.698l-6.499-24.253l0.021-0.006c-0.027-0.096-0.06-0.191-0.06-0.296
+ c0-0.616,0.5-1.118,1.118-1.118c0.525,0,0.946,0.371,1.065,0.86l0.043-0.011l4.065,15.169l0.024-0.007
+ c0.517,1.312,1.788,2.244,3.283,2.244c1.953,0,3.536-1.584,3.536-3.536c0-0.178-0.027-0.349-0.052-0.52L95.534,54.161z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-symbol.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-symbol.svg
new file mode 100644
index 0000000..98a9b12
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male-symbol.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M83.417,18.329c0-0.002,0.001-0.003,0.001-0.005c0-0.853-0.69-1.544-1.542-1.545v-0.016H61.078v0.017
+ c-0.846,0.008-1.53,0.695-1.53,1.543v6.871h0l0,0c0,0.847,0.684,1.534,1.53,1.542v0.001h5.151l-8.713,8.713
+ c-4.202-2.875-9.284-4.56-14.761-4.56c-14.455,0-26.173,11.718-26.173,26.173s11.718,26.174,26.173,26.174
+ c14.455,0,26.173-11.719,26.173-26.174c0-5.373-1.621-10.366-4.398-14.521l8.911-8.911v5.473c0,0.853,0.691,1.544,1.544,1.544
+ h6.887c0.852,0,1.544-0.691,1.544-1.544c0-0.002-0.001-0.003-0.001-0.005V18.329z M42.755,73.262
+ c-8.946,0-16.198-7.252-16.198-16.199c0-8.946,7.252-16.199,16.198-16.199s16.199,7.253,16.199,16.199
+ C58.954,66.01,51.701,73.262,42.755,73.262z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male.svg
new file mode 100644
index 0000000..1e9ad9b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-male.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle fill="#231F20" cx="49.354" cy="19.938" r="8.272"/>
+ <path fill="#231F20" d="M65.016,30.435v-0.04H35.38v0.027c-2.142,0-3.878,1.729-3.894,3.867h-0.003v23.439h0.039
+ c-0.002,0.893,0.337,1.786,1.018,2.467c1.358,1.359,3.56,1.359,4.919,0c0.68-0.681,1.019-1.574,1.017-2.467h0.008V41.537v-0.172
+ h0.009c0.025-0.592,0.505-1.064,1.101-1.064c0.598,0,1.078,0.473,1.103,1.064h0.009v0.172v10.44v32.293
+ c0.003,2.245,1.822,4.063,4.068,4.063c2.246,0,4.068-1.821,4.068-4.068V62.661h0.03c0-0.623,0.504-1.128,1.126-1.128
+ c0.622,0,1.127,0.505,1.127,1.128h0.029v21.604c0,2.247,1.823,4.068,4.069,4.068c2.247,0,4.068-1.821,4.068-4.068V62.661V51.978
+ v-10.44v-0.172c0-0.615,0.497-1.112,1.112-1.112c0.613,0,1.11,0.497,1.11,1.112v0.172v16.191h0.038
+ c-0.002,0.893,0.337,1.786,1.018,2.467c1.359,1.359,3.561,1.359,4.92,0c0.681-0.681,1.02-1.574,1.018-2.467h0.007V34.289
+ C68.516,32.274,66.979,30.636,65.016,30.435z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-map.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-map.svg
new file mode 100644
index 0000000..412854d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-map.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M91.967,7.961c0-0.016,0.005-0.031,0.005-0.047c0-1.51-1.223-2.731-2.73-2.733v0H89.24c0,0,0,0-0.001,0s0,0-0.001,0H39.57
+ v0l0,0h-0.011v0.011L8.031,36.721H8.028l0,55.365h0.003c0,0,0,0,0,0.001c0,1.507,1.227,2.731,2.734,2.731v0h78.479v0
+ c1.307-0.002,2.397-0.923,2.663-2.15h0.06v-0.536c0-0.015,0.004-0.029,0.004-0.044s-0.004-0.029-0.004-0.044L91.967,7.961z
+ M67.639,15.138h14.371l0,24.597L63.897,21.621L67.639,15.138z M39.57,39.453v-0.001c1.504-0.006,2.722-1.226,2.722-2.73
+ c0,0,0-0.001,0-0.001h0V15.138H61.88l-27.17,47.06L17.985,45.473l0-6.02H39.57z M17.985,84.862l0-32.335L32.128,66.67
+ L21.626,84.862H17.985z M27.385,84.862l33.93-58.769l20.696,20.696l0,38.073H27.385z"/>
+ <path d="M62.03,45.576c-6.645,0-12.026,5.387-12.026,12.027c0,2.659,0.873,5.109,2.334,7.1l7.759,13.439
+ c0.047,0.094,0.097,0.186,0.157,0.271l0.016,0.027l0.004-0.002c0.394,0.544,1.028,0.899,1.764,0.899
+ c0.664,0,1.243-0.302,1.641-0.767l0.02,0.011l0.075-0.129c0.114-0.153,0.214-0.317,0.287-0.497l7.608-13.178
+ c1.494-2.004,2.39-4.482,2.39-7.175C74.056,50.963,68.675,45.576,62.03,45.576z M61.911,63.7c-3.274,0-5.926-2.651-5.926-5.925
+ s2.652-5.928,5.926-5.928c3.274,0,5.926,2.654,5.926,5.928S65.185,63.7,61.911,63.7z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-marker.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-marker.svg
new file mode 100644
index 0000000..aa426f6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-marker.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50,10.417c-15.581,0-28.201,12.627-28.201,28.201c0,6.327,2.083,12.168,5.602,16.873L45.49,86.823
+ c0.105,0.202,0.21,0.403,0.339,0.588l0.04,0.069l0.011-0.006c0.924,1.278,2.411,2.111,4.135,2.111c1.556,0,2.912-0.708,3.845-1.799
+ l0.047,0.027l0.179-0.31c0.264-0.356,0.498-0.736,0.667-1.155L72.475,55.65c3.592-4.733,5.726-10.632,5.726-17.032
+ C78.201,23.044,65.581,10.417,50,10.417z M49.721,52.915c-7.677,0-13.895-6.221-13.895-13.895c0-7.673,6.218-13.895,13.895-13.895
+ s13.895,6.222,13.895,13.895C63.616,46.693,57.398,52.915,49.721,52.915z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-megaphone.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-megaphone.svg
new file mode 100644
index 0000000..41a1de1
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-megaphone.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M27.328,28.507c-8.252,0-14.941,6.689-14.941,14.941s6.689,14.941,14.941,14.941c1.357,0,2.472-0.997,2.676-2.296h0.043
+ V31.227C30.047,29.726,28.829,28.507,27.328,28.507z"/>
+ <path d="M87.614,16.314c0-1.501-1.217-2.719-2.719-2.719c-0.623,0-1.19,0.218-1.648,0.57L59.321,27.979H37.753
+ c-1.502,0-2.719,1.217-2.719,2.719v25.809h0.034c0.167,1.341,1.298,2.383,2.685,2.383h19.138l26.16,15.103
+ c0.485,0.45,1.13,0.731,1.844,0.731c1.501,0,2.719-1.218,2.719-2.719c0-0.103-0.019-0.201-0.03-0.301h0.03v-4.604V21.074v-4.602
+ h-0.016C87.601,16.419,87.614,16.369,87.614,16.314z"/>
+ <path d="M56.212,79.572l-0.038-0.066c-0.013-0.024-0.019-0.049-0.033-0.073s-0.032-0.042-0.046-0.064L47.79,64.986l-0.031,0.018
+ c-0.454-0.624-1.13-1.006-1.857-1.096v-0.03H38.68v0.018c-0.388,0.032-0.775,0.139-1.135,0.347
+ c-1.301,0.75-1.746,2.414-0.995,3.714c0.064,0.11,0.142,0.206,0.219,0.303l-0.032,0.019l9.678,16.764
+ c0.001,0.002,0.001,0.003,0.002,0.005c0.001,0.002,0.002,0.003,0.003,0.004l0.097,0.168l0.017-0.01
+ c0.794,1.165,2.356,1.549,3.596,0.832c0.145-0.084,0.276-0.183,0.399-0.287l0.025,0.043l4.983-2.876l-0.023-0.04
+ c0.965-0.797,1.264-2.165,0.691-3.306L56.212,79.572z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-microphone.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-microphone.svg
new file mode 100644
index 0000000..9bfb8c2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-microphone.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M75.46,49.16h0.003v-0.098c0-0.006,0-0.013,0-0.019h0V34.787c0-2.088-1.693-3.781-3.782-3.781
+ c-2.088,0-3.783,1.693-3.783,3.781v14.256c0,9.885-8.013,17.897-17.898,17.897s-17.898-8.013-17.898-17.897h0V34.787
+ c0-2.088-1.693-3.781-3.782-3.781c-2.088,0-3.783,1.693-3.783,3.781V49.16h0.003c0.058,12.724,9.447,23.243,21.678,25.065v5.438
+ H32.839v0.003c-2.074,0.018-3.75,1.701-3.75,3.779c0,2.078,1.676,3.761,3.75,3.779v0.003h34.29l0,0
+ c2.089,0,3.782-1.693,3.782-3.782c0-2.089-1.693-3.782-3.782-3.782l0,0H53.782v-5.438C66.013,72.403,75.403,61.884,75.46,49.16z"/>
+ <path fill="#231F20" d="M37.186,48.941c0,7.088,5.745,12.833,12.833,12.833c7.087,0,12.831-5.746,12.831-12.833
+ c0-0.096-0.012-0.188-0.014-0.283h0.053V25.322h-0.053c-0.153-6.955-5.826-12.549-12.817-12.549
+ c-6.992,0-12.666,5.594-12.819,12.549h-0.052v23.336h0.052C37.199,48.753,37.186,48.845,37.186,48.941z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus-circle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus-circle.svg
new file mode 100644
index 0000000..34009c5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus-circle.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M67.441,44.796H32.559c-0.507,0-0.918,0.411-0.918,0.918v8.572c0,0.507,0.411,0.918,0.918,0.918h34.883
+ c0.507,0,0.918-0.411,0.918-0.918v-8.572C68.359,45.207,67.948,44.796,67.441,44.796z"/>
+ <g>
+ <path fill="#231F20" d="M50,22.44c15.196,0,27.56,12.366,27.56,27.562C77.56,65.199,65.196,77.56,50,77.56
+ S22.44,65.199,22.44,50.002C22.44,34.806,34.804,22.44,50,22.44 M50,12.5c-20.709,0-37.5,16.793-37.5,37.502
+ C12.5,70.712,29.291,87.5,50,87.5c20.709,0,37.5-16.788,37.5-37.498C87.5,29.293,70.709,12.5,50,12.5L50,12.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus.svg
new file mode 100644
index 0000000..649493e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-minus.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M88.447,38.528H11.554c-1.118,0-2.024,0.907-2.024,2.024v18.896c0,1.118,0.907,2.024,2.024,2.024h76.892
+ c1.117,0,2.023-0.907,2.023-2.024V40.552C90.47,39.435,89.564,38.528,88.447,38.528z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile-signal.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile-signal.svg
new file mode 100644
index 0000000..a512948
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile-signal.svg
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M69.328,29.884H30.567v0.01c-1.331,0.056-2.396,1.144-2.396,2.49v59.967c0,1.345,1.065,2.433,2.396,2.489
+ v0.011h38.761c1.38,0,2.5-1.119,2.5-2.5V32.384C71.828,31.003,70.709,29.884,69.328,29.884z M50.059,92.268
+ c-1.353,0-2.45-1.097-2.45-2.45c0-1.354,1.097-2.451,2.45-2.451s2.45,1.097,2.45,2.451C52.509,91.17,51.412,92.268,50.059,92.268z
+ M61.872,84.872H38.128V39.84h23.743V84.872z"/>
+ </g>
+ <g>
+ <path d="M69.603,15.696c0.428-0.55,0.426-1.303-0.006-1.85l0.024-0.024l-0.999-0.999c0,0,0,0,0,0l-0.001-0.001l-0.078-0.078
+ l-0.004,0.004C58.301,2.594,41.714,2.616,31.507,12.821c-0.015,0.015-0.019,0.036-0.034,0.051l-0.008-0.008l-0.955,0.955
+ c0,0-0.002,0.001-0.003,0.002s-0.001,0.002-0.002,0.003l-0.118,0.119l0.024,0.024c-0.464,0.588-0.449,1.427,0.08,1.979
+ l-0.004,0.004l1.918,1.918l0.026-0.026c0.55,0.428,1.303,0.427,1.85-0.006l0.025,0.024l1.079-1.078l-0.022-0.022
+ c0.015-0.015,0.036-0.019,0.051-0.034c8.053-8.052,21.135-8.074,29.221-0.075l-0.009,0.009l0.956,0.957l0,0.001l0.001,0
+ l0.12,0.121l0.024-0.024c0.589,0.464,1.427,0.449,1.979-0.079l0.004,0.004l0.021-0.021l0.001,0l0-0.001l1.768-1.768l0,0l0,0
+ l0.128-0.128L69.603,15.696z"/>
+ <path d="M62.208,21.235l0.024-0.024l-1.079-1.079l-0.004,0.004c-6.165-6.078-16.12-6.054-22.251,0.076
+ c-0.015,0.015-0.019,0.035-0.033,0.05l-0.009-0.008l-1.079,1.079l0.024,0.024c-0.465,0.589-0.45,1.427,0.079,1.979l-0.004,0.004
+ l1.918,1.918l0.026-0.026c0.55,0.428,1.303,0.427,1.85-0.006l0.025,0.025l1.079-1.078l-0.022-0.022
+ c0.015-0.015,0.036-0.019,0.051-0.034c3.977-3.977,10.425-3.995,14.436-0.072l-0.005,0.005l0.957,0.957c0,0,0,0,0,0s0,0,0.001,0
+ l0.121,0.121l0.024-0.025c0.588,0.464,1.427,0.449,1.979-0.079l0.004,0.004l0.021-0.021l0,0l0,0l1.897-1.897l-0.026-0.026
+ C62.642,22.536,62.64,21.782,62.208,21.235z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile.svg
new file mode 100644
index 0000000..359e4c3
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mobile.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M69.328,17.517H30.567v0.01c-1.331,0.056-2.396,1.144-2.396,2.49v59.967c0,1.345,1.065,2.433,2.396,2.489
+ v0.011h38.761c1.38,0,2.5-1.119,2.5-2.5V20.017C71.828,18.636,70.709,17.517,69.328,17.517z M50.059,79.9
+ c-1.353,0-2.45-1.097-2.45-2.45c0-1.354,1.097-2.451,2.45-2.451s2.45,1.097,2.45,2.451C52.509,78.803,51.412,79.9,50.059,79.9z
+ M61.872,72.505H38.128V27.473h23.743V72.505z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-monitor.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-monitor.svg
new file mode 100644
index 0000000..86efcfd
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-monitor.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M90.315,12.993H9.684c-3.119,0-5.644,2.528-5.644,5.645V67.83c0,3.118,2.526,5.645,5.644,5.645h30.359v8.556h-9.402
+ c-0.892,0-1.613,0.721-1.613,1.612v1.751c0,0.892,0.721,1.613,1.613,1.613h37.901c0.891,0,1.613-0.721,1.613-1.613v-1.751
+ c0-0.892-0.722-1.612-1.613-1.612h-8.586v-8.556h30.359c3.119,0,5.645-2.526,5.645-5.645V18.638
+ C95.96,15.521,93.434,12.993,90.315,12.993z M14.091,63.508l0-40.559l71.818,0l0,40.559L14.091,63.508z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mountains.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mountains.svg
new file mode 100644
index 0000000..4071c62
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-mountains.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M95.294,78.127l0.026-0.015L62.074,20.53l-0.014,0.008c-0.732-1.502-2.26-2.547-4.044-2.547
+ c-1.831,0-3.4,1.096-4.107,2.664L31.784,58.975l-5.417-9.382l-0.007,0.004c-0.386-0.792-1.191-1.344-2.133-1.344
+ c-0.964,0-1.791,0.578-2.164,1.402L6.271,77.009H6.2v0.122l-1.529,2.648c-0.177,0.232-0.285,0.518-0.285,0.832
+ c0,0.764,0.619,1.383,1.382,1.383c0.152,0,0.295-0.03,0.432-0.076v0.091h17h20h50v-0.05c1.349-0.108,2.413-1.224,2.413-2.601
+ C95.614,78.91,95.491,78.496,95.294,78.127z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-music.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-music.svg
new file mode 100644
index 0000000..65eda03
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-music.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84.105,13.627L84.105,13.627H32.938l0,0c-1.764,0-3.195,1.431-3.195,3.195v48.069c-1.131-0.249-2.315-0.394-3.543-0.394
+ c-7.456,0-13.5,4.896-13.5,10.938c0,6.041,6.044,10.937,13.5,10.937c7.455,0,13.5-4.896,13.5-10.937V29.257h37.644v26.401
+ c-1.131-0.249-2.315-0.394-3.543-0.394c-7.456,0-13.5,4.896-13.5,10.938s6.044,10.937,13.5,10.937c7.455,0,13.5-4.896,13.5-10.937
+ V16.823C87.3,15.058,85.87,13.628,84.105,13.627z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-next.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-next.svg
new file mode 100644
index 0000000..617c049
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-next.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.765,77.291v-54.72c0-0.002,0.001-0.003,0.001-0.005s-0.001-0.004-0.001-0.005v-0.235h-0.024
+ c-0.123-1.286-1.194-2.296-2.513-2.296c-0.03,0-0.058,0.008-0.087,0.009h-4.569c-0.071-0.006-0.14-0.021-0.213-0.021
+ c-1.4,0-2.537,1.136-2.537,2.537c0,0.117,0.019,0.23,0.035,0.343v23.141l-33.341-19.25c-0.31-0.307-0.736-0.497-1.207-0.497
+ c-0.932,0-1.686,0.743-1.713,1.669H42.59v15.249L14.148,26.788c-0.31-0.307-0.736-0.497-1.207-0.497
+ c-0.932,0-1.687,0.743-1.713,1.669h-0.005v44.031c0,0.949,0.77,1.718,1.718,1.718c0.483,0,0.918-0.2,1.23-0.521L42.59,56.78v15.212
+ c0,0.949,0.769,1.718,1.718,1.718c0.483,0,0.918-0.2,1.23-0.521l33.319-19.237v23.382h0.013c-0.002,0.039-0.012,0.075-0.012,0.114
+ c0,1.399,1.134,2.533,2.532,2.536v0h4.852v-0.024c1.401,0,2.537-1.136,2.537-2.537C88.778,77.377,88.767,77.335,88.765,77.291z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-dogs.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-dogs.svg
new file mode 100644
index 0000000..1a103f6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-dogs.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.56-12.362-27.56-27.559
+ c0-6.702,2.407-12.852,6.4-17.636l12.803,12.803h-4.834v0.009c-0.062,0.005-0.123,0.019-0.184,0.042l-6.043-3.489l-0.005,0.008
+ c-0.195-0.101-0.413-0.164-0.648-0.164c-0.782,0-1.417,0.635-1.417,1.418c0,0.5,0.261,0.939,0.652,1.191l-0.01,0.018l6.124,3.535
+ c-0.237,1.03-0.378,2.294-0.378,3.667c0,2.898,0.625,5.328,1.469,6.025l-3.454,5.98c-0.255,0.328-0.413,0.734-0.413,1.182
+ c0,1.069,0.866,1.935,1.935,1.935c0.626,0,1.176-0.302,1.529-0.762l0.032,0.018l4.037-6.992l4.037,6.992l0.032-0.019
+ c0.354,0.461,0.904,0.763,1.53,0.763c1.069,0,1.936-0.866,1.936-1.935c0-0.448-0.159-0.855-0.415-1.184l-2.609-4.518
+ c1.361,0.078,2.835,0.123,4.383,0.123c1.488,0,2.906-0.042,4.223-0.114l-2.604,4.509c-0.256,0.328-0.414,0.735-0.414,1.183
+ c0,1.069,0.866,1.935,1.935,1.935c0.626,0,1.176-0.302,1.53-0.763l0.032,0.019l3.157-5.467l4.167,4.167l0.751,1.3l0.031-0.018
+ c0.296,0.386,0.73,0.654,1.232,0.732l4.665,4.665C62.852,75.153,56.703,77.561,50,77.561z M71.161,67.635l-9.305-9.305
+ l-0.459-0.795c0.919-0.518,1.619-3.062,1.619-6.13c0-0.688-0.036-1.348-0.101-1.966l1.515-1.515h4.338h1.102v-0.015l1.198-1.196
+ l-0.006-0.005c0.262-0.251,0.427-0.602,0.427-0.993c0-0.458-0.226-0.862-0.571-1.113l-2.151-2.15v-2.24
+ c0-0.841-0.483-1.562-1.181-1.922l-2.789-1.609l-0.007,0.012c-0.038-0.023-0.078-0.044-0.118-0.064l-1.906-3.301l-3.411,5.911
+ h0.199l-5.933,5.932h-4.926l-16.33-16.33c4.782-3.993,10.931-6.4,17.634-6.4c15.198,0,27.56,12.367,27.56,27.562
+ C77.56,56.704,75.153,62.853,71.161,67.635z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-smoking.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-smoking.svg
new file mode 100644
index 0000000..b0c6afb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-no-smoking.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M65.551,45.894c-0.003,0-0.005,0.001-0.008,0.001h-0.657c-0.003,0-0.005-0.001-0.008-0.001
+ c-0.63,0-1.14,0.51-1.14,1.14h0l0.001,5.932l0,0.002l0,0.002v0.15h0.03c0.077,0.553,0.533,0.986,1.108,0.986v0h0.668v-0.001
+ c0.002,0,0.004,0.001,0.005,0.001c0.575,0,1.031-0.433,1.109-0.987h0.031v-6.086C66.69,46.403,66.18,45.894,65.551,45.894z"/>
+ <path fill="#231F20" d="M69.791,45.894c-0.003,0-0.005,0.001-0.008,0.001h-0.656c-0.003,0-0.005-0.001-0.008-0.001
+ c-0.63,0-1.14,0.51-1.14,1.14h-0.001l0.001,6.086h0.031c0.077,0.553,0.533,0.986,1.108,0.986v0h0.668v-0.001
+ c0.002,0,0.003,0.001,0.005,0.001c0.575,0,1.032-0.433,1.109-0.987h0.031v-0.152l0-5.932l0-0.002
+ C70.93,46.403,70.42,45.894,69.791,45.894z"/>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.56-12.362-27.56-27.559
+ c0-6.702,2.407-12.853,6.4-17.636l13.529,13.529h-12.15c-0.003,0-0.005-0.001-0.008-0.001c-0.63,0-1.14,0.51-1.14,1.14l0.001,0.003
+ H29.07l0,5.93h0c0,0.63,0.51,1.14,1.14,1.14h20.37l17.055,17.055C62.852,75.153,56.703,77.561,50,77.561z M71.161,67.635
+ L57.633,54.106h3.463c0.629,0,1.14-0.51,1.14-1.14l0-0.001l0-5.928l0.001-0.004c0-0.63-0.511-1.14-1.14-1.14
+ c-0.003,0-0.005,0.001-0.008,0.001H49.422L32.366,28.839c4.782-3.992,10.931-6.4,17.634-6.4c15.198,0,27.56,12.367,27.56,27.562
+ C77.56,56.704,75.153,62.853,71.161,67.635z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-add.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-add.svg
new file mode 100644
index 0000000..48c5ad3
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-add.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M73.682,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H24.814V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,20.627h0.008c0.003,0.954,0.776,1.726,1.73,1.726h6.49c0.954,0,1.727-0.772,1.729-1.726h0V37.33l0-0.001
+ c0,0,0-0.001,0-0.001l0-24.828h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H42.537v0h-1.73L14.857,32.7v2.447v1.013v52.912
+ v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005l0-8.789l0-0.001
+ C75.412,79.328,74.638,78.553,73.682,78.553z"/>
+ </g>
+ <g>
+ <path d="M83.413,53.562h-7.785v-7.785c0-0.955-0.774-1.73-1.73-1.73h-6.92c-0.956,0-1.73,0.775-1.73,1.73v7.785h-7.785
+ c-0.956,0-1.73,0.774-1.73,1.73v6.92c0,0.955,0.774,1.73,1.73,1.73h7.785v7.785c0,0.956,0.774,1.731,1.73,1.731h6.92
+ c0.956,0,1.73-0.774,1.73-1.731v-7.785h7.785c0.956,0,1.73-0.775,1.73-1.73v-6.92C85.143,54.335,84.368,53.562,83.413,53.562z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-copy.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-copy.svg
new file mode 100644
index 0000000..68dd2b5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-copy.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M75.272,7.482h-0.005v-4.02c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H42.397v0h-1.73l-25.95,25.95v2.447v1.013v52.912v2.447
+ c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L75.272,7.482z M24.674,78.276
+ V31.142h17.723c0.956,0,1.73-0.774,1.73-1.73V11.689h21.188l0,66.587H24.674z"/>
+ </g>
+ <path d="M83.77,24.857h-3.475v66.911c0,0.835-0.677,1.513-1.513,1.513H29.306v3.475c0,0.836,0.677,1.513,1.513,1.513l0.001,0v0
+ h52.95c0.836,0,1.513-0.677,1.513-1.513V26.37C85.283,25.534,84.606,24.857,83.77,24.857z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-csv.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-csv.svg
new file mode 100644
index 0000000..30223c5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-csv.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M40.416,64.173c0.831,0,1.55,0.623,1.786,1.342l2.408-1.121c-0.553-1.273-1.771-2.685-4.193-2.685
+ c-2.893,0-5.079,1.924-5.079,4.775c0,2.837,2.187,4.774,5.079,4.774c2.422,0,3.654-1.467,4.193-2.699l-2.408-1.107
+ c-0.235,0.719-0.955,1.342-1.786,1.342c-1.342,0-2.242-1.024-2.242-2.311S39.074,64.173,40.416,64.173z"/>
+ <path d="M48.605,64.492c0-0.235,0.152-0.415,0.706-0.415c0.872,0,1.91,0.304,2.712,0.913l1.495-1.979
+ c-1.052-0.858-2.408-1.287-3.917-1.287c-2.533,0-3.833,1.495-3.833,3.059c0,3.64,5.148,2.74,5.148,3.626
+ c0,0.36-0.498,0.499-1.024,0.499c-1.246,0-2.284-0.526-2.976-1.19l-1.453,2.076c0.982,0.886,2.325,1.467,4.291,1.467
+ c2.477,0,3.986-1.176,3.986-3.211C53.74,64.616,48.605,65.364,48.605,64.492z"/>
+ <polygon points="59.501,68.076 57.508,61.862 54.339,61.862 57.743,71.093 61.258,71.093 64.663,61.862 61.494,61.862 "/>
+ <path d="M80.277,12.5h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H47.402v0h-1.73L19.722,32.7v2.447v1.013v52.912v2.447
+ c0,0.956,0.774,1.73,1.73,1.73h1.582H76.96h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L80.277,12.5z M29.679,83.294V36.16
+ h17.723c0.956,0,1.73-0.774,1.73-1.73V16.707h21.188l0,66.587H29.679z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-delete.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-delete.svg
new file mode 100644
index 0000000..9be20fb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-delete.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M73.603,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H24.735V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,20.627h0.008c0.003,0.954,0.776,1.726,1.73,1.726h6.49c0.954,0,1.727-0.772,1.729-1.726h0V37.33l0-0.001
+ c0,0,0-0.001,0-0.001l0-24.828h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H42.457v0h-1.73L14.778,32.7v2.447v1.013v52.912
+ v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005l0-8.789l0-0.001
+ C75.333,79.328,74.559,78.553,73.603,78.553z"/>
+ </g>
+ <g>
+ <path d="M79.21,58.751l5.505-5.505c0.676-0.676,0.676-1.771,0-2.447l-4.894-4.893c-0.676-0.676-1.771-0.676-2.446,0l-5.505,5.505
+ l-5.505-5.505c-0.676-0.676-1.77-0.676-2.446,0L59.026,50.8c-0.676,0.676-0.676,1.771,0,2.447l5.505,5.505l-5.505,5.505
+ c-0.676,0.676-0.676,1.771,0,2.446l4.894,4.893c0.676,0.676,1.77,0.676,2.446,0l5.505-5.505l5.505,5.505
+ c0.676,0.676,1.77,0.676,2.446,0l4.894-4.893c0.676-0.676,0.676-1.771,0-2.446L79.21,58.751z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-doc.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-doc.svg
new file mode 100644
index 0000000..61aef5f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-doc.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.277,12.5h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H47.402v0h-1.73L19.722,32.7v2.447v1.013v52.912v2.447
+ c0,0.956,0.774,1.73,1.73,1.73h1.582H76.96h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L80.277,12.5z M29.679,83.294V36.16
+ h17.723c0.956,0,1.73-0.774,1.73-1.73V16.707h21.188l0,66.587H29.679z"/>
+ <path d="M38.663,61.862h-4.124v9.231h4.138c2.893,0,5.052-1.675,5.052-4.623S41.569,61.862,38.663,61.862z M38.663,68.658h-1.329
+ v-4.36h1.342c1.495,0,2.214,0.927,2.214,2.173C40.891,67.633,40.061,68.658,38.663,68.658z"/>
+ <path d="M49.958,61.71c-2.851,0-5.052,1.938-5.052,4.775c0,2.837,2.201,4.774,5.052,4.774c2.851,0,5.051-1.938,5.051-4.774
+ C55.01,63.647,52.809,61.71,49.958,61.71z M49.958,68.796c-1.343,0-2.214-1.024-2.214-2.311s0.872-2.312,2.214-2.312
+ c1.342,0,2.214,1.024,2.214,2.312S51.301,68.796,49.958,68.796z"/>
+ <path d="M61.268,64.173c0.831,0,1.55,0.623,1.786,1.342l2.408-1.121c-0.554-1.273-1.771-2.685-4.194-2.685
+ c-2.892,0-5.079,1.924-5.079,4.775c0,2.837,2.187,4.774,5.079,4.774c2.422,0,3.654-1.467,4.194-2.699l-2.408-1.107
+ c-0.235,0.719-0.955,1.342-1.786,1.342c-1.342,0-2.242-1.024-2.242-2.311S59.925,64.173,61.268,64.173z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-edit.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-edit.svg
new file mode 100644
index 0000000..7abe5ee
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-edit.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M67.041,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H18.173V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,12.34h0.016c0.047,0.913,0.796,1.641,1.721,1.641h6.49c0.925,0,1.674-0.728,1.721-1.641h0.009v-0.088
+ c0,0,0-0.001,0-0.001c0-0.001,0-0.001,0-0.002l0-16.457h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H35.895v0h-1.73
+ L8.216,32.7v2.447v1.013v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448
+ h0.005l0-8.789l0-0.001C68.771,79.328,67.997,78.553,67.041,78.553z"/>
+ </g>
+ <g>
+ <path d="M91.277,39.04L79.656,27.419c-0.676-0.676-1.771-0.676-2.447,0L45.404,59.224l0.069,0.069l-0.109-0.029l-4.351,16.237
+ l0.003,0.001c-0.199,0.601-0.066,1.287,0.412,1.765c0.528,0.528,1.309,0.638,1.948,0.341l0.002,0.006l16.08-4.309l-0.01-0.037
+ l0.023,0.024l31.806-31.806C91.953,40.811,91.953,39.716,91.277,39.04z M46.305,72.353l2.584-9.643l7.059,7.059L46.305,72.353z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-csv.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-csv.svg
new file mode 100644
index 0000000..6043333
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-csv.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.284,65.553L75.825,52.411c-0.389-0.276-0.887-0.312-1.312-0.093c-0.424,0.218-0.684,0.694-0.685,1.173l0.009,6.221
+ H57.231c-0.706,0-1.391,0.497-1.391,1.204v11.442c0,0.707,0.685,1.194,1.391,1.194h16.774v6.27c0,0.478,0.184,0.917,0.609,1.136
+ s0.853,0.182,1.242-0.097l18.432-13.228c0.335-0.239,0.477-0.626,0.477-1.038c0-0.002,0-0.002,0-0.002
+ C94.765,66.179,94.621,65.793,94.284,65.553z"/>
+ <path d="M64.06,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H15.191V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,36.356h0.011c0.021,0.937,0.784,1.691,1.726,1.691h6.49c0.943,0,1.705-0.754,1.726-1.691h0.004v-0.038
+ c0,0,0-0.001,0-0.001c0-0.001,0-0.001,0-0.002l0-40.522h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H32.914v0h-1.73
+ L5.235,32.7v2.447v1.013v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005
+ l0-8.789l0-0.001C65.79,79.328,65.015,78.553,64.06,78.553z"/>
+ <path d="M26.18,64.173c0.831,0,1.55,0.623,1.786,1.342l2.408-1.121c-0.553-1.273-1.771-2.685-4.193-2.685
+ c-2.893,0-5.079,1.924-5.079,4.775c0,2.837,2.187,4.774,5.079,4.774c2.422,0,3.654-1.467,4.193-2.699l-2.408-1.107
+ c-0.235,0.719-0.955,1.342-1.786,1.342c-1.342,0-2.242-1.024-2.242-2.311S24.837,64.173,26.18,64.173z"/>
+ <path d="M35.656,68.907c-1.246,0-2.284-0.526-2.976-1.19l-1.453,2.076c0.982,0.886,2.325,1.467,4.291,1.467
+ c2.477,0,3.986-1.176,3.986-3.211c0-3.432-5.135-2.685-5.135-3.557c0-0.235,0.152-0.415,0.706-0.415
+ c0.872,0,1.91,0.304,2.712,0.913l1.495-1.979c-1.052-0.858-2.408-1.287-3.917-1.287c-2.533,0-3.833,1.495-3.833,3.059
+ c0,3.64,5.148,2.74,5.148,3.626C36.68,68.768,36.182,68.907,35.656,68.907z"/>
+ <polygon points="43.271,61.862 40.102,61.862 43.506,71.093 47.022,71.093 50.426,61.862 47.257,61.862 45.264,68.076 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-doc.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-doc.svg
new file mode 100644
index 0000000..8fd76c8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-doc.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.284,65.553L75.825,52.411c-0.389-0.276-0.887-0.312-1.312-0.093c-0.424,0.218-0.684,0.694-0.685,1.173l0.009,6.221
+ H57.231c-0.706,0-1.391,0.497-1.391,1.204v11.442c0,0.707,0.685,1.194,1.391,1.194h16.774v6.27c0,0.478,0.184,0.917,0.609,1.136
+ c0.425,0.219,0.853,0.182,1.242-0.097l18.432-13.228c0.335-0.239,0.477-0.626,0.477-1.038c0-0.002,0-0.002,0-0.002
+ C94.765,66.179,94.621,65.793,94.284,65.553z"/>
+ <path d="M64.06,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H15.191V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,36.356h0.011c0.021,0.937,0.784,1.691,1.726,1.691h6.49c0.943,0,1.705-0.754,1.726-1.691h0.004v-0.038
+ c0,0,0-0.001,0-0.001c0-0.001,0-0.001,0-0.002l0-40.522h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H32.914v0h-1.73
+ L5.235,32.7v2.447v1.013v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005
+ l0-8.789l0-0.001C65.79,79.328,65.015,78.553,64.06,78.553z"/>
+ <path d="M20.364,61.862v9.231h4.138c2.893,0,5.052-1.675,5.052-4.623s-2.159-4.608-5.065-4.608H20.364z M26.716,66.471
+ c0,1.163-0.83,2.187-2.228,2.187H23.16v-4.36h1.342C25.997,64.298,26.716,65.225,26.716,66.471z"/>
+ <path d="M30.733,66.485c0,2.837,2.201,4.774,5.052,4.774c2.851,0,5.051-1.938,5.051-4.774c0-2.837-2.201-4.775-5.051-4.775
+ C32.933,61.71,30.733,63.647,30.733,66.485z M37.999,66.485c0,1.287-0.872,2.311-2.214,2.311c-1.343,0-2.214-1.024-2.214-2.311
+ s0.872-2.312,2.214-2.312C37.127,64.173,37.999,65.198,37.999,66.485z"/>
+ <path d="M47.093,64.173c0.831,0,1.55,0.623,1.786,1.342l2.408-1.121c-0.554-1.273-1.771-2.685-4.194-2.685
+ c-2.892,0-5.079,1.924-5.079,4.775c0,2.837,2.187,4.774,5.079,4.774c2.422,0,3.654-1.467,4.194-2.699l-2.408-1.107
+ c-0.235,0.719-0.955,1.342-1.786,1.342c-1.342,0-2.242-1.024-2.242-2.311S45.751,64.173,47.093,64.173z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-pdf.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-pdf.svg
new file mode 100644
index 0000000..5e3a745
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export-pdf.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.284,65.553L75.825,52.411c-0.389-0.276-0.887-0.312-1.312-0.093c-0.424,0.218-0.684,0.694-0.685,1.173l0.009,6.221
+ H57.231c-0.706,0-1.391,0.497-1.391,1.204v11.442c0,0.707,0.685,1.194,1.391,1.194h16.774v6.27c0,0.478,0.184,0.917,0.609,1.136
+ s0.853,0.182,1.242-0.097l18.432-13.228c0.335-0.239,0.477-0.626,0.477-1.038c0-0.002,0-0.002,0-0.002
+ C94.765,66.179,94.621,65.793,94.284,65.553z"/>
+ <path d="M64.06,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H15.191V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,36.356h0.011c0.021,0.937,0.784,1.691,1.726,1.691h6.49c0.943,0,1.705-0.754,1.726-1.691h0.004v-0.038
+ c0,0,0-0.001,0-0.001c0-0.001,0-0.001,0-0.002l0-40.522h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H32.914v0h-1.73
+ L5.235,32.7v2.447v1.013v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005
+ l0-8.789l0-0.001C65.79,79.328,65.015,78.553,64.06,78.553z"/>
+ <path d="M21.525,61.862v9.231h2.795v-2.906h2.131c2.159,0,3.321-1.439,3.321-3.156c0-1.73-1.162-3.169-3.321-3.169H21.525z
+ M26.936,65.031c0,0.484-0.374,0.72-0.844,0.72H24.32v-1.453h1.771C26.562,64.298,26.936,64.533,26.936,65.031z"/>
+ <path d="M31.228,61.862v9.231h4.138c2.893,0,5.052-1.675,5.052-4.623s-2.159-4.608-5.065-4.608H31.228z M37.58,66.471
+ c0,1.163-0.83,2.187-2.228,2.187h-1.329v-4.36h1.342C36.86,64.298,37.58,65.225,37.58,66.471z"/>
+ <polygon points="49.116,64.298 49.116,61.862 42.113,61.862 42.113,71.093 44.908,71.093 44.908,67.647 49.018,67.647
+ 49.018,65.211 44.908,65.211 44.908,64.298 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export.svg
new file mode 100644
index 0000000..c2e3f7c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-export.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.284,65.553L75.825,52.411c-0.389-0.276-0.887-0.312-1.312-0.093c-0.424,0.218-0.684,0.694-0.685,1.173l0.009,6.221
+ H57.231c-0.706,0-1.391,0.497-1.391,1.204v11.442c0,0.707,0.685,1.194,1.391,1.194h16.774v6.27c0,0.478,0.184,0.917,0.609,1.136
+ c0.425,0.219,0.853,0.182,1.242-0.096l18.432-13.228c0.335-0.239,0.477-0.626,0.477-1.038c0-0.002,0-0.002,0-0.002
+ C94.765,66.179,94.621,65.793,94.284,65.553z"/>
+ <path d="M64.06,78.553h-6.49h0c-0.956,0-1.73,0.774-1.73,1.73h-0.007v3.01H15.191V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707h21.188l0,36.356h0.011c0.021,0.937,0.784,1.691,1.726,1.691h6.49c0.943,0,1.705-0.754,1.726-1.691h0.004v-0.038
+ c0,0,0-0.001,0-0.001l0-0.001l0-40.522h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H32.914v0h-1.73L5.235,32.7v2.447v1.013
+ v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005l0-8.789l0-0.001
+ C65.79,79.328,65.015,78.553,64.06,78.553z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-filled.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-filled.svg
new file mode 100644
index 0000000..40df8fb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-filled.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M21.455,36.16h25.95c0.956,0,1.729-0.774,1.729-1.73V8.48c0-0.956-0.774-1.73-1.729-1.73h-1.73L19.725,32.7v1.729
+ C19.725,35.386,20.499,36.16,21.455,36.16z"/>
+ <path d="M78.545,6.75H60.821c-0.806,0-1.476,0.553-1.669,1.298h-0.061v36.551h-0.002c0,0.008,0.002,0.015,0.002,0.023
+ c0,0.956-0.774,1.73-1.73,1.73c-0.003,0-0.006-0.001-0.009-0.001v0.001H21.455c-0.873,0-1.586,0.647-1.706,1.487h-0.024V91.52
+ c0,0.956,0.774,1.73,1.73,1.73h57.09c0.956,0,1.73-0.774,1.73-1.73V8.48C80.275,7.524,79.501,6.75,78.545,6.75z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-multiple.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-multiple.svg
new file mode 100644
index 0000000..b8f7376
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-multiple.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.45,23.27h-3.475V90.18c0,0.835-0.677,1.513-1.513,1.513H31.987v3.475c0,0.836,0.677,1.513,1.513,1.513l0.001,0v0h52.95
+ c0.836,0,1.513-0.677,1.513-1.513V24.782C87.963,23.946,87.286,23.27,86.45,23.27z"/>
+ <path d="M77.988,85.193V14.807c0-0.836-0.677-1.513-1.513-1.513h-3.475v66.911c0,0.836-0.677,1.513-1.513,1.513H22.011v3.475
+ c0,0.836,0.677,1.513,1.513,1.513c0,0,0,0,0,0h52.951C77.311,86.706,77.988,86.029,77.988,85.193z"/>
+ <path d="M68.013,75.218V4.832c0-0.836-0.677-1.513-1.513-1.513H13.55c-0.836,0-1.513,0.677-1.513,1.513v70.386
+ c0,0.836,0.677,1.513,1.513,1.513H66.5C67.336,76.731,68.013,76.054,68.013,75.218z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-pdf.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-pdf.svg
new file mode 100644
index 0000000..39b0c6d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-pdf.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M41.131,61.862h-4.927v9.231H39v-2.906h2.131c2.159,0,3.321-1.439,3.321-3.156C44.453,63.301,43.29,61.862,41.131,61.862z
+ M40.771,65.751H39v-1.453h1.771c0.471,0,0.844,0.235,0.844,0.733C41.616,65.516,41.242,65.751,40.771,65.751z"/>
+ <path d="M50.032,61.862h-4.124v9.231h4.138c2.893,0,5.052-1.675,5.052-4.623S52.938,61.862,50.032,61.862z M50.032,68.658h-1.329
+ v-4.36h1.342c1.495,0,2.214,0.927,2.214,2.173C52.26,67.633,51.43,68.658,50.032,68.658z"/>
+ <polygon points="56.792,71.093 59.588,71.093 59.588,67.647 63.698,67.647 63.698,65.211 59.588,65.211 59.588,64.298
+ 63.795,64.298 63.795,61.862 56.792,61.862 "/>
+ <path d="M80.277,12.5h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H47.402v0h-1.73L19.722,32.7v2.447v1.013v52.912v2.447
+ c0,0.956,0.774,1.73,1.73,1.73h1.582H76.96h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L80.277,12.5z M29.679,83.294V36.16
+ h17.723c0.956,0,1.73-0.774,1.73-1.73V16.707h21.188l0,66.587H29.679z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-remove.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-remove.svg
new file mode 100644
index 0000000..7bcfc7d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-remove.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M75.412,70.658v-0.033h-0.003c-0.018-0.939-0.783-1.696-1.727-1.696h-6.49h0c-0.944,0-1.708,0.757-1.727,1.696h-0.01
+ v12.668H24.814V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73V16.707h21.188l0,30.2h0.013c0.034,0.926,0.789,1.668,1.724,1.668h6.49
+ c0.935,0,1.69-0.742,1.724-1.668h0.006v-0.061l0-0.001l0-0.001l0-34.343h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H42.537
+ v0h-1.73L14.857,32.7v2.447v1.013v52.912v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73
+ v-2.448h0.005l0-18.413V70.658L75.412,70.658z"/>
+ </g>
+ <g>
+ <path d="M83.413,53.562h-25.95c-0.956,0-1.73,0.774-1.73,1.73v6.92c0,0.955,0.774,1.73,1.73,1.73h25.95
+ c0.956,0,1.73-0.775,1.73-1.73v-6.92C85.143,54.335,84.368,53.562,83.413,53.562z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-search.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-search.svg
new file mode 100644
index 0000000..757ed6f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page-search.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M89.307,12.5h-0.005V8.48c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H56.431v0h-1.73L28.752,32.7v2.447v1.013v1.777h0.014
+ c0.073,0.888,0.809,1.588,1.716,1.588h6.49h0c0.907,0,1.642-0.7,1.716-1.588h0.021V36.16h17.723c0.956,0,1.73-0.774,1.73-1.73
+ V16.707H79.35l0,66.587H38.708v-3.012h-0.007c-0.001-0.954-0.775-1.728-1.73-1.728h-6.49h0c-0.955,0-1.729,0.773-1.73,1.728h0
+ v8.792v2.447c0,0.956,0.774,1.73,1.73,1.73h1.582h53.925h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L89.307,12.5z"/>
+ <path d="M49.6,59.04c0-8.847-7.169-16.021-16.02-16.021c-8.851,0-16.02,7.174-16.02,16.021c0,2.99,0.834,5.78,2.26,8.175
+ l-7.815,7.815l0.031,0.031c-0.831,0.795-1.344,1.919-1.344,3.194c0,2.463,1.962,4.39,4.423,4.39c1.257,0,2.379-0.506,3.181-1.324
+ l0.022,0.022l8.024-8.024c2.176,1.105,4.63,1.741,7.238,1.741C42.431,75.059,49.6,67.887,49.6,59.04z M24.282,59.039
+ c0-5.135,4.162-9.298,9.299-9.298c5.137,0,9.298,4.163,9.298,9.298c0,5.136-4.161,9.299-9.298,9.299
+ C28.443,68.338,24.282,64.175,24.282,59.039z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page.svg
new file mode 100644
index 0000000..f9057e9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-page.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.277,12.498h-0.005v-4.02c0-0.956-0.774-1.73-1.73-1.73h-2.45v0H47.402v0h-1.73l-25.95,25.95v2.447v1.013v52.912v2.447
+ c0,0.956,0.774,1.73,1.73,1.73h1.582H76.96h1.582c0.956,0,1.73-0.774,1.73-1.73v-2.448h0.005L80.277,12.498z M29.679,83.292V36.158
+ h17.723c0.956,0,1.73-0.774,1.73-1.73V16.705h21.188l0,66.587H29.679z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paint-bucket.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paint-bucket.svg
new file mode 100644
index 0000000..3d8be65
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paint-bucket.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M83.095,47.878c-0.001-0.001-0.003-0.002-0.004-0.003l-32.088-32.09l-0.001,0l0,0c-0.984-0.984-2.578-0.984-3.562,0
+ l-5.26,5.26L30.934,9.799c-0.903-0.943-2.166-1.535-3.571-1.534c-2.743-0.001-4.966,2.231-4.964,4.986
+ c0,1.426,0.603,2.703,1.558,3.612l11.203,11.205L7.883,55.344c0,0,0,0,0,0c-0.984,0.983-0.984,2.578,0,3.562l32.091,32.092
+ c0.984,0.984,2.579,0.984,3.562,0l0.001-0.001L83.095,51.44C84.078,50.456,84.078,48.861,83.095,47.878z M63.391,57.106H20.233
+ l29.003-29.004l21.579,21.58L63.391,57.106z"/>
+ <path d="M91.073,73.735l-5.97-10.339c-0.031-0.058-0.061-0.117-0.098-0.171L84.99,63.2l-0.004,0.002
+ c-0.302-0.418-0.788-0.69-1.351-0.69c-0.508,0-0.952,0.231-1.256,0.588l-0.016-0.009l-0.059,0.103
+ c-0.086,0.116-0.162,0.239-0.217,0.375l-5.835,10.105c-1.144,1.535-1.829,3.432-1.829,5.493c0,5.09,4.124,9.217,9.216,9.217
+ c5.093,0,9.217-4.127,9.217-9.217C92.856,77.133,92.189,75.26,91.073,73.735z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paperclip.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paperclip.svg
new file mode 100644
index 0000000..c26d168
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paperclip.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M30.267,88.384c-2.726,0-6.235-0.922-9.739-4.426c-4.621-4.621-5.203-9.081-4.878-12.013
+ c0.381-3.436,2.14-6.747,5.225-9.833L50.287,32.7c8.215-8.212,13.68-5.208,16.206-2.684c3.056,3.057,5.06,8.338-2.747,16.143
+ L36.668,73.237l-5.271-5.271l27.078-27.078c4.172-4.174,3.211-5.135,2.745-5.601c-0.369-0.369-1.49-1.485-5.662,2.684
+ L26.146,67.383c-1.279,1.281-2.852,3.252-3.087,5.387c-0.213,1.922,0.682,3.859,2.743,5.916c2.555,2.558,4.487,2.286,5.125,2.194
+ c1.74-0.243,3.725-1.442,5.739-3.456c2.495-2.489,32.596-32.591,34.901-34.901c2.849-2.849,4.66-5.62,5.383-8.236
+ c1.048-3.786-0.206-7.387-3.83-11.013c-3.825-3.825-9.986-7.829-19.308,1.495L21.601,56.982c-1.456,1.456-3.815,1.456-5.271,0
+ c-1.457-1.456-1.457-3.815,0-5.271l32.213-32.212c9.957-9.96,20.836-10.508,29.849-1.495c6.989,6.989,6.981,13.789,5.747,18.269
+ c-1.087,3.931-3.473,7.697-7.297,11.522c-2.308,2.31-32.414,32.416-34.904,34.902c-3.208,3.213-6.564,5.086-9.967,5.567
+ C31.448,88.341,30.876,88.384,30.267,88.384z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pause.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pause.svg
new file mode 100644
index 0000000..b708cba
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pause.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M40.531,19.959c-0.097,0-0.19,0.016-0.283,0.029v-0.029H29.912h-0.001c-1.194,0-2.163,0.968-2.163,2.163
+ c0,0.002,0,0.003,0,0.005h-0.001V77.87h0.001c0,0.003-0.001,0.006-0.001,0.009c0,1.194,0.969,2.162,2.163,2.162h0h0H40.53h0
+ c1.194,0,2.162-0.968,2.162-2.162c0-0.003-0.001-0.006-0.001-0.009h0.001V22.127h0c0-0.002,0.001-0.004,0.001-0.005
+ C42.693,20.927,41.724,19.959,40.531,19.959z"/>
+ <path d="M72.251,77.87V22.127h0c0-0.002,0.001-0.004,0.001-0.005c0-1.195-0.969-2.163-2.162-2.163c-0.097,0-0.19,0.016-0.283,0.029
+ v-0.029H59.47H59.47c-1.194,0-2.163,0.968-2.163,2.163c0,0.002,0,0.003,0,0.005h-0.001V77.87h0.001
+ c0,0.003-0.001,0.006-0.001,0.009c0,1.194,0.969,2.162,2.163,2.162h0h0h10.618h0c1.194,0,2.162-0.968,2.162-2.162
+ C72.251,77.876,72.25,77.873,72.251,77.87L72.251,77.87z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paw.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paw.svg
new file mode 100644
index 0000000..3e67ab6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paw.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M34.848,40.708c0-5.6-4.542-10.141-10.143-10.141c-5.601,0-10.141,4.541-10.141,10.141c0,5.604,4.539,10.143,10.141,10.143
+ C30.307,50.851,34.848,46.312,34.848,40.708z"/>
+ <path d="M75.293,32.548c-5.6,0-10.141,4.541-10.141,10.141c0,5.604,4.541,10.141,10.141,10.141c5.601,0,10.142-4.537,10.142-10.141
+ C85.435,37.089,80.895,32.548,75.293,32.548z"/>
+ <path d="M66.082,53.978c-0.705-0.869-1.703-1.875-2.849-2.93c-3.058-3.963-7.841-6.527-13.233-6.527
+ c-4.799,0-9.113,2.032-12.162,5.27c-1.732,1.507-3.272,2.978-4.252,4.188l-0.656,0.801c-3.06,3.731-6.869,8.373-6.841,16.25
+ c0.027,7.315,5.984,13.27,13.278,13.27c4.166,0,7.984-1.926,10.467-5.159c2.481,3.233,6.3,5.159,10.47,5.159
+ c7.291,0,13.247-5.954,13.275-13.27c0.028-7.877-3.782-12.519-6.841-16.25L66.082,53.978z"/>
+ <circle cx="50.703" cy="26.877" r="11.175"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paypal.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paypal.svg
new file mode 100644
index 0000000..6db35ce
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-paypal.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M33.469,70.372l2.732-11.775c0.365-1.647,2.06-3.01,3.779-3.01h2.267c9.698-0.01,17.22-1.993,22.626-5.965
+ c5.398-3.963,8.098-9.217,8.085-15.714c0.013-2.854-0.481-5.241-1.512-7.148c-0.985-1.923-2.463-3.484-4.349-4.663
+ c-1.956-1.207-4.231-2.039-6.883-2.54c-2.668-0.479-5.784-0.714-9.359-0.746l-16.554,0.013c-1.72,0.02-3.406,1.369-3.803,3.022
+ L19.335,70.372c-0.384,1.66,0.69,3.032,2.404,3.032h7.931C31.384,73.404,33.083,72.068,33.469,70.372z M39.955,42.211l2.387-10.287
+ c0.364-1.657,2.073-3.031,3.787-3.016l2.595-0.016c3.031,0,5.335,0.519,6.89,1.551c1.532,1.004,2.311,2.589,2.284,4.722
+ c0.045,3.211-1.172,5.696-3.575,7.45c-2.391,1.748-5.705,2.624-10.006,2.624h-1.944C40.659,45.239,39.577,43.88,39.955,42.211z"/>
+ <path d="M79.23,34.544c-0.986-1.923-2.463-3.484-4.349-4.663c-0.142-0.087-0.289-0.168-0.434-0.252
+ c0.055,0.101,0.115,0.198,0.167,0.301c1.031,1.906,1.525,4.295,1.512,7.148c0.013,6.497-2.687,11.751-8.085,15.714
+ c-5.406,3.971-12.928,5.955-22.627,5.964H43.15c-1.719,0-3.414,1.363-3.779,3.01l-2.732,11.776
+ c-0.385,1.696-2.084,3.032-3.799,3.032h-5.356l-0.364,1.582c-0.384,1.66,0.691,3.033,2.404,3.033h7.93
+ c1.715,0,3.414-1.337,3.799-3.033l2.733-11.775c0.365-1.646,2.06-3.01,3.779-3.01h2.267c9.698-0.01,17.22-1.993,22.626-5.965
+ c5.398-3.963,8.098-9.217,8.084-15.713C80.756,38.84,80.261,36.451,79.23,34.544z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pencil.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pencil.svg
new file mode 100644
index 0000000..93fc87a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pencil.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.79,29.297L70.702,11.209c-1.052-1.052-2.756-1.052-3.808,0L17.389,60.713l0.109,0.109l-0.171-0.046l-6.772,25.272
+ l0.004,0.001c-0.309,0.935-0.103,2.004,0.642,2.748c0.822,0.822,2.038,0.993,3.033,0.531l0.002,0.009l25.027-6.706l-0.016-0.059
+ l0.038,0.038L88.79,33.105C89.842,32.053,89.842,30.349,88.79,29.297z M18.792,81.147l4.022-15.009l10.988,10.988L18.792,81.147z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-photo.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-photo.svg
new file mode 100644
index 0000000..9c4db2f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-photo.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M93.194,18c0-2.47-2.002-4.472-4.472-4.472c-0.228,0-0.447,0.034-0.667,0.067V13.5H11.25v0.028
+ c-2.47,0-4.472,2.002-4.472,4.472l0,0.001v63.998l0,0.001l0,0.001V82.5h0.05c0.252,2.231,2.123,3.972,4.421,3.972V86.5h76.805
+ v-0.095c0.219,0.033,0.438,0.067,0.667,0.067c2.299,0,4.17-1.74,4.422-3.972h0.078V18H93.194z M83.265,76.543H72.404
+ c-0.038-0.155-0.092-0.304-0.166-0.442l0.018-0.01l-22.719-39.35l-0.009,0.005c-0.5-1.027-1.544-1.74-2.764-1.74
+ c-1.251,0-2.324,0.749-2.807,1.821L28.838,63.013l-3.702-6.411l-0.005,0.003c-0.264-0.542-0.814-0.918-1.457-0.918
+ c-0.659,0-1.224,0.395-1.479,0.958l-5.46,9.457V23.485h66.53V76.543z"/>
+ <circle fill="#231F20" cx="68.122" cy="38.584" r="10.1"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-circle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-circle.svg
new file mode 100644
index 0000000..7cbe765
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-circle.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5c20.712,0,37.5-16.788,37.5-37.498
+ C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.56-12.362-27.56-27.559c0-15.195,12.362-27.562,27.56-27.562
+ c15.198,0,27.56,12.367,27.56,27.562C77.56,65.198,65.198,77.561,50,77.561z"/>
+ <path d="M66.352,49.097l0.006-0.01L42.991,35.596l-0.006,0.01c-0.156-0.091-0.328-0.157-0.521-0.157
+ c-0.585,0-1.059,0.475-1.059,1.06c0,0.043,0.019,0.079,0.024,0.12h-0.024V63.61h0.024c0.062,0.526,0.493,0.94,1.035,0.94
+ c0.194,0,0.365-0.066,0.521-0.157l0.016,0.027L66.368,50.93l-0.016-0.027c0.316-0.183,0.538-0.511,0.538-0.903
+ C66.89,49.608,66.668,49.281,66.352,49.097z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-video.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-video.svg
new file mode 100644
index 0000000..e0f3182
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play-video.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M85.527,80.647c2.748,0,4.973-2.225,4.973-4.974V24.327c0-2.749-2.225-4.974-4.973-4.974H14.474
+ c-2.748,0-4.974,2.225-4.974,4.974v51.346c0,2.749,2.225,4.974,4.974,4.974H85.527z M80.553,70.699H19.446V29.301h61.107V70.699z"
+ />
+ </g>
+ <g>
+ <g>
+ <polygon points="64.819,50.288 52.839,57.201 40.865,64.118 40.865,50.288 40.865,36.462 52.839,43.38 "/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play.svg
new file mode 100644
index 0000000..a93c158
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-play.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M76.982,50c0-0.847-0.474-1.575-1.167-1.957L26.541,19.595c-0.363-0.253-0.803-0.404-1.279-0.404
+ c-1.239,0-2.244,1.004-2.244,2.243c0,0.087,0.016,0.169,0.026,0.253h-0.026v57.131h0.026c0.127,1.119,1.066,1.99,2.218,1.99
+ c0.409,0,0.787-0.117,1.117-0.308l0.02,0.035L75.875,51.97l-0.02-0.035C76.526,51.547,76.982,50.83,76.982,50z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-plus.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-plus.svg
new file mode 100644
index 0000000..c4f32c8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-plus.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M84.437,39.721l-24.164,0l0-24.158c0-1.001-0.812-1.812-1.812-1.813L41.536,13.75c-1.001,0-1.812,0.812-1.812,1.813
+ l-0.001,24.16l-24.159-0.001c-0.961,0-1.812,0.851-1.813,1.813l0,16.925c-0.001,0.481,0.191,0.943,0.531,1.282
+ c0.339,0.339,0.801,0.531,1.282,0.53h24.16v24.165c0,0.48,0.191,0.942,0.531,1.282c0.34,0.34,0.802,0.531,1.282,0.531L58.46,86.25
+ c0.48,0,0.943-0.192,1.284-0.533c0.338-0.338,0.529-0.8,0.529-1.28V60.273l24.163-0.001c0.5,0,0.953-0.202,1.282-0.53
+ c0.329-0.329,0.531-0.782,0.531-1.283l0.001-16.925C86.25,40.533,85.439,39.722,84.437,39.721z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pound.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pound.svg
new file mode 100644
index 0000000..0c1685c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pound.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M71.586,72.845c0-0.205-0.068-0.388-0.162-0.555l0.016-0.003l-2.974-7.289c-0.002-0.005-0.004-0.009-0.006-0.014
+ l-0.005-0.013l-0.002,0.002c-0.18-0.403-0.581-0.687-1.051-0.687c-0.334,0-0.63,0.147-0.84,0.375l-0.005-0.01
+ c-1.046,1.448-3.461,2.897-6.922,2.897c-3.944,0-5.795-2.656-10.464-2.656c-1.207,0-2.736,0.241-3.944,0.644
+ c2.897-1.771,5.232-5.151,5.232-8.934c0-0.483-0.081-1.047-0.081-1.529h9.015v-0.007c0.635-0.002,1.15-0.517,1.15-1.153h0V49.6
+ H60.52c-0.058-0.582-0.531-1.041-1.128-1.043v-0.006H47.802c-1.851-2.897-3.944-5.393-3.944-9.497c0-4.508,3.703-7.486,8.451-7.486
+ c3.691,0,6.9,2.322,8.196,5.684c0.172,0.422,0.583,0.72,1.066,0.72c0.159,0,0.31-0.032,0.448-0.09h0
+ c0.002-0.001,0.004-0.002,0.006-0.003l7.132-4.268l-0.008-0.008c0.375-0.19,0.638-0.569,0.638-1.018
+ c0-0.226-0.082-0.424-0.193-0.602l0.022-0.013c-3.381-6.6-9.739-9.739-18.674-9.739c-9.498,0-19.559,6.439-19.559,16.662
+ c0,3.943,1.69,6.922,3.703,9.658h-5.474v0.014c-0.015,0-0.028-0.009-0.044-0.009c-0.637,0-1.153,0.516-1.153,1.153h0v4.312h0.022
+ c0.058,0.583,0.533,1.044,1.131,1.044c0.016,0,0.028-0.008,0.044-0.009v0.014h9.659c0.563,1.368,0.966,2.816,0.966,4.346
+ c0,4.062-3.627,7.57-8.616,9.983c-0.008,0.003-0.014,0.007-0.022,0.011c-0.046,0.022-0.09,0.046-0.136,0.068l0.009,0.018
+ c-0.331,0.203-0.563,0.551-0.563,0.968c0,0.155,0.033,0.302,0.088,0.438l-0.002,0.001l0.003,0.007
+ c0.001,0.003,0.003,0.005,0.004,0.008l2.759,5.759c0.006,0.015,0.014,0.028,0.021,0.043l0.05,0.104l0.017-0.005
+ c0.201,0.34,0.555,0.579,0.978,0.579c0.179,0,0.343-0.049,0.495-0.121l0.004,0.009c3.22-1.771,6.52-3.059,9.337-3.059
+ c4.91,0,7.566,3.541,14.569,3.541c5.876,0,9.659-1.771,11.913-4.024l-0.005-0.01C71.405,73.523,71.586,73.211,71.586,72.845z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-power.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-power.svg
new file mode 100644
index 0000000..cdbfb23
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-power.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M76.587,22.655l-0.043,0.043c-0.39-0.363-0.909-0.59-1.484-0.59c-0.553,0-1.052,0.212-1.437,0.551l-0.001-0.004l-0.09,0.08
+ c-0.006,0.006-0.013,0.01-0.018,0.016l-4.123,3.632c-0.032,0.029-0.067,0.055-0.098,0.086l-0.008,0.006l0.001,0.001
+ c-0.382,0.394-0.619,0.928-0.619,1.52c0,0.778,0.411,1.457,1.024,1.844c4.863,4.973,7.869,11.77,7.869,19.257
+ c0,15.196-12.362,27.559-27.56,27.559c-15.199,0-27.561-12.362-27.561-27.559c0-7.561,3.062-14.42,8.01-19.406l-0.048-0.048
+ c0.464-0.4,0.765-0.986,0.765-1.647c0-0.591-0.237-1.126-0.619-1.52l0.001-0.001l-0.008-0.006
+ c-0.031-0.031-0.066-0.057-0.098-0.086l-4.123-3.632c-0.006-0.006-0.013-0.01-0.018-0.016l-0.09-0.08l-0.001,0.004
+ c-0.385-0.339-0.884-0.551-1.437-0.551c-0.809,0-1.508,0.445-1.885,1.1C16.458,29.94,12.5,39.054,12.5,49.097
+ c0,20.71,16.788,37.498,37.5,37.498c20.712,0,37.5-16.788,37.5-37.498C87.5,38.78,83.331,29.435,76.587,22.655z"/>
+ <path d="M47.203,62.733L47.203,62.733l0.003,0h0.001h0.001h5.585v0c0.001,0,0.002,0,0.003,0c1.206,0,2.184-0.978,2.184-2.184l0,0h0
+ V15.594h-0.001c0,0,0.001-0.004,0.001-0.005c0-1.206-0.978-2.184-2.184-2.184c-0.001,0-0.002,0-0.003,0v0h-5.589v0
+ c-1.204,0.002-2.181,0.979-2.181,2.184c0,0.001,0.001,0.003,0.001,0.003l-0.001,0.002v44.955h0l0,0
+ C45.023,61.755,45.999,62.731,47.203,62.733z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-previous.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-previous.svg
new file mode 100644
index 0000000..7a22b45
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-previous.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M87.06,26.291c-0.483,0-0.918,0.2-1.23,0.521L57.41,43.22V28.009c0-0.949-0.769-1.718-1.718-1.718
+ c-0.483,0-0.918,0.2-1.23,0.521L21.144,46.049V22.667h-0.013c0.002-0.039,0.012-0.075,0.012-0.114c0-1.399-1.134-2.533-2.532-2.536
+ v0h-4.852v0.024c-1.401,0-2.537,1.136-2.537,2.537c0,0.045,0.011,0.086,0.013,0.131v54.721c0,0.002,0,0.003,0,0.005
+ s0,0.003,0,0.005v0.236h0.024c0.123,1.286,1.194,2.296,2.513,2.296c0.03,0,0.058-0.008,0.087-0.009h4.569
+ c0.071,0.006,0.14,0.021,0.213,0.021c1.4,0,2.537-1.136,2.537-2.537c0-0.117-0.019-0.23-0.035-0.343V53.962l33.341,19.25
+ c0.31,0.307,0.736,0.497,1.207,0.497c0.932,0,1.686-0.743,1.713-1.669h0.005V56.791l28.443,16.422
+ c0.31,0.307,0.736,0.497,1.207,0.497c0.932,0,1.687-0.743,1.713-1.669h0.005V28.009C88.778,27.06,88.008,26.291,87.06,26.291z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-price-tag.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-price-tag.svg
new file mode 100644
index 0000000..f8cb16c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-price-tag.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.465,66.127c-0.022-0.038-0.052-0.069-0.076-0.105l0.002-0.001L54.487,19.422l-0.014,0.008
+ c-0.23-0.368-0.558-0.637-0.929-0.801l0.038-0.022l-11.01-6.357l0,0.044c-0.554-0.315-1.232-0.367-1.846-0.107l-0.012-0.021
+ l-0.206,0.119c-0.004,0.003-0.009,0.003-0.013,0.006c-0.004,0.002-0.007,0.006-0.012,0.008l-21.183,12.23
+ c-0.656,0.378-1.021,1.058-1.037,1.764l-0.007-0.004v12.714l0.021-0.012c-0.047,0.427,0.03,0.872,0.261,1.273
+ c0.014,0.024,0.032,0.042,0.047,0.065l0,0l26.816,46.446c0.026,0.055,0.044,0.112,0.075,0.166c0.562,0.971,1.785,1.316,2.772,0.801
+ l0.005,0.008l32.465-18.743l-0.014-0.025C81.7,68.404,82.042,67.126,81.465,66.127z M36.366,29.361
+ c-1.849,1.068-4.214,0.435-5.281-1.414c-1.068-1.849-0.434-4.213,1.415-5.281c1.849-1.068,4.213-0.434,5.281,1.416
+ C38.849,25.929,38.215,28.294,36.366,29.361z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pricetag-multiple.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pricetag-multiple.svg
new file mode 100644
index 0000000..255ec8e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-pricetag-multiple.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.286,67.965c-0.022-0.038-0.052-0.069-0.076-0.105l0.002-0.001L61.307,21.26l-0.015,0.008
+ c-0.23-0.368-0.558-0.637-0.929-0.801l0.038-0.022l-7.986-4.612l8.871,15.365l20.178,34.949l-0.002,0.001
+ c0.024,0.036,0.054,0.067,0.076,0.105c0.577,0.999,0.234,2.277-0.765,2.855l0.014,0.025l-29.861,17.24l1.293,2.239
+ c0.026,0.055,0.044,0.112,0.075,0.166c0.562,0.971,1.785,1.316,2.772,0.801l0.005,0.008l32.465-18.743l-0.014-0.025
+ C88.52,70.243,88.862,68.964,88.286,67.965z"/>
+ <path d="M73.88,67.143c0.999-0.577,1.341-1.855,0.765-2.855c-0.022-0.038-0.052-0.069-0.076-0.105l0.002-0.001L47.666,17.583
+ l-0.015,0.008c-0.23-0.368-0.558-0.637-0.929-0.801l0.038-0.022l-11.01-6.357l0,0.044c-0.554-0.315-1.232-0.367-1.846-0.107
+ l-0.012-0.021l-0.206,0.119c-0.004,0.003-0.009,0.003-0.013,0.006c-0.004,0.003-0.007,0.006-0.012,0.008l-21.183,12.23
+ c-0.656,0.378-1.021,1.058-1.037,1.764l-0.007-0.004v12.714l0.021-0.012c-0.047,0.427,0.03,0.872,0.261,1.273
+ c0.014,0.024,0.032,0.042,0.047,0.065l0,0l26.815,46.446c0.026,0.055,0.044,0.112,0.075,0.166c0.562,0.971,1.785,1.316,2.772,0.801
+ l0.005,0.008l32.465-18.743L73.88,67.143z M29.545,27.522c-1.849,1.068-4.214,0.435-5.281-1.414
+ c-1.068-1.849-0.434-4.213,1.415-5.281c1.849-1.068,4.213-0.434,5.281,1.416C32.028,24.091,31.395,26.456,29.545,27.522z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-print.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-print.svg
new file mode 100644
index 0000000..88aa402
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-print.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M90.443,35.141c-0.064-0.953-0.849-1.708-1.818-1.708H75.511v0h0V11.857c0-1.012-0.819-1.83-1.83-1.83H26.319
+ c-1.011,0-1.83,0.818-1.83,1.83v21.576h0H11.377c0,0-0.002,0-0.002,0c-0.969,0-1.754,0.755-1.818,1.708H9.545V71.91
+ c0,1.01,0.819,1.829,1.83,1.829v0h13.114V58.425h0h4.987h41.047h4.987h0v15.314h13.114c1.011,0,1.83-0.819,1.83-1.829V35.141
+ H90.443z M70.524,41.631H29.476V16.844c0-1.012,0.819-1.83,1.83-1.83h0h37.387c1.011,0,1.83,0.818,1.83,1.83V41.631z"/>
+ <path d="M29.602,88.143c0,1.012,0.819,1.83,1.83,1.83h37.136c1.011,0,1.83-0.818,1.83-1.83v-24.64H29.602V88.143z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-prohibited.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-prohibited.svg
new file mode 100644
index 0000000..e7df040
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-prohibited.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.561-12.362-27.561-27.559
+ c0-6.702,2.407-12.853,6.4-17.636l38.795,38.795C62.852,75.153,56.703,77.561,50,77.561z M71.161,67.635L32.366,28.839
+ c4.782-3.992,10.931-6.4,17.634-6.4c15.198,0,27.56,12.367,27.56,27.562C77.56,56.704,75.153,62.853,71.161,67.635z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-projection-screen.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-projection-screen.svg
new file mode 100644
index 0000000..c6f6502
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-projection-screen.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.158,16.509L88.158,16.509c0-0.986-0.798-1.785-1.785-1.786H13.628c0,0,0,0,0,0c-0.987,0-1.786,0.799-1.786,1.785
+ l0,0.001v6.385l0,0c0,0.986,0.799,1.785,1.786,1.785c0,0,0,0,0.001,0h72.745c0.987,0,1.785-0.799,1.785-1.785h0L88.158,16.509
+ L88.158,16.509z"/>
+ <path d="M82.026,29.659H17.974c-0.986,0.001-1.785,0.8-1.785,1.786c0,0.003,0.001,0.006,0.001,0.006l-0.001,0.003v37.154
+ c0,2.201,1.857,3.982,4.152,3.982h27.17v5.373c-0.966,0.748-1.599,1.906-1.599,3.222c0,2.259,1.831,4.09,4.089,4.09
+ s4.089-1.831,4.089-4.09c0-1.317-0.634-2.476-1.601-3.223v-5.372h27.17c2.294,0,4.152-1.781,4.152-3.982V31.412h-0.003
+ C83.789,30.442,83,29.66,82.026,29.659z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-puzzle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-puzzle.svg
new file mode 100644
index 0000000..34c7988
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-puzzle.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.589,48.774V35.887h-0.001c-0.005-2.155-1.728-3.897-3.87-3.953v-0.038H62.666c-0.059,0.002-0.115,0.018-0.175,0.018
+ s-0.116-0.016-0.175-0.018h-0.203v-0.021c-2.8-0.198-5.016-2.508-5.016-5.356c0-1.236,0.432-2.361,1.131-3.271h-0.106
+ c0.695-1.206,1.098-2.601,1.098-4.092c0-4.541-3.681-8.221-8.223-8.221c-4.541,0-8.221,3.68-8.221,8.221
+ c0,1.491,0.403,2.886,1.098,4.092h-0.091c0.691,0.907,1.117,2.027,1.117,3.256c0,2.847-2.216,5.157-5.017,5.354v0.038H25.361v0.02
+ c-2.185,0.01-3.955,1.783-3.955,3.971c0,0.058,0.015,0.112,0.017,0.17v13.421h0.043c0,1.237,1.004,2.244,2.243,2.244
+ c0.226,0,0.44-0.045,0.645-0.109c1.191-0.517,2.503-0.808,3.883-0.808c5.393,0,9.764,4.371,9.764,9.762
+ c0,5.392-4.371,9.762-9.764,9.762c-1.343,0-2.623-0.272-3.788-0.763v0c-0.241-0.088-0.497-0.144-0.769-0.144
+ c-1.239,0-2.242,1.002-2.242,2.244c0,0.127,0.017,0.25,0.038,0.372h-0.053v12.884c-0.003,0.058-0.017,0.112-0.017,0.17
+ c0,2.191,1.779,3.973,3.973,3.973c0.109,0,0.212-0.023,0.319-0.032H38.89c1.24,0,2.244-1.007,2.244-2.246
+ c0-0.248-0.05-0.481-0.124-0.704c-0.001-0.004-0.003-0.009-0.004-0.014c-0.017-0.051-0.027-0.106-0.048-0.155h0.008
+ c-0.254-0.871-0.397-1.789-0.397-2.741c0-5.393,4.37-9.762,9.762-9.762c5.391,0,9.762,4.369,9.762,9.762
+ c0,0.953-0.143,1.871-0.397,2.741h0.025c-0.115,0.27-0.179,0.567-0.179,0.879c0,1.239,1.005,2.244,2.245,2.244
+ c0.013,0,0.025-0.004,0.038-0.004h12.792c2.178,0,3.944-1.758,3.969-3.933h0.005V72.038h-0.046
+ c-0.139-1.108-1.072-1.964-2.216-1.964v-0.099c-0.819,0.223-1.677,0.353-2.567,0.353c-5.392,0-9.763-4.37-9.763-9.762
+ c0-5.391,4.371-9.762,9.763-9.762c0.89,0,1.748,0.129,2.567,0.353v-0.094c0.008,0,0.016,0.002,0.025,0.002
+ c1.01,0,1.853-0.67,2.134-1.588h0.103v-0.605c0-0.017,0.005-0.032,0.005-0.049C78.594,48.806,78.59,48.791,78.589,48.774z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-quote.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-quote.svg
new file mode 100644
index 0000000..a4f7e77
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-quote.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M17.572,43.713c-0.809,0-1.617,0.101-2.02,0.303c0.899-3.602,4.307-7.642,7.513-9.387c0.007-0.003,0.012-0.008,0.018-0.011
+ c0.024-0.013,0.048-0.031,0.071-0.044l-0.003-0.002c0.355-0.19,0.605-0.552,0.605-0.983c0-0.388-0.208-0.713-0.505-0.916
+ l0.025-0.024l-4.196-2.65l-0.013,0.011c-0.189-0.143-0.413-0.242-0.668-0.242c-0.184,0-0.35,0.054-0.504,0.132l-0.021-0.019
+ c-6.26,4.442-10.401,11.206-10.401,18.78c0,6.562,4.241,10.297,8.985,10.297c4.342,0,7.978-3.634,7.978-7.977
+ C24.437,46.641,21.409,43.713,17.572,43.713z"/>
+ <path d="M38.119,43.713c-0.809,0-1.617,0.101-2.02,0.303c0.899-3.602,4.307-7.642,7.513-9.387c0.007-0.003,0.012-0.008,0.018-0.011
+ c0.024-0.013,0.048-0.031,0.071-0.044l-0.003-0.002c0.355-0.19,0.605-0.552,0.605-0.983c0-0.388-0.208-0.713-0.505-0.916
+ l0.025-0.024l-4.196-2.65l-0.013,0.011c-0.189-0.143-0.413-0.242-0.668-0.242c-0.184,0-0.35,0.054-0.504,0.132l-0.021-0.019
+ c-6.26,4.442-10.401,11.206-10.401,18.78c0,6.562,4.241,10.297,8.985,10.297c4.342,0,7.978-3.634,7.978-7.977
+ C44.984,46.641,41.956,43.713,38.119,43.713z"/>
+ <path d="M62.994,41.041c-4.342,0-7.978,3.634-7.978,7.977c0,4.341,3.028,7.269,6.865,7.269c0.809,0,1.617-0.101,2.02-0.303
+ c-0.899,3.602-4.307,7.642-7.513,9.387c-0.007,0.003-0.012,0.008-0.018,0.011c-0.024,0.013-0.048,0.031-0.071,0.044l0.003,0.002
+ c-0.355,0.19-0.605,0.552-0.605,0.983c0,0.388,0.208,0.713,0.505,0.916l-0.025,0.024l4.196,2.65l0.013-0.011
+ c0.189,0.143,0.413,0.242,0.668,0.242c0.184,0,0.35-0.054,0.504-0.132l0.021,0.019c6.26-4.443,10.401-11.206,10.401-18.78
+ C71.979,44.776,67.738,41.041,62.994,41.041z"/>
+ <path d="M83.541,41.041c-4.342,0-7.978,3.634-7.978,7.977c0,4.341,3.028,7.269,6.865,7.269c0.809,0,1.617-0.101,2.02-0.303
+ c-0.899,3.602-4.307,7.642-7.513,9.387c-0.007,0.003-0.012,0.008-0.018,0.011c-0.024,0.013-0.048,0.031-0.071,0.044l0.003,0.002
+ c-0.355,0.19-0.605,0.552-0.605,0.983c0,0.388,0.208,0.713,0.505,0.916l-0.025,0.024l4.196,2.65l0.013-0.011
+ c0.189,0.143,0.413,0.242,0.668,0.242c0.184,0,0.35-0.054,0.504-0.132l0.021,0.019c6.26-4.443,10.401-11.206,10.401-18.78
+ C92.526,44.776,88.285,41.041,83.541,41.041z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-record.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-record.svg
new file mode 100644
index 0000000..515b8cc
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-record.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.908c-20.485,0-37.092,16.606-37.092,37.092c0,20.485,16.606,37.092,37.092,37.092
+ c20.485,0,37.092-16.606,37.092-37.092C87.092,29.515,70.485,12.908,50,12.908z M50,62.191c-6.733,0-12.191-5.458-12.191-12.191
+ c0-6.733,5.458-12.191,12.191-12.191c6.733,0,12.191,5.458,12.191,12.191C62.191,56.733,56.733,62.191,50,62.191z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-refresh.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-refresh.svg
new file mode 100644
index 0000000..5eb3af1
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-refresh.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M84.539,21.586c-0.007-0.562-0.321-1.083-0.825-1.337c-0.503-0.258-1.107-0.212-1.568,0.115l-5.944,4.261l-0.468,0.337
+ c-6.405-6.392-15.196-10.389-24.937-10.389c-19.535,0-35.427,15.894-35.427,35.428s15.893,35.428,35.427,35.428
+ c11.782,0,22.764-5.838,29.374-15.618c0.263-0.392,0.362-0.867,0.272-1.328c-0.09-0.461-0.357-0.871-0.747-1.134l-8.863-6.151
+ c-0.87-0.576-2.043-0.355-2.628,0.512c-3.918,5.792-10.41,9.25-17.375,9.25c-11.558,0-20.962-9.402-20.962-20.957
+ s9.404-20.957,20.962-20.957c4.878,0,9.352,1.696,12.914,4.5l-1.001,0.72l-5.948,4.26c-0.455,0.328-0.696,0.89-0.611,1.448
+ c0.081,0.558,0.47,1.028,1.008,1.208l25.446,8.669c0.461,0.161,0.966,0.083,1.368-0.203c0.399-0.29,0.629-0.747,0.627-1.231
+ L84.539,21.586z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results-demographics.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results-demographics.svg
new file mode 100644
index 0000000..0b982d8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results-demographics.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M27.953,46.506c-1.385-2.83-2.117-6.008-2.117-9.192c0-1.743,0.252-3.534,0.768-5.468c0.231-0.87,0.521-1.702,0.847-2.509
+ c-1.251-0.683-2.626-1.103-4.101-1.103c-5.47,0-9.898,5.153-9.898,11.517c0,4.452,2.176,8.305,5.354,10.222L5.391,56.217
+ c-0.836,0.393-1.387,1.337-1.387,2.392v10.588c0,1.419,0.991,2.569,2.21,2.569h7.929V60.656c0-3.237,1.802-6.172,4.599-7.481
+ l10.262-4.779C28.624,47.792,28.273,47.161,27.953,46.506z"/>
+ <path d="M60.137,34.801h34.092v-0.001c0.002,0,0.004,0.001,0.006,0.001c0.973,0,1.761-0.789,1.761-1.761c0,0,0-0.001,0-0.001
+ l0-6.43h0c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001v-0.005H56.133c1.614,2.114,2.844,4.627,3.526,7.435
+ C59.874,33.168,60.03,33.999,60.137,34.801z"/>
+ <path d="M95.996,66.436c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001v-0.005H72.007v7.095v1.994
+ c0,0.293-0.016,0.582-0.045,0.867h22.267v-0.001c0.002,0,0.004,0.001,0.006,0.001c0.973,0,1.761-0.789,1.761-1.761l0-0.001
+ L95.996,66.436L95.996,66.436z"/>
+ <path d="M94.235,44.762c-0.002,0-0.004,0.001-0.006,0.001v-0.005H58.944c-0.159,0.419-0.327,0.836-0.514,1.249
+ c-0.364,0.802-0.773,1.569-1.224,2.297l10.288,4.908c0.781,0.378,1.473,0.897,2.078,1.503h24.657v-0.001
+ c0.002,0,0.004,0.001,0.006,0.001c0.973,0,1.761-0.789,1.761-1.761c0,0,0-0.001,0-0.001l0-6.43h0
+ C95.996,45.55,95.207,44.762,94.235,44.762z"/>
+ <path d="M65.323,57.702l-11.551-5.51l-4.885-2.33c2.134-1.344,3.866-3.418,5-5.917c0.899-1.984,1.435-4.231,1.435-6.631
+ c0-1.348-0.213-2.627-0.512-3.863c-1.453-5.983-6.126-10.392-11.736-10.392c-5.504,0-10.106,4.251-11.648,10.065
+ c-0.356,1.333-0.602,2.72-0.602,4.189c0,2.552,0.596,4.93,1.609,7c1.171,2.4,2.906,4.379,5.018,5.651l-4.678,2.178l-11.926,5.554
+ c-1.037,0.485-1.717,1.654-1.717,2.959v11.111v1.994c0,1.756,1.224,3.181,2.735,3.181h42.417c1.511,0,2.735-1.424,2.735-3.181
+ v-1.994V60.656C67.019,59.355,66.349,58.198,65.323,57.702z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results.svg
new file mode 100644
index 0000000..f11a670
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-results.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M92.11,21.929L92.11,21.929c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001v-0.005H44.465v0.014
+ c-0.965,0.005-1.746,0.786-1.751,1.752h-0.001v0.007c0,0.001,0,0.001,0,0.001c0,0.001,0,0.002,0,0.002l0,6.332
+ c-0.001,0.03-0.009,0.057-0.009,0.087c0,0.972,0.788,1.76,1.761,1.761v0h45.878V30.12c0.002,0,0.004,0.001,0.006,0.001
+ c0.973,0,1.761-0.789,1.761-1.761c0,0,0-0.001,0-0.001L92.11,21.929z"/>
+ </g>
+ <g>
+ <path d="M92.11,36.83L92.11,36.83c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001v-0.005H44.465v0.014
+ c-0.965,0.005-1.746,0.786-1.751,1.752h-0.001v0.007l0,0.002c0,0.001,0,0.001,0,0.001l0,6.333
+ c-0.001,0.03-0.009,0.057-0.009,0.087c0,0.972,0.788,1.76,1.761,1.761v0h45.878v-0.001c0.002,0,0.004,0.001,0.006,0.001
+ c0.973,0,1.761-0.789,1.761-1.761l0-0.001L92.11,36.83z"/>
+ </g>
+ <g>
+ <path d="M32.748,21.925L32.748,21.925c0-0.973-0.788-1.761-1.761-1.761c-0.043,0-0.084,0.01-0.126,0.013H9.777
+ c-0.042-0.003-0.083-0.013-0.126-0.013c-0.973,0-1.761,0.789-1.761,1.761l0,0V43.26l0,0v0c0,0.972,0.788,1.761,1.761,1.761v0
+ h21.336l0,0h0c0.973,0,1.761-0.789,1.761-1.761v0h0V21.925z"/>
+ </g>
+ <g>
+ <path d="M92.11,56.744L92.11,56.744c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001v-0.005H44.465v0.014
+ c-0.965,0.005-1.746,0.786-1.751,1.752h-0.001v0.007c0,0.001,0,0.001,0,0.002c0,0,0,0.001,0,0.002l0,6.332
+ c-0.001,0.03-0.009,0.057-0.009,0.087c0,0.972,0.788,1.761,1.761,1.761v0h45.878v-0.001c0.002,0,0.004,0.001,0.006,0.001
+ c0.973,0,1.761-0.789,1.761-1.761l0-0.001L92.11,56.744z"/>
+ </g>
+ <g>
+ <path d="M92.11,71.645L92.11,71.645c0-0.973-0.789-1.761-1.761-1.761c-0.002,0-0.004,0.001-0.006,0.001V69.88H44.465v0.014
+ c-0.965,0.005-1.746,0.786-1.751,1.752h-0.001v0.007c0,0.001,0,0.001,0,0.001c0,0.001,0,0.002,0,0.002l0,6.332
+ c-0.001,0.03-0.009,0.057-0.009,0.087c0,0.972,0.788,1.761,1.761,1.761l0.001,0h45.877v-0.001c0.002,0,0.004,0.001,0.006,0.001
+ c0.973,0,1.761-0.789,1.761-1.761c0,0,0-0.001,0-0.001L92.11,71.645z"/>
+ </g>
+ <g>
+ <path d="M32.748,56.74L32.748,56.74c0-0.973-0.788-1.762-1.761-1.762c-0.043,0-0.084,0.01-0.126,0.013H9.777
+ c-0.042-0.003-0.083-0.013-0.126-0.013c-0.973,0-1.761,0.789-1.761,1.762l0,0v21.335l0,0v0c0,0.972,0.789,1.761,1.761,1.761
+ c0,0,0,0,0.001,0h21.335c0,0,0,0,0,0c0.973,0,1.761-0.789,1.761-1.761v0h0V56.74z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind-ten.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind-ten.svg
new file mode 100644
index 0000000..6c8f514
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind-ten.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.941,49.005c0.393-0.298,0.615-0.759,0.603-1.242l-0.609-26.821c-0.018-0.562-0.341-1.078-0.85-1.322
+ c-0.508-0.248-1.111-0.19-1.566,0.145l-5.861,4.375l-0.461,0.345c-6.527-6.266-15.394-10.094-25.133-9.906
+ C25.532,14.955,9.949,31.153,10.325,50.682c0.376,19.53,16.572,35.115,36.104,34.739c0.704-0.014,1.404-0.051,2.1-0.105
+ c0,0,0.469-0.024,1.008-0.271c0.007-0.003,0.013-0.007,0.019-0.01c0.117-0.055,0.236-0.123,0.355-0.202
+ c0.037-0.024,0.073-0.048,0.109-0.074c0.088-0.064,0.172-0.139,0.255-0.219c0.033-0.031,0.068-0.059,0.099-0.092
+ c0.006-0.006,0.013-0.011,0.019-0.017c0.014-0.015,0.019-0.03,0.031-0.045c0.417-0.471,0.671-1.088,0.658-1.766
+ c0-0.027-0.008-0.052-0.009-0.079l-0.175-9.105l-0.008,0c0-0.028,0.007-0.054,0.007-0.082c-0.028-1.436-1.212-2.576-2.647-2.548h0
+ l0-0.003c-0.683,0.081-1.371,0.138-2.067,0.152c-11.556,0.223-21.14-8.997-21.362-20.55c-0.223-11.554,8.999-21.135,20.555-21.358
+ c4.878-0.094,9.383,1.517,12.998,4.251l-0.986,0.738l-5.866,4.375c-0.448,0.337-0.678,0.904-0.583,1.46
+ c0.092,0.556,0.49,1.019,1.031,1.188l25.609,8.177C78.042,49.386,78.545,49.299,78.941,49.005z"/>
+ <polygon points="67.109,59.835 61.168,66.039 63.552,68.446 66.691,65.124 66.96,79.087 71.056,79.008 70.686,59.766 "/>
+ <path d="M81.525,59.269c-5.51,0.106-7.867,5.115-7.771,10.077c0.096,4.962,2.644,9.906,8.154,9.8
+ c5.51-0.106,7.866-5.145,7.771-10.107C89.583,64.077,87.035,59.163,81.525,59.269z M81.838,75.511
+ c-2.741,0.053-3.832-2.697-3.901-6.245s0.917-6.309,3.658-6.362c2.77-0.053,3.832,2.668,3.9,6.216
+ C85.564,72.668,84.579,75.458,81.838,75.511z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind.svg
new file mode 100644
index 0000000..309aef5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rewind.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84.627,26.291c-0.483,0-0.918,0.2-1.23,0.521L54.978,43.22V28.009c0-0.949-0.769-1.718-1.718-1.718
+ c-0.483,0-0.918,0.2-1.23,0.521L14.485,48.489l0.031,0.054c-0.513,0.297-0.862,0.846-0.862,1.481c0,0.702,0.422,1.303,1.026,1.57
+ l-0.017,0.03l37.391,21.588c0.31,0.307,0.736,0.497,1.207,0.497c0.932,0,1.686-0.743,1.713-1.669h0.005V56.791l28.443,16.422
+ c0.31,0.307,0.736,0.497,1.207,0.497c0.932,0,1.687-0.743,1.713-1.669h0.005V28.009C86.346,27.06,85.576,26.291,84.627,26.291z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rss.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rss.svg
new file mode 100644
index 0000000..b987788
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-rss.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M26.258,64.949c-4.848,0-8.78,3.93-8.78,8.784c0,4.848,3.932,8.782,8.78,8.782c4.855,0,8.784-3.934,8.784-8.782
+ C35.042,68.878,31.113,64.949,26.258,64.949z"/>
+ <path d="M23.536,40.801c-0.046,0-0.09,0.006-0.135,0.007v-0.007h-3.464v0.039c-1.698,0.193-3.021,1.603-3.056,3.344h-0.007v6.159
+ h0.041c0.19,1.581,1.437,2.822,3.021,3.002v0.039h3.464v-0.048c0.045,0.001,0.09,0.007,0.135,0.007
+ c12.772,0,23.173,10.321,23.311,23.061h-0.033v3.464h0.039c0.193,1.698,1.603,3.021,3.344,3.056v0.007h6.158v-0.041
+ c1.581-0.19,2.822-1.437,3.002-3.021h0.039v-3.464h-0.006C59.252,56.748,43.223,40.801,23.536,40.801z"/>
+ <path d="M83.119,76.403C82.98,43.664,56.308,17.07,23.536,17.07c-0.046,0-0.09,0.006-0.135,0.007V17.07h-3.464v0.039
+ c-1.698,0.193-3.021,1.603-3.056,3.344h-0.007v6.159h0.041c0.19,1.582,1.437,2.822,3.021,3.002v0.039h3.464v-0.048
+ c0.045,0.001,0.09,0.007,0.135,0.007c25.857,0,46.902,20.967,47.041,46.792h-0.035v3.464h0.039
+ c0.193,1.698,1.603,3.021,3.344,3.056v0.007h6.159v-0.041c1.581-0.19,2.822-1.437,3.002-3.021h0.039v-3.464H83.119z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-safety-cone.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-safety-cone.svg
new file mode 100644
index 0000000..1561f76
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-safety-cone.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M97.017,82.01v-4.62h-0.002l0.002-0.018c-0.01-1.335-1.092-2.407-2.42-2.417v-0.003h-7.512L54.048,17.732
+ l-0.013,0.008c-0.732-1.503-2.26-2.547-4.044-2.547c-1.832,0-3.401,1.096-4.108,2.665L12.92,74.951H5.386
+ c-1.347,0-2.44,1.091-2.44,2.438v4.863h0.012c-0.002,0.039-0.012,0.075-0.012,0.114c0,1.347,1.092,2.439,2.44,2.439h89.21v-0.004
+ c0.013,0,0.024,0.004,0.037,0.003c1.346-0.01,2.43-1.111,2.42-2.458C97.053,82.232,97.033,82.122,97.017,82.01z M47.513,25.159
+ h4.977l5.748,9.957H41.765L47.513,25.159z M36.017,45.072h27.971l5.748,9.957H30.268L36.017,45.072z M18.766,74.951l5.748-9.957
+ H75.49l5.748,9.957H18.766z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-save.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-save.svg
new file mode 100644
index 0000000..318ccd2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-save.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <rect x="52.872" y="17.026" width="10.352" height="21.471"/>
+ <path d="M86.217,19.195l0.006-0.006l-5.211-5.212c-0.437-0.479-1.06-0.785-1.76-0.785c-0.014,0-0.026,0.004-0.04,0.004h-8.91
+ c-0.013,0-0.025,0-0.038,0h-0.139v0.024c-0.286,0.029-0.564,0.128-0.779,0.344c-0.215,0.215-0.315,0.493-0.343,0.779h-0.028v25.306
+ h-0.009c-0.047,1.277-1.089,2.3-2.378,2.3h-0.297H32.135v-0.012c-1.234-0.062-2.215-1.05-2.259-2.288h-0.009V14.343h-0.048
+ c-0.051-0.266-0.158-0.526-0.367-0.735c-0.311-0.311-0.724-0.427-1.119-0.387v-0.028H15.383v0l-0.001,0
+ c-1.318,0-2.387,1.068-2.386,2.388l0,0v26.368v9.585v32.887l0,0.001c-0.001,1.319,1.067,2.386,2.387,2.386h0h7.57v-2.387h0V53.889
+ l0-0.001c0,0,0-0.001,0-0.001v-0.053v-0.033h0.009c0.041-1.122,0.851-2.046,1.92-2.255v-0.013h0.132
+ c0.108-0.015,0.215-0.032,0.326-0.032h0.001H74.64h0.001h0h0.086v0.009c1.249,0.045,2.247,1.042,2.292,2.291h0.009v33.007h7.581h0
+ c1.319,0,2.387-1.068,2.387-2.386l0-0.001h0V21.029c0.001-0.025,0.007-0.048,0.007-0.073
+ C87.003,20.255,86.697,19.631,86.217,19.195z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-share.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-share.svg
new file mode 100644
index 0000000..5284089
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-share.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M73.213,38.25c-1.478,0-2.886,0.285-4.189,0.782L38.498,21.408c0.017-0.259,0.039-0.517,0.039-0.78
+ c0-6.489-5.261-11.75-11.75-11.75c-6.489,0-11.75,5.261-11.75,11.75c0,6.489,5.261,11.75,11.75,11.75
+ c2.563,0,4.927-0.83,6.858-2.223l28.343,16.364c-0.341,1.1-0.525,2.27-0.525,3.482c0,1.232,0.191,2.418,0.543,3.534L33.693,69.881
+ c-1.94-1.414-4.321-2.258-6.906-2.258c-6.489,0-11.75,5.261-11.75,11.75c0,6.489,5.261,11.75,11.75,11.75
+ c6.489,0,11.75-5.261,11.75-11.75c0-0.243-0.022-0.48-0.036-0.72l30.59-17.661c1.284,0.482,2.67,0.758,4.122,0.758
+ c6.489,0,11.75-5.261,11.75-11.75C84.963,43.511,79.702,38.25,73.213,38.25z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sheriff-badge.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sheriff-badge.svg
new file mode 100644
index 0000000..60e79a9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sheriff-badge.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.066,62.012c-0.861,0-1.663,0.222-2.385,0.583l-6.813-11.801l6.755-11.701c0.438,0.115,0.89,0.196,1.364,0.196
+ c2.971-0.002,5.382-2.415,5.382-5.388c-0.004-2.969-2.411-5.377-5.382-5.374c-1.851-0.002-3.48,0.93-4.449,2.349H61.368
+ l-7.042-12.197c0.547-0.842,0.872-1.841,0.873-2.92c0-2.974-2.415-5.385-5.389-5.385c-2.973,0.002-5.382,2.414-5.382,5.387
+ c0.002,1.049,0.315,2.021,0.835,2.848l-7.083,12.267H22.65c-0.909-1.686-2.668-2.845-4.716-2.842
+ c-2.979-0.004-5.386,2.404-5.389,5.376c0,2.974,2.413,5.386,5.389,5.386c0.861,0,1.663-0.223,2.385-0.583l6.814,11.802
+ l-6.756,11.702c-0.438-0.115-0.89-0.196-1.364-0.196c-2.973,0-5.382,2.414-5.382,5.387c0.004,2.968,2.41,5.377,5.382,5.375
+ c1.851,0.001,3.481-0.931,4.451-2.35h15.169l6.815,11.805c-0.399,0.751-0.646,1.595-0.647,2.505c0,2.975,2.413,5.386,5.389,5.386
+ c2.971-0.002,5.382-2.415,5.382-5.388c-0.002-0.88-0.234-1.698-0.61-2.432l6.857-11.876h15.532
+ c0.909,1.685,2.668,2.844,4.717,2.844c2.977,0.001,5.386-2.406,5.389-5.378C87.455,64.424,85.04,62.012,82.066,62.012z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shield.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shield.svg
new file mode 100644
index 0000000..a1397bd
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shield.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50.027,10.459l-0.018-0.032L16.403,29.831l0.076,0.132v22.893h0.014c0.286,19.111,14.859,34.755,33.519,36.718
+ c18.66-1.962,33.234-17.606,33.519-36.718V29.953l0.066-0.114L50.027,10.459z M50.012,79.556V51.677H26.435V35.651L50.012,22.04
+ v29.637h23.563v1.179h0.017C73.314,66.449,63.153,77.654,50.012,79.556z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-bag.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-bag.svg
new file mode 100644
index 0000000..3f8fc87
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-bag.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M93.031,38.642c-0.213-1.934-1.832-3.443-3.823-3.443h0h-6.1C76.802,23.367,64.344,15.309,50,15.309
+ c-14.345,0-26.802,8.058-33.109,19.891h-6.099c-1.99,0-3.61,1.51-3.823,3.443H6.926v42.185h0c0,2.134,1.731,3.864,3.865,3.864v0
+ h78.417v0l0.001,0c2.135,0.001,3.866-1.73,3.865-3.864V38.642H93.031z M28.818,35.199c5.059-6.076,12.675-9.951,21.182-9.951
+ c8.506,0,16.122,3.875,21.181,9.951H28.818z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-cart.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-cart.svg
new file mode 100644
index 0000000..230b902
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shopping-cart.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <circle cx="32.961" cy="81.02" r="5.889"/>
+ <circle cx="74.309" cy="81.02" r="5.889"/>
+ <path d="M73.513,55.216c1.377,0,2.556-0.812,3.11-1.978l0.003,0.002l14.589-25.27l-0.018-0.01c0.214-0.449,0.344-0.946,0.344-1.477
+ c0-1.907-1.545-3.452-3.452-3.452h0H73.513H44.929h-10.43v-6.488h0c0-1.907-1.545-3.452-3.452-3.452h0h0H12.186v0.028
+ c-0.092-0.008-0.181-0.028-0.275-0.028c-1.763,0-3.202,1.327-3.41,3.035H8.459v3.452v0c0,1.907,1.545,3.452,3.452,3.452
+ c0.094,0,0.183-0.021,0.275-0.028v0.028h12.373v43.733h0.001c0.005,1.902,1.548,3.442,3.451,3.442c0,0,0.001,0,0.002,0v0h59.254
+ v-0.085c1.633-0.103,2.948-1.329,3.185-2.922h0.049v-0.49c0-0.006,0.002-0.012,0.002-0.018c0-0.006-0.002-0.012-0.002-0.018v-3.002
+ c0-0.006,0.002-0.012,0.002-0.018c0-1.833-1.432-3.316-3.236-3.429v-0.022H34.498v-4.988H73.513z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shuffle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shuffle.svg
new file mode 100644
index 0000000..6ccf41e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-shuffle.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M19.401,62.222H8.022c-0.169-0.036-0.344-0.056-0.525-0.056c-1.236,0-2.262,0.885-2.488,2.056H4.962v11h0.076
+ c0.238,0.992,1.056,1.75,2.078,1.906v0.094h17v-0.061c1.739-0.021,3.23-1.008,4.002-2.443L38.63,64.206L28.024,53.599
+ L19.401,62.222z"/>
+ <path d="M94.651,30.776l-18.614-13.26c-0.393-0.28-0.891-0.315-1.319-0.094c-0.428,0.219-0.688,0.662-0.688,1.146l0.002,5.599
+ H59.116v0.026c-1.066,0.06-2.029,0.476-2.781,1.138l-0.021-0.021L45.722,35.9l10.607,10.607l7.341-7.341h10.368l0.002,6.005
+ c0,0.481,0.271,0.924,0.7,1.146c0.429,0.222,0.946,0.183,1.34-0.099l18.576-13.346c0.338-0.241,0.461-0.631,0.461-1.046
+ c0-0.003,0-0.003,0-0.003C95.116,31.406,94.991,31.017,94.651,30.776z"/>
+ <path d="M94.578,67.126L76.002,53.781c-0.394-0.282-0.911-0.319-1.339-0.099c-0.429,0.223-0.7,0.665-0.7,1.146l-0.002,6.005H63.592
+ L28.04,25.281c-0.772-1.435-2.263-2.421-4.001-2.442v-0.061h-17v0.094c-1.022,0.156-1.84,0.914-2.078,1.906H4.884v11h0.049
+ c0.225,1.171,1.252,2.056,2.488,2.056c0.18,0,0.355-0.02,0.525-0.056h11.378l36.913,36.913l0.021-0.021
+ c0.753,0.662,1.716,1.078,2.782,1.138v0.026h14.916l-0.002,5.599c0,0.484,0.26,0.928,0.688,1.146
+ c0.429,0.223,0.926,0.187,1.319-0.093l18.614-13.26c0.34-0.242,0.465-0.631,0.465-1.049c0,0,0,0,0-0.004
+ C95.039,67.758,94.916,67.367,94.578,67.126z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-skull.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-skull.svg
new file mode 100644
index 0000000..74f40c2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-skull.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M87.255,72.316c-2.248-2.246-5.832-2.318-8.118-0.208l-9-9c2.459-3.77,3.894-8.27,3.894-13.107s-1.435-9.337-3.894-13.107
+ l8.949-8.949c2.287,2.111,5.87,2.042,8.118-0.207c2.306-2.3,2.329-6.017,0.054-8.293c-1.371-1.371-3.264-1.9-5.058-1.603
+ c0.33-1.82-0.196-3.755-1.592-5.151c-2.274-2.275-5.985-2.252-8.291,0.055c-2.246,2.248-2.318,5.832-0.208,8.118l-9.001,9.001
+ c-3.77-2.459-8.27-3.893-13.107-3.893c-4.837,0-9.336,1.434-13.107,3.893l-8.95-8.95c2.11-2.286,2.04-5.869-0.206-8.118
+ c-2.305-2.304-6.018-2.328-8.293-0.054c-1.372,1.372-1.901,3.266-1.604,5.059c-1.82-0.33-3.756,0.197-5.152,1.591
+ c-2.275,2.275-2.248,5.986,0.055,8.291c2.249,2.25,5.834,2.319,8.121,0.209l9,9c-2.46,3.77-3.894,8.27-3.894,13.107
+ s1.434,9.337,3.894,13.107l-8.95,8.95c-2.286-2.11-5.869-2.04-8.118,0.206c-2.304,2.305-2.327,6.018-0.054,8.293
+ c1.372,1.372,3.266,1.901,5.059,1.604c-0.33,1.82,0.197,3.756,1.591,5.152c2.275,2.275,5.986,2.248,8.291-0.055
+ c2.249-2.249,2.319-5.834,0.209-8.121l8.726-8.726v5.946c3.645,2.985,8.303,4.779,13.382,4.779c5.079,0,9.738-1.794,13.383-4.779
+ V70.41l8.674,8.674c-2.111,2.287-2.043,5.871,0.206,8.119c2.301,2.306,6.018,2.329,8.293,0.054c1.371-1.371,1.9-3.265,1.603-5.058
+ c1.82,0.331,3.755-0.196,5.151-1.591C89.585,78.333,89.562,74.623,87.255,72.316z M43.445,58.989c-2.539,0-4.596-2.056-4.596-4.592
+ s2.057-4.597,4.596-4.597c2.535,0,4.591,2.061,4.591,4.597S45.979,58.989,43.445,58.989z M56.556,59.056
+ c-2.536,0-4.592-2.056-4.592-4.592c0-2.541,2.056-4.592,4.592-4.592c2.539,0,4.595,2.051,4.595,4.592
+ C61.151,57,59.095,59.056,56.556,59.056z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-500px.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-500px.svg
new file mode 100644
index 0000000..1cd1f57
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-500px.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M65.193,43.131c-1.031,0-2.022,0.22-2.975,0.656
+ c-0.954,0.438-1.854,0.992-2.704,1.661c-0.85,0.669-1.661,1.403-2.434,2.201c-0.772,0.799-1.468,1.532-2.086,2.201
+ c0.669,0.771,1.391,1.532,2.163,2.278c0.773,0.747,1.596,1.417,2.472,2.008c0.875,0.593,1.789,1.069,2.743,1.429
+ c0.952,0.361,1.97,0.541,3.051,0.541c1.905,0,3.373-0.618,4.404-1.854c1.03-1.236,1.545-2.754,1.545-4.557
+ c0-1.802-0.554-3.348-1.661-4.635C68.604,43.775,67.098,43.131,65.193,43.131z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M43.562,47.649c-0.825-0.798-1.688-1.532-2.588-2.201
+ c-0.902-0.669-1.842-1.223-2.82-1.661c-0.979-0.437-1.958-0.656-2.935-0.656c-1.803,0-3.233,0.683-4.288,2.047
+ c-1.056,1.364-1.584,2.896-1.584,4.596c0,1.854,0.541,3.373,1.622,4.557c1.082,1.185,2.575,1.776,4.481,1.776
+ c0.977,0,1.956-0.193,2.935-0.579c0.978-0.387,1.905-0.875,2.781-1.468c0.875-0.592,1.7-1.261,2.472-2.008
+ c0.772-0.746,1.468-1.479,2.086-2.201C45.107,49.182,44.385,48.448,43.562,47.649z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M79,14H21c-3.866,0-7,3.134-7,7v58c0,3.866,3.134,7,7,7h58c3.866,0,7-3.134,7-7
+ V21C86,17.134,82.866,14,79,14z M77.708,55.102c-0.618,1.751-1.494,3.282-2.627,4.596c-1.134,1.312-2.538,2.344-4.21,3.089
+ c-1.674,0.747-3.542,1.12-5.601,1.12c-1.597,0-3.09-0.244-4.481-0.733c-1.391-0.489-2.692-1.132-3.901-1.931
+ c-1.211-0.799-2.356-1.725-3.438-2.781c-1.081-1.055-2.112-2.149-3.09-3.282c-1.082,1.133-2.138,2.227-3.168,3.282
+ c-1.031,1.057-2.124,1.982-3.284,2.781c-1.159,0.799-2.421,1.441-3.785,1.931c-1.365,0.489-2.897,0.733-4.597,0.733
+ c-2.112,0-3.992-0.373-5.64-1.12c-1.649-0.745-3.065-1.749-4.249-3.012c-1.186-1.261-2.086-2.768-2.704-4.519
+ c-0.618-1.75-0.927-3.63-0.927-5.639c0-2.008,0.295-3.873,0.888-5.6c0.591-1.725,1.455-3.217,2.588-4.479
+ c1.132-1.261,2.523-2.265,4.172-3.013c1.648-0.745,3.502-1.119,5.562-1.119c1.7,0,3.257,0.258,4.674,0.773
+ c1.416,0.515,2.729,1.196,3.94,2.046c1.21,0.85,2.343,1.829,3.399,2.935c1.055,1.108,2.098,2.278,3.129,3.515
+ c0.977-1.185,1.995-2.343,3.051-3.476c1.055-1.133,2.188-2.125,3.399-2.975c1.21-0.85,2.523-1.531,3.94-2.046
+ c1.416-0.515,2.948-0.773,4.597-0.773c2.06,0,3.914,0.36,5.562,1.081c1.647,0.722,3.038,1.713,4.172,2.974
+ c1.132,1.262,2.008,2.742,2.627,4.441c0.618,1.699,0.927,3.553,0.927,5.561S78.327,53.352,77.708,55.102z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-adobe.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-adobe.svg
new file mode 100644
index 0000000..6fbeebe
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-adobe.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon fill="#231F20" points="59.386,18.139 86,81.861 86,18.139 "/>
+ <polygon fill="#231F20" points="14,18.139 14,81.861 40.635,18.139 "/>
+ <polygon fill="#231F20" points="38.373,69.043 50.782,69.043 55.857,81.857 66.97,81.857 50.01,41.622 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-amazon.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-amazon.svg
new file mode 100644
index 0000000..c6c5baf
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-amazon.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M52.02,35.981c-4.333,0.371-8.663,0.795-12.852,2.047c-8.593,2.574-12.979,8.387-12.838,16.969
+ c0.128,7.734,4.601,12.865,12.285,13.684c4.953,0.527,9.708-0.293,13.728-3.584c1.151-0.941,2.23-1.971,3.249-2.875
+ c1.665,1.838,3.229,3.666,4.906,5.387c1.063,1.09,2.088,1.047,3.231,0.068c2.144-1.832,4.275-3.68,6.407-5.527
+ c1.152-1,1.302-1.889,0.268-3.059c-2.529-2.867-3.404-6.16-3.337-9.955c0.118-6.76,0.064-13.529-0.161-20.285
+ c-0.171-5.197-2.768-9.066-7.554-11.184c-7.35-3.25-14.798-3.178-22.127,0.051c-4.949,2.184-7.977,6.076-9.16,11.377
+ c-0.388,1.742,0.076,2.392,1.83,2.602c2.529,0.303,5.055,0.627,7.581,0.957c1.393,0.182,2.168-0.236,2.47-1.631
+ c0.899-4.154,5.005-6.209,8.898-5.631c2.513,0.373,4.387,1.963,4.771,4.371c0.312,1.959,0.289,3.973,0.413,5.941
+ c-0.331,0.09-0.456,0.145-0.586,0.156C52.968,35.907,52.494,35.94,52.02,35.981z M51.835,55.753
+ c-1.262,1.906-2.879,3.281-5.155,3.664c-3.688,0.619-6.401-1.754-6.672-5.738c-0.355-5.217,2.309-8.791,7.459-9.781
+ c2.077-0.4,4.213-0.496,6.422-0.742C53.91,47.661,54.362,51.933,51.835,55.753z"/>
+ <path d="M75.38,70.892c-0.357,0.106-0.698,0.262-1.042,0.408c-4.914,2.096-9.966,3.748-15.213,4.783
+ c-4.954,0.979-9.942,1.473-14.99,1.006c-6.205-0.57-11.993-2.566-17.527-5.324c-3.522-1.754-6.962-3.672-10.447-5.502
+ c-1.093-0.574-2.095-0.404-2.656,0.391c-0.554,0.783-0.362,1.814,0.616,2.584c3.468,2.729,6.845,5.594,10.478,8.086
+ c6.773,4.645,14.24,7.418,23.981,7.414c7.914-0.199,16.618-2.611,24.675-7.299c1.434-0.834,2.808-1.785,4.148-2.766
+ c1.021-0.748,1.24-1.848,0.718-2.789C77.617,70.974,76.501,70.56,75.38,70.892z"/>
+ <path d="M82.865,63.228c-3.83-0.387-7.529,0.078-10.761,2.443c-0.751,0.547-1.186,1.287-0.776,2.203
+ c0.391,0.873,1.19,0.986,2.077,0.861c1.678-0.236,3.363-0.428,5.046-0.639c0.004,0.043,0.008,0.086,0.012,0.131
+ c0.612,0,1.223-0.008,1.833,0.002c0.707,0.012,1.084,0.32,0.921,1.08c-0.179,0.828-0.3,1.674-0.55,2.479
+ c-0.481,1.555-1.103,3.068-1.519,4.637c-0.131,0.494,0.031,1.324,0.381,1.621c0.399,0.336,1.175,0.383,1.754,0.305
+ c0.408-0.053,0.806-0.477,1.13-0.811c2.582-2.672,3.898-5.943,4.29-9.576C87.088,64.394,86.455,63.591,82.865,63.228z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-android.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-android.svg
new file mode 100644
index 0000000..0b5d69f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-android.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M60.623,18.128l3.36-6.136c0.179-0.322,0.062-0.733-0.262-0.909c-0.329-0.179-0.734-0.056-0.907,0.265
+ l-3.396,6.197c-2.856-1.267-6.053-1.981-9.432-1.978c-3.373-0.003-6.564,0.707-9.411,1.972l-3.398-6.184
+ c-0.174-0.326-0.584-0.445-0.904-0.267c-0.326,0.174-0.446,0.583-0.265,0.905l3.362,6.13c-6.606,3.408-11.068,9.893-11.064,17.341
+ l43.365-0.004C71.673,28.014,67.219,21.54,60.623,18.128z M40.124,27.609c-0.999-0.002-1.812-0.815-1.812-1.818
+ c0-0.998,0.813-1.818,1.813-1.818c1.006,0,1.819,0.82,1.82,1.818C41.945,26.794,41.131,27.609,40.124,27.609z M59.87,27.605
+ c-1.002,0-1.82-0.811-1.818-1.818c0-0.996,0.814-1.816,1.818-1.82c0.997,0.002,1.815,0.824,1.815,1.822
+ C61.685,26.792,60.872,27.605,59.87,27.605z"/>
+ <path fill="#231F20" d="M83.009,41.038c0-2.66-2.155-4.814-4.815-4.814c-2.658-0.002-4.813,2.156-4.812,4.816l0.002,20.159
+ c0.001,2.662,2.155,4.815,4.816,4.813c2.658,0,4.811-2.151,4.812-4.815L83.009,41.038z"/>
+ <path fill="#231F20" d="M71.523,37.131L71.523,37.131l-43.039,0.008l0.007,31.241c-0.001,0.819,0.207,1.581,0.546,2.267
+ c0.837,1.697,2.567,2.872,4.591,2.872h3.498l0.004,10.666c0,0.332,0.034,0.656,0.098,0.969C37.676,87.348,39.618,89,41.94,89
+ c0.332,0,0.657-0.034,0.971-0.098c2.194-0.45,3.845-2.393,3.845-4.718l-0.003-10.666h6.499l0,10.666
+ c0.003,2.323,1.657,4.268,3.848,4.715c0.313,0.064,0.637,0.097,0.969,0.097c2.66,0.002,4.815-2.159,4.815-4.817l-0.003-10.662
+ l3.511-0.002c0.961,0.001,1.851-0.281,2.621-0.742c1.5-0.897,2.517-2.52,2.518-4.398L71.523,37.131L71.523,37.131z"/>
+ <path fill="#231F20" d="M21.801,36.229c-2.659,0-4.813,2.159-4.814,4.814l0.003,20.161c0.001,1.683,0.862,3.156,2.164,4.017
+ c0.761,0.504,1.671,0.8,2.651,0.802c2.328-0.003,4.269-1.65,4.716-3.847c0.064-0.314,0.097-0.639,0.097-0.972V41.042
+ C26.618,38.385,24.46,36.229,21.801,36.229z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-apple.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-apple.svg
new file mode 100644
index 0000000..18810d5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-apple.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" fill="#231F20" d="M82.047,36.841c-4.124-5.139-9.91-8.112-15.372-8.112
+ c-7.226,0-10.279,3.433-15.292,3.433c-5.167,0-9.096-3.428-15.346-3.428c-6.139,0-12.666,3.729-16.804,10.102
+ c-5.823,8.962-4.837,25.824,4.605,40.193c3.377,5.138,7.887,10.916,13.784,10.971c5.241,0.048,6.724-3.343,13.835-3.383
+ c7.112-0.039,8.457,3.42,13.697,3.371c5.897-0.056,10.655-6.454,14.03-11.593c2.419-3.681,3.32-5.541,5.199-9.702
+ C70.732,63.535,68.537,44.246,82.047,36.841z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" fill="#231F20" d="M61.194,22.988c2.625-3.368,4.619-8.126,3.895-12.988
+ c-4.288,0.296-9.304,3.023-12.232,6.58c-2.658,3.228-4.853,8.015-3.999,12.668C53.539,29.393,58.383,26.596,61.194,22.988z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-behance.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-behance.svg
new file mode 100644
index 0000000..20c5012
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-behance.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M64.165,56.231c-3.279,0-4.361,2.494-4.69,3.652h8.754c-0.082-0.643-0.339-1.773-1.157-2.597
+ C66.375,56.587,65.4,56.231,64.165,56.231z"/>
+ <path fill="#231F20" d="M41.662,60.889c-0.003,0-0.003,0-0.003,0H33.37v7.067h7.839c1.398-0.035,3.13-0.485,3.13-3.422
+ C44.339,60.991,41.936,60.889,41.662,60.889z"/>
+ <path fill="#231F20" d="M79.035,14.073h-58c-3.151,0-5.815,2.083-6.693,4.946v62.107c0.741,2.419,2.757,4.28,5.265,4.8h60.855
+ c2.438-0.505,4.406-2.281,5.196-4.602V18.821C84.719,16.061,82.112,14.073,79.035,14.073z M57.268,44.448
+ c0-0.277,0.226-0.502,0.502-0.502h12.465c0.274,0,0.501,0.225,0.501,0.502v3.721c0,0.277-0.228,0.501-0.501,0.501H57.77
+ c-0.276,0-0.502-0.224-0.502-0.501V44.448z M51.974,65.087c0,4.75-2.513,7.041-4.625,8.12c-2.301,1.179-4.686,1.271-5.364,1.271
+ H26.162c-0.274,0-0.502-0.227-0.502-0.503V43.77c0-0.277,0.228-0.503,0.502-0.503h15.721c5.58,0,9.047,3.274,9.047,8.547
+ c0,3.266-1.591,4.833-2.991,5.579c0.785,0.277,1.47,0.719,2.041,1.329C52.174,61.042,51.986,64.922,51.974,65.087z M75.278,64.632
+ c-0.03,0.25-0.244,0.437-0.497,0.437H59.648c0.109,1.659,0.766,2.856,1.953,3.563c1.05,0.623,2.211,0.691,2.657,0.691
+ c0.093,0,0.151-0.004,0.158-0.006c1.737,0,2.97-0.383,3.697-1.139c0.697-0.726,0.678-1.547,0.673-1.582
+ c0-0.138,0.046-0.271,0.144-0.371c0.093-0.098,0.223-0.155,0.362-0.155h5.313c0.278,0,0.504,0.225,0.504,0.503
+ c0,8.131-8.683,8.543-10.429,8.543c-0.279,0-0.438-0.01-0.438-0.01s-0.002,0-0.005,0c-3.92,0-6.987-1.143-9.091-3.395
+ c-3.297-3.534-2.996-8.478-2.981-8.686c0-0.089,0.014-3.019,1.495-5.992c1.391-2.773,4.352-6.081,10.612-6.081
+ c3.587,0,6.38,1.102,8.287,3.274C76.068,58.227,75.318,64.372,75.278,64.632z"/>
+ <path fill="#231F20" d="M43.29,52.132c0-2.609-1.565-2.639-1.63-2.639h-1.135H33.37v5.734h7.742
+ C42.263,55.227,43.29,54.991,43.29,52.132z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-bing.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-bing.svg
new file mode 100644
index 0000000..8e256be
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-bing.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <ellipse cx="50.156" cy="56.277" rx="19.383" ry="13.568"/>
+ <path d="M77.132,38.339c-7.063-4.908-15.964-7.331-24.577-7.779c-10.167-0.102-20.041,1.224-29.082,7.514v-19.34h-11.32v35.044
+ c-0.129,14.675,9.747,20.961,22.465,25.78c4.621,1.14,9.741,1.709,15.36,1.709c5.526,0,10.588-0.569,15.186-1.709
+ c4.597-1.141,8.568-2.973,11.912-4.984c3.344-2.012,5.944-4.365,7.802-7.061c1.857-2.694,2.786-5.572,2.786-8.63
+ C89.094,48.444,81.907,41.657,77.132,38.339z M53.313,75.017c-12.718,0.398-27.624-3.441-29.07-18.361
+ c-0.804-8.291,7.453-18.73,25.735-19.374c7.517-0.265,25.052,3.927,26.249,18.091C76.964,64.104,66.031,74.62,53.313,75.017z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-blogger.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-blogger.svg
new file mode 100644
index 0000000..8a45b49
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-blogger.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M74.121,14H25.88C19.351,14,14,19.351,14,25.88v48.24
+ C14,80.65,19.351,86,25.88,86h48.241C80.65,86,86,80.65,86,74.12V25.88C86,19.351,80.65,14,74.121,14z M71.821,57.982
+ c-0.044,7.649-6.264,13.913-13.928,13.913H41.886c-7.664,0-13.928-6.264-13.928-13.913V41.725c0-7.665,6.264-13.943,13.928-13.943
+ h9.743c3.596,0.428,8.829,3.508,10.759,7.605c0.531,1.149,0.81,1.326,1.253,4.73c0.236,1.754,0.354,3.051,1.135,3.773
+ c1.105,1.002,5.203,0.324,6.014,0.958l0.619,0.486l0.368,0.767l0.133,0.619L71.821,57.982z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M42.063,44.495h7.724c1.474,0,2.668-1.209,2.668-2.668
+ c0-1.459-1.194-2.653-2.668-2.653h-7.724c-1.474,0-2.667,1.194-2.667,2.653C39.396,43.286,40.589,44.495,42.063,44.495z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M57.76,55.122H42.063c-1.474,0-2.667,1.193-2.667,2.653
+ c0,1.443,1.194,2.652,2.667,2.652H57.76c1.459,0,2.653-1.209,2.653-2.652C60.414,56.315,59.219,55.122,57.76,55.122z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-delicious.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-delicious.svg
new file mode 100644
index 0000000..8e3a592
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-delicious.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon points="50,49.947 50,16.053 16,16.053 16,50.053 50,50.053 50,83.947 84,83.947 84,49.947 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-designer-news.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-designer-news.svg
new file mode 100644
index 0000000..13be8b3
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-designer-news.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon fill="#231F20" points="66.746,37.902 67.007,53.646 57.843,38.842 57.261,37.902 52.68,37.902 51.843,37.902
+ 51.789,37.902 51.789,46.4 51.789,62.903 57.898,62.903 57.636,47.722 67.308,62.903 72.855,62.903 72.855,49.113 72.855,37.902
+ 66.746,37.902 "/>
+ <path fill="#231F20" d="M79,14H21c-3.85,0-7,3.15-7,7v58c0,3.85,3.15,7,7,7h31.825L24.843,63.556V39.288v-2.039v-0.347h1.132h0.312
+ h0.688h8.397c3.975,0,6.096,0.493,8.394,1.945c1.259,0.771,2.411,1.865,3.327,3.156c0.377,0.523,0.703,1.071,0.993,1.637
+ l2.703,2.014v-7.753v-1h1h5.472h0.557l0.293,0.474l0.104,0.167l7.625,6.025l-0.094-5.65l-0.017-1.017h1.017h6.109h1v0.01L86,46.753
+ V21C86,17.15,82.85,14,79,14z"/>
+ <path fill="#231F20" d="M40.842,38.546c-1.324-0.434-2.861-0.613-5-0.636c-0.16-0.002-0.304-0.008-0.471-0.008H31.68h-0.837h-3.868
+ v0.873v24.128h9.822c7.085,0,11.771-5.023,11.771-12.595c0-3.072-0.75-5.586-2.286-7.721c-0.172-0.243-0.359-0.474-0.55-0.702h0
+ l0,0c-0.133-0.159-0.273-0.309-0.414-0.46c-0.08-0.086-0.161-0.172-0.243-0.256c-0.124-0.124-0.249-0.244-0.378-0.361
+ c-0.127-0.116-0.257-0.226-0.388-0.334c-0.102-0.084-0.201-0.169-0.305-0.248c-0.247-0.188-0.499-0.366-0.759-0.526
+ c-0.263-0.167-0.523-0.319-0.784-0.458c-0.244-0.131-0.489-0.248-0.737-0.357c-0.017-0.007-0.033-0.017-0.05-0.024l0,0
+ C41.402,38.744,41.127,38.639,40.842,38.546L40.842,38.546z M42.193,50.496c0,4.387-2.136,6.786-6.109,6.786h-2.737V43.524h2.774
+ C40.02,43.524,42.193,46.037,42.193,50.496z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-deviant-art.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-deviant-art.svg
new file mode 100644
index 0000000..9992d6b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-deviant-art.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M46.347,44.786c2.026-0.797,7.307-1.86,11.093-1.328l4.749,9.896l13.052-3.089c0.664-0.133,0.996-0.996,0-1.893
+ c-8.17-6.575-16.24-7.87-32.181-4.383l9.465,19.727l-33.044,9.316v5.995c0,0.219,0.089,0.419,0.233,0.562
+ c0.144,0.145,0.344,0.233,0.563,0.233h59.248c0.22,0,0.419-0.089,0.563-0.233c0.144-0.144,0.233-0.344,0.233-0.562V56.123
+ l-25.206,6.696C55.115,62.819,48.04,48.572,46.347,44.786z"/>
+ <path d="M79.524,19.513H20.276c-0.165,0-0.31,0.062-0.437,0.148c-0.212,0.143-0.36,0.374-0.36,0.648v25.81
+ c1.266-0.977,5.98-4.468,10.528-5.917l-3.886-8.967h10.959c0,0,2.89,6.276,2.89,6.376c3.985-1.195,23.114-4.284,40.151,3.089
+ l0.199,0.146V20.31c0-0.274-0.148-0.506-0.36-0.648C79.833,19.575,79.689,19.513,79.524,19.513z"/>
+ <path d="M27.185,61.89c2.458-0.531,11.823-3.056,11.823-3.056l-6.045-12.421c-1.66,0.465-8.634,3.653-8.103,14.347
+ C24.86,60.76,24.727,62.421,27.185,61.89z"/>
+ <path d="M80.022,14.133H19.978C16.677,14.133,14,16.81,14,20.11V79.89c0,3.301,2.677,5.977,5.978,5.977h60.044
+ c3.301,0,5.978-2.677,5.978-5.977V20.11C86,16.81,83.323,14.133,80.022,14.133z M82.313,79.026c0,1.538-1.251,2.789-2.789,2.789
+ H20.276c-1.538,0-2.79-1.251-2.79-2.789V20.31c0-1.538,1.252-2.789,2.79-2.789h59.248c1.538,0,2.789,1.251,2.789,2.789V79.026z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-digg.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-digg.svg
new file mode 100644
index 0000000..aec5efd
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-digg.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M92.546,38.012c0-0.333-0.035-0.667-0.059-1.096c-0.347,0-0.625,0-0.903,0c-6.932,0-13.863,0.014-20.794-0.017
+ c-0.825-0.004-1.055,0.236-1.052,1.055c0.029,7.811,0.029,15.623-0.001,23.435c-0.003,0.838,0.26,1.05,1.065,1.042
+ c3.977-0.036,7.954-0.018,11.931-0.014c0.33,0,0.659,0.029,1.071,0.049c0,1.126-0.046,2.173,0.015,3.214
+ c0.044,0.745-0.182,0.972-0.944,0.964c-4.062-0.037-8.125,0.004-12.187-0.035c-0.772-0.008-0.97,0.239-0.947,0.966
+ c0.047,1.504,0.052,3.013-0.002,4.517c-0.027,0.759,0.225,0.944,0.968,0.941c6.931-0.028,13.862-0.037,20.793,0.008
+ c0.914,0.006,1.065-0.293,1.062-1.111C92.541,60.623,92.549,49.317,92.546,38.012z M82.958,56.034
+ c-1.219-0.042-2.442-0.033-3.662-0.002c-0.605,0.016-0.854-0.16-0.85-0.816c0.026-3.719,0.004-7.438,0.031-11.157
+ c0.002-0.254,0.265-0.721,0.419-0.727c1.608-0.054,3.219-0.032,4.909-0.032c0,0.818,0,1.523,0,2.229
+ c0,3.209-0.018,6.417,0.014,9.625C83.826,55.821,83.631,56.058,82.958,56.034z"/>
+ <path d="M66.026,36.899c-6.902,0.029-13.805,0.03-20.707-0.001c-0.814-0.004-1.054,0.215-1.051,1.04
+ c0.03,7.811,0.03,15.622,0,23.434c-0.003,0.81,0.203,1.069,1.039,1.061c4.004-0.041,8.01,0.012,12.014-0.041
+ c0.901-0.012,1.142,0.278,1.068,1.113c-0.064,0.732-0.052,1.478-0.002,2.214c0.048,0.701-0.195,0.927-0.91,0.922
+ c-4.033-0.03-8.067-0.014-12.1-0.014c-0.329,0-0.658,0-1.091,0c0,1.898,0.038,3.683-0.018,5.464
+ c-0.024,0.767,0.227,0.944,0.966,0.941c6.959-0.028,13.918-0.016,20.877-0.018c0.277-0.001,0.554-0.024,0.905-0.041
+ c0.021-0.347,0.056-0.65,0.056-0.953c0.002-11.362-0.007-22.724,0.02-34.086C67.093,37.095,66.828,36.896,66.026,36.899z
+ M58.348,55.458c-0.002,0.188-0.349,0.528-0.544,0.534c-1.418,0.046-2.839,0.042-4.256,0.001c-0.176-0.004-0.493-0.316-0.494-0.488
+ c-0.028-4.025-0.021-8.053-0.021-12.216c1.696,0,3.253-0.02,4.808,0.026c0.183,0.005,0.509,0.365,0.511,0.562
+ C58.38,47.737,58.38,51.599,58.348,55.458z"/>
+ <path d="M21.554,27.974c0,2.557,0,5.114,0,7.671c0,1.271,0,1.272-1.312,1.272c-3.949,0-7.898,0.018-11.847-0.016
+ c-0.746-0.007-0.96,0.202-0.958,0.957c0.026,8.607,0.027,17.217-0.002,25.824c-0.003,0.799,0.232,0.995,1.006,0.991
+ c6.932-0.027,13.864-0.016,20.796-0.018c0.303,0,0.605-0.025,0.927-0.04c0-12.597,0-25.107,0-37.655c-2.874,0-5.674,0-8.611,0
+ C21.554,27.356,21.554,27.665,21.554,27.974z M20.555,58.281c-1.218-0.058-2.441,0.01-3.66-0.04
+ c-0.234-0.009-0.654-0.313-0.655-0.484c-0.036-4.766-0.029-9.53-0.029-14.404c1.821,0,3.535,0,5.343,0c0,0.353,0,0.629,0,0.908
+ c0,4.342-0.02,8.685,0.018,13.027C21.579,58.089,21.324,58.316,20.555,58.281z"/>
+ <path d="M40.852,36.911c-2.328,0.013-4.658,0.037-6.985-0.012c-0.781-0.017-0.952,0.268-0.941,0.985
+ c0.036,2.47,0.014,4.94,0.014,7.412c0,6.134,0.01,12.268-0.013,18.401c-0.003,0.713,0.146,1.036,0.937,0.975
+ c0.903-0.07,1.816-0.017,2.725-0.017c1.641,0,3.281,0,4.961,0c0.04-0.232,0.067-0.315,0.067-0.398
+ c0.004-8.889,0.001-17.776,0.021-26.665C41.638,36.973,41.341,36.909,40.852,36.911z"/>
+ <path d="M33.633,33.511c2.442,0.037,4.886,0.014,7.329,0.031c0.53,0.004,0.69-0.209,0.672-0.712
+ c-0.03-0.823-0.007-1.647-0.007-2.472c0-1.124,0-2.248,0-3.398c-2.935,0-5.737,0-8.68,0c0,2.08-0.017,4.064,0.03,6.049
+ C32.98,33.189,33.401,33.508,33.633,33.511z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dribbble.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dribbble.svg
new file mode 100644
index 0000000..ac6dd61
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dribbble.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M50,13.766c-19.979,0-36.234,16.255-36.234,36.233
+ c0,19.98,16.255,36.234,36.234,36.234S86.234,69.98,86.234,50C86.234,30.021,69.98,13.766,50,13.766z M73.957,30.475
+ c4.311,5.266,6.92,11.974,6.989,19.28c-1.021-0.218-11.253-2.291-21.551-0.997c-0.217-0.53-0.439-1.062-0.666-1.597
+ c-0.644-1.509-1.334-3.01-2.054-4.482C68.118,38.005,73.305,31.359,73.957,30.475z M50,19.097c7.864,0,15.051,2.95,20.517,7.798
+ c-0.557,0.794-5.216,7.056-16.221,11.181c-5.071-9.318-10.693-16.973-11.548-18.119C45.075,19.397,47.503,19.097,50,19.097z
+ M36.843,22.039c0.815,1.118,6.346,8.783,11.474,17.898c-14.477,3.845-27.228,3.788-28.612,3.771
+ C21.711,34.105,28.183,26.123,36.843,22.039z M19.05,50.046c0-0.316,0.006-0.631,0.016-0.945
+ c1.354,0.028,16.353,0.221,31.808-4.404c0.886,1.733,1.732,3.494,2.509,5.253c-0.409,0.115-0.816,0.237-1.22,0.368
+ c-15.962,5.159-24.456,19.224-25.157,20.424C22.064,65.254,19.05,57.996,19.05,50.046z M50,80.998
+ c-7.155,0-13.75-2.441-18.998-6.533c0.558-1.139,6.825-13.246,24.281-19.328c0.068-0.023,0.136-0.045,0.205-0.069
+ c4.345,11.291,6.141,20.755,6.602,23.472C58.374,80.119,54.287,80.998,50,80.998z M67.292,75.704
+ c-0.316-1.883-1.963-10.943-6.012-22.067c9.698-1.552,18.219,0.989,19.278,1.322C79.179,63.572,74.236,71.009,67.292,75.704z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-drive.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-drive.svg
new file mode 100644
index 0000000..6dda57e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-drive.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon fill="#050708" points="40.588,59.659 27.579,82.03 74.491,82.03 87.5,59.659 "/>
+ <polygon fill="#050708" points="85.952,58.379 62.496,17.753 36.617,17.672 60.073,58.3 "/>
+ <polygon fill="#050708" points="35.956,19.249 12.5,59.876 25.37,82.328 48.826,41.701 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dropbox.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dropbox.svg
new file mode 100644
index 0000000..612b04a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-dropbox.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="Layer_1_2_">
+ <polygon points="34.063,13.993 11.288,28.864 27.035,41.476 50,27.295 "/>
+ <polygon points="11.288,54.087 34.063,68.956 50,55.653 27.035,41.476 "/>
+ <polygon points="50,55.653 65.937,68.956 88.712,54.087 72.965,41.476 "/>
+ <polygon points="88.712,28.864 65.937,13.993 50,27.295 72.965,41.476 "/>
+ <polygon points="50.046,58.517 34.063,71.778 27.223,67.314 27.223,72.319 50.046,86.007 72.871,72.319 72.871,67.314
+ 66.03,71.778 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-evernote.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-evernote.svg
new file mode 100644
index 0000000..dd72619
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-evernote.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M23.851,26.072c0,0,0,0,0.005,0h7.331c0.42,0,0.758-0.342,0.759-0.758c0-0.004-0.089-6.286-0.089-8.033V17.26
+ c0-1.436,0.301-2.686,0.826-3.735l0.25-0.471c-0.027,0.005-0.055,0.019-0.083,0.048L18.605,27.226
+ c-0.028,0.022-0.045,0.052-0.054,0.083c0.295-0.147,0.698-0.345,0.755-0.37C20.546,26.379,22.051,26.072,23.851,26.072z"/>
+ <path d="M80.894,24.535c-0.582-3.117-2.435-4.654-4.111-5.258c-1.808-0.653-5.474-1.33-10.08-1.873
+ c-3.706-0.436-8.06-0.401-10.691-0.32c-0.316-2.162-1.833-4.138-3.53-4.822c-4.522-1.818-11.509-1.381-13.303-0.878
+ c-1.425,0.398-3.003,1.216-3.881,2.474c-0.589,0.84-0.971,1.917-0.974,3.421c0,0.852,0.024,2.856,0.045,4.639
+ c0.022,1.788,0.045,3.386,0.045,3.398c-0.001,1.591-1.291,2.887-2.889,2.889h-7.332c-1.564,0-2.759,0.264-3.672,0.678
+ c-0.914,0.414-1.561,0.975-2.053,1.637c-0.979,1.312-1.15,2.936-1.145,4.592c0,0,0.014,1.352,0.34,3.971
+ c0.271,2.026,2.468,16.182,4.555,20.485c0.809,1.674,1.349,2.372,2.938,3.109c3.542,1.518,11.633,3.205,15.424,3.688
+ c3.785,0.484,6.161,1.503,7.577-1.467c0.004-0.006,0.283-0.738,0.667-1.81c1.229-3.724,1.4-7.03,1.4-9.42
+ c0-0.243,0.356-0.255,0.356,0c0,1.689-0.323,7.662,4.191,9.265c1.781,0.632,5.478,1.195,9.233,1.635
+ c3.396,0.391,5.86,1.729,5.86,10.439c0,5.301-1.113,6.027-6.933,6.027c-4.719,0-6.517,0.122-6.517-3.626
+ c0-3.028,2.997-2.712,5.217-2.712c0.992,0,0.272-0.737,0.272-2.606c0-1.86,1.163-2.934,0.063-2.962
+ c-7.678-0.211-12.196-0.01-12.196,9.594c0,8.717,3.336,10.337,14.234,10.337c8.544,0,11.556-0.28,15.084-11.227
+ c0.698-2.162,2.386-8.756,3.409-19.829C83.144,51,81.89,29.869,80.894,24.535z M66,47.892c-1.056-0.037-2.07,0.028-3.018,0.182
+ c0.268-2.153,1.155-4.793,4.301-4.682c3.483,0.119,3.972,3.411,3.984,5.642C69.798,48.378,67.98,47.961,66,47.892z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-facebook.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-facebook.svg
new file mode 100644
index 0000000..303af06
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-facebook.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="White_1_">
+ <path d="M82.026,14H17.974C15.779,14,14,15.779,14,17.974v64.053C14,84.221,15.779,86,17.974,86h34.483V58.118h-9.383V47.252h9.383
+ v-8.014c0-9.3,5.68-14.363,13.976-14.363c3.974,0,7.389,0.295,8.385,0.428v9.719l-5.754,0.003c-4.512,0-5.385,2.144-5.385,5.29
+ v6.938h10.76l-1.401,10.866h-9.359V86h18.348C84.221,86,86,84.221,86,82.026V17.974C86,15.779,84.221,14,82.026,14z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-flickr.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-flickr.svg
new file mode 100644
index 0000000..99ace87
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-flickr.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M79,14H21c-3.85,0-7,3.15-7,7v58c0,3.85,3.15,7,7,7h58c3.85,0,7-3.15,7-7V21C86,17.15,82.85,14,79,14z M35.435,61.5
+ c-6.456,0-11.69-5.233-11.69-11.689c0-6.456,5.234-11.69,11.69-11.69c6.456,0,11.689,5.233,11.689,11.69
+ C47.124,56.267,41.891,61.5,35.435,61.5z M65.068,61.5c-6.456,0-11.69-5.233-11.69-11.689c0-6.456,5.233-11.69,11.69-11.69
+ c6.456,0,11.689,5.233,11.689,11.69C76.758,56.267,71.524,61.5,65.068,61.5z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-forrst.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-forrst.svg
new file mode 100644
index 0000000..7c4aee4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-forrst.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="Forrst_1_">
+ <polygon points="84.173,91 49.968,9 15.827,90.853 44.628,90.853 44.628,88.344 44.628,73.984 35.973,68.049 38.092,64.91
+ 44.628,69.374 44.628,56.299 53.575,56.299 53.575,64.605 60.041,61.191 61.905,64.617 53.575,69.024 53.575,73.732 66.112,67.458
+ 67.777,70.835 53.575,77.958 53.575,90.853 71.398,90.853 71.398,91 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-foursquare.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-foursquare.svg
new file mode 100644
index 0000000..73fa517
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-foursquare.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M36.217,40.748c-0.495-0.498-1.175-0.781-1.878-0.78c-0.698,0.001-1.384,0.281-1.881,0.776l-6.322,6.315
+ c-1.041,1.038-1.044,2.72-0.003,3.759L47.531,72.26c0.429,0.432,0.986,0.697,1.579,0.762c0.099,0.016,0.201,0.02,0.304,0.02
+ c0.007,0,0.013,0,0.019-0.002l0.003,0.002c0.715,0.002,1.393-0.281,1.899-0.781L89.72,33.856c1.04-1.037,1.04-2.716,0.002-3.757
+ l-6.312-6.322c-0.507-0.502-1.168-0.783-1.881-0.778c-0.711-0.005-1.377,0.276-1.883,0.776L49.438,53.994L36.217,40.748z"/>
+ <path d="M87.348,43.137L54.835,75.666c-1.404,1.389-3.262,2.154-5.24,2.154l-1.443-0.002l-0.304-0.204
+ c-1.324-0.315-2.549-0.997-3.518-1.97L22.939,54.208c-1.402-1.399-2.175-3.259-2.174-5.238c0-1.981,0.774-3.845,2.175-5.242
+ l6.33-6.322c1.375-1.368,3.277-2.153,5.236-2.157c1.952,0,3.862,0.797,5.234,2.175l9.863,9.88l20.953-20.96L56.599,12.387
+ c-3.694-3.693-9.738-3.693-13.432,0L12.271,43.283c-3.695,3.693-3.695,9.74,0,13.433l30.897,30.897
+ c3.694,3.693,9.737,3.693,13.432,0l30.897-30.897c3.694-3.692,3.694-9.737,0-13.433L87.348,43.137z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-game-center.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-game-center.svg
new file mode 100644
index 0000000..a9fca3f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-game-center.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M79,14H21c-3.866,0-7,3.134-7,7v58c0,3.866,3.134,7,7,7h58c3.866,0,7-3.134,7-7V21
+ C86,17.134,82.865,14,79,14z M55.955,19.229c10.658,0,19.298,8.641,19.298,19.299c0,4.108-1.294,7.909-3.482,11.039
+ c-2.883-2.27-6.511-3.634-10.465-3.634c-6.582,0-12.275,3.76-15.082,9.242c-5.718-3.35-9.568-9.541-9.568-16.646
+ C36.656,27.87,45.296,19.229,55.955,19.229z M19.852,46.931c0-11.635,8.755-21.22,20.036-22.54
+ c-3.324,3.774-5.356,8.713-5.356,14.138c0,7.981,4.373,14.928,10.845,18.614c-0.267,0.742-0.474,1.511-0.64,2.295
+ c-1.087-0.325-2.237-0.505-3.429-0.505c-4.89,0-9.088,2.941-10.937,7.148C24.048,62.051,19.852,54.983,19.852,46.931z
+ M41.306,81.076c-5.632,0-10.197-4.564-10.197-10.197c0-5.631,4.565-10.196,10.197-10.196c5.631,0,10.197,4.565,10.197,10.196
+ C51.503,76.512,46.937,81.076,41.306,81.076z M61.306,77.826c-3.286,0-6.315-1.073-8.782-2.87c0.463-1.274,0.729-2.643,0.729-4.077
+ c0-4.689-2.708-8.735-6.639-10.691c1.269-6.968,7.357-12.255,14.693-12.255c8.255,0,14.947,6.692,14.947,14.946
+ C76.253,71.135,69.561,77.826,61.306,77.826z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-github.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-github.svg
new file mode 100644
index 0000000..a36ff8b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-github.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" fill="#181616" d="M49.998,11.963C28.461,11.963,11,29.425,11,50.965
+ c0,17.231,11.172,31.849,26.671,37.003c1.952,0.361,2.662-0.84,2.662-1.877c0-0.924-0.034-3.375-0.051-6.633
+ c-10.849,2.359-13.138-5.229-13.138-5.229c-1.774-4.505-4.331-5.703-4.331-5.703c-3.541-2.418,0.269-2.371,0.269-2.371
+ c3.914,0.277,5.974,4.018,5.974,4.018c3.478,5.96,9.129,4.235,11.35,3.243c0.353-2.525,1.363-4.24,2.476-5.217
+ c-8.659-0.984-17.763-4.33-17.763-19.274c0-4.259,1.519-7.741,4.013-10.468c-0.399-0.982-1.74-4.947,0.383-10.319
+ c0,0,3.274-1.048,10.726,4.001c3.109-0.869,6.446-1.303,9.763-1.316c3.312,0.014,6.65,0.447,9.763,1.316
+ c7.447-5.049,10.716-4.001,10.716-4.001c2.128,5.372,0.788,9.337,0.388,10.319c2.5,2.727,4.008,6.209,4.008,10.468
+ c0,14.979-9.117,18.279-17.805,19.241c1.398,1.205,2.646,3.59,2.646,7.229c0,5.211-0.047,9.416-0.047,10.695
+ c0,1.045,0.701,2.26,2.681,1.873C77.836,82.798,89,68.191,89,50.965C89,29.425,71.539,11.963,49.998,11.963z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-google-plus.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-google-plus.svg
new file mode 100644
index 0000000..6866506
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-google-plus.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M25.194,51.591c1.757,1.379,3.766,2.068,6.026,2.068c2.855-0.105,5.234-1.131,7.138-3.076
+ c0.918-1.377,1.508-2.791,1.77-4.24c0.157-1.447,0.236-2.668,0.236-3.658c0-4.276-1.094-8.588-3.281-12.936
+ c-1.026-2.084-2.376-3.781-4.051-5.09c-1.71-1.236-3.675-1.891-5.897-1.961c-2.939,0.07-5.384,1.256-7.331,3.553
+ c-1.644,2.404-2.43,5.09-2.358,8.057c0,3.924,1.147,8.008,3.444,12.248C22.001,48.534,23.436,50.214,25.194,51.591z"/>
+ <path d="M31.781,68.05c-0.782-1.027-1.479-2.127-2.091-3.299c-0.714-1.133-1.07-2.5-1.07-4.096c0-0.957,0.135-1.756,0.407-2.395
+ c0.238-0.674,0.459-1.293,0.663-1.861c-1.232,0.143-2.394,0.213-3.485,0.213C21.036,56.55,16.968,55.085,14,52.224v19.338
+ c2.652-1.215,5.399-2.068,8.241-2.561C26.07,68.437,29.25,68.12,31.781,68.05z"/>
+ <path d="M34.74,71.114c-0.691-0.072-1.502-0.107-2.435-0.107c-0.553-0.07-1.969,0-4.248,0.213c-2.246,0.317-4.542,0.828-6.89,1.533
+ c-0.553,0.213-1.33,0.529-2.331,0.953c-1.002,0.459-2.021,1.111-3.056,1.959c-0.662,0.582-1.254,1.258-1.78,2.025v2.949
+ c0,2.766,2.248,5.014,5.013,5.014h27.326c0.001-0.068,0.005-0.133,0.005-0.199c0-2.752-0.899-5.15-2.694-7.197
+ C41.75,76.317,38.781,73.937,34.74,71.114z"/>
+ <path d="M80.986,14.347H68.035H50.004H31.688H19.013c-2.766,0-5.013,2.246-5.013,5.014v5.43v1.293c0.316-0.336,0.643-0.67,0.985-1
+ c3.083-2.539,6.288-4.195,9.612-4.973c3.29-0.67,6.375-1.004,9.253-1.004h21.692l-6.699,3.91h-6.689
+ c0.681,0.422,1.448,1.041,2.299,1.852c0.817,0.846,1.618,1.887,2.401,3.121c0.749,1.164,1.413,2.539,1.992,4.127
+ c0.476,1.586,0.715,3.44,0.715,5.555c-0.064,3.881-0.921,6.984-2.569,9.312c-0.809,1.129-1.665,2.168-2.569,3.121
+ c-1.002,0.953-2.068,1.922-3.199,2.91c-0.646,0.67-1.244,1.428-1.793,2.275c-0.646,0.881-0.97,1.904-0.97,3.068
+ c0,1.129,0.332,2.062,0.994,2.803c0.563,0.707,1.11,1.324,1.641,1.854l3.68,3.016c2.287,1.869,4.292,3.932,6.016,6.189
+ c1.625,2.293,2.47,5.291,2.536,8.994c0,1.531-0.198,3.01-0.592,4.439h28.25c2.766,0,5.014-2.248,5.014-5.014V24.79v-5.43
+ C86,16.593,83.752,14.347,80.986,14.347z M84.931,36.464H73.549v11.383h-5.514V36.464H56.653V30.95h11.382V19.569h5.514V30.95
+ h11.382V36.464z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hacker-news.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hacker-news.svg
new file mode 100644
index 0000000..b09bae7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hacker-news.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M79,14H21c-3.866,0-7,3.134-7,7v58c0,3.866,3.134,7,7,7h58c3.866,0,7-3.134,7-7V21
+ C86,17.134,82.866,14,79,14z M53.134,52.654V69.83h-5.267V52.714L35.12,29.494h5.925l5.685,11.132
+ c1.556,3.051,2.752,5.505,4.01,8.318h0.12c1.137-2.634,2.514-5.268,4.07-8.318l5.805-11.132h5.924L53.134,52.654z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hi5.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hi5.svg
new file mode 100644
index 0000000..f886c65
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-hi5.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M93.246,44.073c0.244-5.331,0.487-10.662,0.731-15.993c-10.425,0-20.851,0-31.276,0l-1.564,8.465v-6.128
+ c-5.724,0-11.448,0-17.171,0v7.947h-5.567v1.736c-3.268-2.575-8.316-2.712-12.109-1.3V28.08c-7.58,0-15.159,0-22.739,0
+ c0,5.014,0,10.027,0,15.041h2.956v12.864H3.55c0,4.968,0,9.935,0,14.903c20.181,0,40.361,0,60.542,0v-1.955
+ c3.732,2.115,8.155,2.986,12.412,2.986c5.88,0,10.547-1.768,13.888-4.518c3.461-2.849,5.606-7.444,5.994-12.132
+ C96.717,51.262,95.763,47.185,93.246,44.073z M47.912,34.363h9.279v6.255h-9.279V34.363z M41.648,66.943H25.361v-7.011h1.557V51.37
+ c0-4.036-4.575-2.609-4.575,4.052v4.51h1.375v7.011H7.497v-7.011h2.955V39.175H7.497v-7.148h14.846V47.18
+ c1.955-3.149,4.606-5.295,8.998-5.295c6.221,0,7.154,5.391,7.154,7.53v10.517h3.152V66.943z M60.146,66.943H42.413v-7.011H45.3
+ V49.484h-2.956v-7.174H57.19v17.621h2.956V66.943z M76.504,67.974c-6.803,0-12.444-2.532-14.475-6.278
+ c-2.098-3.868-0.452-9.839,4.657-9.849c3.333-0.006,5.436,1.477,4.732,5.283c-0.884,2.564,0.797,3.414,2.423,3.414
+ c2.464,0,4.336-2.837,4.464-5.733c0.12-2.721-1-5.366-3.508-5.395c-1.017-0.012-2.227,0.371-3.379,1.778l-8.77-1.183l3.323-17.985
+ h23.886l-0.43,9.416H73.663l-0.362,3.016c2.267-1.005,4.984-1.689,7.482-1.689c6.628,0,11.978,3.343,11.667,12.077
+ C92.45,61.584,86.938,67.974,76.504,67.974z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-instagram.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-instagram.svg
new file mode 100644
index 0000000..bb333e2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-instagram.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M67.961,45.288c0,9.919-8.041,17.96-17.96,17.96c-9.919,0-17.96-8.041-17.96-17.96
+ c0-2.795,0.657-5.43,1.795-7.788H14v42c0,3.85,3.15,7,7,7h58c3.85,0,7-3.15,7-7v-42H66.165
+ C67.304,39.858,67.961,42.493,67.961,45.288z"/>
+ <path fill="#231F20" d="M79,13.5H21c-3.85,0-7,3.15-7,7v14h21.665c3.278-4.349,8.47-7.172,14.335-7.172s11.057,2.823,14.335,7.172
+ H86v-14C86,16.65,82.85,13.5,79,13.5z M19.756,31.216H17.15V21.121c0-1.766,1.076-3.279,2.607-3.922V31.216z M24.026,31.216h-2.469
+ V16.868h2.469V31.216z M28.295,31.216h-2.469V16.868h2.469V31.216z M32.561,21.121v5.842v4.253h-2.466V16.868h2.466V21.121z
+ M82.351,26.963c0,2.35-1.904,4.253-4.251,4.253h-6.909c-2.348,0-4.252-1.903-4.252-4.253v-5.842c0-2.35,1.904-4.253,4.252-4.253
+ h6.909c2.348,0,4.251,1.903,4.251,4.253V26.963z"/>
+ <path fill="#231F20" d="M50.001,61.148c8.736,0,15.818-7.085,15.818-15.819c0-8.735-7.081-15.82-15.818-15.82
+ c-8.738,0-15.82,7.085-15.82,15.82C34.181,54.062,41.263,61.148,50.001,61.148z M50,32.725c6.96,0,12.604,5.643,12.604,12.604
+ c0,6.96-5.643,12.604-12.604,12.604s-12.604-5.643-12.604-12.604C37.397,38.367,43.04,32.725,50,32.725z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-joomla.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-joomla.svg
new file mode 100644
index 0000000..addec2e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-joomla.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.433,68.316c-1.245-1.029-2.883-1.582-4.507-2.443c1.247-6.475-1.226-11.717-6.169-16.113
+ c-2.454-2.184-4.671-4.638-6.935-7.027c-2.06-2.176-4.038-4.43-6.348-6.976c-2.581,2.82-4.663,5.095-6.986,7.634
+ c0.418,0.318,0.987,0.655,1.438,1.109c4.596,4.621,9.167,9.27,13.76,13.895c1.703,1.715,2.339,3.752,1.544,6.012
+ c-0.786,2.234-2.489,3.82-4.891,3.749c-1.728-0.05-3.432-0.926-5.163-1.438c-1.97,1.938-4.17,4.104-6.474,6.37
+ c4.344,4.493,9.656,5.624,15.729,4.274c0.854,3.877,3.5,5.938,6.805,7.368c1.55,0,3.101,0,4.652,0
+ c0.324-0.168,0.638-0.363,0.975-0.501C85.625,81.467,87.046,72.96,81.433,68.316z"/>
+ <path d="M56.4,51.269c-0.291,0.411-0.625,1.066-1.122,1.559c-4.63,4.592-9.271,9.173-13.943,13.722
+ c-2.322,2.261-5.26,2.342-7.651,0.31c-2.307-1.962-2.666-5.088-0.869-7.652c0.283-0.403,0.6-0.783,0.745-0.971
+ c-2.294-2.315-4.464-4.506-6.729-6.793c-4.257,4.049-5.51,9.106-4.458,14.934c-4.266,1.211-6.417,4.191-7.282,8.273
+ c0,0.646,0,1.293,0,1.938c0.938,4.087,3.357,6.832,7.365,8.141c1.421,0,2.843,0,4.264,0c2.657-1.11,5.172-2.475,6.204-5.362
+ c0.519-1.451,1.195-1.79,2.67-1.595c4.759,0.63,8.983-0.766,12.37-4.129c5.173-5.138,10.189-10.435,15.56-15.96
+ C61.41,55.78,59.078,53.681,56.4,51.269z"/>
+ <path d="M35.946,42.96c1.963,1.91,4.17,4.056,6.537,6.358c2.867-2.889,5.67-5.742,8.507-8.561c2.288-2.273,4.571-4.553,6.939-6.742
+ c2.057-1.901,4.531-2.146,6.761-0.85c2.125,1.235,3.316,3.697,2.677,6.104c-0.318,1.197-1.119,2.266-1.673,3.338
+ c2.153,2.159,4.376,4.389,6.65,6.669c4.362-4.219,5.631-9.397,4.411-15.264c6.022-2.594,8.531-5.794,8.055-10.204
+ c-0.457-4.231-3.475-7.902-7.386-8.341c-1.958-0.22-4.138,0.099-5.998,0.776c-3.06,1.114-4.471,3.871-5.263,6.897
+ c-0.565-0.045-0.955-0.033-1.325-0.112c-4.585-0.969-8.977-0.134-12.308,2.989C46.803,31.389,41.513,37.224,35.946,42.96z"/>
+ <path d="M22.564,33.799c-1.655,6.861,0.583,12.263,5.552,16.803c2.381,2.176,4.605,4.527,6.86,6.837
+ c2.244,2.299,4.438,4.646,6.653,6.97c2.479-2.451,4.659-4.605,6.918-6.839c-0.526-0.554-1-1.065-1.489-1.563
+ c-4.568-4.649-9.164-9.274-13.7-13.955c-2.186-2.256-2.243-5.441-0.27-7.695c2.055-2.347,5.236-2.633,7.811-0.705
+ c0.34,0.255,0.69,0.496,0.633,0.455c2.356-2.362,4.563-4.575,6.786-6.805c-3.857-3.83-8.686-5.32-14.261-4.3
+ c-2.728-6.083-5.454-8.083-10.412-7.681c-3.768,0.305-7.274,3.067-8.018,6.787C14.465,27.932,17.096,31.767,22.564,33.799z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-lastfm.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-lastfm.svg
new file mode 100644
index 0000000..e9ac380
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-lastfm.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.404,46.408l-5.97-1.306c-4.104-0.932-5.316-2.611-5.316-5.41c0-3.171,2.518-5.037,6.622-5.037
+ c4.478,0,6.903,1.68,7.276,5.69l9.328-1.119c-0.746-8.396-6.529-11.848-16.044-11.848c-8.395,0-16.604,3.172-16.604,13.34
+ c0,6.344,3.078,10.354,10.82,12.22l6.344,1.492c4.757,1.12,6.342,3.079,6.342,5.784c0,3.451-3.357,4.85-9.701,4.85
+ c-9.421,0-13.338-4.943-15.578-11.753l-3.078-9.327c-3.917-12.127-10.167-16.606-22.575-16.606
+ c-13.712,0-20.988,8.676-20.988,23.414c0,14.18,7.276,21.828,20.336,21.828c10.541,0,15.578-4.944,15.578-4.944l-2.985-8.115
+ c0,0-4.851,5.411-12.126,5.411c-6.437,0-11.008-5.598-11.008-14.553c0-11.474,5.783-15.578,11.474-15.578
+ c8.208,0,10.82,5.317,13.059,12.127l2.985,9.328c2.984,9.048,8.581,16.324,24.719,16.324c11.568,0,19.403-3.545,19.403-12.873
+ C90.718,52.192,86.426,48.274,78.404,46.408z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-linkedin.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-linkedin.svg
new file mode 100644
index 0000000..e68b824
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-linkedin.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.667,14H19.315C16.381,14,14,16.325,14,19.188v61.617C14,83.672,16.381,86,19.315,86h61.352
+ C83.603,86,86,83.672,86,80.805V19.188C86,16.325,83.603,14,80.667,14z M35.354,75.354H24.67V40.995h10.684V75.354z M30.012,36.297
+ c-3.423,0-6.19-2.774-6.19-6.194c0-3.415,2.767-6.189,6.19-6.189c3.415,0,6.189,2.774,6.189,6.189
+ C36.201,33.523,33.427,36.297,30.012,36.297z M75.35,75.354H64.683V58.646c0-3.986-0.078-9.111-5.551-9.111
+ c-5.558,0-6.405,4.341-6.405,8.822v16.998H42.052V40.995h10.245v4.692h0.146c1.426-2.7,4.91-5.549,10.106-5.549
+ c10.806,0,12.802,7.114,12.802,16.369V75.354z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-medium.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-medium.svg
new file mode 100644
index 0000000..7fe39dc
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-medium.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M81.652,14H18.001c-1.891,0.784-3.363,2.37-4.001,4.336v62.793C14.917,83.955,17.562,86,20.687,86h58.279
+ C82.851,86,86,82.843,86,78.948V20.517C86,17.576,84.204,15.058,81.652,14z M67.867,40.385h-1.4c-0.52,0-1.119,0.682-1.119,1.163
+ v17.437c0,0.482,0.6,1.203,1.119,1.203h1.4v4.048H55.312v-4.048h2.519v-18.32h-0.12l-6.198,22.368h-4.798l-6.118-22.368h-0.12
+ v18.32h2.639v4.048H32.481v-4.048h1.359c0.56,0,1.16-0.721,1.16-1.203V41.548c0-0.481-0.6-1.163-1.16-1.163h-1.359v-4.209h13.275
+ l4.358,16.275h0.12l4.398-16.275h13.235V40.385z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-myspace.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-myspace.svg
new file mode 100644
index 0000000..a4633a4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-myspace.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.841,51.036c7.792,0,14.111-6.294,14.111-14.061c0-7.765-6.319-14.061-14.111-14.061
+ c-7.798,0-14.118,6.297-14.118,14.061C64.722,44.742,71.043,51.036,78.841,51.036z"/>
+ <ellipse cx="47.046" cy="40.984" rx="12.703" ry="12.656"/>
+ <path d="M18.214,55.984c6.313,0,11.433-5.096,11.433-11.386c0-6.292-5.12-11.39-11.433-11.39c-6.315,0-11.433,5.098-11.433,11.39
+ C6.781,50.889,11.898,55.984,18.214,55.984z"/>
+ <path d="M18.214,58.585c-7.25,0-12.565,6.363-12.565,12.936v4.425c0,0.626,0.512,1.14,1.142,1.14h0.405H29.23h0.404
+ c0.632,0,1.144-0.514,1.144-1.14v-4.425C30.778,64.948,25.463,58.585,18.214,58.585z"/>
+ <path d="M47.046,56.526c-8.055,0-13.962,7.071-13.962,14.376v4.917c0,0.695,0.569,1.267,1.269,1.267h0.45h24.483h0.449
+ c0.703,0,1.271-0.571,1.271-1.267v-4.917C61.007,63.598,55.101,56.526,47.046,56.526z"/>
+ <path d="M78.839,54.243c-8.95,0-15.512,7.856-15.512,15.974v5.462c0,0.773,0.632,1.407,1.41,1.407h0.5H92.44h0.497
+ c0.782,0,1.414-0.635,1.414-1.407v-5.462C94.351,62.1,87.789,54.243,78.839,54.243z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-orkut.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-orkut.svg
new file mode 100644
index 0000000..335b4ec
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-orkut.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M50.104,34.348c-8.863,0-16.062,7.198-16.062,16.076
+ c0,8.878,7.199,16.062,16.062,16.062c8.878,0,16.077-7.185,16.077-16.062C66.181,41.546,58.982,34.348,50.104,34.348z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M79,14H21c-3.866,0-7,3.134-7,7v58c0,3.866,3.134,7,7,7h58c3.866,0,7-3.134,7-7
+ V21C86,17.134,82.866,14,79,14z M50.104,74.707c-13.404,0-24.297-10.864-24.297-24.283c0-13.419,10.893-24.311,24.297-24.311
+ c13.419,0,24.297,10.893,24.297,24.311C74.401,63.843,63.523,74.707,50.104,74.707z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-path.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-path.svg
new file mode 100644
index 0000000..41fb4b2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-path.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M84,41.515c0-16.82-13.663-28.125-34-28.125c-20.015,0-34,11.566-34,28.125c0,5.924,2.539,14.568,7.225,18.93l7.917-8.503
+ c-1.744-1.621-3.519-6.884-3.519-10.427c0-11.408,11.244-16.516,22.377-16.516c10.824,0,22.378,4.341,22.378,16.516
+ c0,13.641-15.881,15.154-21.729,15.242V34.755H38.24v35.283c0,3.574-3.863,5.129-7.984,2.14v12.733
+ c2.565,1.26,4.895,1.699,6.891,1.699c2.235,0,4.067-0.555,5.333-1.119c4.89-2.152,8.169-7.258,8.169-12.691v-4.441
+ C70.921,68.137,84,57.659,84,41.515z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-picasa.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-picasa.svg
new file mode 100644
index 0000000..e665e03
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-picasa.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M66.078,14.577c-5.087-2.312-10.495-3.495-16.08-3.495c-4.65,0-9.221,0.894-13.62,2.542
+ c1.031,0.936,28.368,25.748,29.7,26.959C66.078,38.791,66.078,15.127,66.078,14.577L66.078,14.577z"/>
+ <path fill="#231F20" d="M29.924,83.389c0-1.524,0-31.734,0-33.531C28.621,51.045,14.259,64.095,13.81,64.5
+ C16.936,72.339,22.642,78.987,29.924,83.389L29.924,83.389z"/>
+ <path fill="#231F20" d="M11,50.082c0,3.35,0.505,6.757,1.416,10.132c1.058-0.959,33.894-30.793,34.569-31.408
+ c-0.659-0.6-14.314-12.995-14.759-13.398C19.134,22.127,11,35.377,11,50.082L11,50.082z"/>
+ <path fill="#231F20" d="M34.019,67.034c0,0.807,0,18.047,0,18.605c3.965,1.776,8.111,2.885,12.378,3.279h7.161
+ c13.471-1.256,25.498-9.561,31.474-21.885C83.624,67.034,34.857,67.034,34.019,67.034L34.019,67.034z"/>
+ <path fill="#231F20" d="M70.189,16.813c0,1.547,0,45.275,0,46.111c0.802,0,15.979,0,16.598,0C88.24,58.767,89,54.448,89,50.082
+ C89,36.529,81.794,23.876,70.189,16.813L70.189,16.813z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-pinterest.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-pinterest.svg
new file mode 100644
index 0000000..0eb447d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-pinterest.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M50.001,10.999C28.464,10.999,11,28.461,11,50c0,15.97,9.603,29.688,23.345,35.72c-0.11-2.723-0.021-5.994,0.679-8.953
+ c0.75-3.168,5.018-21.252,5.018-21.252s-1.246-2.49-1.246-6.17c0-5.779,3.35-10.098,7.52-10.098c3.547,0,5.261,2.664,5.261,5.855
+ c0,3.566-2.273,8.896-3.443,13.84c-0.978,4.139,2.075,7.512,6.156,7.512c7.389,0,12.365-9.49,12.365-20.736
+ c0-8.545-5.756-14.943-16.227-14.943c-11.831,0-19.201,8.822-19.201,18.676c0,3.4,1.002,5.795,2.572,7.648
+ c0.721,0.853,0.821,1.196,0.56,2.176c-0.187,0.717-0.617,2.444-0.794,3.129c-0.259,0.988-1.059,1.34-1.953,0.976
+ c-5.449-2.225-7.987-8.192-7.987-14.9c0-11.08,9.343-24.363,27.873-24.363c14.891,0,24.691,10.775,24.691,22.344
+ c0,15.297-8.506,26.727-21.044,26.727c-4.209,0-8.17-2.277-9.527-4.861c0,0-2.264,8.984-2.743,10.722
+ c-0.827,3.007-2.446,6.013-3.926,8.354c3.508,1.035,7.213,1.6,11.053,1.6C71.538,89.001,89,71.538,89,50
+ C89,28.461,71.538,10.999,50.001,10.999z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-rdio.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-rdio.svg
new file mode 100644
index 0000000..ef788c2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-rdio.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M90.326,30.746c-9.825,0.285-21.688-7.424-26.286-10.327c-0.426-0.27-0.861-0.518-1.301-0.742
+ c-0.481-0.268-0.979-0.517-1.477-0.761v28.36h-0.014c0.018,2.54-0.736,5.217-2.324,7.784l-0.139,0.226
+ c-4.594,7.427-14.258,11.756-23.322,8.695c-8.803-2.976-11.154-11.501-6.493-19.041l0.141-0.227
+ c4.589-7.424,14.253-11.754,23.318-8.693c0.699,0.236,1.344,0.517,1.957,0.823V16.333c-3.245-0.878-6.687-1.381-10.313-1.381
+ C23.094,14.952,7.518,30.654,7.518,50v0.252c0,19.346,15.449,34.797,36.304,34.797C64.8,85.048,80.378,69.347,80.378,50v-0.25
+ c0-1.51-0.105-2.988-0.287-4.443C91.018,42.458,95.523,31.152,90.326,30.746z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-reddit.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-reddit.svg
new file mode 100644
index 0000000..5c2563a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-reddit.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.762,48.994c0-5.688-4.63-10.314-10.315-10.314c-2.463,0-4.767,0.901-6.626,2.477c-0.06,0.037-0.122,0.072-0.181,0.11
+ c-6.707-4.291-15.601-7.031-25.439-7.403l5.872-16.698l14.656,3.504c0.012,4.633,3.781,8.4,8.42,8.4
+ c4.642,0,8.422-3.777,8.422-8.421c0-4.646-3.78-8.423-8.422-8.423c-3.529,0-6.544,2.182-7.794,5.26l-17.364-4.15l-7.211,20.49
+ c-10.259,0.193-19.556,2.969-26.513,7.404c-1.873-1.625-4.21-2.551-6.718-2.551c-5.687,0-10.31,4.627-10.31,10.314
+ c0,3.518,1.815,6.768,4.756,8.66c-0.179,1.025-0.293,2.064-0.293,3.123c0,14.886,18.043,26.997,40.219,26.997
+ c22.18,0,40.224-12.111,40.224-26.997c0-1.027-0.103-2.037-0.272-3.035C92.893,55.863,94.762,52.566,94.762,48.994z M63.598,62.347
+ c-3.5,0-6.334-2.834-6.334-6.338c0-3.498,2.834-6.334,6.334-6.334c3.5,0,6.339,2.836,6.339,6.334
+ C69.937,59.513,67.097,62.347,63.598,62.347z M64.859,73.153c-0.19,0.194-4.733,4.821-15.009,4.821
+ c-10.333,0-14.463-4.689-14.636-4.891c-0.579-0.677-0.5-1.703,0.178-2.283c0.677-0.575,1.692-0.501,2.278,0.166
+ c0.092,0.104,3.54,3.771,12.18,3.771c8.784,0,12.639-3.798,12.68-3.835c0.62-0.636,1.646-0.648,2.284-0.027
+ C65.451,71.494,65.474,72.506,64.859,73.153z M30.809,56.009c0-3.498,2.833-6.334,6.339-6.334c3.494,0,6.334,2.836,6.334,6.334
+ c0,3.504-2.84,6.338-6.334,6.338C33.643,62.347,30.809,59.513,30.809,56.009z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skillshare.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skillshare.svg
new file mode 100644
index 0000000..12fb8e6
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skillshare.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="none" d="M32.092,55.916h14.575c1.087,0,2.563,2.496,4.734,4.039v-1.776c0,0-0.07-1.053,0.348-1.69
+ c0.424-0.639,1.308-0.809,1.584-0.809c0.279,0,14.575,0,14.575,0s4.401-0.74,9.294-3.044L23.408,53.15
+ C28.05,55.232,32.092,55.916,32.092,55.916z"/>
+ <path d="M16.868,55.111c-0.385-0.293-0.733-0.576-1.061-0.855C16.054,54.652,16.416,54.959,16.868,55.111z"/>
+ <path d="M19.538,15.561h60.708v35.516c2.128-1.18,3.271-1.984,4.054-2.499V13.528c0-1.118-0.907-2.028-2.03-2.028H17.508
+ c-1.123,0-2.033,0.91-2.033,2.028v35.14c0.771,0.486,1.878,1.301,4.063,2.52V15.561z"/>
+ <path d="M87.791,47.978c-0.523-0.417-1.247-0.415-2.396,0c-0.335,0.122-0.674,0.325-1.095,0.6
+ c-0.783,0.515-1.925,1.319-4.054,2.499c-0.657,0.36-1.373,0.748-2.241,1.183c-0.272,0.136-0.534,0.247-0.803,0.377
+ c-4.893,2.304-9.294,3.044-9.294,3.044s-14.295,0-14.575,0c-0.276,0-1.16,0.17-1.584,0.809c-0.418,0.638-0.348,1.69-0.348,1.69
+ v1.776c0.526,0.373,1.082,0.707,1.695,0.918c4.394,1.498,7.367,0.192,8.664-1.628c1.517-2.134,2.289-3.329,3.955-2.705
+ c1.666,0.624,0,4.68-2.08,6.763c-2.085,2.084-4.584,3.749-8.12,3.749c-1.486,0-2.926-0.223-4.114-0.476c0,2.941,0,11.611,0,15.131
+ c0,4.27,4.538,6.552,7.658,6.552c3.119,0,9.367-1.768,12.387-9.263c3.017-7.493-0.205-17.381-0.205-17.381s4.888-2.191,9.991-5.414
+ c5.098-3.225,6.455-6.246,6.559-6.67C87.891,49.105,88.307,48.396,87.791,47.978z"/>
+ <path d="M63.635,63.303c2.08-2.083,3.746-6.139,2.08-6.763c-1.666-0.624-2.438,0.571-3.955,2.705
+ c-1.297,1.82-4.27,3.126-8.664,1.628c-0.613-0.211-1.169-0.545-1.695-0.918c-2.17-1.543-3.647-4.039-4.734-4.039H32.092
+ c0,0-4.043-0.684-8.684-2.766c-0.466-0.21-0.935-0.418-1.411-0.657c-0.968-0.485-1.751-0.91-2.459-1.306
+ c-2.185-1.219-3.292-2.033-4.063-2.52c-0.321-0.203-0.593-0.355-0.871-0.455c-1.144-0.416-1.873-0.416-2.394,0
+ c-0.518,0.418-0.104,1.128,0,1.553c0.08,0.325,0.913,2.184,3.596,4.49c0.328,0.279,0.676,0.562,1.061,0.855
+ c0.57,0.434,1.192,0.877,1.902,1.326c5.098,3.227,9.991,5.412,9.991,5.412s-3.227,9.886-0.205,17.381
+ c3.018,7.494,9.263,9.27,12.385,9.27c3.123,0,7.661-2.297,7.661-6.564c0-4.266,0-16.131,0-16.131s1.152,0.42,2.799,0.771
+ c1.188,0.253,2.628,0.476,4.114,0.476C59.051,67.052,61.55,65.387,63.635,63.303z"/>
+ <path d="M61.017,34.381c-5.003,0-9.058,4.057-9.058,9.057c0,4.999,4.055,9.056,9.058,9.056c4.998,0,9.052-4.057,9.052-9.056
+ C70.069,38.438,66.015,34.381,61.017,34.381z"/>
+ <path d="M39.544,34.381c-5,0-9.053,4.057-9.053,9.057c0,4.999,4.052,9.056,9.053,9.056c5.003,0,9.058-4.057,9.058-9.056
+ C48.602,38.438,44.547,34.381,39.544,34.381z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skype.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skype.svg
new file mode 100644
index 0000000..0be5e38
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-skype.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path fill="#231F20" d="M86.284,58.294c0.555-2.541,0.851-5.176,0.851-7.883c0-20.283-16.442-36.727-36.727-36.727
+ c-2.14,0-4.236,0.186-6.279,0.539c-3.282-2.069-7.163-3.27-11.33-3.27c-11.761,0-21.299,9.534-21.299,21.3
+ c0,3.93,1.069,7.609,2.929,10.768c-0.487,2.391-0.744,4.861-0.744,7.391c0,20.282,16.44,36.725,36.723,36.725
+ c2.299,0,4.545-0.215,6.729-0.615c2.998,1.608,6.423,2.525,10.065,2.525c11.763,0,21.299-9.531,21.299-21.297
+ C88.5,64.349,87.7,61.14,86.284,58.294z M69.247,67.964c-1.701,2.401-4.212,4.307-7.462,5.658
+ c-3.223,1.342-7.081,2.021-11.479,2.021c-5.272,0-9.695-0.932-13.147-2.762c-2.467-1.336-4.502-3.138-6.046-5.366
+ c-1.561-2.249-2.354-4.483-2.354-6.636c0-1.343,0.518-2.51,1.534-3.465c1.006-0.947,2.294-1.429,3.833-1.429
+ c1.261,0,2.351,0.38,3.234,1.126c0.845,0.718,1.571,1.776,2.151,3.148c0.652,1.488,1.363,2.748,2.112,3.74
+ c0.718,0.949,1.757,1.754,3.081,2.379c1.329,0.631,3.125,0.952,5.333,0.952c3.036,0,5.527-0.649,7.396-1.93
+ c1.831-1.249,2.72-2.747,2.72-4.583c0-1.449-0.466-2.59-1.421-3.482c-0.998-0.934-2.315-1.662-3.916-2.16
+ c-1.669-0.521-3.938-1.082-6.74-1.67c-3.81-0.816-7.047-1.784-9.625-2.88c-2.633-1.12-4.757-2.674-6.308-4.617
+ c-1.576-1.976-2.376-4.452-2.376-7.362c0-2.774,0.838-5.273,2.494-7.432c1.643-2.143,4.042-3.807,7.127-4.949
+ c3.05-1.129,6.676-1.697,10.776-1.697c3.28,0,6.164,0.379,8.57,1.125c2.421,0.758,4.461,1.771,6.066,3.027
+ c1.612,1.262,2.816,2.611,3.567,4.012c0.765,1.416,1.152,2.827,1.152,4.191c0,1.312-0.507,2.502-1.508,3.543
+ c-1.006,1.045-2.273,1.574-3.771,1.574c-1.36,0-2.425-0.33-3.163-0.983c-0.688-0.608-1.402-1.556-2.191-2.919
+ c-0.917-1.738-2.023-3.11-3.295-4.078c-1.235-0.938-3.299-1.414-6.131-1.414c-2.636,0-4.777,0.527-6.364,1.57
+ c-1.533,1.004-2.276,2.154-2.276,3.521c0,0.837,0.239,1.535,0.731,2.136c0.525,0.64,1.258,1.195,2.191,1.664
+ c0.965,0.484,1.958,0.871,2.954,1.145c1.024,0.285,2.733,0.705,5.084,1.246c2.969,0.641,5.702,1.354,8.116,2.127
+ c2.445,0.783,4.56,1.749,6.283,2.871c1.76,1.143,3.153,2.616,4.144,4.372c0.989,1.765,1.49,3.938,1.49,6.467
+ C71.813,62.791,70.95,65.549,69.247,67.964z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-smashing-mag.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-smashing-mag.svg
new file mode 100644
index 0000000..8e12c3f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-smashing-mag.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M45.718,55.325c-3.727-1.408-7.229-3.226-10.202-5.401c-0.077-0.056-0.157-0.111-0.233-0.168
+ c-0.433-0.322-0.851-0.654-1.259-0.991c-0.107-0.088-0.211-0.178-0.316-0.267c-0.353-0.301-0.697-0.606-1.03-0.919
+ c-0.062-0.058-0.127-0.115-0.188-0.173c-0.373-0.357-0.73-0.724-1.074-1.096c-0.091-0.098-0.179-0.197-0.268-0.296
+ c-0.305-0.34-0.598-0.685-0.877-1.037c-0.041-0.052-0.085-0.102-0.125-0.154c-0.306-0.393-0.591-0.796-0.862-1.204
+ c-0.07-0.104-0.137-0.21-0.204-0.315c-0.246-0.385-0.479-0.774-0.693-1.171c-0.021-0.039-0.045-0.077-0.066-0.117
+ c-0.227-0.429-0.428-0.867-0.615-1.309c-0.047-0.11-0.091-0.221-0.135-0.333c-0.172-0.434-0.331-0.872-0.463-1.318
+ c-0.006-0.02-0.014-0.04-0.02-0.06c-0.135-0.463-0.241-0.934-0.331-1.41c-0.022-0.117-0.043-0.234-0.062-0.352
+ c-0.08-0.482-0.144-0.968-0.176-1.464c-0.042-0.665-0.055-1.318-0.047-1.963c0.002-0.199,0.018-0.392,0.025-0.589
+ c0.016-0.447,0.039-0.892,0.081-1.329c0.021-0.219,0.051-0.435,0.078-0.652c0.052-0.412,0.113-0.821,0.189-1.225
+ c0.039-0.211,0.083-0.42,0.129-0.629c0.091-0.413,0.198-0.82,0.315-1.224c0.053-0.183,0.104-0.366,0.163-0.547
+ c0.148-0.454,0.316-0.9,0.499-1.341c0.049-0.12,0.092-0.242,0.144-0.361c0.77-1.752,1.821-3.401,3.185-4.943L16.21,24.575
+ c-3.027,0.724-4.895,3.765-4.171,6.793l12.535,52.421c0.725,3.027,3.766,4.896,6.793,4.171l6.451-1.543
+ c-2.504-0.829-6.833-2.409-10.982-4.623l6.015-13.644c0,0,7.079,6.304,17.242,6.304C60.258,74.454,64.775,62.524,45.718,55.325z"/>
+ <path fill="#231F20" d="M87.961,68.632L75.425,16.211c-0.723-3.028-3.765-4.895-6.793-4.171l-10.797,2.581
+ c0.86,0.136,1.984,0.346,3.307,0.667c0.313,0.076,0.641,0.16,0.975,0.249c0.117,0.031,0.237,0.064,0.357,0.097
+ c0.241,0.066,0.488,0.136,0.738,0.209c0.131,0.038,0.261,0.075,0.394,0.115c0.353,0.106,0.714,0.218,1.083,0.339
+ c0.116,0.038,0.237,0.081,0.355,0.12c0.276,0.093,0.556,0.189,0.84,0.29c0.159,0.057,0.319,0.115,0.481,0.174
+ c0.285,0.105,0.575,0.215,0.867,0.329c0.133,0.052,0.263,0.1,0.397,0.154c0.406,0.162,0.818,0.335,1.235,0.515
+ c0.141,0.061,0.285,0.127,0.428,0.19c0.314,0.14,0.63,0.284,0.949,0.434c0.147,0.069,0.294,0.138,0.441,0.21
+ c0.452,0.219,0.906,0.444,1.365,0.685l-4.702,13.03c0,0-3.913-4.371-14.405-4.903c-9.974-0.504-15.522,10.285,3.931,16.647
+ c0.573,0.188,1.127,0.384,1.67,0.585c0.15,0.055,0.298,0.112,0.446,0.169c0.42,0.16,0.832,0.324,1.234,0.492
+ c0.123,0.051,0.248,0.101,0.369,0.153c0.508,0.218,1.004,0.441,1.484,0.671c0.062,0.029,0.12,0.06,0.181,0.09
+ c0.418,0.203,0.824,0.411,1.221,0.622c0.119,0.063,0.236,0.127,0.353,0.191c0.379,0.208,0.75,0.42,1.109,0.636
+ c0.064,0.038,0.131,0.076,0.194,0.115c0.424,0.259,0.833,0.523,1.229,0.792c0.069,0.047,0.134,0.094,0.202,0.141
+ c0.327,0.226,0.645,0.456,0.953,0.689c0.084,0.064,0.169,0.127,0.252,0.192c0.357,0.276,0.706,0.556,1.038,0.841c0,0,0,0,0,0
+ c5.631,4.835,7.638,10.851,7.476,16.562c-0.128,4.513-1.707,8.184-3.538,10.953l11.048-2.641
+ C86.817,74.702,88.684,71.659,87.961,68.632z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-snapchat.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-snapchat.svg
new file mode 100644
index 0000000..3b3fb50
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-snapchat.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g id="XMLID_2_">
+ <g>
+ <path d="M71.925,43.847c0.846-0.21,1.651-0.773,2.481-0.789c1.279-0.032,2.724-0.045,3.813,0.498
+ c1.89,0.943,2.04,2.999,0.312,4.25c-1.384,0.992-3.052,1.647-4.667,2.267c-3.594,1.388-4.072,2.433-2.255,5.837
+ c3.012,5.639,7.229,9.836,13.681,11.39c0.668,0.158,1.741,0.895,1.708,1.283c-0.073,0.882-0.506,2.178-1.174,2.485
+ c-2.17,1.016-4.469,1.878-6.804,2.38c-1.457,0.3-2.004,0.838-2.311,2.21c-0.656,2.894-1.231,3.254-4.036,2.692
+ c-4.461-0.899-8.383-0.125-12.184,2.619c-7.67,5.549-13.386,5.525-21.04-0.032c-3.732-2.72-7.598-3.481-11.993-2.578
+ c-2.947,0.603-3.453,0.247-4.157-2.752c-0.291-1.226-0.749-1.858-2.178-2.129c-2.218-0.417-4.432-1.146-6.476-2.105
+ c-0.826-0.38-1.481-1.692-1.643-2.659c-0.065-0.397,1.316-1.307,2.161-1.542c6.946-1.898,11.176-6.65,14.021-12.949
+ c0.672-1.49,0.105-2.546-1.129-3.238c-1.101-0.607-2.348-0.951-3.522-1.441c-0.741-0.312-1.498-0.623-2.178-1.044
+ c-1.384-0.854-2.546-1.915-1.745-3.752c0.652-1.51,2.801-2.311,4.493-1.769c0.959,0.304,1.898,0.7,2.874,0.915
+ c1.279,0.275,2-0.089,1.951-1.656c-0.113-3.558-0.316-7.144-0.028-10.686c0.607-7.484,4.983-12.423,11.718-15.05
+ c9.735-3.781,21.36-0.927,26.61,8.492c1.842,3.303,2.121,6.877,2.275,10.524c-0.146,2.287-0.263,4.57-0.445,6.845
+ C69.946,43.847,70.723,44.146,71.925,43.847z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-spotify.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-spotify.svg
new file mode 100644
index 0000000..487ee88
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-spotify.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M49.999,10.999C28.461,10.999,11,28.46,11,49.999c0,10.158,3.886,19.408,10.249,26.346
+ c2.549-2.887,5.569-5.242,9.011-6.986c4.271-2.164,8.868-3.262,13.665-3.262c7.622,0,14.906,2.848,20.511,8.014
+ c2.714,2.504,4.91,5.449,6.558,8.75C81.818,75.929,89,63.808,89,49.999C89,28.46,71.539,10.999,49.999,10.999z M68.467,65.146
+ c-0.505,0.727-1.315,1.117-2.139,1.117c-0.511,0-1.027-0.15-1.479-0.463c-6.106-4.236-13.268-6.475-20.71-6.475
+ c-4.305,0-8.518,0.744-12.52,2.211c-1.349,0.496-2.842-0.197-3.336-1.547c-0.495-1.348,0.198-2.842,1.547-3.336
+ c4.577-1.678,9.392-2.525,14.309-2.525c8.506,0,16.693,2.559,23.673,7.398C68.992,62.345,69.285,63.964,68.467,65.146z
+ M74.14,53.153c-0.555,0.889-1.508,1.375-2.483,1.375c-0.529,0-1.065-0.143-1.547-0.445c-7.779-4.861-16.759-7.432-25.971-7.432
+ c-5.119,0-10.167,0.787-15.005,2.342c-1.539,0.49-3.185-0.355-3.679-1.894c-0.493-1.539,0.354-3.186,1.892-3.68
+ c5.417-1.736,11.067-2.619,16.793-2.619c10.309,0,20.361,2.879,29.07,8.322C74.58,49.979,74.996,51.782,74.14,53.153z
+ M77.004,42.751c-0.56,0-1.126-0.145-1.643-0.449c-9.433-5.539-20.23-8.469-31.223-8.469c-5.94,0-11.821,0.848-17.481,2.516
+ c-1.724,0.506-3.529-0.481-4.037-2.201c-0.506-1.723,0.478-3.529,2.2-4.035c6.257-1.842,12.756-2.779,19.318-2.779
+ c12.149,0,24.085,3.238,34.514,9.365c1.548,0.908,2.065,2.9,1.157,4.447C79.204,42.177,78.118,42.751,77.004,42.751z"/>
+ <path d="M54.908,84.444c-3.001-2.768-6.902-4.293-10.983-4.293c-2.569,0-5.029,0.586-7.312,1.746
+ c-1.521,0.771-2.882,1.773-4.085,2.969c5.257,2.639,11.188,4.135,17.471,4.135c2.709,0,5.353-0.277,7.907-0.805
+ C57.095,86.806,56.099,85.542,54.908,84.444z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-squidoo.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-squidoo.svg
new file mode 100644
index 0000000..22eb38d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-squidoo.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <g>
+ <path fill="#050708" d="M90.624,66.304c-2.183-7.806-8.903-13.12-16.914-13.415c-1.315-0.048-2.246-0.641-2.768-1.781
+ c-0.873-1.911-0.825-3.857,0.09-5.752c0.855-1.768,1.788-3.498,2.615-5.279c1.093-2.353,1.786-4.754,1.303-7.436
+ c-0.572-3.186-2.348-5.565-4.615-7.671c-3.786-3.518-8.419-5.38-13.33-6.632c-3.276-0.829-5.171-2.894-5.898-6.129
+ c-0.204-0.906-0.38-1.816-0.571-2.727c-0.331,0.528-0.421,1.053-0.479,1.581c-0.468,4.473,1.55,7.812,5.688,9.432
+ c0.487,0.188,0.979,0.361,1.458,0.567c3.119,1.337,6.103,2.878,8.448,5.421c3.19,3.463,3.458,6.984,0.775,10.809
+ c-1.561,2.225-3.585,4.088-5.046,6.621c-0.067-0.357-0.093-0.508-0.122-0.656c-0.631-3.022-1.328-6.016-3.086-8.656
+ c-3.785-5.672-8.855-9.774-15.038-12.582c-2.406-1.092-4.819-2.156-6.77-4.068c-3.494-3.422-4.804-7.583-4.519-12.355
+ c-0.16,0-0.32,0-0.482,0c0.011,0.157,0.052,0.318,0.026,0.473c-1.328,7.803,0.982,14.318,6.875,19.602
+ c2.26,2.022,4.78,3.652,7.396,5.155c3.435,1.975,5.693,4.819,6.158,8.839c0.244,2.111,0.253,4.246,0.408,6.368
+ c0.059,0.78-0.424,0.508-0.768,0.456c-4.072-0.635-7.94-1.886-11.692-3.598c-3.792-1.73-6.243-4.537-7.444-8.492
+ c-0.233-0.766-0.485-1.531-0.714-2.298c-0.816-2.724-1.428-5.518-2.653-8.107c-1.139-2.408-2.727-4.489-5.382-5.188
+ c-5.015-1.32-9.939-0.958-14.629,1.432C8.704,20.357,8.4,20.457,8.532,20.84c0.224,0.195,0.454,0.051,0.682,0.012
+ c2.507-0.437,4.997-0.496,7.539-0.085c5.069,0.816,8.188,3.558,9.154,8.667c0.321,1.692,0.834,3.354,1.12,5.051
+ c1.537,9.107,6.444,15.828,14.341,20.472c1.579,0.927,3.131,1.905,4.907,2.989c-2.072,0.373-3.938,0.721-5.808,1.049
+ c-3.875,0.676-7.755,1.319-11.715,1.094c-2.149-0.118-4.088-0.591-4.943-2.9c-0.251-0.674-0.492-1.359-0.655-2.057
+ c-0.987-4.239-0.801-8.553-0.628-12.838c0.187-4.564-2.917-8.449-7.45-8.964c-0.219-0.023-0.536-0.143-0.687,0.122
+ c2.471,1.934,4.377,4.141,4.104,7.482c-0.138,1.674-0.469,3.336-0.768,4.994c-0.735,4.078-1.42,8.158-0.813,12.322
+ c0.587,4.023,2.304,7.344,6.01,9.349c2.296,1.245,4.777,1.817,7.391,1.899c4.685,0.146,9.281-0.672,13.876-1.352
+ c4.19-0.619,6.912,1.089,7.659,5.25c0.14,0.788,0.235,1.59,0.284,2.389c0.3,4.939,1.989,9.313,5.376,12.953
+ c4.094,4.395,9.272,6.291,15.128,5.488c9.154-1.254,14.866-6.853,17.803-15.406C91.853,74.707,91.792,70.48,90.624,66.304z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stack-overflow.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stack-overflow.svg
new file mode 100644
index 0000000..56cdd39
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stack-overflow.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="layer1_1_">
+ <polygon fill="#231F20" points="65.269,85.165 23.208,85.165 23.429,57.022 17.109,56.962 17.074,92 71.927,92 71.927,57.126
+ 65.269,57.126 "/>
+ <rect x="27.414" y="73.601" fill="#231F20" width="32.947" height="7.008"/>
+
+ <rect x="27.765" y="62.557" transform="matrix(0.9954 0.0961 -0.0961 0.9954 6.5615 -3.9532)" fill="#231F20" width="33.122" height="7.186"/>
+
+ <rect x="29.605" y="51.079" transform="matrix(0.9624 0.2716 -0.2716 0.9624 16.5844 -10.4838)" fill="#231F20" width="33.122" height="7.184"/>
+
+ <rect x="34.687" y="38.636" transform="matrix(0.856 0.517 -0.517 0.856 29.2145 -20.4144)" fill="#231F20" width="33.122" height="7.186"/>
+
+ <rect x="45.221" y="27.283" transform="matrix(-0.5824 -0.8129 0.8129 -0.5824 72.6673 99.0802)" fill="#231F20" width="33.122" height="7.185"/>
+
+ <rect x="73.06" y="8.366" transform="matrix(0.9863 -0.1649 0.1649 0.9863 -3.0607 12.9782)" fill="#231F20" width="7.185" height="33.123"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-steam.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-steam.svg
new file mode 100644
index 0000000..2cce5a7
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-steam.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path id="Gears" d="M92.43,40.935c0,3.889-3.155,7.039-7.041,7.039c-3.886,0-7.039-3.15-7.039-7.039
+ c0-3.883,3.153-7.039,7.039-7.039C89.275,33.895,92.43,37.052,92.43,40.935z M85.354,27.831c-7.218,0-13.08,5.822-13.145,13.025
+ l-8.19,11.736c-0.333-0.035-0.672-0.055-1.016-0.055c-1.829,0-3.539,0.504-5.008,1.381L20.901,39.001
+ c-0.97-4.4-4.903-7.719-9.586-7.719c-5.406,0-9.815,4.424-9.815,9.828c0,5.41,4.409,9.816,9.815,9.816
+ c1.83,0,3.541-0.504,5.009-1.379l37.094,14.889c0.959,4.412,4.893,7.733,9.584,7.733c5.083,0,9.275-3.896,9.762-8.858l12.589-9.201
+ c7.258,0,13.146-5.877,13.146-13.135S92.612,27.831,85.354,27.831z M85.354,32.163c4.863,0,8.813,3.951,8.813,8.812
+ c0,4.863-3.951,8.801-8.813,8.801c-4.861,0-8.813-3.938-8.813-8.801C76.541,36.114,80.493,32.163,85.354,32.163z M11.315,33.882
+ c2.773,0,5.166,1.549,6.377,3.832l-3.588-1.436v0.016c-2.891-1.041-6.102,0.375-7.256,3.248c-1.156,2.873,0.174,6.127,2.978,7.379
+ v0.014l3.046,1.215c-0.501,0.111-1.023,0.178-1.557,0.178c-3.999,0-7.215-3.217-7.215-7.217C4.1,37.112,7.315,33.882,11.315,33.882z
+ M63.002,55.136c4.001,0,7.216,3.217,7.216,7.217c0,3.998-3.215,7.215-7.216,7.215c-2.781,0-5.184-1.551-6.389-3.844
+ c1.187,0.48,2.375,0.953,3.56,1.436c2.941,1.182,6.292-0.242,7.473-3.182c1.183-2.941-0.254-6.275-3.196-7.459l-3.004-1.205
+ C61.947,55.206,62.469,55.136,63.002,55.136z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stumbleupon.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stumbleupon.svg
new file mode 100644
index 0000000..6249230
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-stumbleupon.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M80.801,26.084C85.94,32.686,89,40.988,89,50c0,21.536-17.464,39-38.999,39
+ c-15.153,0-28.29-8.646-34.746-21.271h16.998c8.1,0,13.758-4.366,13.758-11.345c0-14.791-17.063-8.765-17.063-14.014
+ c0-2.529,2.029-3.449,5.742-3.449h6.187h5.643c3.279,0,7.136,0.588,7.136,4.166v11.787c0,8.535,6.665,12.854,13.573,12.854
+ c7.026,0,13.571-4.319,13.571-12.854V26.084L80.801,26.084z"/>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M50.001,11c8.136,0,15.687,2.496,21.937,6.756V55.15
+ c0,2.592-2.12,4.713-4.708,4.713l0,0c-2.591,0-4.709-2.121-4.709-4.713V43.945c0-8.945-4.527-12.666-10.423-12.666
+ c-6.4,0-12.794,0-19.189,0c-6.947,0-12.71,4.422-12.71,11.434c0,3.588,1.537,8.846,8.806,10.15
+ c5.921,1.066,8.258,0.756,8.258,3.924c0,3.076-3.446,3.076-7.995,3.076H12.261C11.437,56.711,11,53.407,11,50
+ C11,28.469,28.466,11,50.001,11L50.001,11z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-treehouse.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-treehouse.svg
new file mode 100644
index 0000000..6dca6f4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-treehouse.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M49.165,39.829c-4.657,3.569-9.147,7.375-14.374,10.134c-0.805,0.424-1.617,0.818-2.504,1.064
+ c-2.403,0.664-4.022,2.848-3.995,5.316c0.027,2.404,1.728,4.602,4.035,5.211c2.397,0.632,5.021-0.336,6.117-2.566
+ c1.441-2.941,3.917-4.77,6.447-6.576c0.98-0.698,1.347-0.599,2.136,0.34c0.879-1.788,1.739-3.531,2.602-5.285
+ c0.268,0.158,0.206,0.327,0.168,0.455c-1.433,4.971-2.683,9.996-4.333,14.9c-0.362,1.081-0.887,1.932-1.946,2.604
+ c-2.8,1.774-3.509,5.462-1.78,8.305c1.687,2.773,5.243,3.746,8.16,2.229c2.886-1.498,4.159-5.016,2.731-7.971
+ c-0.511-1.059-0.546-2.004-0.267-3.055c0.733-2.781,1.176-5.658,2.691-8.183c0.67-1.116,1.462-2.126,2.563-2.85
+ c1.274-0.842,2.244-0.669,3.166,0.536c1.108,1.451,1.659,3.041,1.506,4.908c-0.209,2.553,1.348,4.816,3.712,5.617
+ c2.311,0.787,4.852-0.047,6.253-2.044c1.464-2.086,1.402-4.719-0.332-6.697c-1.985-2.269-4.128-4.39-5.936-6.815
+ c-3.092-4.147-3.367-8.433-0.753-12.913c1.425-2.437,2.8-4.904,4.218-7.347c1.265-2.175,2.849-4.059,5.091-5.302
+ c1.893-1.051,3.756-1.246,5.676,0.016c1.229,0.809,2.566,1.455,3.838,2.201c2.888,1.695,4.422,4.222,4.429,7.576
+ c0.021,10.938,0.021,21.873-0.001,32.806c-0.008,3.282-1.496,5.829-4.325,7.442c-9.868,5.629-19.764,11.21-29.668,16.776
+ c-2.933,1.648-5.955,1.656-8.891,0.013c-9.965-5.585-19.925-11.18-29.85-16.836c-2.759-1.572-4.228-4.072-4.234-7.291
+ c-0.019-11.027-0.018-22.059,0-33.087c0.006-3.18,1.436-5.686,4.159-7.238c10.054-5.743,20.144-11.43,30.264-17.06
+ c2.595-1.441,5.385-1.381,8.061-0.079c1.551,0.752,3.02,1.671,4.515,2.532c1.19,0.682,1.715,1.797,1.872,3.101
+ c0.279,2.302-0.282,4.427-1.402,6.418c-1.368,2.434-2.693,4.899-4.153,7.278c-2.641,4.301-6.46,6.925-11.48,7.723
+ c-3.206,0.506-6.39,0.077-9.571-0.28c-2.353-0.267-4.523,0.997-5.311,3.159c-0.802,2.211,0.017,4.577,2.016,5.828
+ c1.977,1.233,4.445,0.929,6.099-0.826c1.041-1.099,2.44-1.039,3.743-1.266c1.015-0.178,2.056-0.212,3.09-0.27
+ c0.37-0.021,0.655-0.187,0.957-0.345c1.556-0.818,3.106-1.635,4.657-2.458C49.074,39.732,49.12,39.778,49.165,39.829z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-tumblr.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-tumblr.svg
new file mode 100644
index 0000000..b9b12e5
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-tumblr.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M79,14H21c-3.85,0-7,3.15-7,7v58c0,3.85,3.15,7,7,7h58c3.85,0,7-3.15,7-7V21C86,17.15,82.85,14,79,14z M66.715,74.172
+ c-2.319,1.092-4.419,1.861-6.298,2.3c-1.88,0.44-3.913,0.659-6.098,0.659c-2.479,0-4.672-0.313-6.579-0.939
+ c-1.906-0.627-3.532-1.522-4.878-2.678c-1.347-1.161-2.28-2.394-2.799-3.701c-0.52-1.305-0.78-3.198-0.78-5.678V45.102h-5.998
+ v-7.678c2.131-0.693,3.959-1.685,5.478-2.979c1.521-1.292,2.739-2.846,3.659-4.659c0.921-1.811,1.553-4.117,1.899-6.916h7.718
+ v13.715h12.877v8.518H52.039v13.916c0,3.145,0.166,5.164,0.5,6.059c0.332,0.893,0.953,1.606,1.858,2.139
+ c1.2,0.719,2.573,1.08,4.119,1.08c2.746,0,5.479-0.894,8.198-2.681V74.172z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-twitter.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-twitter.svg
new file mode 100644
index 0000000..d34adff
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-twitter.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M88.5,26.12c-2.833,1.256-5.877,2.105-9.073,2.486c3.261-1.955,5.767-5.051,6.945-8.738
+ c-3.052,1.81-6.434,3.126-10.031,3.832c-2.881-3.068-6.987-4.988-11.531-4.988c-8.724,0-15.798,7.072-15.798,15.798
+ c0,1.237,0.14,2.444,0.41,3.601c-13.13-0.659-24.77-6.949-32.562-16.508c-1.36,2.334-2.139,5.049-2.139,7.943
+ c0,5.481,2.789,10.315,7.028,13.149c-2.589-0.083-5.025-0.794-7.155-1.976c-0.002,0.066-0.002,0.131-0.002,0.199
+ c0,7.652,5.445,14.037,12.671,15.49c-1.325,0.359-2.72,0.553-4.161,0.553c-1.019,0-2.008-0.098-2.973-0.283
+ c2.01,6.275,7.844,10.844,14.757,10.972c-5.407,4.236-12.218,6.763-19.62,6.763c-1.275,0-2.532-0.074-3.769-0.221
+ c6.991,4.482,15.295,7.096,24.216,7.096c29.058,0,44.948-24.071,44.948-44.945c0-0.684-0.016-1.367-0.046-2.046
+ C83.704,32.071,86.383,29.288,88.5,26.12z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-vimeo.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-vimeo.svg
new file mode 100644
index 0000000..7277649
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-vimeo.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M79.048,14H20.952C17.128,14,14,17.128,14,20.952v58.096C14,82.872,17.128,86,20.952,86h58.096
+ C82.872,86,86,82.872,86,79.048V20.952C86,17.128,82.872,14,79.048,14z M74.41,36.852c-0.565,2.938-4.314,13.219-11.107,22.297
+ c-2.97,3.836-6.442,7.604-10.897,10.206c-1.643,0.96-4.893,2.172-7.052,1.266c-1.512-0.629-2.672-1.955-3.601-3.617
+ c-1.672-2.998-2.577-7.097-3.362-10.206c-0.725-2.851-1.405-5.558-2.291-8.036c-0.516-1.455-0.83-2.927-1.43-4.325
+ c-0.003-0.005-0.006-0.01-0.009-0.014c0.003,0.004,0.005,0.009,0.007,0.014c-0.024-0.038-0.045-0.069-0.068-0.104
+ c0.02,0.03,0.041,0.059,0.061,0.091c-0.168-0.39-0.352-0.773-0.577-1.148c-1.7-2.828-4.133-0.11-6.686-0.481
+ c-0.689-0.1-1.211-0.595-1.549-1.121C25.655,41.373,26,41.062,25,40.81v-0.275c4-2.916,7.17-6.455,11.46-8.939
+ c1.345-0.782,3.736-1.668,5.591-1.129c1.46,0.422,2.791,1.779,3.508,3.752c0.002,0,0.002,0,0.002,0
+ c0.131,0,0.247,0.651,0.34,0.942c0.715,2.214,1.099,5.043,1.463,7.194c0.577,3.387,0.481,8.631,2.415,11.59h0.002
+ c0.255,0,0.544,0.686,0.875,1.038c3.169,3.345,5.587-1.36,6.878-3.724c1.116-2.052,2.115-4.219,2.288-6.172
+ c0.099-1.107,0.045-2.004-0.15-2.699c-0.553-1.973-2.255-2.446-4.921-2.355c-0.34,0.012-0.694,0.027-1.064,0.056
+ c2.424-7.427,9.553-10.53,11.658-10.848c2.593-0.39,6.372-0.312,8.149,1.907c0.356,0.441,0.611,0.927,0.79,1.436
+ C74.74,33.897,74.675,35.389,74.41,36.852z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-windows.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-windows.svg
new file mode 100644
index 0000000..c30d003
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-windows.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon points="85.905,47.797 85.905,13 45.935,18.83 45.935,47.797 "/>
+ <polygon points="43.121,19.241 14.095,23.475 14.095,47.797 43.121,47.797 "/>
+ <polygon points="14.095,51.774 14.095,76.406 43.121,80.689 43.121,51.774 "/>
+ <polygon points="45.935,81.105 85.905,87 85.905,51.774 45.935,51.774 "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-xbox.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-xbox.svg
new file mode 100644
index 0000000..1503532
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-xbox.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g id="g3">
+ <path d="M39.749,33.478c-11.464-7.078-18.27-10.103-18.27-10.103C14.977,30.353,11,39.719,11,50.019
+ c0,9.229,3.19,17.695,8.522,24.373C19.522,74.393,14.173,60.023,39.749,33.478z"/>
+ <path d="M49.971,25.935l0.032,0.018c-0.014-0.01-0.026-0.018-0.026-0.018c15.609-11.279,25.305-5.611,25.305-5.611
+ c-6.803-5.846-15.642-9.381-25.305-9.381c-9.659,0-18.498,3.535-25.301,9.381C24.675,20.324,34.371,14.523,49.971,25.935z"/>
+ <path d="M49.846,41.947C28.15,58.006,21.824,76.959,21.824,76.959c7.083,7.455,17.08,12.098,28.152,12.098
+ c11.101,0,21.114-4.658,28.199-12.141C78.175,76.916,74.055,59.869,49.846,41.947z"/>
+ <path d="M89,50.019c0-10.301-3.978-19.666-10.479-26.644c0,0-6.806,3.025-18.27,10.103c25.576,26.545,20.227,40.914,20.227,40.914
+ C85.81,67.715,89,59.248,89,50.019z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yahoo.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yahoo.svg
new file mode 100644
index 0000000..cd91c7e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yahoo.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <polygon fill-rule="evenodd" clip-rule="evenodd" fill="#231F20" points="89.782,77.807 79.567,76.559 80.703,67.596
+ 90.918,68.842 89.782,77.807 "/>
+ <polygon fill-rule="evenodd" clip-rule="evenodd" fill="#231F20" points="100,23.438 82.519,21.283 82.631,61.805 90.238,62.824
+ 100,23.438 "/>
+ <g>
+ <g>
+ <path fill-rule="evenodd" clip-rule="evenodd" fill="#231F20" d="M64.813,30.477c-7.038-5.336-16.118-7.941-27.13-7.941
+ c-11.123,0-20.203,2.605-27.126,7.941C3.519,35.695,0,42.396,0,50.68c0,8.4,3.519,15.213,10.557,20.435
+ c5.742,4.33,12.97,6.865,21.615,7.602h10.981c8.582-0.736,15.822-3.271,21.661-7.602c6.923-5.223,10.441-12.035,10.441-20.435
+ C75.254,42.396,71.736,35.695,64.813,30.477z M59.591,43.756l-5.335,1.137c-0.793,0.225-2.951,1.816-6.696,4.881
+ c-3.974,3.178-6.017,5.221-6.356,6.242l-0.227,2.84l-0.114,1.703l0.455,4.312l7.038,0.109l-0.115,2.158H36.776L26.56,67.252
+ l0.341-2.043l3.292-0.109c1.703-0.119,2.726-0.344,3.064-0.686c0.228-0.227,0.341-1.59,0.341-3.973v-1.475l-0.113-2.951
+ c-0.228-0.678-2.044-3.178-5.562-7.492c-3.632-4.426-6.015-7.037-7.151-7.947l-6.583-0.904V37.74
+ c0.341-0.225,3.973-0.225,10.669-0.113c4.654-0.111,8.513-0.111,11.579,0.113l-0.228,1.592l-6.925,0.678
+ c2.157,3.18,5.45,7.605,9.876,13.17c5.789-4.43,8.854-7.268,8.966-8.518l-5.901-0.906l-0.453-2.041h9.874l9.308,0.113
+ L59.591,43.756z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yelp.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yelp.svg
new file mode 100644
index 0000000..0394e91
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-yelp.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M57.852,61.469c-1.4,1.409-0.215,3.981-0.215,3.981L68.18,83.056c0,0,1.732,2.32,3.231,2.32
+ c1.506,0,2.996-1.236,2.996-1.236l8.335-11.916c0,0,0.839-1.504,0.859-2.819c0.03-1.871-2.793-2.388-2.793-2.388l-19.737-6.338
+ C61.072,60.679,59.139,60.166,57.852,61.469z"/>
+ <path d="M56.852,52.594c1.011,1.71,3.795,1.212,3.795,1.212l19.691-5.756c0,0,2.683-1.09,3.067-2.543
+ c0.375-1.459-0.444-3.213-0.444-3.213l-9.409-11.085c0,0-0.816-1.403-2.508-1.543c-1.865-0.157-3.015,2.099-3.015,2.099
+ L56.904,49.272C56.904,49.272,55.921,51.019,56.852,52.594z"/>
+ <path d="M47.547,45.767c2.32-0.572,2.688-3.94,2.688-3.94l-0.158-28.035c0,0-0.349-3.457-1.903-4.397
+ c-2.438-1.477-3.16-0.707-3.857-0.602l-16.348,6.074c0,0-1.602,0.529-2.435,1.865c-1.191,1.891,1.209,4.663,1.209,4.663
+ L43.736,44.56C43.736,44.56,45.412,46.296,47.547,45.767z"/>
+ <path d="M43.51,57.112c0.06-2.162-2.596-3.461-2.596-3.461l-17.57-8.88c0,0-2.605-1.072-3.869-0.324
+ c-0.969,0.573-1.828,1.609-1.911,2.524L16.419,61.06c0,0-0.171,2.443,0.461,3.552c0.896,1.573,3.845,0.479,3.845,0.479
+ l20.514-4.535C42.036,60.02,43.434,59.97,43.51,57.112z"/>
+ <path d="M48.612,64.714c-1.761-0.904-3.868,0.971-3.868,0.971l-13.736,15.12c0,0-1.714,2.313-1.279,3.732
+ c0.412,1.333,1.091,1.995,2.053,2.46l13.794,4.354c0,0,1.673,0.347,2.94-0.019c1.797-0.523,1.466-3.334,1.466-3.334l0.311-20.479
+ C50.293,67.519,50.224,65.548,48.612,64.714z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-youtube.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-youtube.svg
new file mode 100644
index 0000000..f152e73
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-youtube.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <g>
+ <path fill="#231F20" d="M45.19,70.391c-0.696,0.984-1.355,1.469-1.985,1.469c-0.42,0-0.659-0.246-0.735-0.734
+ c-0.03-0.101-0.03-0.484-0.03-1.22V57.146h-3.138V70.85c0,1.225,0.104,2.051,0.277,2.576c0.313,0.878,1.011,1.289,2.023,1.289
+ c1.154,0,2.34-0.697,3.587-2.129v1.891h3.143v-17.33H45.19V70.391z"/>
+ <polygon fill="#231F20" points="27.897,54.492 31.591,54.492 31.591,74.477 35.083,74.477 35.083,54.492 38.845,54.492
+ 38.845,51.218 27.897,51.218 "/>
+ <path fill="#231F20" d="M49.281,39.34c1.023,0,1.513-0.81,1.513-2.431v-7.368c0-1.619-0.49-2.426-1.513-2.426
+ c-1.024,0-1.515,0.807-1.515,2.426v7.368C47.767,38.529,48.257,39.34,49.281,39.34z"/>
+ <path fill="#231F20" d="M57.434,56.935c-1.154,0-2.23,0.632-3.243,1.88v-7.597H51.05v23.259h3.141v-1.682
+ c1.048,1.299,2.127,1.92,3.243,1.92c1.251,0,2.091-0.658,2.511-1.947c0.209-0.735,0.316-1.889,0.316-3.492v-6.901
+ c0-1.64-0.107-2.786-0.316-3.483C59.524,57.593,58.685,56.935,57.434,56.935z M57.121,69.522c0,1.565-0.461,2.337-1.366,2.337
+ c-0.516,0-1.04-0.246-1.565-0.771V60.524c0.525-0.517,1.048-0.763,1.565-0.763c0.906,0,1.366,0.802,1.366,2.365V69.522z"/>
+ <path fill="#231F20" d="M67.435,56.935c-1.602,0-2.854,0.591-3.76,1.778c-0.668,0.875-0.971,2.229-0.971,4.08v6.072
+ c0,1.84,0.342,3.209,1.009,4.074c0.907,1.183,2.157,1.775,3.801,1.775c1.64,0,2.927-0.621,3.797-1.877
+ c0.38-0.559,0.628-1.188,0.733-1.883c0.028-0.315,0.067-1.013,0.067-2.023v-0.46h-3.205c0,1.26-0.039,1.957-0.068,2.128
+ c-0.179,0.839-0.631,1.259-1.403,1.259c-1.078,0-1.602-0.8-1.602-2.404v-3.072h6.279v-3.59c0-1.852-0.315-3.205-0.972-4.08
+ C70.261,57.525,69.011,56.935,67.435,56.935z M68.972,63.769h-3.139v-1.603c0-1.602,0.524-2.404,1.574-2.404
+ c1.039,0,1.565,0.802,1.565,2.404V63.769z"/>
+ <path fill="#231F20" d="M79,14H21c-3.85,0-7,3.15-7,7v58c0,3.85,3.15,7,7,7h58c3.85,0,7-3.15,7-7V21C86,17.15,82.85,14,79,14z
+ M56.58,24.47h3.163v12.892c0,0.746,0,1.133,0.039,1.235c0.07,0.492,0.318,0.743,0.744,0.743c0.634,0,1.301-0.492,2.004-1.486
+ V24.47h3.174V41.98H62.53v-1.91c-1.263,1.449-2.468,2.153-3.625,2.153c-1.022,0-1.727-0.415-2.044-1.303
+ c-0.175-0.529-0.281-1.368-0.281-2.604V24.47z M44.593,30.178c0-1.871,0.319-3.24,0.994-4.125
+ c0.878-1.196,2.114-1.795,3.694-1.795c1.59,0,2.824,0.599,3.703,1.795c0.664,0.885,0.985,2.254,0.985,4.125v6.135
+ c0,1.86-0.32,3.24-0.985,4.119c-0.879,1.193-2.112,1.792-3.703,1.792c-1.581,0-2.817-0.599-3.694-1.792
+ c-0.675-0.879-0.994-2.259-0.994-4.119V30.178z M36.107,18.482l2.499,9.227l2.399-9.227h3.558l-4.232,13.982v9.516h-3.52v-9.516
+ c-0.318-1.688-1.022-4.158-2.15-7.435c-0.742-2.18-1.515-4.37-2.256-6.547H36.107z M75.073,75.518
+ c-0.634,2.763-2.896,4.801-5.616,5.104c-6.444,0.72-12.965,0.724-19.457,0.72c-6.493,0.004-13.014,0-19.457-0.72
+ c-2.721-0.304-4.979-2.342-5.614-5.104c-0.905-3.936-0.905-8.232-0.905-12.282c0-4.054,0.01-8.347,0.916-12.284
+ c0.634-2.762,2.893-4.799,5.614-5.103c6.443-0.722,12.964-0.724,19.457-0.722c6.492-0.002,13.013,0,19.457,0.722
+ c2.719,0.304,4.98,2.341,5.615,5.103c0.905,3.938,0.9,8.23,0.9,12.284C75.984,67.286,75.979,71.582,75.073,75.518z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zerply.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zerply.svg
new file mode 100644
index 0000000..aa3cabf
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zerply.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M37.483,61.48c7.221,0.67,12.822,4.535,18.604,8.086c4.091,2.512,8.593,3.973,13.483,3.91
+ c2.35-0.029,4.435-0.799,6.224-2.303c0.767-0.646,1.085-0.514,1.312,0.43c1.756,7.254-4.007,14.668-11.467,14.891
+ c-3.72,0.111-6.915-1.223-9.895-3.17c-3.4-2.225-6.648-4.686-10.036-6.928c-6.246-4.137-13.147-5.551-20.546-4.674
+ c-2.162,0.258-2.375,0.086-2.547-2.199c-0.321-4.287,1.237-7.81,4.117-10.93c8.217-8.893,16.293-17.912,23.846-27.389
+ c0.647-0.812,1.289-1.629,1.92-2.453c0.181-0.238,0.557-0.445,0.377-0.795c-0.175-0.34-0.564-0.185-0.859-0.17
+ c-3.609,0.201-7.217,0.402-10.834,0.322c-1.868-0.045-3.691-0.299-5.413-1.059c-2.893-1.271-3.835-3.455-2.733-6.391
+ c0.896-2.383,2.238-4.523,3.709-6.594c0.416-0.584,0.778-0.727,1.449-0.381c3.368,1.727,7.045,2.184,10.744,2.477
+ c7.833,0.621,15.604,0.076,23.297-1.486c1.005-0.203,1.029,0.293,1.118,0.982c0.456,3.51-0.722,6.443-3.028,9.047
+ c-8.268,9.332-16.146,19.008-24.974,27.846C42.616,55.285,39.882,58.058,37.483,61.48z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zurb.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zurb.svg
new file mode 100644
index 0000000..5fcaa0e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-social-zurb.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#231F20" d="M79,14H21c-3.866,0-7,3.134-7,7v58c0,3.866,3.134,7,7,7h58c3.866,0,7-3.134,7-7V21
+ C86,17.134,82.866,14,79,14z M70.353,57.23v5.339c-0.104,1.056-0.924,1.888-1.973,2.019L38.235,64.59
+ c-2.232,0-4.135-0.72-5.707-2.157c-1.571-1.438-2.357-3.177-2.357-5.221c0-1.626,0.531-3.071,1.594-4.345
+ c1.064-1.27,2.411-2.154,4.041-2.656l26.341-7.527H30.172v-5.096c0.015-1.07,0.771-1.955,1.779-2.177h30.338
+ c2.232,0,4.133,0.714,5.705,2.139c1.572,1.427,2.359,3.13,2.359,5.112c0,1.655-0.536,3.111-1.607,4.371
+ c-1.071,1.262-2.449,2.141-4.134,2.635L38.235,57.23H70.353z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sound.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sound.svg
new file mode 100644
index 0000000..0e8d932
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-sound.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M45.697,45.697c-2.377,2.375-2.377,6.227-0.002,8.603c2.379,2.38,6.231,2.378,8.606,0.001c2.38-2.378,2.38-6.228,0-8.607
+ C51.926,43.318,48.075,43.317,45.697,45.697z"/>
+ <path d="M76.549,79.165c15.972-16.109,15.934-42.207-0.122-58.263c-0.023-0.023-0.05-0.037-0.073-0.059l0.006-0.006l-1.696-1.698
+ l-0.02,0.02c-0.927-0.738-2.266-0.695-3.136,0.141l-0.003-0.003l-0.026,0.026c-0.003,0.002-0.005,0.004-0.008,0.007
+ c-0.002,0.002-0.004,0.005-0.006,0.008l-2.773,2.772c-0.001,0.001-0.002,0.001-0.002,0.002s-0.001,0.002-0.002,0.002l-0.2,0.2
+ l0.02,0.02c-0.682,0.868-0.678,2.087,0.01,2.951l-0.019,0.019l0.19,0.19l0,0.001l0.001,0l1.506,1.505l0.027-0.027
+ c0.022,0.023,0.037,0.05,0.06,0.073c12.667,12.668,12.707,33.254,0.122,45.974l-0.017-0.017l-1.504,1.504
+ c-0.001,0.001-0.002,0.001-0.003,0.002s-0.001,0.002-0.002,0.003l-0.188,0.188l0.019,0.019c-0.738,0.927-0.695,2.266,0.141,3.136
+ l-0.003,0.003l0.031,0.031c0.001,0.001,0.001,0.002,0.002,0.003c0.001,0.001,0.002,0.001,0.003,0.002l1.396,1.396
+ c0.001,0.001,0.002,0.002,0.002,0.003s0.002,0.001,0.003,0.002l1.376,1.376c0.001,0.001,0.002,0.002,0.002,0.003
+ c0.001,0.001,0.002,0.001,0.003,0.002l0.198,0.198l0.02-0.02c0.868,0.682,2.088,0.679,2.952-0.009l0.019,0.019l1.567-1.568
+ c0.002-0.002,0.003-0.003,0.005-0.004c0.006-0.006,0.012-0.012,0.018-0.019l0.107-0.107L76.549,79.165z"/>
+ <path d="M64.923,67.54c9.561-9.699,9.523-25.365-0.123-35.01c-0.023-0.023-0.05-0.037-0.073-0.06l0.007-0.007l-1.697-1.698
+ l-0.02,0.02c-0.927-0.737-2.266-0.695-3.136,0.141l-0.003-0.003l-0.029,0.029c-0.002,0.002-0.003,0.003-0.005,0.004
+ s-0.003,0.003-0.004,0.005l-2.774,2.774c-0.001,0.001-0.003,0.002-0.004,0.003c-0.001,0.001-0.002,0.002-0.003,0.004l-0.198,0.198
+ l0.02,0.02c-0.682,0.867-0.679,2.087,0.009,2.951l-0.019,0.019l0.189,0.189c0.001,0.001,0.001,0.001,0.002,0.002
+ c0.001,0.001,0.001,0.001,0.002,0.002l1.504,1.505l0.027-0.027c0.022,0.023,0.037,0.05,0.06,0.073
+ c6.258,6.257,6.293,16.407,0.119,22.717l-0.013-0.013l-1.505,1.505c-0.001,0-0.001,0.001-0.002,0.001s-0.001,0.001-0.001,0.002
+ l-0.189,0.189l0.019,0.019c-0.737,0.927-0.695,2.265,0.141,3.135l-0.004,0.004l2.816,2.815l0,0l0,0l0.201,0.201l0.02-0.02
+ c0.868,0.681,2.087,0.678,2.951-0.009l0.02,0.02l1.572-1.572l0,0h0l0.125-0.125L64.923,67.54z"/>
+ </g>
+ <g>
+ <path d="M54.305,45.7c-2.379-2.38-6.231-2.377-8.606-0.001c-2.379,2.379-2.379,6.228,0,8.605c2.376,2.377,6.227,2.379,8.605-0.001
+ C56.68,51.928,56.68,48.076,54.305,45.7z"/>
+ <path d="M43.109,63.089l0.019-0.019l-0.188-0.188c-0.001-0.001-0.002-0.002-0.003-0.004c-0.001-0.001-0.002-0.002-0.003-0.003
+ l-1.503-1.504l-0.027,0.027c-0.022-0.023-0.037-0.05-0.059-0.072c-6.258-6.258-6.293-16.408-0.119-22.718l0.013,0.013l1.697-1.696
+ l-0.02-0.02c0.738-0.927,0.695-2.266-0.141-3.135l0.004-0.004l-3.018-3.017l-0.02,0.02c-0.868-0.682-2.086-0.679-2.951,0.009
+ l-0.019-0.019l-0.191,0.191l0,0l0,0l-1.381,1.381l0,0h0l-0.125,0.125l0.003,0.003c-9.562,9.699-9.523,25.365,0.123,35.011
+ c0.022,0.022,0.049,0.037,0.072,0.059l-0.006,0.006l1.697,1.698l0.02-0.02c0.926,0.737,2.264,0.694,3.135-0.141l0.003,0.003
+ l0.029-0.029c0.002-0.002,0.004-0.003,0.005-0.004s0.003-0.004,0.004-0.005l2.775-2.775c0.001-0.001,0.002-0.001,0.003-0.002
+ s0.001-0.002,0.002-0.002l0.199-0.199l-0.02-0.02C43.8,65.172,43.797,63.953,43.109,63.089z"/>
+ <path d="M31.483,74.715l0.019-0.019l-0.19-0.19c0,0,0-0.001-0.001-0.001c0,0-0.001,0-0.001-0.001l-1.506-1.505l-0.027,0.027
+ c-0.022-0.023-0.037-0.05-0.059-0.073C17.05,60.284,17.012,39.7,29.597,26.98l0.016,0.016l1.504-1.504
+ c0.001-0.001,0.002-0.001,0.003-0.002s0.001-0.002,0.002-0.003l0.188-0.188l-0.019-0.019c0.738-0.927,0.696-2.266-0.141-3.136
+ l0.004-0.004l-1.434-1.434c0,0-0.001-0.001-0.001-0.001c-0.001-0.001-0.001-0.001-0.001-0.001l-1.581-1.581l-0.02,0.021
+ c-0.867-0.682-2.086-0.679-2.951,0.009l-0.02-0.02l-1.696,1.697l0.003,0.003C7.479,36.943,7.517,63.042,23.574,79.098
+ c0.023,0.023,0.05,0.037,0.073,0.059l-0.007,0.007l1.697,1.698l0.02-0.02c0.927,0.737,2.266,0.694,3.136-0.142l0.003,0.003
+ l0.033-0.033h0l0,0l2.778-2.779c0.002-0.002,0.004-0.003,0.005-0.004c0.002-0.002,0.003-0.004,0.004-0.005l0.196-0.196l-0.02-0.02
+ C32.174,76.799,32.171,75.58,31.483,74.715z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-star.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-star.svg
new file mode 100644
index 0000000..7f84dd9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-star.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M91.532,39.844c-0.278-0.804-1.036-1.343-1.888-1.343H61.482l-9.597-27.159c-0.284-0.799-1.039-1.334-1.886-1.334
+ c-0.846,0-1.602,0.534-1.885,1.334l-9.598,27.159H10.357c-0.851,0-1.609,0.539-1.891,1.343c-0.278,0.804-0.018,1.698,0.651,2.226
+ l21.986,17.409l-9.84,27.846c-0.281,0.795-0.031,1.682,0.62,2.215c0.654,0.536,1.573,0.603,2.297,0.167l25.818-15.488l25.818,15.488
+ c0.317,0.191,0.677,0.285,1.032,0.285c0.447,0,0.898-0.152,1.266-0.452c0.651-0.533,0.901-1.42,0.62-2.215l-9.84-27.846
+ l21.992-17.409C91.553,41.542,91.813,40.648,91.532,39.844z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-stop.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-stop.svg
new file mode 100644
index 0000000..1f37886
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-stop.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.049,22.127c-0.004-1.192-0.97-2.156-2.163-2.156c-0.028,0-0.054,0.007-0.082,0.008v0H22.302
+ c-0.063-0.006-0.125-0.019-0.19-0.019c-1.194,0-2.163,0.968-2.163,2.163c0,0.101,0.016,0.198,0.03,0.295V77.87h0.001
+ c0,0.003-0.001,0.006-0.001,0.009c0,1.194,0.969,2.162,2.163,2.162c0.046,0,0.089-0.011,0.134-0.013v0.002h55.688v-0.018
+ c1.153-0.042,2.077-0.98,2.084-2.142h0.001L80.049,22.127L80.049,22.127z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-strikethrough.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-strikethrough.svg
new file mode 100644
index 0000000..186b858
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-strikethrough.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M77.5,49.719c-0.035,0-0.068,0.009-0.103,0.01v-0.01h-55v0.01c-1.608,0.056-2.897,1.368-2.897,2.99
+ c0,1.621,1.289,2.934,2.897,2.99v0.01h55v-0.01c0.035,0.001,0.068,0.01,0.103,0.01c1.657,0,3-1.343,3-3
+ C80.5,51.062,79.157,49.719,77.5,49.719z"/>
+ <path d="M70.928,59.469h-7.14v0.011c-0.035-0.002-0.069-0.011-0.105-0.011c-0.863,0-1.562,0.699-1.562,1.562
+ c0,0.126,0.019,0.247,0.047,0.365h-0.018c0.092,0.393,0.157,0.802,0.157,1.249c0,3.819-3.14,7.808-11.288,7.808
+ c-7.741,0-13.842-3.592-17.678-7.653c-0.286-0.373-0.731-0.617-1.237-0.617c-0.528,0-0.992,0.264-1.275,0.664l-0.001-0.002
+ l-0.01,0.015c-0.007,0.01-0.013,0.019-0.019,0.029l-3.425,5.212l0.003,0.001c-0.245,0.276-0.398,0.635-0.398,1.033
+ c0,0.515,0.253,0.969,0.637,1.253c5.091,5.205,12.61,8.891,22.978,8.891c15.191,0,21.896-8.147,21.896-17.568
+ c0-0.172-0.011-0.335-0.018-0.501c0.007-0.06,0.018-0.118,0.018-0.179C72.49,60.168,71.791,59.469,70.928,59.469z"/>
+ <path d="M31.868,45.677c0.269,0.471,0.77,0.792,1.351,0.792h23.542c0.277,0,0.502-0.225,0.502-0.502
+ c0-0.277-0.225-0.502-0.502-0.502v-0.008c-8.471-2.48-17.2-3.403-17.2-8.866c0-4.159,3.734-7.044,9.505-7.044
+ c5.941,0,11.967,2.037,16.465,6.535l0.006-0.008c0.272,0.231,0.62,0.375,1.005,0.375c0.491,0,0.923-0.231,1.21-0.584l0.002,0.003
+ l0.028-0.039c0.028-0.037,0.056-0.074,0.081-0.114l3.409-4.788l-0.003-0.001c0.245-0.276,0.398-0.635,0.398-1.033
+ c0-0.473-0.215-0.892-0.547-1.178l0.011-0.015C65.956,23.606,58.742,20.72,50,20.72c-12.476,0-20.623,7.214-20.623,16.634
+ C29.377,40.853,30.316,43.549,31.868,45.677L31.868,45.677z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-subscript.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-subscript.svg
new file mode 100644
index 0000000..8b2acdd
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-subscript.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M90.694,76.981c-0.194-0.194-0.448-0.291-0.703-0.291v-0.012h-5.208c3.816-2.52,5.064-4.32,5.064-6.504
+ c0-3.216-2.712-5.521-6.865-5.521c-2.138,0-4.685,0.695-6.521,2.481c-0.043,0.031-0.092,0.048-0.13,0.087
+ c-0.027,0.027-0.038,0.063-0.062,0.093c-0.018,0.018-0.038,0.033-0.055,0.052l0.012,0.014c-0.225,0.336-0.224,0.761,0.005,1.096
+ l-0.016,0.01l1.367,1.995l0.001,0c0.347,0.346,0.878,0.365,1.265,0.092l0.007,0.009c0.036-0.03,0.072-0.056,0.108-0.085
+ c0.007-0.007,0.017-0.009,0.025-0.016c0.002-0.002,0.003-0.005,0.005-0.007c1.184-0.965,2.446-1.548,4.088-1.548
+ c1.032,0,1.848,0.48,1.848,1.248c0,1.2-0.696,1.8-8.017,6.96v0.022c-0.067,0.041-0.139,0.073-0.197,0.131
+ c-0.162,0.162-0.24,0.367-0.267,0.578h-0.024v2.609c0,0.241,0.195,0.437,0.437,0.437c0.018,0,0.034-0.008,0.052-0.01v0.004h13.082
+ c0.254,0,0.509-0.097,0.703-0.291c0.194-0.194,0.291-0.448,0.291-0.703v-2.225C90.985,77.429,90.888,77.175,90.694,76.981z"/>
+ <path d="M70.495,33.34l-3.389-3.39c-1.017-1.017-2.666-1.017-3.683,0l-0.016-0.016L50.374,42.968L37.34,29.934
+ c-1.017-1.017-2.666-1.017-3.683,0l-3.389,3.389c-1.017,1.017-1.017,2.666,0,3.683l-0.016,0.016l13.033,13.033L30.252,63.09
+ l0.016,0.016h0c-1.017,1.017-1.017,2.666,0,3.683l3.389,3.389c1.017,1.017,2.666,1.017,3.683,0l0,0l13.033-13.033l13.033,13.033
+ l0.016-0.016v0c1.017,1.017,2.666,1.017,3.683,0l3.389-3.389c1.017-1.017,1.017-2.666,0-3.683l0,0L57.462,50.056l13.033-13.033l0,0
+ C71.513,36.006,71.513,34.357,70.495,33.34z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-superscript.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-superscript.svg
new file mode 100644
index 0000000..35f1560
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-superscript.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M90.478,31.418c-0.194-0.194-0.448-0.291-0.703-0.291v-0.011h-5.208c3.816-2.52,5.064-4.32,5.064-6.504
+ c0-3.216-2.712-5.521-6.865-5.521c-2.138,0-4.685,0.695-6.521,2.481c-0.043,0.031-0.092,0.048-0.13,0.087
+ c-0.027,0.027-0.038,0.063-0.062,0.093c-0.018,0.018-0.038,0.033-0.055,0.052l0.012,0.014c-0.225,0.336-0.224,0.761,0.005,1.095
+ l-0.016,0.01l1.367,1.995l0.001,0c0.347,0.346,0.878,0.365,1.265,0.093l0.007,0.009c0.036-0.03,0.072-0.056,0.108-0.085
+ c0.007-0.007,0.017-0.009,0.025-0.016c0.002-0.002,0.003-0.005,0.005-0.007c1.184-0.965,2.446-1.548,4.088-1.548
+ c1.032,0,1.848,0.48,1.848,1.248c0,1.2-0.696,1.8-8.017,6.96v0.022c-0.067,0.041-0.139,0.073-0.197,0.131
+ c-0.162,0.162-0.24,0.367-0.267,0.578h-0.024v2.609c0,0.241,0.195,0.437,0.437,0.437c0.018,0,0.034-0.008,0.052-0.01v0.004h13.082
+ c0.254,0,0.509-0.097,0.703-0.291c0.194-0.194,0.291-0.448,0.291-0.703v-2.225C90.769,31.866,90.672,31.612,90.478,31.418z"/>
+ <path d="M70.279,33.467l-3.389-3.39c-1.017-1.017-2.666-1.017-3.683,0l-0.016-0.016L50.157,43.095L37.124,30.061
+ c-1.017-1.017-2.666-1.017-3.683,0l-3.389,3.389c-1.017,1.017-1.017,2.666,0,3.683l-0.016,0.016l13.033,13.033L30.035,63.217
+ l0.016,0.016h0c-1.017,1.017-1.017,2.666,0,3.683l3.389,3.389c1.017,1.017,2.666,1.017,3.683,0l0,0l13.033-13.033l13.033,13.033
+ l0.016-0.016v0c1.017,1.017,2.666,1.017,3.683,0l3.389-3.389c1.017-1.017,1.017-2.666,0-3.683l0,0L57.246,50.183L70.279,37.15l0,0
+ C71.296,36.133,71.296,34.484,70.279,33.467z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-landscape.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-landscape.svg
new file mode 100644
index 0000000..07d9646
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-landscape.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M92.566,22.081c0-1.676-1.358-3.035-3.035-3.035H10.469c-1.676,0-3.035,1.359-3.035,3.035
+ c0,0.043,0.011,0.084,0.013,0.127H7.434v55.838h0.013c0.068,1.616,1.389,2.908,3.022,2.908h79.062c1.633,0,2.954-1.292,3.022-2.908
+ h0.013V22.208h-0.013C92.555,22.164,92.566,22.124,92.566,22.081z M82.609,70.997H17.391V29.003h65.219V70.997z M87.587,52.611
+ c-1.372,0-2.484-1.112-2.484-2.484c0-1.372,1.112-2.484,2.484-2.484c1.372,0,2.485,1.112,2.485,2.484
+ C90.072,51.499,88.959,52.611,87.587,52.611z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-portrait.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-portrait.svg
new file mode 100644
index 0000000..dfe77df
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-tablet-portrait.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M77.919,7.434c-0.043,0-0.084,0.011-0.127,0.013V7.434H21.954v0.013c-1.616,0.068-2.908,1.389-2.908,3.022
+ v79.062c0,1.633,1.292,2.954,2.908,3.022v0.013h55.838v-0.013c0.043,0.002,0.083,0.013,0.127,0.013
+ c1.676,0,3.035-1.358,3.035-3.035V10.469C80.954,8.792,79.595,7.434,77.919,7.434z M49.873,90.072
+ c-1.372,0-2.484-1.113-2.484-2.485c0-1.372,1.112-2.484,2.484-2.484c1.372,0,2.484,1.112,2.484,2.484
+ C52.357,88.959,51.245,90.072,49.873,90.072z M70.997,82.609H29.003V17.391h41.995V82.609z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target-two.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target-two.svg
new file mode 100644
index 0000000..298c015
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target-two.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M94.988,47.506h-7.58c-1.231-18.719-16.193-33.684-34.914-34.915v-7.58c0-1.377-1.117-2.493-2.494-2.493
+ s-2.493,1.116-2.493,2.493v7.58c-18.722,1.231-33.683,16.195-34.914,34.915h-7.58c-1.377,0-2.493,1.117-2.493,2.494
+ s1.116,2.494,2.493,2.494h7.579c1.229,18.722,16.191,33.684,34.915,34.914v7.58c0,1.377,1.117,2.493,2.494,2.493
+ s2.493-1.116,2.493-2.493v-7.58c18.723-1.23,33.685-16.193,34.915-34.914h7.579c1.377,0,2.493-1.117,2.493-2.495
+ C97.481,48.622,96.365,47.506,94.988,47.506z M47.506,77.443c-13.212-1.191-23.759-11.739-24.949-24.949h4.99
+ c1.152,10.484,9.475,18.807,19.959,19.959V77.443z M47.506,27.547c-10.484,1.152-18.807,9.475-19.959,19.959h-4.99
+ c1.192-13.208,11.738-23.757,24.948-24.949V27.547z M52.494,22.558c13.21,1.191,23.756,11.74,24.948,24.948h-4.989
+ c-1.152-10.485-9.475-18.808-19.959-19.959V22.558z M52.494,77.443v-4.989c10.484-1.152,18.807-9.475,19.959-19.959h4.989
+ C76.252,65.704,65.705,76.251,52.494,77.443z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target.svg
new file mode 100644
index 0000000..5c3538c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-target.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M49.984,27.452c-12.453,0-22.548,10.095-22.548,22.548c0,12.453,10.095,22.548,22.548,22.548S72.531,62.453,72.531,50
+ C72.531,37.547,62.436,27.452,49.984,27.452z M49.984,62.608c-6.964,0-12.609-5.645-12.609-12.608
+ c0-6.964,5.645-12.609,12.609-12.609S62.592,43.036,62.592,50C62.592,56.963,56.947,62.608,49.984,62.608z"/>
+ <path d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5c20.712,0,37.5-16.788,37.5-37.498
+ C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.56-12.362-27.56-27.559c0-15.195,12.362-27.562,27.56-27.562
+ c15.198,0,27.56,12.367,27.56,27.562C77.56,65.198,65.198,77.561,50,77.561z"/>
+ <circle cx="49.984" cy="50" r="7.621"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone-accessible.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone-accessible.svg
new file mode 100644
index 0000000..f428683
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone-accessible.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M19.777,37.475c0.662,0.48,1.511,0.607,2.336,0.365l12.607-3.262l0.104-0.023
+ c0.484-0.156,0.941-0.444,1.321-0.83c0.665-0.661,1.049-1.548,1.047-2.434l-0.001-4.684c0.006-0.193,0.195-0.658,0.287-0.763
+ c0.028-0.022,2.92-2.528,12.854-2.528c9.913-0.002,12.832,2.496,12.834,2.494c0.134,0.141,0.323,0.604,0.328,0.799l-0.001,3.994
+ c0.002,1.409,0.962,2.787,2.281,3.273l12.709,3.893c0.981,0.34,2.012,0.124,2.704-0.57c0.489-0.486,0.755-1.156,0.755-1.893
+ l0.014-10.879c0.004-1.041-0.455-2.398-1.088-3.228c-0.302-0.397-7.673-9.699-30.535-9.7c-19.405,0.001-27.724,6.815-29.815,8.906
+ c-0.449,0.449-0.68,0.74-0.723,0.796c-0.63,0.827-1.089,2.183-1.088,3.22v10.883C18.709,36.193,19.098,36.984,19.777,37.475z"/>
+ <path fill="#231F20" d="M24.359,58.576v2.543c0,1.168,0.95,2.12,2.121,2.12h6.836c1.171,0,2.117-0.952,2.117-2.12v-2.543
+ c0-1.168-0.946-2.123-2.117-2.123h-6.836C25.31,56.453,24.359,57.408,24.359,58.576z"/>
+ <path fill="#231F20" d="M48.904,61.119v-2.543c0-1.168-0.95-2.123-2.119-2.123h-6.838c-1.17,0-2.117,0.955-2.117,2.123v2.543
+ c0,1.168,0.947,2.12,2.117,2.12h6.838C47.955,63.239,48.904,62.287,48.904,61.119z"/>
+ <path fill="#231F20" d="M62.375,61.119v-2.543c0-1.168-0.95-2.123-2.121-2.123h-6.836c-1.171,0-2.121,0.955-2.121,2.123v2.543
+ c0,1.168,0.949,2.12,2.121,2.12h6.836C61.425,63.239,62.375,62.287,62.375,61.119z"/>
+ <path fill="#231F20" d="M75.846,61.119v-2.543c0-1.168-0.95-2.123-2.122-2.123h-6.836c-1.171,0-2.122,0.955-2.122,2.123v2.543
+ c0,1.168,0.95,2.12,2.122,2.12h6.836C74.896,63.239,75.846,62.287,75.846,61.119z"/>
+ <path fill="#231F20" d="M19.641,50.609h6.84c1.167,0,2.117-0.953,2.117-2.121v-2.543c0-1.166-0.95-2.121-2.117-2.121h-6.84
+ c-1.167,0-2.117,0.955-2.117,2.121v2.543C17.523,49.656,18.474,50.609,19.641,50.609z"/>
+ <path fill="#231F20" d="M39.947,50.609c1.171,0,2.121-0.953,2.121-2.121v-2.543c0-1.166-0.95-2.121-2.121-2.121h-6.836
+ c-1.171,0-2.117,0.955-2.117,2.121v2.543c0,1.168,0.946,2.121,2.117,2.121H39.947z"/>
+ <path fill="#231F20" d="M53.418,50.609c1.171,0,2.122-0.953,2.122-2.121v-2.543c0-1.166-0.95-2.121-2.122-2.121h-6.836
+ c-1.172,0-2.122,0.955-2.122,2.121v2.543c0,1.168,0.95,2.121,2.122,2.121H53.418z"/>
+ <path fill="#231F20" d="M66.889,43.824h-6.835c-1.172,0-2.122,0.955-2.122,2.121v2.543c0,1.168,0.95,2.121,2.122,2.121h6.835
+ c1.172,0,2.117-0.953,2.117-2.121v-2.543C69.006,44.779,68.06,43.824,66.889,43.824z"/>
+ <path fill="#231F20" d="M80.36,43.824h-6.84c-1.167,0-2.117,0.955-2.117,2.121v2.543c0,1.168,0.95,2.121,2.117,2.121h6.84
+ c1.167,0,2.117-0.953,2.117-2.121v-2.543C82.477,44.779,81.526,43.824,80.36,43.824z"/>
+ <path fill="#231F20" d="M28.598,73.748v-2.542c0-1.167-0.95-2.12-2.117-2.12h-6.84c-1.167,0-2.117,0.953-2.117,2.12v2.542
+ c0,1.17,0.951,2.123,2.117,2.123h6.84C27.648,75.871,28.598,74.918,28.598,73.748z"/>
+ <path fill="#231F20" d="M33.111,75.871h6.836c1.171,0,2.121-0.953,2.121-2.123v-2.542c0-1.167-0.95-2.12-2.121-2.12h-6.836
+ c-1.171,0-2.117,0.953-2.117,2.12v2.542C30.994,74.918,31.94,75.871,33.111,75.871z"/>
+ <path fill="#231F20" d="M46.583,75.871h6.836c1.171,0,2.122-0.953,2.122-2.123v-2.542c0-1.167-0.95-2.12-2.122-2.12h-6.836
+ c-1.172,0-2.122,0.953-2.122,2.12v2.542C44.461,74.918,45.411,75.871,46.583,75.871z"/>
+ <path fill="#231F20" d="M60.053,75.871h6.835c1.172,0,2.117-0.953,2.117-2.123v-2.542c0-1.167-0.945-2.12-2.117-2.12h-6.835
+ c-1.172,0-2.122,0.953-2.122,2.12v2.542C57.932,74.918,58.881,75.871,60.053,75.871z"/>
+ <path fill="#231F20" d="M80.36,69.086h-6.84c-1.167,0-2.117,0.953-2.117,2.12v2.542c0,1.17,0.95,2.123,2.117,2.123h6.84
+ c1.167,0,2.117-0.953,2.117-2.123v-2.542C82.477,70.039,81.526,69.086,80.36,69.086z"/>
+ <path fill="#231F20" d="M72.427,81.715H26.971c-1.167,0-2.117,0.955-2.117,2.121v2.543c0,1.172,0.951,2.121,2.117,2.121h45.456
+ c1.168,0,2.118-0.949,2.118-2.121v-2.543C74.545,82.67,73.595,81.715,72.427,81.715z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone.svg
new file mode 100644
index 0000000..fe9640f
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-telephone.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M84.96,70.237c-0.167-1.032-0.814-1.914-1.783-2.438l-14.335-8.446l-0.118-0.066
+ c-0.579-0.297-1.249-0.45-1.937-0.45c-1.201,0-2.348,0.455-3.144,1.253l-4.231,4.233c-0.181,0.172-0.771,0.421-0.95,0.43
+ c-0.049-0.004-4.923-0.355-13.896-9.329c-8.957-8.955-9.337-13.844-9.34-13.844c0.005-0.25,0.251-0.838,0.426-1.02l3.608-3.607
+ c1.271-1.274,1.652-3.386,0.898-5.022L32.19,16.938c-0.579-1.192-1.704-1.928-2.952-1.928c-0.883,0-1.735,0.366-2.401,1.031
+ l-9.835,9.813c-0.943,0.938-1.755,2.578-1.932,3.898c-0.086,0.631-1.831,15.693,18.819,36.346
+ C51.42,83.627,65.09,84.989,68.865,84.989l0,0c0.812,0,1.285-0.058,1.376-0.071c1.316-0.176,2.954-0.986,3.891-1.925l9.827-9.826
+ C84.761,72.361,85.127,71.296,84.96,70.237z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-text-color.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-text-color.svg
new file mode 100644
index 0000000..234b7a4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-text-color.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M84,78.754c-0.035,0-0.068,0.009-0.104,0.01v-0.01h-68v0.01C14.288,78.82,13,80.133,13,81.754s1.288,2.934,2.897,2.99v0.01
+ h68v-0.01c0.035,0.001,0.068,0.01,0.104,0.01c1.656,0,3-1.343,3-3S85.656,78.754,84,78.754z"/>
+ <path d="M25.371,71.854h5.679c1.138,0,2.096-0.735,2.45-1.754l3.493-9.195h25.97l3.605,9.492l0.021-0.004
+ c0.392,0.795,1.171,1.353,2.095,1.437v0.024h5.679V71.83c0.078,0.007,0.153,0.024,0.233,0.024c1.439,0,2.604-1.166,2.604-2.604
+ c0-0.266-0.051-0.517-0.125-0.759l0.012-0.002l-0.061-0.156c-0.019-0.051-0.037-0.101-0.059-0.15L56.876,17.036h-0.018
+ c-0.343-1.037-1.31-1.79-2.462-1.79h-8.812c-1.169,0-2.147,0.776-2.476,1.836h0l-20.194,51.3l0.012,0.002
+ c-0.096,0.272-0.159,0.56-0.159,0.865C22.767,70.688,23.934,71.854,25.371,71.854z M49.978,25.176l10.185,26.989H39.793
+ L49.978,25.176z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-thumbnails.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-thumbnails.svg
new file mode 100644
index 0000000..a622fb2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-thumbnails.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M30.278,17.553L30.278,17.553H19.823v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269c0,0,0,0,0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.269,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V19.823h0c0,0,0,0,0,0
+ C32.547,18.57,31.531,17.553,30.278,17.553z"/>
+ <path d="M55.227,17.553L55.227,17.553H44.773v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269c0,0,0,0,0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.269,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V19.823h0c0,0,0,0,0,0
+ C57.497,18.57,56.481,17.553,55.227,17.553z"/>
+ <path d="M82.446,19.822c0-1.252-1.016-2.269-2.269-2.269l0,0H69.722v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269l0,0.001v10.453
+ c0,0,0,0,0,0.001c0,1.253,1.016,2.27,2.269,2.27l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V19.822L82.446,19.822
+ C82.446,19.822,82.446,19.822,82.446,19.822z"/>
+ <path d="M30.278,42.506L30.278,42.506H19.823v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269c0,0,0,0,0,0h0V55.23h0
+ c0,1.253,1.016,2.269,2.269,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V44.776h0c0,0,0,0,0,0
+ C32.547,43.523,31.531,42.506,30.278,42.506z"/>
+ <path d="M55.227,42.506L55.227,42.506H44.773v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269c0,0,0,0,0,0h0V55.23h0
+ c0,1.253,1.016,2.269,2.269,2.269l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V44.776h0c0,0,0,0,0,0
+ C57.497,43.523,56.481,42.506,55.227,42.506z"/>
+ <path d="M80.177,42.506L80.177,42.506H69.722v0l-0.001,0c-1.253,0-2.269,1.017-2.269,2.269l0,0.001v10.453c0,0,0,0,0,0.001
+ c0,1.253,1.016,2.27,2.269,2.27l0.001,0v0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V44.776h0c0,0,0,0,0,0
+ C82.446,43.523,81.43,42.506,80.177,42.506z"/>
+ <path d="M30.278,67.454L30.278,67.454H19.823l0,0h-0.001c-1.253,0-2.269,1.017-2.269,2.269l0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.269,2.269h0.001l0,0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V69.723h0l0,0
+ C32.547,68.471,31.531,67.454,30.278,67.454z"/>
+ <path d="M55.227,67.454L55.227,67.454H44.773l0,0h-0.001c-1.253,0-2.269,1.017-2.269,2.269l0,0h0v10.454h0
+ c0,1.253,1.016,2.269,2.269,2.269h0.001l0,0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V69.723h0l0,0
+ C57.497,68.471,56.481,67.454,55.227,67.454z"/>
+ <path d="M80.177,67.454L80.177,67.454H69.722l0,0h-0.001c-1.253,0-2.269,1.017-2.269,2.269l0,0v10.453l0,0.001
+ c0,1.253,1.016,2.27,2.269,2.27h0.001l0,0h10.454l0,0c1.253,0,2.269-1.016,2.269-2.269h0V69.723h0l0,0
+ C82.446,68.471,81.43,67.454,80.177,67.454z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-ticket.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-ticket.svg
new file mode 100644
index 0000000..a9cc430
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-ticket.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M99.483,33.642c-0.029-0.029-0.063-0.05-0.094-0.077L87.158,21.327c-2.378,1.59-5.623,1.336-7.722-0.763
+ c-2.1-2.1-2.353-5.347-0.761-7.725L66.358,0.516c-0.689-0.688-1.805-0.687-2.494,0l0,0L0.52,63.862
+ c-0.001,0.001-0.002,0.002-0.003,0.003c-0.689,0.689-0.689,1.805,0,2.494l0.001,0.001l0,0l12.325,12.313
+ c2.377-1.59,5.623-1.336,7.722,0.763c2.098,2.098,2.353,5.34,0.767,7.718l12.166,12.154c0.046,0.06,0.089,0.122,0.144,0.176
+ c0.689,0.689,1.804,0.689,2.493,0l0.001,0.001l63.347-63.349l0,0C100.172,35.446,100.172,34.33,99.483,33.642z M85.518,36.135
+ L36.136,85.518l0,0l0,0c-0.689,0.689-1.804,0.689-2.493,0h0l0,0l-19.159-19.16l0,0c-0.689-0.689-0.689-1.804,0-2.493l0,0
+ l49.381-49.382l0,0c0.689-0.688,1.805-0.688,2.493,0l0,0l19.16,19.161C86.207,34.331,86.207,35.447,85.518,36.135z"/>
+ <path d="M61.923,51.521l-6.821-3.259l0.83-7.134c0.025-0.216-0.09-0.425-0.286-0.52c-0.195-0.094-0.43-0.055-0.585,0.099
+ l-5.097,5.098l-6.653-3.178c-0.196-0.094-0.429-0.054-0.583,0.099c-0.154,0.152-0.193,0.386-0.1,0.582l3.179,6.655l-5.098,5.096
+ c-0.154,0.153-0.193,0.389-0.099,0.586c0.095,0.195,0.304,0.309,0.52,0.284l7.132-0.829l3.26,6.822
+ c0.093,0.194,0.299,0.309,0.513,0.288c0.215-0.021,0.394-0.176,0.446-0.386l1.87-7.476l7.478-1.871
+ c0.091-0.023,0.173-0.071,0.238-0.135c0.081-0.081,0.135-0.191,0.148-0.311C62.234,51.819,62.119,51.613,61.923,51.521z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-business.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-business.svg
new file mode 100644
index 0000000..c6b2746
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-business.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.161,60.441l-15.66-7.47l-6.622-3.159c2.892-1.822,5.241-4.634,6.778-8.021c1.219-2.69,1.945-5.734,1.945-8.99
+ c0-1.827-0.29-3.562-0.694-5.236c-1.97-8.112-8.305-14.088-15.91-14.088c-7.461,0-13.7,5.763-15.792,13.644
+ c-0.483,1.808-0.815,3.688-0.815,5.68c0,3.459,0.808,6.684,2.181,9.489c1.587,3.254,3.94,5.937,6.804,7.662l-6.342,2.953
+ l-16.168,7.53c-1.404,0.658-2.327,2.242-2.327,4.011v15.062v2.703c0,2.381,1.659,4.311,3.707,4.311h24.013V72.92
+ c0-0.147,0.05-0.278,0.119-0.396l-0.01-0.006l3.933-6.812l0.01,0.006c0.14-0.24,0.389-0.41,0.687-0.41
+ c0.298,0,0.547,0.169,0.687,0.41l0.004-0.003l0.036,0.063c0.005,0.01,0.012,0.018,0.016,0.028l3.881,6.721l-0.005,0.003
+ c0.069,0.119,0.119,0.249,0.119,0.397v13.602h24.013c2.048,0,3.708-1.93,3.708-4.311v-2.703V64.446
+ C82.46,62.683,81.552,61.114,80.161,60.441z M54.62,55.886l0.01,0.006l-3.934,6.812l-0.01-0.006
+ c-0.14,0.24-0.389,0.409-0.687,0.409c-0.298,0-0.547-0.169-0.687-0.409l-0.005,0.003l-0.04-0.069
+ c-0.003-0.007-0.009-0.013-0.012-0.02l-3.881-6.723l0.004-0.003c-0.069-0.119-0.119-0.249-0.119-0.397
+ c0-0.445,0.361-0.806,0.806-0.806h7.866c0.445,0,0.806,0.361,0.806,0.806C54.739,55.637,54.689,55.767,54.62,55.886z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-female.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-female.svg
new file mode 100644
index 0000000..944cc3c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso-female.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.161,60.442l-15.66-7.47l-6.622-3.159c0.166-0.105,0.324-0.224,0.487-0.335h8.695c1.346,0,2.438-1.091,2.438-2.438
+ v-6.415h-0.022c-0.266-8.94-3.371-16.805-8.034-21.737c-2.459-2.773-5.646-4.657-9.211-5.22c-0.159-0.026-0.318-0.05-0.478-0.071
+ c-0.184-0.023-0.367-0.046-0.553-0.061c-0.398-0.035-0.798-0.059-1.202-0.059h0h0c-0.001,0-0.001,0-0.002,0
+ c-0.398,0-0.791,0.023-1.183,0.057c-0.188,0.016-0.374,0.039-0.56,0.062c-0.156,0.02-0.311,0.042-0.465,0.068
+ c-3.536,0.553-6.701,2.408-9.153,5.141c-4.708,4.927-7.847,12.829-8.115,21.821H30.5v6.415c0,1.346,1.091,2.438,2.438,2.438h8.719
+ c0.238,0.162,0.475,0.327,0.721,0.475l-6.342,2.953l-16.168,7.53c-1.405,0.658-2.327,2.242-2.327,4.011v15.062v2.703
+ c0,2.381,1.659,4.311,3.708,4.311h57.504c2.049,0,3.708-1.93,3.708-4.311v-2.703V64.446C82.46,62.683,81.552,61.114,80.161,60.442z
+ "/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso.svg
new file mode 100644
index 0000000..e55236e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torso.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M80.161,60.441l-15.66-7.47l-6.622-3.159c2.892-1.822,5.241-4.634,6.778-8.022c1.22-2.69,1.946-5.734,1.946-8.99
+ c0-1.827-0.29-3.562-0.694-5.236C63.94,19.453,57.605,13.477,50,13.477c-7.461,0-13.701,5.763-15.792,13.645
+ c-0.482,1.808-0.815,3.688-0.815,5.68c0,3.459,0.808,6.684,2.181,9.489c1.587,3.254,3.94,5.937,6.804,7.662l-6.342,2.953
+ l-16.168,7.53c-1.404,0.658-2.327,2.242-2.327,4.011v15.062v2.703c0,2.381,1.659,4.312,3.708,4.312h57.505
+ c2.048,0,3.708-1.93,3.708-4.312v-2.703V64.446C82.46,62.683,81.552,61.114,80.161,60.441z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all-female.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all-female.svg
new file mode 100644
index 0000000..558c6bb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all-female.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M77.067,59.255L62.99,52.54l-5.754-2.745c0.101-0.069,0.201-0.139,0.301-0.208h7.833c1.212,0,2.196-0.983,2.196-2.196
+ v-5.779h-0.02c-0.228-7.653-2.767-14.425-6.622-18.894c-2.71-3.484-6.605-5.681-10.971-5.681c-4.732,0-8.911,2.586-11.625,6.593
+ c-3.435,4.452-5.664,10.833-5.877,17.982h-0.02v5.779c0,1.213,0.983,2.196,2.196,2.196h7.855c0.155,0.105,0.312,0.207,0.469,0.309
+ l-5.551,2.584l-14.534,6.768c-1.152,0.54-1.936,1.776-2.065,3.198c-0.029,0.205-0.046,0.414-0.046,0.626v13.57v2.435
+ c0,2.146,1.495,3.884,3.34,3.884h51.806c1.846,0,3.34-1.739,3.34-3.884v-2.435v-13.57c0-0.805-0.212-1.563-0.582-2.196
+ C78.3,60.165,77.752,59.586,77.067,59.255z"/>
+ <path d="M25.646,52.52v-6.081h0.027c0.243-8.172,2.377-15.627,5.776-21.472c-1.654-1.008-3.513-1.623-5.511-1.623
+ c-6.666,0-12.062,6.28-12.062,14.034c0,5.425,2.651,10.12,6.524,12.457l-16.349,7.61c-1.02,0.479-1.691,1.629-1.691,2.915v12.903
+ c0,1.729,1.209,3.13,2.694,3.13h10.805v-13.54c0-3.503,1.938-6.672,4.943-8.08L25.646,52.52z"/>
+ <path d="M95.948,57.635L79.6,50.025c3.873-2.337,6.524-7.032,6.524-12.457c0-7.754-5.396-14.034-12.062-14.034
+ c-1.998,0-3.857,0.615-5.511,1.623c3.399,5.845,5.532,13.3,5.776,21.472h0.027v6.081l4.844,2.256
+ c3.005,1.407,4.943,4.576,4.943,8.08v13.54h10.805c1.485,0,2.694-1.401,2.694-3.13V60.55
+ C97.639,59.264,96.968,58.114,95.948,57.635z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all.svg
new file mode 100644
index 0000000..0228bf8
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-all.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M96.117,57.583l-16.185-7.719c3.774-2.373,6.338-7.016,6.338-12.354c0-7.754-5.397-14.034-12.058-14.034
+ c-2.289,0-4.403,0.781-6.223,2.066c1.086,2.756,1.701,5.796,1.701,8.999c0,4.782-1.411,9.317-3.825,13.066
+ c0.833,0.932,1.771,1.735,2.809,2.36l-0.01,0.003l10.426,4.971c2.947,1.427,4.853,4.583,4.853,8.045v13.54h11.148
+ c1.489,0,2.694-1.401,2.694-3.13V60.492C97.785,59.21,97.126,58.072,96.117,57.583z"/>
+ <path d="M31.567,49.825c0.861-0.548,1.651-1.221,2.368-1.987c-2.514-3.781-3.972-8.401-3.972-13.297c0-3.271,0.646-6.37,1.777-9.17
+ c-1.76-1.172-3.773-1.895-5.948-1.895c-6.666,0-12.062,6.28-12.062,14.034c0,5.425,2.651,10.12,6.524,12.457l-16.349,7.61
+ c-1.02,0.479-1.691,1.629-1.691,2.915v12.903c0,1.729,1.209,3.13,2.694,3.13h10.805v-13.54c0-3.503,1.938-6.672,4.943-8.08
+ L31.567,49.825z"/>
+ <path d="M76.94,59.386l-14.077-6.715l-5.952-2.84c2.6-1.637,4.711-4.165,6.093-7.21c1.096-2.418,1.749-5.155,1.749-8.081
+ c0-1.642-0.26-3.201-0.623-4.706c-1.771-7.293-7.466-12.665-14.302-12.665c-6.708,0-12.316,5.181-14.196,12.266
+ c-0.434,1.625-0.733,3.315-0.733,5.105c0,3.109,0.727,6.008,1.961,8.529c1.427,2.925,3.542,5.337,6.116,6.888l-5.702,2.654
+ l-14.534,6.768c-1.262,0.591-2.092,2.016-2.092,3.606v13.54v2.43c0,2.14,1.492,3.875,3.333,3.875h51.691
+ c1.841,0,3.333-1.735,3.333-3.875v-2.43v-13.54C79.006,61.401,78.19,59.99,76.94,59.386z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-female-male.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-female-male.svg
new file mode 100644
index 0000000..5e4567a
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-female-male.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M34.199,47.04v-0.977v-5.438h0.022c0.163-5.466,1.39-10.528,3.382-14.767c0.223-0.731,0.474-1.447,0.756-2.145
+ c-1.879-1.251-4.026-2.022-6.349-2.022c-7.114,0-12.872,6.702-12.872,14.978c0,5.79,2.83,10.801,6.962,13.295L8.652,58.086
+ c-1.088,0.511-1.804,1.739-1.804,3.111v13.771c0,1.846,1.289,3.341,2.874,3.341h11.532v-14.45c0-3.739,2.068-7.121,5.275-8.623
+ l7.669-3.572V47.04z"/>
+ <path d="M90.853,60.441l-15.66-7.47l-6.621-3.159c0.166-0.105,0.324-0.224,0.487-0.335h8.695c1.346,0,2.438-1.091,2.438-2.438
+ v-6.415H80.17c-0.266-8.937-3.368-16.798-8.029-21.731c-2.46-2.777-5.65-4.663-9.219-5.226c-0.157-0.026-0.315-0.049-0.474-0.07
+ c-0.185-0.023-0.369-0.046-0.555-0.062c-0.398-0.035-0.798-0.059-1.202-0.059c-0.398,0-0.793,0.023-1.186,0.057
+ c-0.187,0.016-0.372,0.039-0.557,0.062c-0.157,0.02-0.313,0.043-0.469,0.068c-3.532,0.553-6.694,2.405-9.145,5.134
+ c-4.712,4.927-7.853,12.832-8.121,21.827h-0.022v6.415c0,1.346,1.091,2.438,2.438,2.438h8.719c0.238,0.162,0.475,0.327,0.721,0.475
+ l-6.342,2.953l-16.168,7.53c-1.405,0.658-2.328,2.242-2.328,4.011v15.062v2.703c0,2.381,1.659,4.311,3.708,4.311h57.505
+ c2.049,0,3.708-1.93,3.708-4.311v-2.703V64.446C93.152,62.683,92.244,61.114,90.853,60.441z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-male-female.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-male-female.svg
new file mode 100644
index 0000000..6b28f12
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos-male-female.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <g>
+ <path d="M90.937,63.235c-0.185-1.43-0.998-2.653-2.166-3.218l-15.023-7.167l-6.353-3.03c2.775-1.747,5.028-4.445,6.503-7.695
+ c1.169-2.581,1.866-5.502,1.866-8.625c0-1.753-0.278-3.416-0.666-5.023c-1.89-7.782-7.968-13.515-15.263-13.515h0h0
+ c-6.494,0-12.011,4.557-14.48,11.047c-0.253,0.664-0.484,1.341-0.67,2.043c-0.347,1.3-0.613,2.64-0.725,4.035
+ c-0.037,0.465-0.057,0.936-0.057,1.413c0,0.415,0.012,0.826,0.036,1.234c0.166,2.852,0.904,5.515,2.056,7.87
+ c1.523,3.121,3.78,5.695,6.527,7.35l-6.084,2.833l-15.51,7.223c-1.011,0.474-1.761,1.447-2.074,2.62
+ c-0.104,0.391-0.159,0.804-0.159,1.229v14.45v2.593c0,2.284,1.591,4.136,3.557,4.136H87.42c1.965,0,3.557-1.852,3.557-4.136
+ v-2.593v-14.45C90.977,63.648,90.964,63.439,90.937,63.235z"/>
+ <path d="M39.227,50.335l2.85-1.452c-3.165-4.206-5.065-9.555-5.065-15.383c0-4.041,0.917-7.85,2.531-11.21
+ c-1.566-0.772-3.238-1.212-4.983-1.212c-8.365,0-15.186,9.612-15.544,21.665H19v5.119c0,1.074,0.871,1.945,1.945,1.945h7.089
+ c0.081,0.051,0.159,0.108,0.24,0.157l-17.448,8.122c-1.087,0.511-1.804,1.739-1.804,3.111v13.771
+ c0,1.846,1.289,3.341,2.875,3.341h11.531v-14.45c0-3.739,2.068-7.121,5.275-8.623L39.227,50.335z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos.svg
new file mode 100644
index 0000000..77f13a2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-torsos.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M40.348,49.813c0.919-0.584,1.763-1.303,2.527-2.121c-2.683-4.036-4.239-8.966-4.239-14.191
+ c0-3.492,0.689-6.798,1.896-9.787c-1.879-1.25-4.026-2.022-6.349-2.022c-7.114,0-12.872,6.702-12.872,14.978
+ c0,5.79,2.83,10.801,6.962,13.295l-17.448,8.121c-1.087,0.511-1.804,1.739-1.804,3.111v13.771c0,1.846,1.289,3.341,2.874,3.341
+ h11.532v-14.45c0-3.739,2.068-7.121,5.275-8.623L40.348,49.813z"/>
+ <path d="M88.772,60.017l-15.023-7.167l-6.353-3.03c2.775-1.748,5.028-4.445,6.503-7.695c1.169-2.581,1.866-5.502,1.866-8.625
+ c0-1.753-0.278-3.416-0.666-5.023c-1.89-7.782-7.968-13.515-15.263-13.515c-7.158,0-13.144,5.529-15.15,13.09
+ c-0.463,1.734-0.782,3.538-0.782,5.448c0,3.319,0.775,6.412,2.092,9.103c1.523,3.121,3.78,5.696,6.527,7.35l-6.085,2.834
+ L30.93,60.01c-1.348,0.631-2.233,2.151-2.233,3.849v14.45v2.593c0,2.284,1.591,4.136,3.557,4.136H87.42
+ c1.965,0,3.557-1.852,3.557-4.136v-2.593v-14.45C90.977,62.168,90.106,60.662,88.772,60.017z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trash.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trash.svg
new file mode 100644
index 0000000..84fcebf
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trash.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M75.834,33.388h-51.67c-1.311,0-2.375,1.058-2.375,2.373v49.887c0,1.314,1.064,2.377,2.375,2.377h51.67
+ c1.314,0,2.375-1.063,2.375-2.377V35.76C78.209,34.446,77.148,33.388,75.834,33.388z"/>
+ </g>
+ <g>
+ <path d="M79.004,17.352H59.402v-2.999c0-1.314-1.061-2.377-2.373-2.377H42.971c-1.312,0-2.375,1.063-2.375,2.377v2.999H20.996
+ c-1.312,0-2.375,1.059-2.375,2.373v6.932c0,1.314,1.063,2.373,2.375,2.373h58.008c1.314,0,2.375-1.059,2.375-2.373v-6.932
+ C81.379,18.41,80.318,17.352,79.004,17.352z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trees.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trees.svg
new file mode 100644
index 0000000..0747314
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trees.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M91.963,80.982l0.023-0.013l-7.285-12.617h2.867v-0.013c0.598,0,1.083-0.484,1.083-1.082
+ c0-0.185-0.059-0.351-0.14-0.503l0.019-0.011l-6.737-11.669h1.639v-0.009c0.427,0,0.773-0.347,0.773-0.772
+ c0-0.132-0.042-0.25-0.1-0.359l0.013-0.008l-9.802-16.979l-0.01,0.006c-0.216-0.442-0.66-0.754-1.186-0.754
+ c-0.524,0-0.968,0.311-1.185,0.752l-0.005-0.003l-9.802,16.978l0.002,0.001c-0.061,0.11-0.105,0.231-0.105,0.366
+ c0,0.426,0.346,0.772,0.773,0.772v0.009h1.661l-6.737,11.669l0.003,0.001c-0.085,0.155-0.147,0.324-0.147,0.513
+ c0,0.598,0.485,1.082,1.083,1.082v0.013h2.894l-2.1,3.638l-8.399-14.548h4.046v-0.018c0.844,0,1.528-0.685,1.528-1.528
+ c0-0.26-0.071-0.502-0.186-0.717l0.015-0.009l-9.507-16.467h2.313v-0.012c0.603,0,1.091-0.488,1.091-1.092
+ c0-0.186-0.059-0.353-0.141-0.506l0.019-0.011L36.4,13.125l-0.005,0.003c-0.305-0.625-0.94-1.06-1.683-1.06
+ c-0.758,0-1.408,0.452-1.704,1.1L19.201,37.082l0.003,0.002c-0.086,0.156-0.148,0.326-0.148,0.516c0,0.604,0.488,1.092,1.09,1.092
+ v0.012h2.345l-9.395,16.272c-0.195,0.257-0.316,0.573-0.316,0.92c0,0.844,0.685,1.528,1.528,1.528v0.018h4.084L8.252,75.007
+ c-0.24,0.314-0.387,0.702-0.387,1.128c0,1.032,0.838,1.87,1.871,1.87v0.021h19.779v8.43c0,0.815,0.661,1.477,1.476,1.477h7.383
+ c0.815,0,1.477-0.661,1.477-1.477v-8.43h16.12l-1.699,2.943l0.003,0.002c-0.104,0.189-0.18,0.396-0.18,0.628
+ c0,0.732,0.593,1.325,1.325,1.325v0.015h14.016v3.941c0,0.578,0.469,1.046,1.046,1.046h5.232c0.578,0,1.046-0.468,1.046-1.046
+ v-3.941H90.81v-0.015c0.732,0,1.326-0.593,1.326-1.325C92.135,81.372,92.064,81.168,91.963,80.982z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trophy.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trophy.svg
new file mode 100644
index 0000000..b32ff9b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-trophy.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M82.296,23.931c0-1.059-0.859-1.918-1.918-1.918h0h-8.074v-6.998c0.004-0.061,0.018-0.118,0.018-0.179
+ c0-1.62-1.314-2.935-2.934-2.935c-0.036,0-0.07,0.009-0.106,0.011v-0.011H30.365v0.054c-1.507,0.123-2.696,1.372-2.696,2.911
+ c0,0.062,0.014,0.119,0.018,0.179v6.967H19.62c-1.031,0-1.867,0.818-1.909,1.839h-0.007v0.073l-0.001,0.007
+ c0,0,0.001,0.004,0.001,0.007v26.038c0,0.002-0.001,0.004-0.001,0.004s0.001,0.007,0.001,0.009V50h0.001
+ c0.01,1.051,0.863,1.9,1.916,1.9h0.001h8.327c1.354,9.109,8.197,16.422,17.069,18.449v12.746h-9.969
+ c-1.378,0-2.492,1.118-2.492,2.494s1.114,2.493,2.492,2.494v0.017h29.894v-0.017h0c1.377,0,2.492-1.118,2.492-2.494
+ c0-1.376-1.115-2.494-2.492-2.494h0h-9.969V70.353c8.881-2.02,15.733-9.337,17.087-18.453h8.317h0.001
+ c1.028,0,1.86-0.81,1.909-1.825h0.011V23.931H82.296z M27.687,46.913H22.69V27h4.997V46.913z M77.31,46.913h-5.007V27h5.007V46.913
+ z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-underline.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-underline.svg
new file mode 100644
index 0000000..40487af
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-underline.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M77.5,75.545c-0.036,0-0.068,0.009-0.103,0.01v-0.01h-55v0.01c-1.608,0.056-2.897,1.368-2.897,2.99s1.288,2.934,2.897,2.99
+ v0.01h55v-0.01c0.035,0.001,0.068,0.01,0.103,0.01c1.656,0,3-1.343,3-3S79.156,75.545,77.5,75.545z"/>
+ <path d="M50,72.12c15.829,0,23.581-9.057,23.581-22.521V21.383c0-1.617-1.311-2.928-2.929-2.928h-3.864
+ c-1.618,0-2.929,1.311-2.929,2.928c0,0.04,0.01,0.076,0.012,0.116v27.856c0,8.649-4.814,14.28-13.871,14.28
+ c-9.057,0-13.871-5.631-13.871-14.28V21.49c0.001-0.036,0.011-0.071,0.011-0.107c0-1.617-1.311-2.928-2.928-2.928h-3.865
+ c-1.617,0-2.929,1.311-2.929,2.928v28.216C26.418,63.063,34.252,72.12,50,72.12z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-universal-access.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-universal-access.svg
new file mode 100644
index 0000000..527a6d4
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-universal-access.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M50,77.561c-15.199,0-27.56-12.362-27.56-27.559
+ c0-15.195,12.362-27.562,27.56-27.562c15.198,0,27.56,12.367,27.56,27.562C77.56,65.198,65.198,77.561,50,77.561z"/>
+ <circle fill="#231F20" cx="49.63" cy="32.546" r="4.723"/>
+ <path fill="#231F20" d="M65.892,48.189l-8.973-8.974c-0.029-0.031-0.059-0.06-0.089-0.089l-0.061-0.061l-0.006,0.006
+ c-0.391-0.342-0.897-0.556-1.457-0.556c-0.051,0-0.098,0.012-0.148,0.015H44.703c-0.003,0-0.005-0.001-0.008-0.001
+ c-0.561,0-1.067,0.214-1.458,0.557l-0.005-0.005l-0.055,0.055c-0.035,0.032-0.068,0.065-0.1,0.1l-8.968,8.968l0.015,0.015
+ c-0.361,0.359-0.584,0.856-0.584,1.406c0,1.097,0.889,1.986,1.986,1.986c0.549,0,1.046-0.223,1.406-0.583l0.003,0.003l6.673-6.673
+ v0.004c0.115-0.118,0.275-0.192,0.452-0.192c0.35,0,0.634,0.284,0.634,0.635h0v6.032v6.1v12.334c0,1.282,1.04,2.322,2.323,2.322
+ c1.282,0,2.322-1.04,2.322-2.322V56.935h0.017c0-0.356,0.288-0.644,0.643-0.644c0.355,0,0.643,0.288,0.643,0.644h0.017v12.334
+ c0,1.282,1.04,2.322,2.322,2.322c1.283,0,2.323-1.04,2.323-2.322V56.935v-6.1v-5.96h0.02c-0.005-0.034-0.02-0.064-0.02-0.099
+ c0-0.35,0.284-0.633,0.635-0.633c0.155,0,0.292,0.062,0.402,0.155v-0.007l0.021,0.021c0.015,0.014,0.029,0.027,0.042,0.042
+ l6.66,6.661l0.003-0.003c0.36,0.36,0.857,0.583,1.406,0.583c1.097,0,1.986-0.889,1.986-1.986c0-0.549-0.223-1.046-0.584-1.406
+ L65.892,48.189z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlink.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlink.svg
new file mode 100644
index 0000000..130d145
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlink.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M16.201,20.386l9.719,9.721c1.12,1.118,2.935,1.118,4.054,0c1.118-1.121,1.118-2.933,0-4.055l-9.679-9.677
+ c-0.002-0.003-0.004-0.005-0.006-0.008s-0.005-0.004-0.008-0.006l-0.026-0.026l-0.003,0.003c-1.122-1.085-2.909-1.077-4.017,0.03
+ c-1.107,1.108-1.115,2.895-0.03,4.015L16.201,20.386z"/>
+ <path d="M32.898,16.546l3.558,13.277c0.41,1.529,1.981,2.437,3.51,2.026c1.527-0.409,2.435-1.981,2.027-3.51l-3.545-13.224
+ c0-0.002,0-0.005-0.001-0.007s-0.002-0.004-0.003-0.007l-0.011-0.04l-0.004,0.001c-0.429-1.5-1.98-2.387-3.493-1.982
+ c-1.513,0.405-2.413,1.949-2.035,3.463L32.898,16.546z"/>
+ <path d="M16.054,39.423l-0.001,0.005l0.046,0.012c0,0,0.001,0,0.001,0l0.001,0l13.229,3.544c1.53,0.41,3.101-0.498,3.511-2.025
+ c0.41-1.529-0.498-3.101-2.026-3.51L17.6,33.908c-0.005-0.002-0.01-0.005-0.016-0.006s-0.011-0.001-0.017-0.003l-0.03-0.008
+ l-0.001,0.003c-1.515-0.377-3.058,0.523-3.463,2.035C13.668,37.442,14.555,38.992,16.054,39.423z"/>
+ <path d="M83.798,79.613l-9.72-9.72c-1.119-1.119-2.934-1.119-4.053,0c-1.118,1.12-1.118,2.933,0,4.055l9.679,9.677
+ c0.002,0.003,0.004,0.005,0.006,0.008c0.003,0.002,0.005,0.004,0.008,0.006l0.026,0.026l0.003-0.003
+ c1.122,1.085,2.908,1.077,4.017-0.03c1.107-1.108,1.115-2.895,0.03-4.016L83.798,79.613z"/>
+ <path d="M67.101,83.454l-3.559-13.277c-0.41-1.529-1.98-2.436-3.51-2.026c-1.53,0.409-2.436,1.981-2.027,3.509l3.546,13.231
+ c0,0,0,0.001,0,0.001c0,0.001,0,0.001,0,0.001l0.012,0.045l0.005-0.001c0.428,1.501,1.98,2.387,3.493,1.983
+ c1.513-0.406,2.412-1.95,2.034-3.463L67.101,83.454z"/>
+ <path d="M83.943,60.577l0.001-0.004l-0.041-0.011c-0.002,0-0.003-0.001-0.005-0.002c-0.002,0-0.003,0-0.005-0.001l-13.226-3.544
+ c-1.53-0.41-3.1,0.499-3.511,2.026c-0.409,1.529,0.498,3.1,2.027,3.511l13.224,3.542c0.002,0.001,0.004,0.002,0.006,0.002
+ c0.002,0.001,0.005,0,0.007,0.001l0.04,0.011l0.001-0.004c1.514,0.378,3.058-0.522,3.462-2.035
+ C86.331,62.557,85.443,61.006,83.943,60.577z"/>
+ <path d="M48.212,51.756c-7.552-7.552-19.648-7.79-27.486-0.713l-0.019-0.019L10.61,61.121c-7.797,7.797-7.797,20.44,0,28.237
+ c7.797,7.798,20.439,7.798,28.237,0l10.098-10.098l-0.019-0.019C56.001,71.404,55.764,59.308,48.212,51.756z M41.659,72.558
+ l-0.619,0.619l-0.001,0.001l-0.001,0l-9.005,9.005l-0.001,0.001c-3.935,3.935-10.314,3.935-14.248,0s-3.935-10.314,0-14.248
+ l0.001-0.001l9.005-9.006l0.001-0.001l0.001-0.001l0.619-0.619l0.029,0.028c3.959-3.329,9.874-3.134,13.6,0.591
+ c3.726,3.726,3.921,9.642,0.591,13.6L41.659,72.558z"/>
+ <path d="M89.389,10.641c-7.552-7.552-19.648-7.79-27.486-0.713l-0.019-0.019L51.787,20.006c-7.797,7.797-7.797,20.44,0,28.237
+ c7.797,7.798,20.439,7.798,28.237,0l10.098-10.098l-0.019-0.019C97.178,30.289,96.941,18.193,89.389,10.641z M82.836,31.443
+ l-0.619,0.619l-0.001,0.001l-0.001,0l-9.005,9.005l-0.001,0.001c-3.935,3.935-10.314,3.935-14.248,0
+ c-3.935-3.935-3.935-10.314,0-14.248l0.001-0.001l9.005-9.006c0,0,0,0,0.001-0.001l0.001-0.001l0.619-0.619l0.029,0.028
+ c3.959-3.329,9.874-3.134,13.6,0.591s3.921,9.642,0.591,13.6L82.836,31.443z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlock.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlock.svg
new file mode 100644
index 0000000..433aa09
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-unlock.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M82.105,45.587h-3.714H65.29H41.236V34.945c0-5.207,4.372-9.437,9.747-9.437c5.372,0,9.744,4.23,9.746,9.437
+ c0,1.051,0.881,1.904,1.966,1.904H72.73c0.018,0,0.038,0,0.051,0c1.087,0,1.965-0.853,1.965-1.904c0-0.159-0.018-0.312-0.056-0.457
+ C74.437,22.032,63.9,11.975,50.983,11.975c-13.074,0-23.71,10.305-23.71,22.97v10.642h-5.664h-3.713
+ c-1.449,0-2.621,1.135-2.621,2.539v37.361c0,1.403,1.172,2.539,2.621,2.539h64.21c1.449,0,2.621-1.136,2.621-2.539V48.125
+ C84.726,46.722,83.554,45.587,82.105,45.587z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload-cloud.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload-cloud.svg
new file mode 100644
index 0000000..0c03336
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload-cloud.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M79.437,36.831c-3.51-12.982-14.464-22.083-27.134-22.083c-8.835,0-17.065,4.454-22.414,12.018
+ c-1.484-0.339-2.987-0.514-4.501-0.514C13.5,26.251,3.825,36.79,3.825,49.749c0,4.647,1.251,9.148,3.612,13.018
+ c0.555,0.906,1.49,1.449,2.49,1.449H29.85c0.143-9.265,7.688-16.734,16.987-16.734c9.299,0,16.843,7.469,16.987,16.734h26.945
+ c0.947,0,1.836-0.485,2.403-1.315c1.964-2.876,3.004-6.255,3.004-9.768C96.175,43.477,88.36,35.662,79.437,36.831z"/>
+ </g>
+ <g>
+ <path d="M57.345,70.33l-9.918-13.861c-0.179-0.25-0.472-0.4-0.779-0.4h-0.002c-0.31,0-0.598,0.15-0.779,0.404L36.013,70.33
+ c-0.207,0.292-0.233,0.675-0.069,0.996c0.164,0.32,0.494,0.518,0.853,0.518h4.634v12.449c0,0.532,0.43,0.96,0.958,0.96h8.58
+ c0.53,0,0.958-0.428,0.958-0.96V71.844h4.638c0.358,0,0.687-0.202,0.851-0.518C57.581,71.005,57.553,70.623,57.345,70.33z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload.svg
new file mode 100644
index 0000000..3f2809e
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-upload.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M85.886,49.615H67.685c-2.218,0-4.185,1.374-4.865,3.406c-1.803,5.375-6.957,8.983-12.819,8.983
+ c-5.864,0-11.016-3.608-12.818-8.983c-0.682-2.032-2.647-3.406-4.867-3.406h-18.2c-2.825,0-5.115,2.2-5.115,4.919v28.054
+ c0,2.714,2.29,4.917,5.115,4.917h71.771c2.827,0,5.114-2.203,5.114-4.917V54.534C91,51.815,88.712,49.615,85.886,49.615z"/>
+ <path d="M35.81,34.276h6.653v17.188c0,0.735,0.617,1.326,1.376,1.326h12.317c0.762,0,1.376-0.591,1.376-1.326V34.276h6.658
+ c0.514,0,0.986-0.279,1.221-0.716c0.238-0.442,0.197-0.971-0.102-1.374L51.072,13.048c-0.257-0.346-0.677-0.553-1.119-0.553H49.95
+ c-0.445,0-0.859,0.207-1.119,0.558L34.686,32.187c-0.297,0.403-0.334,0.932-0.1,1.374C34.821,34.002,35.296,34.276,35.81,34.276z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-usb.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-usb.svg
new file mode 100644
index 0000000..a80912d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-usb.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M64.603,35.504c-0.032-1.506-1.259-2.719-2.774-2.72c-0.047,0-0.091,0.012-0.138,0.014h-2.039V17.776h0l0-0.002
+ c-0.001-0.929-0.755-1.683-1.684-1.684H41.765v0.03c-0.788,0.141-1.386,0.826-1.386,1.654c0,0.001,0,0.003,0,0.004l0,15.018h-2.052
+ c-0.043-0.002-0.083-0.013-0.126-0.013c-1.515,0-2.742,1.213-2.774,2.72h-0.036l0,45.625h0.001c0,1.535,1.245,2.78,2.78,2.781
+ c0.005,0,0.01-0.001,0.014-0.001l23.638,0c0.002,0,0.004,0,0.005,0c1.534,0,2.779-1.244,2.78-2.779h0V35.504H64.603z
+ M54.665,32.798l-9.329,0l0-11.72h9.329L54.665,32.798z"/>
+ <rect x="47.506" y="27.933" width="4.988" height="2.072"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-video.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-video.svg
new file mode 100644
index 0000000..a245c44
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-video.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M66.272,61.337v10.565c0,2.497-2.043,4.535-4.539,4.535H14.54c-2.496,0-4.54-2.038-4.54-4.535V28.097
+ c0-2.496,2.043-4.535,4.54-4.535h47.193c2.496,0,4.539,2.038,4.539,4.535v10.432v-0.146L90,27.265v45.294L66.272,61.337z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-none.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-none.svg
new file mode 100644
index 0000000..ab33319
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-none.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M73.684,23.396H73.66c-0.117-1.031-0.983-1.837-2.047-1.837c-0.378,0-0.726,0.108-1.031,0.285l-0.019-0.032L50.1,33.627
+ v0.012l-7.74,4.469H27.879v0.04c-0.013,0-0.024-0.004-0.037-0.004c-0.842,0-1.525,0.684-1.525,1.525v20.66
+ c0,0.842,0.684,1.524,1.525,1.524c0.013,0,0.024-0.003,0.037-0.004v0.041H42.36l11.524,6.653v-0.031l16.549,9.555
+ c0.336,0.232,0.741,0.372,1.18,0.372c1.144,0,2.071-0.927,2.071-2.07c0-0.081-0.015-0.155-0.024-0.233h0.024V23.396z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-strike.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-strike.svg
new file mode 100644
index 0000000..7db3895
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume-strike.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M60.416,35.232l-0.022,0.022l1.923,1.924l0.031-0.031c0.025,0.026,0.042,0.057,0.067,0.083
+ c4.39,4.39,6.071,10.47,5.059,16.163l7.868,7.868c4.384-10.269,2.403-22.629-5.964-30.995c-0.026-0.026-0.056-0.042-0.082-0.067
+ l0.008-0.008l-1.924-1.923l-0.022,0.021c-1.05-0.835-2.568-0.787-3.554,0.161l-0.004-0.004l-0.035,0.035
+ c-0.001,0.001-0.002,0.001-0.003,0.002s-0.002,0.002-0.002,0.003l-3.149,3.148c-0.001,0.001-0.002,0.002-0.003,0.002
+ c-0.001,0.001-0.002,0.002-0.002,0.003l-0.225,0.225l0.023,0.022C59.633,32.872,59.636,34.253,60.416,35.232z"/>
+ <path d="M78.868,17.089c-0.026-0.025-0.056-0.042-0.082-0.067l0.008-0.008l-1.924-1.923l-0.022,0.022
+ c-1.05-0.836-2.567-0.788-3.553,0.161l-0.004-0.004l-3.419,3.418l0.023,0.023c-0.773,0.983-0.77,2.365,0.01,3.345l-0.022,0.021
+ l0.216,0.216l0,0h0l1.707,1.708l0.031-0.031c0.025,0.026,0.042,0.057,0.067,0.083c11.153,11.153,13.663,27.718,7.545,41.315
+ l7.332,7.332C96.533,54.93,93.906,32.127,78.868,17.089z"/>
+ <path d="M54.826,25.708h-0.024c-0.117-1.031-0.983-1.837-2.047-1.837c-0.378,0-0.727,0.108-1.031,0.285l-0.018-0.032l-8.558,4.941
+ l11.679,11.679V25.708z"/>
+ <path d="M23.502,40.42H9.021v0.04c-0.012,0-0.024-0.003-0.037-0.003c-0.842,0-1.525,0.684-1.525,1.525v20.66
+ c0,0.842,0.683,1.524,1.525,1.524c0.013,0,0.024-0.003,0.037-0.004v0.041h14.482l11.524,6.653v-0.031l16.548,9.555
+ c0.336,0.232,0.742,0.372,1.181,0.372c1.143,0,2.071-0.927,2.071-2.07c0-0.081-0.015-0.155-0.024-0.233h0.024v-9.413L25.219,39.428
+ L23.502,40.42z"/>
+ <path d="M85.818,78.788L21.172,14.141l-0.002,0.002c-0.006-0.006-0.01-0.013-0.016-0.02c-0.971-0.971-2.545-0.97-3.516,0
+ c-0.034,0.034-0.058,0.074-0.09,0.11l-3.458,3.476c-0.004,0.004-0.008,0.006-0.012,0.01c-0.971,0.97-0.971,2.545,0,3.515
+ l64.651,64.651l0.001-0.001c0.971,0.962,2.538,0.959,3.507-0.009l0.004,0.004l3.432-3.449c0.049-0.042,0.103-0.076,0.15-0.123
+ c0.97-0.971,0.97-2.545,0-3.516C85.821,78.791,85.819,78.79,85.818,78.788z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume.svg
new file mode 100644
index 0000000..8580f1d
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-volume.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M78.864,17.021c-0.026-0.026-0.056-0.042-0.082-0.067l0.008-0.008l-1.924-1.923l-0.022,0.022
+ c-1.05-0.836-2.567-0.788-3.553,0.161l-0.004-0.004l-3.419,3.418l0.023,0.023c-0.773,0.983-0.77,2.365,0.01,3.345l-0.022,0.022
+ l0.216,0.216c0,0,0,0,0,0h0l1.707,1.708l0.031-0.031c0.025,0.026,0.042,0.057,0.067,0.083
+ c14.358,14.358,14.401,37.688,0.138,52.104l-0.019-0.019l-1.707,1.707l0,0c0,0,0,0,0,0l-0.216,0.216l0.022,0.022
+ c-0.836,1.05-0.787,2.568,0.16,3.553l-0.004,0.004l3.42,3.42l0.023-0.023c0.983,0.773,2.365,0.769,3.345-0.011l0.022,0.022
+ l0.216-0.216h0l0,0l1.707-1.707l-0.004-0.004C97.105,64.797,97.061,35.219,78.864,17.021z"/>
+ <path d="M69.376,30.198c-0.026-0.026-0.056-0.042-0.082-0.067l0.008-0.008L67.377,28.2l-0.022,0.022
+ c-1.05-0.836-2.568-0.787-3.554,0.16l-0.004-0.004l-0.035,0.035c-0.001,0.001-0.002,0.002-0.003,0.002
+ c-0.001,0.001-0.002,0.002-0.002,0.003l-3.149,3.148c-0.001,0.001-0.002,0.002-0.003,0.002c-0.001,0.001-0.002,0.002-0.002,0.003
+ l-0.225,0.225l0.023,0.023c-0.773,0.984-0.769,2.365,0.011,3.344l-0.022,0.022l1.923,1.924l0.031-0.031
+ c0.025,0.026,0.042,0.057,0.067,0.083c7.091,7.091,7.132,18.594,0.135,25.746l-0.014-0.014L60.825,64.6c0,0,0,0-0.001,0l-0.001,0
+ l-0.215,0.215l0.022,0.022c-0.836,1.05-0.788,2.569,0.16,3.554l-0.004,0.004l3.42,3.42l0.023-0.023
+ c0.983,0.773,2.364,0.769,3.344-0.011l0.022,0.022l1.923-1.923l-0.004-0.004C80.352,58.886,80.308,41.131,69.376,30.198z"/>
+ <path d="M52.751,23.803c-0.378,0-0.727,0.108-1.031,0.285l-0.018-0.032L31.238,35.871v0.012l-7.74,4.469H9.016v0.04
+ c-0.012,0-0.024-0.004-0.037-0.004c-0.842,0-1.525,0.684-1.525,1.525v20.66c0,0.842,0.683,1.524,1.525,1.524
+ c0.013,0,0.024-0.003,0.037-0.004v0.041h14.482l11.524,6.653v-0.031l16.548,9.555c0.336,0.232,0.742,0.372,1.181,0.372
+ c1.143,0,2.071-0.927,2.071-2.07c0-0.081-0.015-0.155-0.024-0.233h0.024V25.64h-0.024C54.681,24.609,53.815,23.803,52.751,23.803z"
+ />
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-web.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-web.svg
new file mode 100644
index 0000000..1bf45fb
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-web.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M50,12.5c-20.712,0-37.5,16.793-37.5,37.502C12.5,70.712,29.288,87.5,50,87.5
+ c20.712,0,37.5-16.788,37.5-37.498C87.5,29.293,70.712,12.5,50,12.5z M22.897,54.969h5.752c0.985,7.432,4.148,14.173,8.826,19.569
+ C29.974,70.694,24.46,63.516,22.897,54.969z M28.649,45.03h-5.752c1.564-8.546,7.078-15.724,14.579-19.568
+ C32.798,30.858,29.634,37.599,28.649,45.03z M45.03,68.059c-3.177-3.65-5.406-8.14-6.313-13.089h6.313V68.059z M45.03,45.03h-6.313
+ c0.907-4.948,3.136-9.437,6.313-13.088V45.03z M77.102,45.03h-5.751c-0.985-7.431-4.148-14.172-8.825-19.567
+ C70.025,29.308,75.539,36.486,77.102,45.03z M54.97,68.057V54.969h6.313C60.375,59.917,58.146,64.407,54.97,68.057z M54.97,45.03
+ V31.941c3.177,3.65,5.406,8.14,6.313,13.089H54.97z M62.523,74.539c4.678-5.396,7.843-12.137,8.828-19.57h5.752
+ C75.54,63.517,70.025,70.695,62.523,74.539z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wheelchair.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wheelchair.svg
new file mode 100644
index 0000000..caff281
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wheelchair.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M51.77,75.42c-2.255,1.564-4.988,2.487-7.941,2.487c-7.706,0-13.954-6.248-13.954-13.954c0-2.952,0.922-5.686,2.487-7.94
+ l-5.348-5.348c-3.026,3.725-4.852,8.465-4.852,13.639c0,11.967,9.701,21.668,21.667,21.668c5.174,0,9.923-1.816,13.649-4.843
+ L51.77,75.42z"/>
+ <circle cx="68.862" cy="21.181" r="7.152"/>
+ <path d="M73.35,45.582H57.609l8.977-8.978c0.271-0.215,0.515-0.458,0.73-0.729l0.073-0.073l-0.007-0.007
+ c0.569-0.752,0.919-1.679,0.919-2.694c0-1.623-0.869-3.031-2.159-3.819l0.001-0.001L46.04,17.675l-0.017,0.03
+ C45.459,17.45,44.839,17.3,44.18,17.3c-1.152,0-2.191,0.447-2.986,1.16l-0.006-0.006l-0.06,0.06
+ c-0.077,0.072-0.15,0.145-0.222,0.222l-8.865,8.865l0.008,0.008c-0.762,0.804-1.237,1.884-1.237,3.08
+ c0,2.479,2.009,4.487,4.487,4.487c1.196,0,2.276-0.475,3.08-1.237l0.008,0.008l0.081-0.081c0.003-0.003,0.005-0.005,0.008-0.008
+ l6.457-6.457l5.514,3.184L37.436,43.597c-2.514,0.775-4.823,2.008-6.854,3.582l5.307,5.307c2.255-1.564,4.988-2.487,7.94-2.487
+ c7.707,0,13.954,6.248,13.954,13.954c0,2.952-0.922,5.686-2.487,7.94l5.666,5.667c2.839-3.665,4.534-8.261,4.534-13.256
+ c0-3.507-0.838-6.816-2.317-9.746h5.683v18.371c0,2.479,2.009,4.488,4.488,4.488c2.479,0,4.488-2.01,4.488-4.488V50.069
+ C77.838,47.591,75.828,45.582,73.35,45.582z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-widget.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-widget.svg
new file mode 100644
index 0000000..d79f0b0
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-widget.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M88.553,43.441l-10.276-1.013c-0.661-2.466-1.644-4.832-2.936-7.059l6.561-7.993c0.703-0.859,0.639-2.111-0.145-2.893
+ l-6.24-6.243c-0.42-0.419-0.97-0.633-1.525-0.633c-0.485,0-0.97,0.162-1.369,0.491L64.63,24.66
+ c-2.231-1.293-4.596-2.276-7.06-2.936l-1.011-10.278C56.45,10.342,55.522,9.5,54.412,9.5h-8.823c-1.11,0-2.038,0.842-2.148,1.946
+ L42.43,21.727c-2.464,0.66-4.829,1.643-7.054,2.936l-7.998-6.564c-0.4-0.329-0.884-0.49-1.369-0.49
+ c-0.555,0-1.105,0.212-1.525,0.633l-6.24,6.241c-0.784,0.782-0.848,2.037-0.145,2.893l6.566,7.996
+ c-1.291,2.225-2.277,4.59-2.936,7.057l-10.281,1.013C10.343,43.547,9.5,44.477,9.5,45.587v8.825c0,1.11,0.843,2.04,1.947,2.146
+ l10.281,1.013c0.659,2.466,1.644,4.829,2.936,7.054l-6.562,7.994c-0.708,0.858-0.648,2.111,0.14,2.895l6.24,6.242
+ c0.42,0.418,0.97,0.631,1.525,0.631c0.485,0,0.97-0.162,1.369-0.489l7.993-6.562c2.231,1.293,4.59,2.276,7.06,2.938l1.011,10.279
+ c0.109,1.104,1.038,1.946,2.148,1.946h8.823c1.11,0,2.039-0.842,2.148-1.946l1.011-10.278c2.469-0.66,4.829-1.643,7.06-2.939
+ l7.993,6.562c0.4,0.327,0.884,0.489,1.369,0.489c0.555,0,1.105-0.213,1.525-0.631l6.24-6.242c0.788-0.783,0.848-2.037,0.14-2.895
+ l-6.557-7.991c1.292-2.228,2.275-4.591,2.936-7.057l10.276-1.013c1.104-0.109,1.947-1.036,1.947-2.146v-8.825
+ C90.5,44.477,89.657,43.55,88.553,43.441z M50.002,61.95c-6.603,0-11.953-5.351-11.953-11.95c0-6.602,5.351-11.951,11.953-11.951
+ c6.598,0,11.948,5.349,11.948,11.951C61.951,56.599,56.6,61.95,50.002,61.95z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wrench.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wrench.svg
new file mode 100644
index 0000000..e9dac12
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-wrench.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M86.257,23.405l-3.866,3.866l-3.737,3.737l-4.759,4.759c-2.521,0.161-5.096-0.713-7.023-2.64
+ c-1.927-1.927-2.8-4.502-2.64-7.023l4.759-4.759l3.737-3.737l3.866-3.866c0.251-0.251,0.251-0.659,0-0.911
+ c-0.046-0.046-0.101-0.074-0.155-0.103l0.001-0.001c-0.003-0.001-0.007-0.003-0.01-0.004c-0.034-0.017-0.066-0.032-0.102-0.043
+ c-2.677-1.193-5.629-1.878-8.749-1.878c-11.939,0-21.618,9.679-21.618,21.618c0,2.28,0.358,4.475,1.012,6.538L24.428,61.504
+ c-7.545,0.122-13.627,6.267-13.627,13.842c0,7.65,6.203,13.853,13.853,13.853c7.574,0,13.72-6.083,13.842-13.628l22.546-22.546
+ c2.063,0.654,4.259,1.012,6.539,1.012c11.939,0,21.618-9.679,21.618-21.618c0-3.118-0.686-6.066-1.877-8.742
+ c-0.012-0.041-0.029-0.079-0.05-0.118c-0.008-0.017-0.014-0.035-0.022-0.052l-0.007,0.007c-0.024-0.037-0.041-0.078-0.074-0.111
+ C86.916,23.153,86.509,23.153,86.257,23.405z M30.378,75.346c0,3.161-2.563,5.724-5.724,5.724c-3.161,0-5.724-2.563-5.724-5.724
+ c0-3.162,2.563-5.725,5.724-5.725C27.815,69.621,30.378,72.184,30.378,75.346z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x-circle.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x-circle.svg
new file mode 100644
index 0000000..dc20f8c
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x-circle.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path fill="#231F20" d="M68.056,59.756l-9.758-9.757l9.755-9.756c0.404-0.404,0.404-1.06,0-1.464l-6.833-6.835
+ c-0.405-0.404-1.06-0.404-1.464,0L49.999,41.7l-9.755-9.756c-0.388-0.388-1.075-0.388-1.464,0l-6.835,6.835
+ c-0.194,0.195-0.304,0.458-0.304,0.732c0,0.274,0.11,0.538,0.304,0.732l9.756,9.756l-9.758,9.758
+ c-0.194,0.193-0.304,0.458-0.304,0.732c0,0.273,0.11,0.538,0.304,0.731l6.833,6.834c0.194,0.194,0.459,0.304,0.733,0.304
+ c0.274,0,0.538-0.11,0.731-0.304l9.757-9.757l9.758,9.756c0.202,0.203,0.466,0.304,0.732,0.304c0.266,0,0.53-0.101,0.732-0.304
+ l6.835-6.834C68.46,60.816,68.46,60.16,68.056,59.756z"/>
+ <g>
+ <path fill="#231F20" d="M50,22.44c15.196,0,27.56,12.367,27.56,27.562c0,15.197-12.364,27.559-27.56,27.559
+ S22.44,65.199,22.44,50.002C22.44,34.807,34.804,22.44,50,22.44 M50,12.5c-20.71,0-37.5,16.793-37.5,37.502
+ C12.5,70.712,29.29,87.5,50,87.5c20.709,0,37.5-16.788,37.5-37.498C87.5,29.293,70.709,12.5,50,12.5L50,12.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x.svg
new file mode 100644
index 0000000..0f33db9
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-x.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<path d="M84.707,68.752L65.951,49.998l18.75-18.752c0.777-0.777,0.777-2.036,0-2.813L71.566,15.295
+ c-0.777-0.777-2.037-0.777-2.814,0L49.999,34.047l-18.75-18.752c-0.746-0.747-2.067-0.747-2.814,0L15.297,28.431
+ c-0.373,0.373-0.583,0.88-0.583,1.407c0,0.527,0.21,1.034,0.583,1.407L34.05,49.998L15.294,68.753
+ c-0.373,0.374-0.583,0.88-0.583,1.407c0,0.528,0.21,1.035,0.583,1.407l13.136,13.137c0.373,0.373,0.881,0.583,1.41,0.583
+ c0.525,0,1.031-0.21,1.404-0.583l18.755-18.755l18.756,18.754c0.389,0.388,0.896,0.583,1.407,0.583c0.511,0,1.019-0.195,1.408-0.583
+ l13.138-13.137C85.484,70.789,85.484,69.53,84.707,68.752z"/>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-yen.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-yen.svg
new file mode 100644
index 0000000..0e51289
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-yen.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <path d="M76.275,22.811c0.049-0.049,0.079-0.116,0.079-0.191c0-0.134-0.103-0.233-0.232-0.255v-0.017h-0.488h-0.488H64.121
+ c-0.338,0-0.62,0.191-0.78,0.463h-0.016l-13.281,21.49l-13.281-21.49h-0.014c-0.159-0.272-0.442-0.463-0.78-0.463H24.893h-0.438
+ h-0.538c-0.15,0-0.272,0.122-0.272,0.272c0,0.074,0.031,0.142,0.079,0.191h-0.001l16.42,25.354H25.977v0.017
+ c-0.025-0.002-0.046-0.015-0.072-0.015c-0.637,0-1.153,0.516-1.153,1.153l0,0v4.05l0,0l0,0v0.07h0.014
+ c0.038,0.602,0.527,1.083,1.139,1.083c0.026,0,0.047-0.012,0.072-0.014v0.015h18.352v6.439H25.977v0.002
+ c-0.004,0-0.008-0.002-0.012-0.002c-0.637,0-1.153,0.516-1.153,1.153v3.969c0,0.637,0.516,1.153,1.153,1.153
+ c0.004,0,0.008-0.002,0.012-0.002v0.004h18.352v9.199c-0.001,0.021-0.012,0.038-0.012,0.058c0,0.637,0.516,1.153,1.153,1.153
+ c0.001,0,0.002,0,0.002,0l0.001,0.001h9.141v-0.001c0.636-0.001,1.151-0.517,1.151-1.153c0-0.011-0.006-0.021-0.006-0.031v-9.225
+ h18.433v-0.004c0.004,0,0.007,0.002,0.01,0.002c0.637,0,1.153-0.516,1.153-1.153v-3.969c0-0.637-0.516-1.153-1.153-1.153
+ c-0.004,0-0.007,0.002-0.01,0.002v-0.002H55.759v-6.439h18.433v-0.003c0.004,0,0.007,0.002,0.01,0.002
+ c0.637,0,1.153-0.516,1.153-1.153V49.25h-0.014c-0.038-0.602-0.527-1.083-1.139-1.083c-0.004,0-0.007,0.002-0.01,0.002v-0.004
+ H59.864l16.42-25.354H76.275z"/>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-in.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-in.svg
new file mode 100644
index 0000000..b1fa45b
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-in.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <path d="M56.774,10.391c-17.679,0-32,14.329-32,32c0,6.044,1.676,11.695,4.588,16.517L13.846,74.423l0.054,0.054
+ c-1.656,1.585-2.673,3.835-2.673,6.378c-0.001,4.913,3.913,8.755,8.821,8.754c2.507-0.001,4.749-1.004,6.349-2.636l0.039,0.039
+ l16.008-16.009c4.312,2.163,9.176,3.388,14.33,3.388c17.68,0,32-14.327,32-32C88.773,24.72,74.453,10.391,56.774,10.391z
+ M56.968,61.808c-11.05,0-20-8.954-20-20c0-11.044,8.951-20,20-20c11.05,0,20,8.955,20,20
+ C76.968,52.854,68.018,61.808,56.968,61.808z"/>
+ </g>
+ <g>
+ <path d="M68.751,37.111l0-0.03l-7.076,0.008l-0.009-7.058c0-0.868-0.703-1.57-1.569-1.57c-0.033,0-0.064,0.008-0.097,0.01h-6.084
+ c-0.033-0.002-0.064-0.01-0.097-0.01c-0.867,0-1.569,0.702-1.569,1.57c0,0.054,0.011,0.105,0.016,0.158l-0.007,6.911l-7.061,0.008
+ c-0.868,0-1.569,0.703-1.569,1.57v6.278c0,0.867,0.702,1.569,1.569,1.569c0.054,0,0.105-0.011,0.158-0.016l6.893,0.007
+ L52.24,53.55l0.011,0c0,0.008-0.002,0.016-0.002,0.024c0,0.868,0.703,1.569,1.569,1.569c0.003,0,0.006-0.001,0.01-0.001v0.011
+ h6.278v-0.011c0.858-0.006,1.551-0.698,1.558-1.556l0.03,0l-0.009-7.059l7.028,0.007l0-0.011c0.008,0,0.016,0.002,0.024,0.002
+ c0.868,0,1.569-0.703,1.569-1.569v-6.278C70.308,37.817,69.613,37.117,68.751,37.111z"/>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-out.svg b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-out.svg
new file mode 100644
index 0000000..f3088c2
--- /dev/null
+++ b/afb-client/bower_components/foundation-icon-fonts/svgs/fi-zoom-out.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
+<g>
+ <g>
+ <g>
+ <path d="M56.774,10.391c-17.679,0-32,14.329-32,32c0,6.044,1.676,11.695,4.588,16.517L13.845,74.423l0.054,0.054
+ c-1.656,1.585-2.673,3.835-2.673,6.378c-0.001,4.913,3.913,8.755,8.821,8.754c2.507-0.001,4.749-1.004,6.349-2.636l0.039,0.039
+ l16.008-16.009c4.312,2.163,9.176,3.388,14.33,3.388c17.68,0,32-14.327,32-32C88.773,24.72,74.453,10.391,56.774,10.391z
+ M56.968,61.808c-11.05,0-20-8.954-20-20c0-11.044,8.951-20,20-20c11.05,0,20,8.955,20,20
+ C76.968,52.854,68.018,61.808,56.968,61.808z"/>
+ <path d="M68.739,37.099H45.197c-0.868,0-1.57,0.702-1.57,1.569h0v6.278c0,0.867,0.702,1.569,1.57,1.569h23.542
+ c0.868,0,1.57-0.703,1.57-1.569v-6.278h0C70.308,37.802,69.606,37.099,68.739,37.099z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/afb-client/bower_components/hammerjs/.bower.json b/afb-client/bower_components/hammerjs/.bower.json
new file mode 100644
index 0000000..c1d04f3
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/.bower.json
@@ -0,0 +1,27 @@
+{
+ "name": "hammerjs",
+ "main": "hammer.js",
+ "ignore": [
+ "tests",
+ "src",
+ ".bowerrc",
+ ".gitignore",
+ ".jscsrc",
+ ".jshintrc",
+ ".travis.yml",
+ "component.json",
+ "Gruntfile.coffee",
+ "package.json"
+ ],
+ "homepage": "https://github.com/EightMedia/hammer.js",
+ "version": "2.0.6",
+ "_release": "2.0.6",
+ "_resolution": {
+ "type": "version",
+ "tag": "v2.0.6",
+ "commit": "05f0872c6130daf537bad27a393310cd5833c9a1"
+ },
+ "_source": "git://github.com/EightMedia/hammer.js.git",
+ "_target": "~2.0.4",
+ "_originalSource": "hammerjs"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/hammerjs/CHANGELOG.md b/afb-client/bower_components/hammerjs/CHANGELOG.md
new file mode 100644
index 0000000..d3bc17d
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/CHANGELOG.md
@@ -0,0 +1,54 @@
+# Changelog
+
+### 2.0.6, 2015-12-23
+- Add Assign method and deprecate merge and extend ([#895](https://github.com/hammerjs/hammer.js/pull/895)[fc01eae](https://github.com/hammerjs/hammer.js/commit/fc01eaea678acc430c664eb374555fbe3d403bdd))
+- Expose Hammer on window or self if either is defined to avoid issues when AMD is present but not used. ( [356f795](https://github.com/hammerjs/hammer.js/commit/356f7955b01f3679c29d6c45931679256b45036e))
+- Add support for PointerEvent instead of MSPointerEvent if supported. ([#754](https://github.com/hammerjs/hammer.js/issues/754), [439c7a6](https://github.com/hammerjs/hammer.js/commit/439c7a6c46978ab387b4b8289399e904d1c49535))
+- Fixed moz-prefix, prefix should be Moz not moz. ([3ea47f3](https://github.com/hammerjs/hammer.js/commit/3ea47f3aebadc9d3bb6bf52bc8402cad135ef8a9))
+- Removed non-existant recognizer ([f1c2d3b](https://github.com/hammerjs/hammer.js/commit/f1c2d3bf05f530ae092ecfc2335fceeff0e9eec9))
+- Fixed config leaking between instances([189098f](https://github.com/hammerjs/hammer.js/commit/189098ff7736f6ed2fce9a3d3e1f5a3afee085ba))
+- Fixed gaps in gesture configs and update tests to match ([70c2902](https://github.com/hammerjs/hammer.js/commit/70c2902d773a750e92ce8c423f8a4165c07eab97))
+- Fixed Manager off method ([#768](https://github.com/hammerjs/hammer.js/issues/768), [da49a27](https://github.com/hammerjs/hammer.js/commit/da49a2730779ecc3b4dd147cc418a0df7c70fad9))
+- Added compatibility with requirejs optimizer namespaces ( [70075f2](https://github.com/hammerjs/hammer.js/commit/70075f2df1b855f7c6d8d3caac49b9276b88c8d6))
+- Made touchaction test zoomable ( [50264a7](https://github.com/hammerjs/hammer.js/commit/50264a70251ca88bbaf7b666401e527eee616de5))
+- Fixed preventing default when for `pan-x pan-y` case ( [95eaafa](https://github.com/hammerjs/hammer.js/commit/95eaafadad27bd1b25d20cf976811a451922f1c4))
+- Fixed incorrect touch action pan direction ( [a81da57](https://github.com/hammerjs/hammer.js/commit/a81da57a82ebf37e695e7c443e4e2715e7f32856))
+- Fixed combined pan-x pan-y to resolve to none ( [fdae07b](https://github.com/hammerjs/hammer.js/commit/fdae07bc2ba3c90aad28da6791b3d5df627bc612))
+- Fixed inverted touch-action for pan recognizer ([#728](https://github.com/hammerjs/hammer.js/issues/728), [605bd3b](https://github.com/hammerjs/hammer.js/commit/605bd3beca780be91dd43f9da8b809d155a43d1a))
+- Fixed dependency on non standard touch list ordering ([#610](https://github.com/hammerjs/hammer.js/issues/610), [#791](https://github.com/hammerjs/hammer.js/issues/791), [287720a](https://github.com/hammerjs/hammer.js/commit/287720a6e5067e7f28be8b8b3b266d22905361c4))
+- Fixed swipe to not trigger after multitouch gesture ([#640](https://github.com/hammerjs/hammer.js/issues/640), [711d8a1](https://github.com/hammerjs/hammer.js/commit/711d8a1df1aa5057ecb536454a36257e3c0d6d91))
+- Fixed swipe recognizer to use overall gesture direction and velocity ( [963fe69](https://github.com/hammerjs/hammer.js/commit/963fe697515273fee508414bc29e2656465cea55))
+- Fixed getDirection returning reversed direction ( [e40dcde](https://github.com/hammerjs/hammer.js/commit/e40dcde43bdac7a74c8ce5c05a4f62121089cd91))
+- Fixed detection of tap when multi touch gestures are present ( [c46cbba](https://github.com/hammerjs/hammer.js/commit/c46cbba1c2cbbf874b59913416858d9dae297e64))
+- Fixed incorrect event order ([#824](https://github.com/hammerjs/hammer.js/issues/824), [92f2d76](https://github.com/hammerjs/hammer.js/commit/92f2d76188480d967e738a19cd508d0b94a31329))
+- Fixed leaking options between recognizer instances ([#813](https://github.com/hammerjs/hammer.js/issues/813), [af32c9b](https://github.com/hammerjs/hammer.js/commit/af32c9bace3f04bb34bee852ff56a33cc8fc27cd))
+- Fixed detection when element has no style attribute ( [5ca6d8c](https://github.com/hammerjs/hammer.js/commit/5ca6d8cbead02c71929a8073e95ddf98e11c0e06))
+
+### 2.0.4, 2014-09-28
+- Fix IE pointer issue. [#665](https://github.com/hammerjs/hammer.js/pull/665)
+- Fix multi-touch at different elements. [#668](https://github.com/hammerjs/hammer.js/pull/668)
+- Added experimental [single-user Touch input handler](src/input/singletouch.js). This to improve performance/ux when only a single user has to be supported. Plans are to release 2.1 with this as default, and a settings to enable the multi-user handler.
+
+### 2.0.3, 2014-09-10
+- Manager.set improvements.
+- Fix requireFailure() call in Manager.options.recognizers.
+- Make DIRECTION_ALL for pan and swipe gestures less blocking.
+- Fix Swipe recognizer threshold option.
+- Expose the Input classes.
+- Added the option `inputClass` to set the used input handler.
+
+### 2.0.2, 2014-07-26
+- Improved mouse and pointer-events input, now able to move outside the window.
+- Added the export name (`Hammer`) as an argument to the wrapper.
+- Add the option *experimental* `inputTarget` to change the element that receives the events.
+- Improved performance when only one touch being active.
+- Fixed the jumping deltaXY bug when going from single to multi-touch.
+- Improved velocity calculations.
+
+### 2.0.1, 2014-07-15
+- Fix issue when no document.body is available
+- Added pressup event for the press recognizer
+- Removed alternative for Object.create
+
+### 2.0.0, 2014-07-11
+- Full rewrite of the library.
diff --git a/afb-client/bower_components/hammerjs/CONTRIBUTING.md b/afb-client/bower_components/hammerjs/CONTRIBUTING.md
new file mode 100644
index 0000000..b1934de
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/CONTRIBUTING.md
@@ -0,0 +1,41 @@
+# Contributing to Hammer.js
+
+Looking to contribute something to Hammer.js? **Here's how you can help.**
+
+
+## Reporting issues
+
+We only accept issues that are bug reports or feature requests. Bugs must be
+isolated and reproducible problems that can be fixed within the Hammer.js.
+Please read the following guidelines before opening any issue.
+
+1. [**Read the documentation**](https://hammerjs.github.io)
+
+2. **Search for existing issues.** We get a lot of duplicate issues, and you'd
+help us out a lot by first checking if someone else has reported the same issue.
+Moreover, the issue may have already been resolved with a fix available. Also
+take a look if your problem is explained at the Wiki.
+
+3. **Create an isolated and reproducible test case.** Be sure the problem exists
+in Hammer's code with a reduced test case that should be included in each bug
+report.
+
+4. **Include a live example.** Make use of jsFiddle or jsBin to share your
+isolated test cases. Also, a screen capture would work, with tools like LICEcap.
+
+5. **Share as much information as possible.** Include operating system and
+version, browser and version, version of Hammer.js, customized or vanilla build,
+etc. where appropriate. Also include steps to reproduce the bug.
+
+## Pull requests
+
+1. Changes must be done in `/src` files, never just the compiled files. Also, don't
+commit the compiled files.
+
+2. Try not to pollute your pull request with unintended changes. Keep them simple
+and small
+
+3. Try to share which browsers your code has been tested in before submitting a
+pull request
+
+4. Write tests for your code, these can be found in `/tests`.
diff --git a/afb-client/bower_components/hammerjs/LICENSE.md b/afb-client/bower_components/hammerjs/LICENSE.md
new file mode 100644
index 0000000..e067655
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (C) 2011-2014 by Jorik Tangelder (Eight Media)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/hammerjs/README.md b/afb-client/bower_components/hammerjs/README.md
new file mode 100644
index 0000000..404c8c3
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/README.md
@@ -0,0 +1,49 @@
+# Hammer.js 2.0.6
+
+[![Build Status](https://travis-ci.org/hammerjs/hammer.js.svg)](https://travis-ci.org/hammerjs/hammer.js)
+
+## Support, Questions, and Collaboration
+
+[![Slack Status](https://hammerjs.herokuapp.com/badge.svg)](https://hammerjs.herokuapp.com/)
+
+## Documentation
+
+Visit [hammerjs.github.io](http://hammerjs.github.io) for detailed documentation.
+
+```js
+// get a reference to an element
+var stage = document.getElementById('stage');
+
+// create a manager for that element
+var mc = new Hammer.Manager(stage);
+
+// create a recognizer
+var Rotate = new Hammer.Rotate();
+
+// add the recognizer
+mc.add(Rotate);
+
+// subscribe to events
+mc.on('rotate', function(e) {
+ // do something cool
+ var rotation = Math.round(e.rotation);
+ stage.style.transform = 'rotate('+rotation+'deg)';
+});
+```
+
+
+## Contributing
+
+Read the [contributing guidelines](./CONTRIBUTING.md).
+
+For PRs.
+
+- Use [Angular Style commit messages](https://github.com/angular/angular.js/blob/v1.4.8/CONTRIBUTING.md#commit)
+- Rebase your PR branch when necessary
+- If you add a feature or fix a bug, please add or fix any necessary tests.
+- If a new feature, open a docs PR to go with.
+
+## Building
+
+You can get the pre-build versions from the Hammer.js website, or do this by yourself running
+`npm install -g grunt-cli && npm install && grunt build`
diff --git a/afb-client/bower_components/hammerjs/bower.json b/afb-client/bower_components/hammerjs/bower.json
new file mode 100644
index 0000000..f241608
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/bower.json
@@ -0,0 +1,16 @@
+{
+ "name": "hammerjs",
+ "main": "hammer.js",
+ "ignore": [
+ "tests",
+ "src",
+ ".bowerrc",
+ ".gitignore",
+ ".jscsrc",
+ ".jshintrc",
+ ".travis.yml",
+ "component.json",
+ "Gruntfile.coffee",
+ "package.json"
+ ]
+}
diff --git a/afb-client/bower_components/hammerjs/changelog.js b/afb-client/bower_components/hammerjs/changelog.js
new file mode 100644
index 0000000..887a329
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/changelog.js
@@ -0,0 +1,71 @@
+var changelog = require( "changelogplease" );
+var gittags = require( "git-tags" ).get( function( error, tags ) {
+ if ( error ) {
+ throw error
+ }
+ console.log( tags[ 1 ] + ".." + tags[ 0 ] );
+ var exclude = [ "Merge", "Whitespace", "Fixup", "Cleanup", "Formatting", "Ignore" ];
+ changelog( {
+ ticketUrl: "https://github.com/hammerjs/hammer.js/issues/{id}",
+ commitUrl: "https://github.com/hammerjs/hammerjs/commit/{id}",
+ sort: false,
+ repo: "./",
+ committish: tags[ 1 ] + ".." + tags[ 0 ]
+ }, function( error, log ) {
+ if ( error ) {
+ throw error;
+ }
+ log = parseLog( log );
+ console.log( log );
+ } );
+ function parseLog( log ) {
+ var lines = log.split( "\n" );
+ var newLog = [];
+ var log = [];
+ var currentComponent;
+
+
+ lines.shift();
+ lines.forEach( function( line ) {
+ var newLine = parseLine( line );
+ if ( newLine ) {
+ log.push( line );
+ }
+ } );
+ var log = log.join( "\n" );
+ return log.replace( /\*/g, "-" ).replace( /__TICKETREF__,/g, "" );
+ }
+ function parseLine( line ) {
+ var parts = getParts( line );
+
+ if ( exclude.indexOf( parts.component ) > -1 ) {
+ return false;
+ }
+ return parts;
+ }
+ function getParts( line ) {
+ var parts = line.split( ":" );
+ var component = "";
+ var message;
+ var commits = line.match( /\{\{([A-Za-z0-9 ]){0,99}\}\}/ )
+
+ if ( parts.length > 1 && parts[ 0 ].length <= 20 ) {
+ component = parts[ 0 ];
+ parts.shift();
+ message = parts.join( ":" );
+ } else {
+ parts = line.split( " " );
+ component = parts[ 1 ];
+ parts.shift();
+ message = parts.join( " " );
+ }
+
+ if ( component ) {
+ component = component.replace( /\* |,/, "" );
+ }
+ return {
+ component: component,
+ message: message
+ };
+ }
+} );
diff --git a/afb-client/bower_components/hammerjs/hammer.js b/afb-client/bower_components/hammerjs/hammer.js
new file mode 100644
index 0000000..bbabf73
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/hammer.js
@@ -0,0 +1,2568 @@
+/*! Hammer.JS - v2.0.6 - 2015-12-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2015 Jorik Tangelder;
+ * Licensed under the license */
+(function(window, document, exportName, undefined) {
+ 'use strict';
+
+var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
+var TEST_ELEMENT = document.createElement('div');
+
+var TYPE_FUNCTION = 'function';
+
+var round = Math.round;
+var abs = Math.abs;
+var now = Date.now;
+
+/**
+ * set a timeout with a given scope
+ * @param {Function} fn
+ * @param {Number} timeout
+ * @param {Object} context
+ * @returns {number}
+ */
+function setTimeoutContext(fn, timeout, context) {
+ return setTimeout(bindFn(fn, context), timeout);
+}
+
+/**
+ * if the argument is an array, we want to execute the fn on each entry
+ * if it aint an array we don't want to do a thing.
+ * this is used by all the methods that accept a single and array argument.
+ * @param {*|Array} arg
+ * @param {String} fn
+ * @param {Object} [context]
+ * @returns {Boolean}
+ */
+function invokeArrayArg(arg, fn, context) {
+ if (Array.isArray(arg)) {
+ each(arg, context[fn], context);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * walk objects and arrays
+ * @param {Object} obj
+ * @param {Function} iterator
+ * @param {Object} context
+ */
+function each(obj, iterator, context) {
+ var i;
+
+ if (!obj) {
+ return;
+ }
+
+ if (obj.forEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length !== undefined) {
+ i = 0;
+ while (i < obj.length) {
+ iterator.call(context, obj[i], i, obj);
+ i++;
+ }
+ } else {
+ for (i in obj) {
+ obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
+ }
+ }
+}
+
+/**
+ * wrap a method with a deprecation warning and stack trace
+ * @param {Function} method
+ * @param {String} name
+ * @param {String} message
+ * @returns {Function} A new function wrapping the supplied method.
+ */
+function deprecate(method, name, message) {
+ var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
+ return function() {
+ var e = new Error('get-stack-trace');
+ var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
+ .replace(/^\s+at\s+/gm, '')
+ .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
+
+ var log = window.console && (window.console.warn || window.console.log);
+ if (log) {
+ log.call(window.console, deprecationMessage, stack);
+ }
+ return method.apply(this, arguments);
+ };
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} target
+ * @param {...Object} objects_to_assign
+ * @returns {Object} target
+ */
+var assign;
+if (typeof Object.assign !== 'function') {
+ assign = function assign(target) {
+ if (target === undefined || target === null) {
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var output = Object(target);
+ for (var index = 1; index < arguments.length; index++) {
+ var source = arguments[index];
+ if (source !== undefined && source !== null) {
+ for (var nextKey in source) {
+ if (source.hasOwnProperty(nextKey)) {
+ output[nextKey] = source[nextKey];
+ }
+ }
+ }
+ }
+ return output;
+ };
+} else {
+ assign = Object.assign;
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} dest
+ * @param {Object} src
+ * @param {Boolean=false} [merge]
+ * @returns {Object} dest
+ */
+var extend = deprecate(function extend(dest, src, merge) {
+ var keys = Object.keys(src);
+ var i = 0;
+ while (i < keys.length) {
+ if (!merge || (merge && dest[keys[i]] === undefined)) {
+ dest[keys[i]] = src[keys[i]];
+ }
+ i++;
+ }
+ return dest;
+}, 'extend', 'Use `assign`.');
+
+/**
+ * merge the values from src in the dest.
+ * means that properties that exist in dest will not be overwritten by src
+ * @param {Object} dest
+ * @param {Object} src
+ * @returns {Object} dest
+ */
+var merge = deprecate(function merge(dest, src) {
+ return extend(dest, src, true);
+}, 'merge', 'Use `assign`.');
+
+/**
+ * simple class inheritance
+ * @param {Function} child
+ * @param {Function} base
+ * @param {Object} [properties]
+ */
+function inherit(child, base, properties) {
+ var baseP = base.prototype,
+ childP;
+
+ childP = child.prototype = Object.create(baseP);
+ childP.constructor = child;
+ childP._super = baseP;
+
+ if (properties) {
+ assign(childP, properties);
+ }
+}
+
+/**
+ * simple function bind
+ * @param {Function} fn
+ * @param {Object} context
+ * @returns {Function}
+ */
+function bindFn(fn, context) {
+ return function boundFn() {
+ return fn.apply(context, arguments);
+ };
+}
+
+/**
+ * let a boolean value also be a function that must return a boolean
+ * this first item in args will be used as the context
+ * @param {Boolean|Function} val
+ * @param {Array} [args]
+ * @returns {Boolean}
+ */
+function boolOrFn(val, args) {
+ if (typeof val == TYPE_FUNCTION) {
+ return val.apply(args ? args[0] || undefined : undefined, args);
+ }
+ return val;
+}
+
+/**
+ * use the val2 when val1 is undefined
+ * @param {*} val1
+ * @param {*} val2
+ * @returns {*}
+ */
+function ifUndefined(val1, val2) {
+ return (val1 === undefined) ? val2 : val1;
+}
+
+/**
+ * addEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function addEventListeners(target, types, handler) {
+ each(splitStr(types), function(type) {
+ target.addEventListener(type, handler, false);
+ });
+}
+
+/**
+ * removeEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function removeEventListeners(target, types, handler) {
+ each(splitStr(types), function(type) {
+ target.removeEventListener(type, handler, false);
+ });
+}
+
+/**
+ * find if a node is in the given parent
+ * @method hasParent
+ * @param {HTMLElement} node
+ * @param {HTMLElement} parent
+ * @return {Boolean} found
+ */
+function hasParent(node, parent) {
+ while (node) {
+ if (node == parent) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+}
+
+/**
+ * small indexOf wrapper
+ * @param {String} str
+ * @param {String} find
+ * @returns {Boolean} found
+ */
+function inStr(str, find) {
+ return str.indexOf(find) > -1;
+}
+
+/**
+ * split string on whitespace
+ * @param {String} str
+ * @returns {Array} words
+ */
+function splitStr(str) {
+ return str.trim().split(/\s+/g);
+}
+
+/**
+ * find if a array contains the object using indexOf or a simple polyFill
+ * @param {Array} src
+ * @param {String} find
+ * @param {String} [findByKey]
+ * @return {Boolean|Number} false when not found, or the index
+ */
+function inArray(src, find, findByKey) {
+ if (src.indexOf && !findByKey) {
+ return src.indexOf(find);
+ } else {
+ var i = 0;
+ while (i < src.length) {
+ if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+ }
+}
+
+/**
+ * convert array-like objects to real arrays
+ * @param {Object} obj
+ * @returns {Array}
+ */
+function toArray(obj) {
+ return Array.prototype.slice.call(obj, 0);
+}
+
+/**
+ * unique array with objects based on a key (like 'id') or just by the array's value
+ * @param {Array} src [{id:1},{id:2},{id:1}]
+ * @param {String} [key]
+ * @param {Boolean} [sort=False]
+ * @returns {Array} [{id:1},{id:2}]
+ */
+function uniqueArray(src, key, sort) {
+ var results = [];
+ var values = [];
+ var i = 0;
+
+ while (i < src.length) {
+ var val = key ? src[i][key] : src[i];
+ if (inArray(values, val) < 0) {
+ results.push(src[i]);
+ }
+ values[i] = val;
+ i++;
+ }
+
+ if (sort) {
+ if (!key) {
+ results = results.sort();
+ } else {
+ results = results.sort(function sortUniqueArray(a, b) {
+ return a[key] > b[key];
+ });
+ }
+ }
+
+ return results;
+}
+
+/**
+ * get the prefixed property
+ * @param {Object} obj
+ * @param {String} property
+ * @returns {String|Undefined} prefixed
+ */
+function prefixed(obj, property) {
+ var prefix, prop;
+ var camelProp = property[0].toUpperCase() + property.slice(1);
+
+ var i = 0;
+ while (i < VENDOR_PREFIXES.length) {
+ prefix = VENDOR_PREFIXES[i];
+ prop = (prefix) ? prefix + camelProp : property;
+
+ if (prop in obj) {
+ return prop;
+ }
+ i++;
+ }
+ return undefined;
+}
+
+/**
+ * get a unique id
+ * @returns {number} uniqueId
+ */
+var _uniqueId = 1;
+function uniqueId() {
+ return _uniqueId++;
+}
+
+/**
+ * get the window object of an element
+ * @param {HTMLElement} element
+ * @returns {DocumentView|Window}
+ */
+function getWindowForElement(element) {
+ var doc = element.ownerDocument || element;
+ return (doc.defaultView || doc.parentWindow || window);
+}
+
+var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
+
+var SUPPORT_TOUCH = ('ontouchstart' in window);
+var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
+var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
+
+var INPUT_TYPE_TOUCH = 'touch';
+var INPUT_TYPE_PEN = 'pen';
+var INPUT_TYPE_MOUSE = 'mouse';
+var INPUT_TYPE_KINECT = 'kinect';
+
+var COMPUTE_INTERVAL = 25;
+
+var INPUT_START = 1;
+var INPUT_MOVE = 2;
+var INPUT_END = 4;
+var INPUT_CANCEL = 8;
+
+var DIRECTION_NONE = 1;
+var DIRECTION_LEFT = 2;
+var DIRECTION_RIGHT = 4;
+var DIRECTION_UP = 8;
+var DIRECTION_DOWN = 16;
+
+var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
+var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
+var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
+
+var PROPS_XY = ['x', 'y'];
+var PROPS_CLIENT_XY = ['clientX', 'clientY'];
+
+/**
+ * create new input type manager
+ * @param {Manager} manager
+ * @param {Function} callback
+ * @returns {Input}
+ * @constructor
+ */
+function Input(manager, callback) {
+ var self = this;
+ this.manager = manager;
+ this.callback = callback;
+ this.element = manager.element;
+ this.target = manager.options.inputTarget;
+
+ // smaller wrapper around the handler, for the scope and the enabled state of the manager,
+ // so when disabled the input events are completely bypassed.
+ this.domHandler = function(ev) {
+ if (boolOrFn(manager.options.enable, [manager])) {
+ self.handler(ev);
+ }
+ };
+
+ this.init();
+
+}
+
+Input.prototype = {
+ /**
+ * should handle the inputEvent data and trigger the callback
+ * @virtual
+ */
+ handler: function() { },
+
+ /**
+ * bind the events
+ */
+ init: function() {
+ this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
+ this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
+ this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+ },
+
+ /**
+ * unbind the events
+ */
+ destroy: function() {
+ this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
+ this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
+ this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+ }
+};
+
+/**
+ * create new input type manager
+ * called by the Manager constructor
+ * @param {Hammer} manager
+ * @returns {Input}
+ */
+function createInputInstance(manager) {
+ var Type;
+ var inputClass = manager.options.inputClass;
+
+ if (inputClass) {
+ Type = inputClass;
+ } else if (SUPPORT_POINTER_EVENTS) {
+ Type = PointerEventInput;
+ } else if (SUPPORT_ONLY_TOUCH) {
+ Type = TouchInput;
+ } else if (!SUPPORT_TOUCH) {
+ Type = MouseInput;
+ } else {
+ Type = TouchMouseInput;
+ }
+ return new (Type)(manager, inputHandler);
+}
+
+/**
+ * handle input events
+ * @param {Manager} manager
+ * @param {String} eventType
+ * @param {Object} input
+ */
+function inputHandler(manager, eventType, input) {
+ var pointersLen = input.pointers.length;
+ var changedPointersLen = input.changedPointers.length;
+ var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
+ var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
+
+ input.isFirst = !!isFirst;
+ input.isFinal = !!isFinal;
+
+ if (isFirst) {
+ manager.session = {};
+ }
+
+ // source event is the normalized value of the domEvents
+ // like 'touchstart, mouseup, pointerdown'
+ input.eventType = eventType;
+
+ // compute scale, rotation etc
+ computeInputData(manager, input);
+
+ // emit secret event
+ manager.emit('hammer.input', input);
+
+ manager.recognize(input);
+ manager.session.prevInput = input;
+}
+
+/**
+ * extend the data with some usable properties like scale, rotate, velocity etc
+ * @param {Object} manager
+ * @param {Object} input
+ */
+function computeInputData(manager, input) {
+ var session = manager.session;
+ var pointers = input.pointers;
+ var pointersLength = pointers.length;
+
+ // store the first input to calculate the distance and direction
+ if (!session.firstInput) {
+ session.firstInput = simpleCloneInputData(input);
+ }
+
+ // to compute scale and rotation we need to store the multiple touches
+ if (pointersLength > 1 && !session.firstMultiple) {
+ session.firstMultiple = simpleCloneInputData(input);
+ } else if (pointersLength === 1) {
+ session.firstMultiple = false;
+ }
+
+ var firstInput = session.firstInput;
+ var firstMultiple = session.firstMultiple;
+ var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
+
+ var center = input.center = getCenter(pointers);
+ input.timeStamp = now();
+ input.deltaTime = input.timeStamp - firstInput.timeStamp;
+
+ input.angle = getAngle(offsetCenter, center);
+ input.distance = getDistance(offsetCenter, center);
+
+ computeDeltaXY(session, input);
+ input.offsetDirection = getDirection(input.deltaX, input.deltaY);
+
+ var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
+ input.overallVelocityX = overallVelocity.x;
+ input.overallVelocityY = overallVelocity.y;
+ input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
+
+ input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
+ input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
+
+ input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
+ session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
+
+ computeIntervalInputData(session, input);
+
+ // find the correct target
+ var target = manager.element;
+ if (hasParent(input.srcEvent.target, target)) {
+ target = input.srcEvent.target;
+ }
+ input.target = target;
+}
+
+function computeDeltaXY(session, input) {
+ var center = input.center;
+ var offset = session.offsetDelta || {};
+ var prevDelta = session.prevDelta || {};
+ var prevInput = session.prevInput || {};
+
+ if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
+ prevDelta = session.prevDelta = {
+ x: prevInput.deltaX || 0,
+ y: prevInput.deltaY || 0
+ };
+
+ offset = session.offsetDelta = {
+ x: center.x,
+ y: center.y
+ };
+ }
+
+ input.deltaX = prevDelta.x + (center.x - offset.x);
+ input.deltaY = prevDelta.y + (center.y - offset.y);
+}
+
+/**
+ * velocity is calculated every x ms
+ * @param {Object} session
+ * @param {Object} input
+ */
+function computeIntervalInputData(session, input) {
+ var last = session.lastInterval || input,
+ deltaTime = input.timeStamp - last.timeStamp,
+ velocity, velocityX, velocityY, direction;
+
+ if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
+ var deltaX = input.deltaX - last.deltaX;
+ var deltaY = input.deltaY - last.deltaY;
+
+ var v = getVelocity(deltaTime, deltaX, deltaY);
+ velocityX = v.x;
+ velocityY = v.y;
+ velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
+ direction = getDirection(deltaX, deltaY);
+
+ session.lastInterval = input;
+ } else {
+ // use latest velocity info if it doesn't overtake a minimum period
+ velocity = last.velocity;
+ velocityX = last.velocityX;
+ velocityY = last.velocityY;
+ direction = last.direction;
+ }
+
+ input.velocity = velocity;
+ input.velocityX = velocityX;
+ input.velocityY = velocityY;
+ input.direction = direction;
+}
+
+/**
+ * create a simple clone from the input used for storage of firstInput and firstMultiple
+ * @param {Object} input
+ * @returns {Object} clonedInputData
+ */
+function simpleCloneInputData(input) {
+ // make a simple copy of the pointers because we will get a reference if we don't
+ // we only need clientXY for the calculations
+ var pointers = [];
+ var i = 0;
+ while (i < input.pointers.length) {
+ pointers[i] = {
+ clientX: round(input.pointers[i].clientX),
+ clientY: round(input.pointers[i].clientY)
+ };
+ i++;
+ }
+
+ return {
+ timeStamp: now(),
+ pointers: pointers,
+ center: getCenter(pointers),
+ deltaX: input.deltaX,
+ deltaY: input.deltaY
+ };
+}
+
+/**
+ * get the center of all the pointers
+ * @param {Array} pointers
+ * @return {Object} center contains `x` and `y` properties
+ */
+function getCenter(pointers) {
+ var pointersLength = pointers.length;
+
+ // no need to loop when only one touch
+ if (pointersLength === 1) {
+ return {
+ x: round(pointers[0].clientX),
+ y: round(pointers[0].clientY)
+ };
+ }
+
+ var x = 0, y = 0, i = 0;
+ while (i < pointersLength) {
+ x += pointers[i].clientX;
+ y += pointers[i].clientY;
+ i++;
+ }
+
+ return {
+ x: round(x / pointersLength),
+ y: round(y / pointersLength)
+ };
+}
+
+/**
+ * calculate the velocity between two points. unit is in px per ms.
+ * @param {Number} deltaTime
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Object} velocity `x` and `y`
+ */
+function getVelocity(deltaTime, x, y) {
+ return {
+ x: x / deltaTime || 0,
+ y: y / deltaTime || 0
+ };
+}
+
+/**
+ * get the direction between two points
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Number} direction
+ */
+function getDirection(x, y) {
+ if (x === y) {
+ return DIRECTION_NONE;
+ }
+
+ if (abs(x) >= abs(y)) {
+ return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
+ }
+ return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
+}
+
+/**
+ * calculate the absolute distance between two points
+ * @param {Object} p1 {x, y}
+ * @param {Object} p2 {x, y}
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} distance
+ */
+function getDistance(p1, p2, props) {
+ if (!props) {
+ props = PROPS_XY;
+ }
+ var x = p2[props[0]] - p1[props[0]],
+ y = p2[props[1]] - p1[props[1]];
+
+ return Math.sqrt((x * x) + (y * y));
+}
+
+/**
+ * calculate the angle between two coordinates
+ * @param {Object} p1
+ * @param {Object} p2
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} angle
+ */
+function getAngle(p1, p2, props) {
+ if (!props) {
+ props = PROPS_XY;
+ }
+ var x = p2[props[0]] - p1[props[0]],
+ y = p2[props[1]] - p1[props[1]];
+ return Math.atan2(y, x) * 180 / Math.PI;
+}
+
+/**
+ * calculate the rotation degrees between two pointersets
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} rotation
+ */
+function getRotation(start, end) {
+ return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
+}
+
+/**
+ * calculate the scale factor between two pointersets
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} scale
+ */
+function getScale(start, end) {
+ return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
+}
+
+var MOUSE_INPUT_MAP = {
+ mousedown: INPUT_START,
+ mousemove: INPUT_MOVE,
+ mouseup: INPUT_END
+};
+
+var MOUSE_ELEMENT_EVENTS = 'mousedown';
+var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
+
+/**
+ * Mouse events input
+ * @constructor
+ * @extends Input
+ */
+function MouseInput() {
+ this.evEl = MOUSE_ELEMENT_EVENTS;
+ this.evWin = MOUSE_WINDOW_EVENTS;
+
+ this.allow = true; // used by Input.TouchMouse to disable mouse events
+ this.pressed = false; // mousedown state
+
+ Input.apply(this, arguments);
+}
+
+inherit(MouseInput, Input, {
+ /**
+ * handle mouse events
+ * @param {Object} ev
+ */
+ handler: function MEhandler(ev) {
+ var eventType = MOUSE_INPUT_MAP[ev.type];
+
+ // on start we want to have the left mouse button down
+ if (eventType & INPUT_START && ev.button === 0) {
+ this.pressed = true;
+ }
+
+ if (eventType & INPUT_MOVE && ev.which !== 1) {
+ eventType = INPUT_END;
+ }
+
+ // mouse must be down, and mouse events are allowed (see the TouchMouse input)
+ if (!this.pressed || !this.allow) {
+ return;
+ }
+
+ if (eventType & INPUT_END) {
+ this.pressed = false;
+ }
+
+ this.callback(this.manager, eventType, {
+ pointers: [ev],
+ changedPointers: [ev],
+ pointerType: INPUT_TYPE_MOUSE,
+ srcEvent: ev
+ });
+ }
+});
+
+var POINTER_INPUT_MAP = {
+ pointerdown: INPUT_START,
+ pointermove: INPUT_MOVE,
+ pointerup: INPUT_END,
+ pointercancel: INPUT_CANCEL,
+ pointerout: INPUT_CANCEL
+};
+
+// in IE10 the pointer types is defined as an enum
+var IE10_POINTER_TYPE_ENUM = {
+ 2: INPUT_TYPE_TOUCH,
+ 3: INPUT_TYPE_PEN,
+ 4: INPUT_TYPE_MOUSE,
+ 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
+};
+
+var POINTER_ELEMENT_EVENTS = 'pointerdown';
+var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
+
+// IE10 has prefixed support, and case-sensitive
+if (window.MSPointerEvent && !window.PointerEvent) {
+ POINTER_ELEMENT_EVENTS = 'MSPointerDown';
+ POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
+}
+
+/**
+ * Pointer events input
+ * @constructor
+ * @extends Input
+ */
+function PointerEventInput() {
+ this.evEl = POINTER_ELEMENT_EVENTS;
+ this.evWin = POINTER_WINDOW_EVENTS;
+
+ Input.apply(this, arguments);
+
+ this.store = (this.manager.session.pointerEvents = []);
+}
+
+inherit(PointerEventInput, Input, {
+ /**
+ * handle mouse events
+ * @param {Object} ev
+ */
+ handler: function PEhandler(ev) {
+ var store = this.store;
+ var removePointer = false;
+
+ var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
+ var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
+ var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
+
+ var isTouch = (pointerType == INPUT_TYPE_TOUCH);
+
+ // get index of the event in the store
+ var storeIndex = inArray(store, ev.pointerId, 'pointerId');
+
+ // start and mouse must be down
+ if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
+ if (storeIndex < 0) {
+ store.push(ev);
+ storeIndex = store.length - 1;
+ }
+ } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+ removePointer = true;
+ }
+
+ // it not found, so the pointer hasn't been down (so it's probably a hover)
+ if (storeIndex < 0) {
+ return;
+ }
+
+ // update the event in the store
+ store[storeIndex] = ev;
+
+ this.callback(this.manager, eventType, {
+ pointers: store,
+ changedPointers: [ev],
+ pointerType: pointerType,
+ srcEvent: ev
+ });
+
+ if (removePointer) {
+ // remove from the store
+ store.splice(storeIndex, 1);
+ }
+ }
+});
+
+var SINGLE_TOUCH_INPUT_MAP = {
+ touchstart: INPUT_START,
+ touchmove: INPUT_MOVE,
+ touchend: INPUT_END,
+ touchcancel: INPUT_CANCEL
+};
+
+var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
+var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Touch events input
+ * @constructor
+ * @extends Input
+ */
+function SingleTouchInput() {
+ this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
+ this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
+ this.started = false;
+
+ Input.apply(this, arguments);
+}
+
+inherit(SingleTouchInput, Input, {
+ handler: function TEhandler(ev) {
+ var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
+
+ // should we handle the touch events?
+ if (type === INPUT_START) {
+ this.started = true;
+ }
+
+ if (!this.started) {
+ return;
+ }
+
+ var touches = normalizeSingleTouches.call(this, ev, type);
+
+ // when done, reset the started state
+ if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
+ this.started = false;
+ }
+
+ this.callback(this.manager, type, {
+ pointers: touches[0],
+ changedPointers: touches[1],
+ pointerType: INPUT_TYPE_TOUCH,
+ srcEvent: ev
+ });
+ }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function normalizeSingleTouches(ev, type) {
+ var all = toArray(ev.touches);
+ var changed = toArray(ev.changedTouches);
+
+ if (type & (INPUT_END | INPUT_CANCEL)) {
+ all = uniqueArray(all.concat(changed), 'identifier', true);
+ }
+
+ return [all, changed];
+}
+
+var TOUCH_INPUT_MAP = {
+ touchstart: INPUT_START,
+ touchmove: INPUT_MOVE,
+ touchend: INPUT_END,
+ touchcancel: INPUT_CANCEL
+};
+
+var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Multi-user touch events input
+ * @constructor
+ * @extends Input
+ */
+function TouchInput() {
+ this.evTarget = TOUCH_TARGET_EVENTS;
+ this.targetIds = {};
+
+ Input.apply(this, arguments);
+}
+
+inherit(TouchInput, Input, {
+ handler: function MTEhandler(ev) {
+ var type = TOUCH_INPUT_MAP[ev.type];
+ var touches = getTouches.call(this, ev, type);
+ if (!touches) {
+ return;
+ }
+
+ this.callback(this.manager, type, {
+ pointers: touches[0],
+ changedPointers: touches[1],
+ pointerType: INPUT_TYPE_TOUCH,
+ srcEvent: ev
+ });
+ }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function getTouches(ev, type) {
+ var allTouches = toArray(ev.touches);
+ var targetIds = this.targetIds;
+
+ // when there is only one touch, the process can be simplified
+ if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
+ targetIds[allTouches[0].identifier] = true;
+ return [allTouches, allTouches];
+ }
+
+ var i,
+ targetTouches,
+ changedTouches = toArray(ev.changedTouches),
+ changedTargetTouches = [],
+ target = this.target;
+
+ // get target touches from touches
+ targetTouches = allTouches.filter(function(touch) {
+ return hasParent(touch.target, target);
+ });
+
+ // collect touches
+ if (type === INPUT_START) {
+ i = 0;
+ while (i < targetTouches.length) {
+ targetIds[targetTouches[i].identifier] = true;
+ i++;
+ }
+ }
+
+ // filter changed touches to only contain touches that exist in the collected target ids
+ i = 0;
+ while (i < changedTouches.length) {
+ if (targetIds[changedTouches[i].identifier]) {
+ changedTargetTouches.push(changedTouches[i]);
+ }
+
+ // cleanup removed touches
+ if (type & (INPUT_END | INPUT_CANCEL)) {
+ delete targetIds[changedTouches[i].identifier];
+ }
+ i++;
+ }
+
+ if (!changedTargetTouches.length) {
+ return;
+ }
+
+ return [
+ // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
+ uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
+ changedTargetTouches
+ ];
+}
+
+/**
+ * Combined touch and mouse input
+ *
+ * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
+ * This because touch devices also emit mouse events while doing a touch.
+ *
+ * @constructor
+ * @extends Input
+ */
+function TouchMouseInput() {
+ Input.apply(this, arguments);
+
+ var handler = bindFn(this.handler, this);
+ this.touch = new TouchInput(this.manager, handler);
+ this.mouse = new MouseInput(this.manager, handler);
+}
+
+inherit(TouchMouseInput, Input, {
+ /**
+ * handle mouse and touch events
+ * @param {Hammer} manager
+ * @param {String} inputEvent
+ * @param {Object} inputData
+ */
+ handler: function TMEhandler(manager, inputEvent, inputData) {
+ var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
+ isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
+
+ // when we're in a touch event, so block all upcoming mouse events
+ // most mobile browser also emit mouseevents, right after touchstart
+ if (isTouch) {
+ this.mouse.allow = false;
+ } else if (isMouse && !this.mouse.allow) {
+ return;
+ }
+
+ // reset the allowMouse when we're done
+ if (inputEvent & (INPUT_END | INPUT_CANCEL)) {
+ this.mouse.allow = true;
+ }
+
+ this.callback(manager, inputEvent, inputData);
+ },
+
+ /**
+ * remove the event listeners
+ */
+ destroy: function destroy() {
+ this.touch.destroy();
+ this.mouse.destroy();
+ }
+});
+
+var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
+var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
+
+// magical touchAction value
+var TOUCH_ACTION_COMPUTE = 'compute';
+var TOUCH_ACTION_AUTO = 'auto';
+var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
+var TOUCH_ACTION_NONE = 'none';
+var TOUCH_ACTION_PAN_X = 'pan-x';
+var TOUCH_ACTION_PAN_Y = 'pan-y';
+
+/**
+ * Touch Action
+ * sets the touchAction property or uses the js alternative
+ * @param {Manager} manager
+ * @param {String} value
+ * @constructor
+ */
+function TouchAction(manager, value) {
+ this.manager = manager;
+ this.set(value);
+}
+
+TouchAction.prototype = {
+ /**
+ * set the touchAction value on the element or enable the polyfill
+ * @param {String} value
+ */
+ set: function(value) {
+ // find out the touch-action by the event handlers
+ if (value == TOUCH_ACTION_COMPUTE) {
+ value = this.compute();
+ }
+
+ if (NATIVE_TOUCH_ACTION && this.manager.element.style) {
+ this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
+ }
+ this.actions = value.toLowerCase().trim();
+ },
+
+ /**
+ * just re-set the touchAction value
+ */
+ update: function() {
+ this.set(this.manager.options.touchAction);
+ },
+
+ /**
+ * compute the value for the touchAction property based on the recognizer's settings
+ * @returns {String} value
+ */
+ compute: function() {
+ var actions = [];
+ each(this.manager.recognizers, function(recognizer) {
+ if (boolOrFn(recognizer.options.enable, [recognizer])) {
+ actions = actions.concat(recognizer.getTouchAction());
+ }
+ });
+ return cleanTouchActions(actions.join(' '));
+ },
+
+ /**
+ * this method is called on each input cycle and provides the preventing of the browser behavior
+ * @param {Object} input
+ */
+ preventDefaults: function(input) {
+ // not needed with native support for the touchAction property
+ if (NATIVE_TOUCH_ACTION) {
+ return;
+ }
+
+ var srcEvent = input.srcEvent;
+ var direction = input.offsetDirection;
+
+ // if the touch action did prevented once this session
+ if (this.manager.session.prevented) {
+ srcEvent.preventDefault();
+ return;
+ }
+
+ var actions = this.actions;
+ var hasNone = inStr(actions, TOUCH_ACTION_NONE);
+ var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
+ var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
+
+ if (hasNone) {
+ //do not prevent defaults if this is a tap gesture
+
+ var isTapPointer = input.pointers.length === 1;
+ var isTapMovement = input.distance < 2;
+ var isTapTouchTime = input.deltaTime < 250;
+
+ if (isTapPointer && isTapMovement && isTapTouchTime) {
+ return;
+ }
+ }
+
+ if (hasPanX && hasPanY) {
+ // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
+ return;
+ }
+
+ if (hasNone ||
+ (hasPanY && direction & DIRECTION_HORIZONTAL) ||
+ (hasPanX && direction & DIRECTION_VERTICAL)) {
+ return this.preventSrc(srcEvent);
+ }
+ },
+
+ /**
+ * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
+ * @param {Object} srcEvent
+ */
+ preventSrc: function(srcEvent) {
+ this.manager.session.prevented = true;
+ srcEvent.preventDefault();
+ }
+};
+
+/**
+ * when the touchActions are collected they are not a valid value, so we need to clean things up. *
+ * @param {String} actions
+ * @returns {*}
+ */
+function cleanTouchActions(actions) {
+ // none
+ if (inStr(actions, TOUCH_ACTION_NONE)) {
+ return TOUCH_ACTION_NONE;
+ }
+
+ var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
+ var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
+
+ // if both pan-x and pan-y are set (different recognizers
+ // for different directions, e.g. horizontal pan but vertical swipe?)
+ // we need none (as otherwise with pan-x pan-y combined none of these
+ // recognizers will work, since the browser would handle all panning
+ if (hasPanX && hasPanY) {
+ return TOUCH_ACTION_NONE;
+ }
+
+ // pan-x OR pan-y
+ if (hasPanX || hasPanY) {
+ return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
+ }
+
+ // manipulation
+ if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
+ return TOUCH_ACTION_MANIPULATION;
+ }
+
+ return TOUCH_ACTION_AUTO;
+}
+
+/**
+ * Recognizer flow explained; *
+ * All recognizers have the initial state of POSSIBLE when a input session starts.
+ * The definition of a input session is from the first input until the last input, with all it's movement in it. *
+ * Example session for mouse-input: mousedown -> mousemove -> mouseup
+ *
+ * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
+ * which determines with state it should be.
+ *
+ * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
+ * POSSIBLE to give it another change on the next cycle.
+ *
+ * Possible
+ * |
+ * +-----+---------------+
+ * | |
+ * +-----+-----+ |
+ * | | |
+ * Failed Cancelled |
+ * +-------+------+
+ * | |
+ * Recognized Began
+ * |
+ * Changed
+ * |
+ * Ended/Recognized
+ */
+var STATE_POSSIBLE = 1;
+var STATE_BEGAN = 2;
+var STATE_CHANGED = 4;
+var STATE_ENDED = 8;
+var STATE_RECOGNIZED = STATE_ENDED;
+var STATE_CANCELLED = 16;
+var STATE_FAILED = 32;
+
+/**
+ * Recognizer
+ * Every recognizer needs to extend from this class.
+ * @constructor
+ * @param {Object} options
+ */
+function Recognizer(options) {
+ this.options = assign({}, this.defaults, options || {});
+
+ this.id = uniqueId();
+
+ this.manager = null;
+
+ // default is enable true
+ this.options.enable = ifUndefined(this.options.enable, true);
+
+ this.state = STATE_POSSIBLE;
+
+ this.simultaneous = {};
+ this.requireFail = [];
+}
+
+Recognizer.prototype = {
+ /**
+ * @virtual
+ * @type {Object}
+ */
+ defaults: {},
+
+ /**
+ * set options
+ * @param {Object} options
+ * @return {Recognizer}
+ */
+ set: function(options) {
+ assign(this.options, options);
+
+ // also update the touchAction, in case something changed about the directions/enabled state
+ this.manager && this.manager.touchAction.update();
+ return this;
+ },
+
+ /**
+ * recognize simultaneous with an other recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ recognizeWith: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
+ return this;
+ }
+
+ var simultaneous = this.simultaneous;
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ if (!simultaneous[otherRecognizer.id]) {
+ simultaneous[otherRecognizer.id] = otherRecognizer;
+ otherRecognizer.recognizeWith(this);
+ }
+ return this;
+ },
+
+ /**
+ * drop the simultaneous link. it doesnt remove the link on the other recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ dropRecognizeWith: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
+ return this;
+ }
+
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ delete this.simultaneous[otherRecognizer.id];
+ return this;
+ },
+
+ /**
+ * recognizer can only run when an other is failing
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ requireFailure: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
+ return this;
+ }
+
+ var requireFail = this.requireFail;
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ if (inArray(requireFail, otherRecognizer) === -1) {
+ requireFail.push(otherRecognizer);
+ otherRecognizer.requireFailure(this);
+ }
+ return this;
+ },
+
+ /**
+ * drop the requireFailure link. it does not remove the link on the other recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ dropRequireFailure: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
+ return this;
+ }
+
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ var index = inArray(this.requireFail, otherRecognizer);
+ if (index > -1) {
+ this.requireFail.splice(index, 1);
+ }
+ return this;
+ },
+
+ /**
+ * has require failures boolean
+ * @returns {boolean}
+ */
+ hasRequireFailures: function() {
+ return this.requireFail.length > 0;
+ },
+
+ /**
+ * if the recognizer can recognize simultaneous with an other recognizer
+ * @param {Recognizer} otherRecognizer
+ * @returns {Boolean}
+ */
+ canRecognizeWith: function(otherRecognizer) {
+ return !!this.simultaneous[otherRecognizer.id];
+ },
+
+ /**
+ * You should use `tryEmit` instead of `emit` directly to check
+ * that all the needed recognizers has failed before emitting.
+ * @param {Object} input
+ */
+ emit: function(input) {
+ var self = this;
+ var state = this.state;
+
+ function emit(event) {
+ self.manager.emit(event, input);
+ }
+
+ // 'panstart' and 'panmove'
+ if (state < STATE_ENDED) {
+ emit(self.options.event + stateStr(state));
+ }
+
+ emit(self.options.event); // simple 'eventName' events
+
+ if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
+ emit(input.additionalEvent);
+ }
+
+ // panend and pancancel
+ if (state >= STATE_ENDED) {
+ emit(self.options.event + stateStr(state));
+ }
+ },
+
+ /**
+ * Check that all the require failure recognizers has failed,
+ * if true, it emits a gesture event,
+ * otherwise, setup the state to FAILED.
+ * @param {Object} input
+ */
+ tryEmit: function(input) {
+ if (this.canEmit()) {
+ return this.emit(input);
+ }
+ // it's failing anyway
+ this.state = STATE_FAILED;
+ },
+
+ /**
+ * can we emit?
+ * @returns {boolean}
+ */
+ canEmit: function() {
+ var i = 0;
+ while (i < this.requireFail.length) {
+ if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
+ return false;
+ }
+ i++;
+ }
+ return true;
+ },
+
+ /**
+ * update the recognizer
+ * @param {Object} inputData
+ */
+ recognize: function(inputData) {
+ // make a new copy of the inputData
+ // so we can change the inputData without messing up the other recognizers
+ var inputDataClone = assign({}, inputData);
+
+ // is is enabled and allow recognizing?
+ if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
+ this.reset();
+ this.state = STATE_FAILED;
+ return;
+ }
+
+ // reset when we've reached the end
+ if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
+ this.state = STATE_POSSIBLE;
+ }
+
+ this.state = this.process(inputDataClone);
+
+ // the recognizer has recognized a gesture
+ // so trigger an event
+ if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
+ this.tryEmit(inputDataClone);
+ }
+ },
+
+ /**
+ * return the state of the recognizer
+ * the actual recognizing happens in this method
+ * @virtual
+ * @param {Object} inputData
+ * @returns {Const} STATE
+ */
+ process: function(inputData) { }, // jshint ignore:line
+
+ /**
+ * return the preferred touch-action
+ * @virtual
+ * @returns {Array}
+ */
+ getTouchAction: function() { },
+
+ /**
+ * called when the gesture isn't allowed to recognize
+ * like when another is being recognized or it is disabled
+ * @virtual
+ */
+ reset: function() { }
+};
+
+/**
+ * get a usable string, used as event postfix
+ * @param {Const} state
+ * @returns {String} state
+ */
+function stateStr(state) {
+ if (state & STATE_CANCELLED) {
+ return 'cancel';
+ } else if (state & STATE_ENDED) {
+ return 'end';
+ } else if (state & STATE_CHANGED) {
+ return 'move';
+ } else if (state & STATE_BEGAN) {
+ return 'start';
+ }
+ return '';
+}
+
+/**
+ * direction cons to string
+ * @param {Const} direction
+ * @returns {String}
+ */
+function directionStr(direction) {
+ if (direction == DIRECTION_DOWN) {
+ return 'down';
+ } else if (direction == DIRECTION_UP) {
+ return 'up';
+ } else if (direction == DIRECTION_LEFT) {
+ return 'left';
+ } else if (direction == DIRECTION_RIGHT) {
+ return 'right';
+ }
+ return '';
+}
+
+/**
+ * get a recognizer by name if it is bound to a manager
+ * @param {Recognizer|String} otherRecognizer
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer}
+ */
+function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
+ var manager = recognizer.manager;
+ if (manager) {
+ return manager.get(otherRecognizer);
+ }
+ return otherRecognizer;
+}
+
+/**
+ * This recognizer is just used as a base for the simple attribute recognizers.
+ * @constructor
+ * @extends Recognizer
+ */
+function AttrRecognizer() {
+ Recognizer.apply(this, arguments);
+}
+
+inherit(AttrRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof AttrRecognizer
+ */
+ defaults: {
+ /**
+ * @type {Number}
+ * @default 1
+ */
+ pointers: 1
+ },
+
+ /**
+ * Used to check if it the recognizer receives valid input, like input.distance > 10.
+ * @memberof AttrRecognizer
+ * @param {Object} input
+ * @returns {Boolean} recognized
+ */
+ attrTest: function(input) {
+ var optionPointers = this.options.pointers;
+ return optionPointers === 0 || input.pointers.length === optionPointers;
+ },
+
+ /**
+ * Process the input and return the state for the recognizer
+ * @memberof AttrRecognizer
+ * @param {Object} input
+ * @returns {*} State
+ */
+ process: function(input) {
+ var state = this.state;
+ var eventType = input.eventType;
+
+ var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
+ var isValid = this.attrTest(input);
+
+ // on cancel input and we've recognized before, return STATE_CANCELLED
+ if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
+ return state | STATE_CANCELLED;
+ } else if (isRecognized || isValid) {
+ if (eventType & INPUT_END) {
+ return state | STATE_ENDED;
+ } else if (!(state & STATE_BEGAN)) {
+ return STATE_BEGAN;
+ }
+ return state | STATE_CHANGED;
+ }
+ return STATE_FAILED;
+ }
+});
+
+/**
+ * Pan
+ * Recognized when the pointer is down and moved in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PanRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+
+ this.pX = null;
+ this.pY = null;
+}
+
+inherit(PanRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof PanRecognizer
+ */
+ defaults: {
+ event: 'pan',
+ threshold: 10,
+ pointers: 1,
+ direction: DIRECTION_ALL
+ },
+
+ getTouchAction: function() {
+ var direction = this.options.direction;
+ var actions = [];
+ if (direction & DIRECTION_HORIZONTAL) {
+ actions.push(TOUCH_ACTION_PAN_Y);
+ }
+ if (direction & DIRECTION_VERTICAL) {
+ actions.push(TOUCH_ACTION_PAN_X);
+ }
+ return actions;
+ },
+
+ directionTest: function(input) {
+ var options = this.options;
+ var hasMoved = true;
+ var distance = input.distance;
+ var direction = input.direction;
+ var x = input.deltaX;
+ var y = input.deltaY;
+
+ // lock to axis?
+ if (!(direction & options.direction)) {
+ if (options.direction & DIRECTION_HORIZONTAL) {
+ direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
+ hasMoved = x != this.pX;
+ distance = Math.abs(input.deltaX);
+ } else {
+ direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
+ hasMoved = y != this.pY;
+ distance = Math.abs(input.deltaY);
+ }
+ }
+ input.direction = direction;
+ return hasMoved && distance > options.threshold && direction & options.direction;
+ },
+
+ attrTest: function(input) {
+ return AttrRecognizer.prototype.attrTest.call(this, input) &&
+ (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
+ },
+
+ emit: function(input) {
+
+ this.pX = input.deltaX;
+ this.pY = input.deltaY;
+
+ var direction = directionStr(input.direction);
+
+ if (direction) {
+ input.additionalEvent = this.options.event + direction;
+ }
+ this._super.emit.call(this, input);
+ }
+});
+
+/**
+ * Pinch
+ * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PinchRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(PinchRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof PinchRecognizer
+ */
+ defaults: {
+ event: 'pinch',
+ threshold: 0,
+ pointers: 2
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_NONE];
+ },
+
+ attrTest: function(input) {
+ return this._super.attrTest.call(this, input) &&
+ (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
+ },
+
+ emit: function(input) {
+ if (input.scale !== 1) {
+ var inOut = input.scale < 1 ? 'in' : 'out';
+ input.additionalEvent = this.options.event + inOut;
+ }
+ this._super.emit.call(this, input);
+ }
+});
+
+/**
+ * Press
+ * Recognized when the pointer is down for x ms without any movement.
+ * @constructor
+ * @extends Recognizer
+ */
+function PressRecognizer() {
+ Recognizer.apply(this, arguments);
+
+ this._timer = null;
+ this._input = null;
+}
+
+inherit(PressRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof PressRecognizer
+ */
+ defaults: {
+ event: 'press',
+ pointers: 1,
+ time: 251, // minimal time of the pointer to be pressed
+ threshold: 9 // a minimal movement is ok, but keep it low
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_AUTO];
+ },
+
+ process: function(input) {
+ var options = this.options;
+ var validPointers = input.pointers.length === options.pointers;
+ var validMovement = input.distance < options.threshold;
+ var validTime = input.deltaTime > options.time;
+
+ this._input = input;
+
+ // we only allow little movement
+ // and we've reached an end event, so a tap is possible
+ if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
+ this.reset();
+ } else if (input.eventType & INPUT_START) {
+ this.reset();
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_RECOGNIZED;
+ this.tryEmit();
+ }, options.time, this);
+ } else if (input.eventType & INPUT_END) {
+ return STATE_RECOGNIZED;
+ }
+ return STATE_FAILED;
+ },
+
+ reset: function() {
+ clearTimeout(this._timer);
+ },
+
+ emit: function(input) {
+ if (this.state !== STATE_RECOGNIZED) {
+ return;
+ }
+
+ if (input && (input.eventType & INPUT_END)) {
+ this.manager.emit(this.options.event + 'up', input);
+ } else {
+ this._input.timeStamp = now();
+ this.manager.emit(this.options.event, this._input);
+ }
+ }
+});
+
+/**
+ * Rotate
+ * Recognized when two or more pointer are moving in a circular motion.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function RotateRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(RotateRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof RotateRecognizer
+ */
+ defaults: {
+ event: 'rotate',
+ threshold: 0,
+ pointers: 2
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_NONE];
+ },
+
+ attrTest: function(input) {
+ return this._super.attrTest.call(this, input) &&
+ (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
+ }
+});
+
+/**
+ * Swipe
+ * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function SwipeRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(SwipeRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof SwipeRecognizer
+ */
+ defaults: {
+ event: 'swipe',
+ threshold: 10,
+ velocity: 0.3,
+ direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
+ pointers: 1
+ },
+
+ getTouchAction: function() {
+ return PanRecognizer.prototype.getTouchAction.call(this);
+ },
+
+ attrTest: function(input) {
+ var direction = this.options.direction;
+ var velocity;
+
+ if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
+ velocity = input.overallVelocity;
+ } else if (direction & DIRECTION_HORIZONTAL) {
+ velocity = input.overallVelocityX;
+ } else if (direction & DIRECTION_VERTICAL) {
+ velocity = input.overallVelocityY;
+ }
+
+ return this._super.attrTest.call(this, input) &&
+ direction & input.offsetDirection &&
+ input.distance > this.options.threshold &&
+ input.maxPointers == this.options.pointers &&
+ abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
+ },
+
+ emit: function(input) {
+ var direction = directionStr(input.offsetDirection);
+ if (direction) {
+ this.manager.emit(this.options.event + direction, input);
+ }
+
+ this.manager.emit(this.options.event, input);
+ }
+});
+
+/**
+ * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
+ * between the given interval and position. The delay option can be used to recognize multi-taps without firing
+ * a single tap.
+ *
+ * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
+ * multi-taps being recognized.
+ * @constructor
+ * @extends Recognizer
+ */
+function TapRecognizer() {
+ Recognizer.apply(this, arguments);
+
+ // previous time and center,
+ // used for tap counting
+ this.pTime = false;
+ this.pCenter = false;
+
+ this._timer = null;
+ this._input = null;
+ this.count = 0;
+}
+
+inherit(TapRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof PinchRecognizer
+ */
+ defaults: {
+ event: 'tap',
+ pointers: 1,
+ taps: 1,
+ interval: 300, // max time between the multi-tap taps
+ time: 250, // max time of the pointer to be down (like finger on the screen)
+ threshold: 9, // a minimal movement is ok, but keep it low
+ posThreshold: 10 // a multi-tap can be a bit off the initial position
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_MANIPULATION];
+ },
+
+ process: function(input) {
+ var options = this.options;
+
+ var validPointers = input.pointers.length === options.pointers;
+ var validMovement = input.distance < options.threshold;
+ var validTouchTime = input.deltaTime < options.time;
+
+ this.reset();
+
+ if ((input.eventType & INPUT_START) && (this.count === 0)) {
+ return this.failTimeout();
+ }
+
+ // we only allow little movement
+ // and we've reached an end event, so a tap is possible
+ if (validMovement && validTouchTime && validPointers) {
+ if (input.eventType != INPUT_END) {
+ return this.failTimeout();
+ }
+
+ var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
+ var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
+
+ this.pTime = input.timeStamp;
+ this.pCenter = input.center;
+
+ if (!validMultiTap || !validInterval) {
+ this.count = 1;
+ } else {
+ this.count += 1;
+ }
+
+ this._input = input;
+
+ // if tap count matches we have recognized it,
+ // else it has began recognizing...
+ var tapCount = this.count % options.taps;
+ if (tapCount === 0) {
+ // no failing requirements, immediately trigger the tap event
+ // or wait as long as the multitap interval to trigger
+ if (!this.hasRequireFailures()) {
+ return STATE_RECOGNIZED;
+ } else {
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_RECOGNIZED;
+ this.tryEmit();
+ }, options.interval, this);
+ return STATE_BEGAN;
+ }
+ }
+ }
+ return STATE_FAILED;
+ },
+
+ failTimeout: function() {
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_FAILED;
+ }, this.options.interval, this);
+ return STATE_FAILED;
+ },
+
+ reset: function() {
+ clearTimeout(this._timer);
+ },
+
+ emit: function() {
+ if (this.state == STATE_RECOGNIZED) {
+ this._input.tapCount = this.count;
+ this.manager.emit(this.options.event, this._input);
+ }
+ }
+});
+
+/**
+ * Simple way to create a manager with a default set of recognizers.
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Hammer(element, options) {
+ options = options || {};
+ options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
+ return new Manager(element, options);
+}
+
+/**
+ * @const {string}
+ */
+Hammer.VERSION = '2.0.6';
+
+/**
+ * default settings
+ * @namespace
+ */
+Hammer.defaults = {
+ /**
+ * set if DOM events are being triggered.
+ * But this is slower and unused by simple implementations, so disabled by default.
+ * @type {Boolean}
+ * @default false
+ */
+ domEvents: false,
+
+ /**
+ * The value for the touchAction property/fallback.
+ * When set to `compute` it will magically set the correct value based on the added recognizers.
+ * @type {String}
+ * @default compute
+ */
+ touchAction: TOUCH_ACTION_COMPUTE,
+
+ /**
+ * @type {Boolean}
+ * @default true
+ */
+ enable: true,
+
+ /**
+ * EXPERIMENTAL FEATURE -- can be removed/changed
+ * Change the parent input target element.
+ * If Null, then it is being set the to main element.
+ * @type {Null|EventTarget}
+ * @default null
+ */
+ inputTarget: null,
+
+ /**
+ * force an input class
+ * @type {Null|Function}
+ * @default null
+ */
+ inputClass: null,
+
+ /**
+ * Default recognizer setup when calling `Hammer()`
+ * When creating a new Manager these will be skipped.
+ * @type {Array}
+ */
+ preset: [
+ // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
+ [RotateRecognizer, {enable: false}],
+ [PinchRecognizer, {enable: false}, ['rotate']],
+ [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
+ [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
+ [TapRecognizer],
+ [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
+ [PressRecognizer]
+ ],
+
+ /**
+ * Some CSS properties can be used to improve the working of Hammer.
+ * Add them to this method and they will be set when creating a new Manager.
+ * @namespace
+ */
+ cssProps: {
+ /**
+ * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
+ * @type {String}
+ * @default 'none'
+ */
+ userSelect: 'none',
+
+ /**
+ * Disable the Windows Phone grippers when pressing an element.
+ * @type {String}
+ * @default 'none'
+ */
+ touchSelect: 'none',
+
+ /**
+ * Disables the default callout shown when you touch and hold a touch target.
+ * On iOS, when you touch and hold a touch target such as a link, Safari displays
+ * a callout containing information about the link. This property allows you to disable that callout.
+ * @type {String}
+ * @default 'none'
+ */
+ touchCallout: 'none',
+
+ /**
+ * Specifies whether zooming is enabled. Used by IE10>
+ * @type {String}
+ * @default 'none'
+ */
+ contentZooming: 'none',
+
+ /**
+ * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
+ * @type {String}
+ * @default 'none'
+ */
+ userDrag: 'none',
+
+ /**
+ * Overrides the highlight color shown when the user taps a link or a JavaScript
+ * clickable element in iOS. This property obeys the alpha value, if specified.
+ * @type {String}
+ * @default 'rgba(0,0,0,0)'
+ */
+ tapHighlightColor: 'rgba(0,0,0,0)'
+ }
+};
+
+var STOP = 1;
+var FORCED_STOP = 2;
+
+/**
+ * Manager
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Manager(element, options) {
+ this.options = assign({}, Hammer.defaults, options || {});
+
+ this.options.inputTarget = this.options.inputTarget || element;
+
+ this.handlers = {};
+ this.session = {};
+ this.recognizers = [];
+
+ this.element = element;
+ this.input = createInputInstance(this);
+ this.touchAction = new TouchAction(this, this.options.touchAction);
+
+ toggleCssProps(this, true);
+
+ each(this.options.recognizers, function(item) {
+ var recognizer = this.add(new (item[0])(item[1]));
+ item[2] && recognizer.recognizeWith(item[2]);
+ item[3] && recognizer.requireFailure(item[3]);
+ }, this);
+}
+
+Manager.prototype = {
+ /**
+ * set options
+ * @param {Object} options
+ * @returns {Manager}
+ */
+ set: function(options) {
+ assign(this.options, options);
+
+ // Options that need a little more setup
+ if (options.touchAction) {
+ this.touchAction.update();
+ }
+ if (options.inputTarget) {
+ // Clean up existing event listeners and reinitialize
+ this.input.destroy();
+ this.input.target = options.inputTarget;
+ this.input.init();
+ }
+ return this;
+ },
+
+ /**
+ * stop recognizing for this session.
+ * This session will be discarded, when a new [input]start event is fired.
+ * When forced, the recognizer cycle is stopped immediately.
+ * @param {Boolean} [force]
+ */
+ stop: function(force) {
+ this.session.stopped = force ? FORCED_STOP : STOP;
+ },
+
+ /**
+ * run the recognizers!
+ * called by the inputHandler function on every movement of the pointers (touches)
+ * it walks through all the recognizers and tries to detect the gesture that is being made
+ * @param {Object} inputData
+ */
+ recognize: function(inputData) {
+ var session = this.session;
+ if (session.stopped) {
+ return;
+ }
+
+ // run the touch-action polyfill
+ this.touchAction.preventDefaults(inputData);
+
+ var recognizer;
+ var recognizers = this.recognizers;
+
+ // this holds the recognizer that is being recognized.
+ // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
+ // if no recognizer is detecting a thing, it is set to `null`
+ var curRecognizer = session.curRecognizer;
+
+ // reset when the last recognizer is recognized
+ // or when we're in a new session
+ if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
+ curRecognizer = session.curRecognizer = null;
+ }
+
+ var i = 0;
+ while (i < recognizers.length) {
+ recognizer = recognizers[i];
+
+ // find out if we are allowed try to recognize the input for this one.
+ // 1. allow if the session is NOT forced stopped (see the .stop() method)
+ // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
+ // that is being recognized.
+ // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
+ // this can be setup with the `recognizeWith()` method on the recognizer.
+ if (session.stopped !== FORCED_STOP && ( // 1
+ !curRecognizer || recognizer == curRecognizer || // 2
+ recognizer.canRecognizeWith(curRecognizer))) { // 3
+ recognizer.recognize(inputData);
+ } else {
+ recognizer.reset();
+ }
+
+ // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
+ // current active recognizer. but only if we don't already have an active recognizer
+ if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
+ curRecognizer = session.curRecognizer = recognizer;
+ }
+ i++;
+ }
+ },
+
+ /**
+ * get a recognizer by its event name.
+ * @param {Recognizer|String} recognizer
+ * @returns {Recognizer|Null}
+ */
+ get: function(recognizer) {
+ if (recognizer instanceof Recognizer) {
+ return recognizer;
+ }
+
+ var recognizers = this.recognizers;
+ for (var i = 0; i < recognizers.length; i++) {
+ if (recognizers[i].options.event == recognizer) {
+ return recognizers[i];
+ }
+ }
+ return null;
+ },
+
+ /**
+ * add a recognizer to the manager
+ * existing recognizers with the same event name will be removed
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer|Manager}
+ */
+ add: function(recognizer) {
+ if (invokeArrayArg(recognizer, 'add', this)) {
+ return this;
+ }
+
+ // remove existing
+ var existing = this.get(recognizer.options.event);
+ if (existing) {
+ this.remove(existing);
+ }
+
+ this.recognizers.push(recognizer);
+ recognizer.manager = this;
+
+ this.touchAction.update();
+ return recognizer;
+ },
+
+ /**
+ * remove a recognizer by name or instance
+ * @param {Recognizer|String} recognizer
+ * @returns {Manager}
+ */
+ remove: function(recognizer) {
+ if (invokeArrayArg(recognizer, 'remove', this)) {
+ return this;
+ }
+
+ recognizer = this.get(recognizer);
+
+ // let's make sure this recognizer exists
+ if (recognizer) {
+ var recognizers = this.recognizers;
+ var index = inArray(recognizers, recognizer);
+
+ if (index !== -1) {
+ recognizers.splice(index, 1);
+ this.touchAction.update();
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * bind event
+ * @param {String} events
+ * @param {Function} handler
+ * @returns {EventEmitter} this
+ */
+ on: function(events, handler) {
+ var handlers = this.handlers;
+ each(splitStr(events), function(event) {
+ handlers[event] = handlers[event] || [];
+ handlers[event].push(handler);
+ });
+ return this;
+ },
+
+ /**
+ * unbind event, leave emit blank to remove all handlers
+ * @param {String} events
+ * @param {Function} [handler]
+ * @returns {EventEmitter} this
+ */
+ off: function(events, handler) {
+ var handlers = this.handlers;
+ each(splitStr(events), function(event) {
+ if (!handler) {
+ delete handlers[event];
+ } else {
+ handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
+ }
+ });
+ return this;
+ },
+
+ /**
+ * emit event to the listeners
+ * @param {String} event
+ * @param {Object} data
+ */
+ emit: function(event, data) {
+ // we also want to trigger dom events
+ if (this.options.domEvents) {
+ triggerDomEvent(event, data);
+ }
+
+ // no handlers, so skip it all
+ var handlers = this.handlers[event] && this.handlers[event].slice();
+ if (!handlers || !handlers.length) {
+ return;
+ }
+
+ data.type = event;
+ data.preventDefault = function() {
+ data.srcEvent.preventDefault();
+ };
+
+ var i = 0;
+ while (i < handlers.length) {
+ handlers[i](data);
+ i++;
+ }
+ },
+
+ /**
+ * destroy the manager and unbinds all events
+ * it doesn't unbind dom events, that is the user own responsibility
+ */
+ destroy: function() {
+ this.element && toggleCssProps(this, false);
+
+ this.handlers = {};
+ this.session = {};
+ this.input.destroy();
+ this.element = null;
+ }
+};
+
+/**
+ * add/remove the css properties as defined in manager.options.cssProps
+ * @param {Manager} manager
+ * @param {Boolean} add
+ */
+function toggleCssProps(manager, add) {
+ var element = manager.element;
+ if (!element.style) {
+ return;
+ }
+ each(manager.options.cssProps, function(value, name) {
+ element.style[prefixed(element.style, name)] = add ? value : '';
+ });
+}
+
+/**
+ * trigger dom event
+ * @param {String} event
+ * @param {Object} data
+ */
+function triggerDomEvent(event, data) {
+ var gestureEvent = document.createEvent('Event');
+ gestureEvent.initEvent(event, true, true);
+ gestureEvent.gesture = data;
+ data.target.dispatchEvent(gestureEvent);
+}
+
+assign(Hammer, {
+ INPUT_START: INPUT_START,
+ INPUT_MOVE: INPUT_MOVE,
+ INPUT_END: INPUT_END,
+ INPUT_CANCEL: INPUT_CANCEL,
+
+ STATE_POSSIBLE: STATE_POSSIBLE,
+ STATE_BEGAN: STATE_BEGAN,
+ STATE_CHANGED: STATE_CHANGED,
+ STATE_ENDED: STATE_ENDED,
+ STATE_RECOGNIZED: STATE_RECOGNIZED,
+ STATE_CANCELLED: STATE_CANCELLED,
+ STATE_FAILED: STATE_FAILED,
+
+ DIRECTION_NONE: DIRECTION_NONE,
+ DIRECTION_LEFT: DIRECTION_LEFT,
+ DIRECTION_RIGHT: DIRECTION_RIGHT,
+ DIRECTION_UP: DIRECTION_UP,
+ DIRECTION_DOWN: DIRECTION_DOWN,
+ DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
+ DIRECTION_VERTICAL: DIRECTION_VERTICAL,
+ DIRECTION_ALL: DIRECTION_ALL,
+
+ Manager: Manager,
+ Input: Input,
+ TouchAction: TouchAction,
+
+ TouchInput: TouchInput,
+ MouseInput: MouseInput,
+ PointerEventInput: PointerEventInput,
+ TouchMouseInput: TouchMouseInput,
+ SingleTouchInput: SingleTouchInput,
+
+ Recognizer: Recognizer,
+ AttrRecognizer: AttrRecognizer,
+ Tap: TapRecognizer,
+ Pan: PanRecognizer,
+ Swipe: SwipeRecognizer,
+ Pinch: PinchRecognizer,
+ Rotate: RotateRecognizer,
+ Press: PressRecognizer,
+
+ on: addEventListeners,
+ off: removeEventListeners,
+ each: each,
+ merge: merge,
+ extend: extend,
+ assign: assign,
+ inherit: inherit,
+ bindFn: bindFn,
+ prefixed: prefixed
+});
+
+// this prevents errors when Hammer is loaded in the presence of an AMD
+// style loader but by script tag, not by the loader.
+var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
+freeGlobal.Hammer = Hammer;
+
+if (typeof define === 'function' && define.amd) {
+ define(function() {
+ return Hammer;
+ });
+} else if (typeof module != 'undefined' && module.exports) {
+ module.exports = Hammer;
+} else {
+ window[exportName] = Hammer;
+}
+
+})(window, document, 'Hammer');
diff --git a/afb-client/bower_components/hammerjs/hammer.min.js b/afb-client/bower_components/hammerjs/hammer.min.js
new file mode 100644
index 0000000..d5def77
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/hammer.min.js
@@ -0,0 +1,7 @@
+/*! Hammer.JS - v2.0.6 - 2015-12-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2015 Jorik Tangelder;
+ * Licensed under the license */
+!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e<a.length;)b.call(c,a[e],e,a),e++;else for(e in a)a.hasOwnProperty(e)&&b.call(c,a[e],e,a)}function h(b,c,d){var e="DEPRECATED METHOD: "+c+"\n"+d+" AT \n";return function(){var c=new Error("get-stack-trace"),d=c&&c.stack?c.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&hb(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==kb?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.length;){if(c&&a[d][c]==b||!c&&a[d]===b)return d;d++}return-1}function s(a){return Array.prototype.slice.call(a,0)}function t(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f];r(e,g)<0&&d.push(a[f]),e[f]=g,f++}return c&&(d=b?d.sort(function(a,c){return a[b]>c[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g<ib.length;){if(c=ib[g],e=c?c+f:b,e in a)return e;g++}return d}function v(){return qb++}function w(b){var c=b.ownerDocument||b;return c.defaultView||c.parentWindow||a}function x(a,b){var c=this;this.manager=a,this.callback=b,this.element=a.element,this.target=a.options.inputTarget,this.domHandler=function(b){k(a.options.enable,[a])&&c.handler(b)},this.init()}function y(a){var b,c=a.options.inputClass;return new(b=c?c:tb?M:ub?P:sb?R:L)(a,z)}function z(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=b&Ab&&d-e===0,g=b&(Cb|Db)&&d-e===0;c.isFirst=!!f,c.isFinal=!!g,f&&(a.session={}),c.eventType=b,A(a,c),a.emit("hammer.input",c),a.recognize(c),a.session.prevInput=c}function A(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(c.firstInput=D(b)),e>1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=nb(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=mb(j.x)>mb(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===Ab||f.eventType===Cb)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Db&&(i>zb||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=mb(l.x)>mb(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:lb(a.pointers[c].clientX),clientY:lb(a.pointers[c].clientY)},c++;return{timeStamp:nb(),pointers:b,center:E(b),deltaX:a.deltaX,deltaY:a.deltaY}}function E(a){var b=a.length;if(1===b)return{x:lb(a[0].clientX),y:lb(a[0].clientY)};for(var c=0,d=0,e=0;b>e;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:lb(c/b),y:lb(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Eb:mb(a)>=mb(b)?0>a?Fb:Gb:0>b?Hb:Ib}function H(a,b,c){c||(c=Mb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Mb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Nb)+I(a[1],a[0],Nb)}function K(a,b){return H(b[0],b[1],Nb)/H(a[0],a[1],Nb)}function L(){this.evEl=Pb,this.evWin=Qb,this.allow=!0,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Tb,this.evWin=Ub,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=Wb,this.evWin=Xb,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Cb|Db)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=Zb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ab|Bb)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ab)for(e=0;e<f.length;)d[f[e].identifier]=!0,e++;for(e=0;e<g.length;)d[g[e].identifier]&&h.push(g[e]),b&(Cb|Db)&&delete d[g[e].identifier],e++;return h.length?[t(f.concat(h),"identifier",!0),h]:void 0}function R(){x.apply(this,arguments);var a=j(this.handler,this);this.touch=new P(this.manager,a),this.mouse=new L(this.manager,a)}function S(a,b){this.manager=a,this.set(b)}function T(a){if(p(a,dc))return dc;var b=p(a,ec),c=p(a,fc);return b&&c?dc:b||c?b?ec:fc:p(a,cc)?cc:bc}function U(a){this.options=hb({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=gc,this.simultaneous={},this.requireFail=[]}function V(a){return a&lc?"cancel":a&jc?"end":a&ic?"move":a&hc?"start":""}function W(a){return a==Ib?"down":a==Hb?"up":a==Fb?"left":a==Gb?"right":""}function X(a,b){var c=b.manager;return c?c.get(a):a}function Y(){U.apply(this,arguments)}function Z(){Y.apply(this,arguments),this.pX=null,this.pY=null}function $(){Y.apply(this,arguments)}function _(){U.apply(this,arguments),this._timer=null,this._input=null}function ab(){Y.apply(this,arguments)}function bb(){Y.apply(this,arguments)}function cb(){U.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function db(a,b){return b=b||{},b.recognizers=l(b.recognizers,db.defaults.preset),new eb(a,b)}function eb(a,b){this.options=hb({},db.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.element=a,this.input=y(this),this.touchAction=new S(this,this.options.touchAction),fb(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function fb(a,b){var c=a.element;c.style&&g(a.options.cssProps,function(a,d){c.style[u(c.style,d)]=b?a:""})}function gb(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var hb,ib=["","webkit","Moz","MS","ms","o"],jb=b.createElement("div"),kb="function",lb=Math.round,mb=Math.abs,nb=Date.now;hb="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;c<arguments.length;c++){var e=arguments[c];if(e!==d&&null!==e)for(var f in e)e.hasOwnProperty(f)&&(b[f]=e[f])}return b}:Object.assign;var ob=h(function(a,b,c){for(var e=Object.keys(b),f=0;f<e.length;)(!c||c&&a[e[f]]===d)&&(a[e[f]]=b[e[f]]),f++;return a},"extend","Use `assign`."),pb=h(function(a,b){return ob(a,b,!0)},"merge","Use `assign`."),qb=1,rb=/mobile|tablet|ip(ad|hone|od)|android/i,sb="ontouchstart"in a,tb=u(a,"PointerEvent")!==d,ub=sb&&rb.test(navigator.userAgent),vb="touch",wb="pen",xb="mouse",yb="kinect",zb=25,Ab=1,Bb=2,Cb=4,Db=8,Eb=1,Fb=2,Gb=4,Hb=8,Ib=16,Jb=Fb|Gb,Kb=Hb|Ib,Lb=Jb|Kb,Mb=["x","y"],Nb=["clientX","clientY"];x.prototype={handler:function(){},init:function(){this.evEl&&m(this.element,this.evEl,this.domHandler),this.evTarget&&m(this.target,this.evTarget,this.domHandler),this.evWin&&m(w(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&n(this.element,this.evEl,this.domHandler),this.evTarget&&n(this.target,this.evTarget,this.domHandler),this.evWin&&n(w(this.element),this.evWin,this.domHandler)}};var Ob={mousedown:Ab,mousemove:Bb,mouseup:Cb},Pb="mousedown",Qb="mousemove mouseup";i(L,x,{handler:function(a){var b=Ob[a.type];b&Ab&&0===a.button&&(this.pressed=!0),b&Bb&&1!==a.which&&(b=Cb),this.pressed&&this.allow&&(b&Cb&&(this.pressed=!1),this.callback(this.manager,b,{pointers:[a],changedPointers:[a],pointerType:xb,srcEvent:a}))}});var Rb={pointerdown:Ab,pointermove:Bb,pointerup:Cb,pointercancel:Db,pointerout:Db},Sb={2:vb,3:wb,4:xb,5:yb},Tb="pointerdown",Ub="pointermove pointerup pointercancel";a.MSPointerEvent&&!a.PointerEvent&&(Tb="MSPointerDown",Ub="MSPointerMove MSPointerUp MSPointerCancel"),i(M,x,{handler:function(a){var b=this.store,c=!1,d=a.type.toLowerCase().replace("ms",""),e=Rb[d],f=Sb[a.pointerType]||a.pointerType,g=f==vb,h=r(b,a.pointerId,"pointerId");e&Ab&&(0===a.button||g)?0>h&&(b.push(a),h=b.length-1):e&(Cb|Db)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Vb={touchstart:Ab,touchmove:Bb,touchend:Cb,touchcancel:Db},Wb="touchstart",Xb="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Vb[a.type];if(b===Ab&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Cb|Db)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:vb,srcEvent:a})}}});var Yb={touchstart:Ab,touchmove:Bb,touchend:Cb,touchcancel:Db},Zb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=Yb[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:vb,srcEvent:a})}}),i(R,x,{handler:function(a,b,c){var d=c.pointerType==vb,e=c.pointerType==xb;if(d)this.mouse.allow=!1;else if(e&&!this.mouse.allow)return;b&(Cb|Db)&&(this.mouse.allow=!0),this.callback(a,b,c)},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var $b=u(jb.style,"touchAction"),_b=$b!==d,ac="compute",bc="auto",cc="manipulation",dc="none",ec="pan-x",fc="pan-y";S.prototype={set:function(a){a==ac&&(a=this.compute()),_b&&this.manager.element.style&&(this.manager.element.style[$b]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),T(a.join(" "))},preventDefaults:function(a){if(!_b){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,dc),f=p(d,fc),g=p(d,ec);if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}if(!g||!f)return e||f&&c&Jb||g&&c&Kb?this.preventSrc(b):void 0}},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var gc=1,hc=2,ic=4,jc=8,kc=jc,lc=16,mc=32;U.prototype={defaults:{},set:function(a){return hb(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=X(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=X(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=X(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=X(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;jc>d&&b(c.options.event+V(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=jc&&b(c.options.event+V(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=mc)},canEmit:function(){for(var a=0;a<this.requireFail.length;){if(!(this.requireFail[a].state&(mc|gc)))return!1;a++}return!0},recognize:function(a){var b=hb({},a);return k(this.options.enable,[this,b])?(this.state&(kc|lc|mc)&&(this.state=gc),this.state=this.process(b),void(this.state&(hc|ic|jc|lc)&&this.tryEmit(b))):(this.reset(),void(this.state=mc))},process:function(){},getTouchAction:function(){},reset:function(){}},i(Y,U,{defaults:{pointers:1},attrTest:function(a){var b=this.options.pointers;return 0===b||a.pointers.length===b},process:function(a){var b=this.state,c=a.eventType,d=b&(hc|ic),e=this.attrTest(a);return d&&(c&Db||!e)?b|lc:d||e?c&Cb?b|jc:b&hc?b|ic:hc:mc}}),i(Z,Y,{defaults:{event:"pan",threshold:10,pointers:1,direction:Lb},getTouchAction:function(){var a=this.options.direction,b=[];return a&Jb&&b.push(fc),a&Kb&&b.push(ec),b},directionTest:function(a){var b=this.options,c=!0,d=a.distance,e=a.direction,f=a.deltaX,g=a.deltaY;return e&b.direction||(b.direction&Jb?(e=0===f?Eb:0>f?Fb:Gb,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Eb:0>g?Hb:Ib,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return Y.prototype.attrTest.call(this,a)&&(this.state&hc||!(this.state&hc)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=W(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i($,Y,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[dc]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&hc)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(_,U,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[bc]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,f=a.deltaTime>b.time;if(this._input=a,!d||!c||a.eventType&(Cb|Db)&&!f)this.reset();else if(a.eventType&Ab)this.reset(),this._timer=e(function(){this.state=kc,this.tryEmit()},b.time,this);else if(a.eventType&Cb)return kc;return mc},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===kc&&(a&&a.eventType&Cb?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=nb(),this.manager.emit(this.options.event,this._input)))}}),i(ab,Y,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[dc]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&hc)}}),i(bb,Y,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Jb|Kb,pointers:1},getTouchAction:function(){return Z.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Jb|Kb)?b=a.overallVelocity:c&Jb?b=a.overallVelocityX:c&Kb&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&mb(b)>this.options.velocity&&a.eventType&Cb},emit:function(a){var b=W(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(cb,U,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[cc]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,f=a.deltaTime<b.time;if(this.reset(),a.eventType&Ab&&0===this.count)return this.failTimeout();if(d&&f&&c){if(a.eventType!=Cb)return this.failTimeout();var g=this.pTime?a.timeStamp-this.pTime<b.interval:!0,h=!this.pCenter||H(this.pCenter,a.center)<b.posThreshold;this.pTime=a.timeStamp,this.pCenter=a.center,h&&g?this.count+=1:this.count=1,this._input=a;var i=this.count%b.taps;if(0===i)return this.hasRequireFailures()?(this._timer=e(function(){this.state=kc,this.tryEmit()},b.interval,this),hc):kc}return mc},failTimeout:function(){return this._timer=e(function(){this.state=mc},this.options.interval,this),mc},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==kc&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),db.VERSION="2.0.6",db.defaults={domEvents:!1,touchAction:ac,enable:!0,inputTarget:null,inputClass:null,preset:[[ab,{enable:!1}],[$,{enable:!1},["rotate"]],[bb,{direction:Jb}],[Z,{direction:Jb},["swipe"]],[cb],[cb,{event:"doubletap",taps:2},["tap"]],[_]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var nc=1,oc=2;eb.prototype={set:function(a){return hb(this.options,a),a.touchAction&&this.touchAction.update(),a.inputTarget&&(this.input.destroy(),this.input.target=a.inputTarget,this.input.init()),this},stop:function(a){this.session.stopped=a?oc:nc},recognize:function(a){var b=this.session;if(!b.stopped){this.touchAction.preventDefaults(a);var c,d=this.recognizers,e=b.curRecognizer;(!e||e&&e.state&kc)&&(e=b.curRecognizer=null);for(var f=0;f<d.length;)c=d[f],b.stopped===oc||e&&c!=e&&!c.canRecognizeWith(e)?c.reset():c.recognize(a),!e&&c.state&(hc|ic|jc)&&(e=b.curRecognizer=c),f++}},get:function(a){if(a instanceof U)return a;for(var b=this.recognizers,c=0;c<b.length;c++)if(b[c].options.event==a)return b[c];return null},add:function(a){if(f(a,"add",this))return this;var b=this.get(a.options.event);return b&&this.remove(b),this.recognizers.push(a),a.manager=this,this.touchAction.update(),a},remove:function(a){if(f(a,"remove",this))return this;if(a=this.get(a)){var b=this.recognizers,c=r(b,a);-1!==c&&(b.splice(c,1),this.touchAction.update())}return this},on:function(a,b){var c=this.handlers;return g(q(a),function(a){c[a]=c[a]||[],c[a].push(b)}),this},off:function(a,b){var c=this.handlers;return g(q(a),function(a){b?c[a]&&c[a].splice(r(c[a],b),1):delete c[a]}),this},emit:function(a,b){this.options.domEvents&&gb(a,b);var c=this.handlers[a]&&this.handlers[a].slice();if(c&&c.length){b.type=a,b.preventDefault=function(){b.srcEvent.preventDefault()};for(var d=0;d<c.length;)c[d](b),d++}},destroy:function(){this.element&&fb(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},hb(db,{INPUT_START:Ab,INPUT_MOVE:Bb,INPUT_END:Cb,INPUT_CANCEL:Db,STATE_POSSIBLE:gc,STATE_BEGAN:hc,STATE_CHANGED:ic,STATE_ENDED:jc,STATE_RECOGNIZED:kc,STATE_CANCELLED:lc,STATE_FAILED:mc,DIRECTION_NONE:Eb,DIRECTION_LEFT:Fb,DIRECTION_RIGHT:Gb,DIRECTION_UP:Hb,DIRECTION_DOWN:Ib,DIRECTION_HORIZONTAL:Jb,DIRECTION_VERTICAL:Kb,DIRECTION_ALL:Lb,Manager:eb,Input:x,TouchAction:S,TouchInput:P,MouseInput:L,PointerEventInput:M,TouchMouseInput:R,SingleTouchInput:N,Recognizer:U,AttrRecognizer:Y,Tap:cb,Pan:Z,Swipe:bb,Pinch:$,Rotate:ab,Press:_,on:m,off:n,each:g,merge:pb,extend:ob,assign:hb,inherit:i,bindFn:j,prefixed:u});var pc="undefined"!=typeof a?a:"undefined"!=typeof self?self:{};pc.Hammer=db,"function"==typeof define&&define.amd?define(function(){return db}):"undefined"!=typeof module&&module.exports?module.exports=db:a[c]=db}(window,document,"Hammer");
+//# sourceMappingURL=hammer.min.map \ No newline at end of file
diff --git a/afb-client/bower_components/hammerjs/hammer.min.map b/afb-client/bower_components/hammerjs/hammer.min.map
new file mode 100644
index 0000000..91d29e5
--- /dev/null
+++ b/afb-client/bower_components/hammerjs/hammer.min.map
@@ -0,0 +1 @@
+{"version":3,"file":"hammer.min.js","sources":["hammer.js"],"names":["window","document","exportName","undefined","setTimeoutContext","fn","timeout","context","setTimeout","bindFn","invokeArrayArg","arg","Array","isArray","each","obj","iterator","i","forEach","length","call","hasOwnProperty","deprecate","method","name","message","deprecationMessage","e","Error","stack","replace","log","console","warn","apply","this","arguments","inherit","child","base","properties","childP","baseP","prototype","Object","create","constructor","_super","assign","boolOrFn","val","args","TYPE_FUNCTION","ifUndefined","val1","val2","addEventListeners","target","types","handler","splitStr","type","addEventListener","removeEventListeners","removeEventListener","hasParent","node","parent","parentNode","inStr","str","find","indexOf","trim","split","inArray","src","findByKey","toArray","slice","uniqueArray","key","sort","results","values","push","a","b","prefixed","property","prefix","prop","camelProp","toUpperCase","VENDOR_PREFIXES","uniqueId","_uniqueId","getWindowForElement","element","doc","ownerDocument","defaultView","parentWindow","Input","manager","callback","self","options","inputTarget","domHandler","ev","enable","init","createInputInstance","Type","inputClass","SUPPORT_POINTER_EVENTS","PointerEventInput","SUPPORT_ONLY_TOUCH","TouchInput","SUPPORT_TOUCH","TouchMouseInput","MouseInput","inputHandler","eventType","input","pointersLen","pointers","changedPointersLen","changedPointers","isFirst","INPUT_START","isFinal","INPUT_END","INPUT_CANCEL","session","computeInputData","emit","recognize","prevInput","pointersLength","firstInput","simpleCloneInputData","firstMultiple","offsetCenter","center","getCenter","timeStamp","now","deltaTime","angle","getAngle","distance","getDistance","computeDeltaXY","offsetDirection","getDirection","deltaX","deltaY","overallVelocity","getVelocity","overallVelocityX","x","overallVelocityY","y","abs","scale","getScale","rotation","getRotation","maxPointers","computeIntervalInputData","srcEvent","offset","offsetDelta","prevDelta","velocity","velocityX","velocityY","direction","last","lastInterval","COMPUTE_INTERVAL","v","clientX","round","clientY","DIRECTION_NONE","DIRECTION_LEFT","DIRECTION_RIGHT","DIRECTION_UP","DIRECTION_DOWN","p1","p2","props","PROPS_XY","Math","sqrt","atan2","PI","start","end","PROPS_CLIENT_XY","evEl","MOUSE_ELEMENT_EVENTS","evWin","MOUSE_WINDOW_EVENTS","allow","pressed","POINTER_ELEMENT_EVENTS","POINTER_WINDOW_EVENTS","store","pointerEvents","SingleTouchInput","evTarget","SINGLE_TOUCH_TARGET_EVENTS","SINGLE_TOUCH_WINDOW_EVENTS","started","normalizeSingleTouches","all","touches","changed","changedTouches","concat","TOUCH_TARGET_EVENTS","targetIds","getTouches","allTouches","INPUT_MOVE","identifier","targetTouches","changedTargetTouches","filter","touch","mouse","TouchAction","value","set","cleanTouchActions","actions","TOUCH_ACTION_NONE","hasPanX","TOUCH_ACTION_PAN_X","hasPanY","TOUCH_ACTION_PAN_Y","TOUCH_ACTION_MANIPULATION","TOUCH_ACTION_AUTO","Recognizer","defaults","id","state","STATE_POSSIBLE","simultaneous","requireFail","stateStr","STATE_CANCELLED","STATE_ENDED","STATE_CHANGED","STATE_BEGAN","directionStr","getRecognizerByNameIfManager","otherRecognizer","recognizer","get","AttrRecognizer","PanRecognizer","pX","pY","PinchRecognizer","PressRecognizer","_timer","_input","RotateRecognizer","SwipeRecognizer","TapRecognizer","pTime","pCenter","count","Hammer","recognizers","preset","Manager","handlers","touchAction","toggleCssProps","item","add","recognizeWith","requireFailure","style","cssProps","triggerDomEvent","event","data","gestureEvent","createEvent","initEvent","gesture","dispatchEvent","TEST_ELEMENT","createElement","Date","TypeError","output","index","source","nextKey","extend","dest","merge","keys","MOBILE_REGEX","test","navigator","userAgent","INPUT_TYPE_TOUCH","INPUT_TYPE_PEN","INPUT_TYPE_MOUSE","INPUT_TYPE_KINECT","DIRECTION_HORIZONTAL","DIRECTION_VERTICAL","DIRECTION_ALL","destroy","MOUSE_INPUT_MAP","mousedown","mousemove","mouseup","button","which","pointerType","POINTER_INPUT_MAP","pointerdown","pointermove","pointerup","pointercancel","pointerout","IE10_POINTER_TYPE_ENUM",2,3,4,5,"MSPointerEvent","PointerEvent","removePointer","eventTypeNormalized","toLowerCase","isTouch","storeIndex","pointerId","splice","SINGLE_TOUCH_INPUT_MAP","touchstart","touchmove","touchend","touchcancel","TOUCH_INPUT_MAP","inputEvent","inputData","isMouse","PREFIXED_TOUCH_ACTION","NATIVE_TOUCH_ACTION","TOUCH_ACTION_COMPUTE","compute","update","getTouchAction","join","preventDefaults","prevented","preventDefault","hasNone","isTapPointer","isTapMovement","isTapTouchTime","preventSrc","STATE_RECOGNIZED","STATE_FAILED","dropRecognizeWith","dropRequireFailure","hasRequireFailures","canRecognizeWith","additionalEvent","tryEmit","canEmit","inputDataClone","process","reset","attrTest","optionPointers","isRecognized","isValid","threshold","directionTest","hasMoved","inOut","time","validPointers","validMovement","validTime","clearTimeout","taps","interval","posThreshold","validTouchTime","failTimeout","validInterval","validMultiTap","tapCount","VERSION","domEvents","userSelect","touchSelect","touchCallout","contentZooming","userDrag","tapHighlightColor","STOP","FORCED_STOP","stop","force","stopped","curRecognizer","existing","remove","on","events","off","Tap","Pan","Swipe","Pinch","Rotate","Press","freeGlobal","define","amd","module","exports"],"mappings":"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"} \ No newline at end of file
diff --git a/afb-client/bower_components/jszip/.bower.json b/afb-client/bower_components/jszip/.bower.json
new file mode 100644
index 0000000..01759e5
--- /dev/null
+++ b/afb-client/bower_components/jszip/.bower.json
@@ -0,0 +1,32 @@
+{
+ "name": "jszip",
+ "version": "2.5.0",
+ "homepage": "http://stuartk.com/jszip",
+ "authors": [
+ "Stuart Knightley <stuart@stuartk.com>"
+ ],
+ "description": "Create, read and edit .zip files with Javascript http://stuartk.com/jszip",
+ "main": "dist/jszip.js",
+ "keywords": [
+ "zip",
+ "deflate",
+ "inflate"
+ ],
+ "license": "MIT or GPLv3",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ],
+ "_release": "2.5.0",
+ "_resolution": {
+ "type": "version",
+ "tag": "v2.5.0",
+ "commit": "39c69fde2d3779889dbf874d3c3ee9d556614fe2"
+ },
+ "_source": "git://github.com/Stuk/jszip.git",
+ "_target": "~2.5.0",
+ "_originalSource": "Stuk/jszip"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/jszip/CHANGES.md b/afb-client/bower_components/jszip/CHANGES.md
new file mode 100644
index 0000000..1b13776
--- /dev/null
+++ b/afb-client/bower_components/jszip/CHANGES.md
@@ -0,0 +1,69 @@
+---
+title: Changelog
+layout: default
+section: main
+---
+
+### v2.5.0 2015-03-10
+- add support for custom mime-types (see [#199](https://github.com/Stuk/jszip/issues/199)).
+- add an option to set the DEFLATE level (see [#201](https://github.com/Stuk/jszip/issues/201)).
+- improve the error message with corrupted zip (see [#202](https://github.com/Stuk/jszip/issues/202)).
+- add support for UNIX / DOS permissions (see [#200](https://github.com/Stuk/jszip/issues/200) and [#205](https://github.com/Stuk/jszip/issues/205)).
+
+### v2.4.0 2014-07-24
+- update pako to 0.2.5 (see [#156](https://github.com/Stuk/jszip/issues/156)).
+- make JSZip work in a Firefox addon context (see [#151](https://github.com/Stuk/jszip/issues/151)).
+- add an option (`createFolders`) to control the subfolder generation (see [#154](https://github.com/Stuk/jszip/issues/154)).
+- allow `Buffer` polyfill in the browser (see [#139](https://github.com/Stuk/jszip/issues/139)).
+
+### v2.3.0 2014-06-18
+- don't generate subfolders (see [#130](https://github.com/Stuk/jszip/issues/130)).
+- add comment support (see [#134](https://github.com/Stuk/jszip/issues/134)).
+- on `ZipObject#options`, the attributes `date` and `dir` have been deprecated and are now on `ZipObject` (see [the upgrade guide](http://stuk.github.io/jszip/documentation/upgrade_guide.html)).
+- on `ZipObject#options`, the attributes `base64` and `binary` have been deprecated (see [the upgrade guide](http://stuk.github.io/jszip/documentation/upgrade_guide.html)).
+- deprecate internal functions exposed in the public API (see [#123](https://github.com/Stuk/jszip/issues/123)).
+- improve UTF-8 support (see [#142](https://github.com/Stuk/jszip/issues/142)).
+
+### v2.2.2, 2014-05-01
+ - update pako to v0.2.1, fix an error when decompressing some files (see [#126](https://github.com/Stuk/jszip/issues/126)).
+
+### v2.2.1, 2014-04-23
+ - fix unreadable generated file on Windows 8 (see [#112](https://github.com/Stuk/jszip/issues/112)).
+ - replace zlibjs with pako.
+
+### v2.2.0, 2014-02-25
+ - make the `new` operator optional before the `JSZip` constructor (see [#93](https://github.com/Stuk/jszip/pull/93)).
+ - update zlibjs to v0.2.0.
+
+### v2.1.1, 2014-02-13
+ - use the npm package for zlib.js instead of the github url.
+
+### v2.1.0, 2014-02-06
+ - split the files and use Browserify to generate the final file (see [#74](https://github.com/Stuk/jszip/pull/74))
+ - packaging change : instead of 4 files (jszip.js, jszip-load.js, jszip-inflate.js, jszip-deflate.js) we now have 2 files : dist/jszip.js and dist/jszip.min.js
+ - add component/bower support
+ - rename variable: 'byte' is a reserved word (see [#76](https://github.com/Stuk/jszip/pull/76))
+ - add support for the unicode path extra field (see [#82](https://github.com/Stuk/jszip/pull/82))
+ - ensure that the generated files have a header with the licenses (see [#80](https://github.com/Stuk/jszip/pull/80))
+
+# v2.0.0, 2013-10-20
+
+ - `JSZipBase64` has been renamed to `JSZip.base64`.
+ - The `data` attribute on the object returned by `zip.file(name)` has been removed. Use `asText()`, `asBinary()`, `asUint8Array()`, `asArrayBuffer()` or `asNodeBuffer()`.
+
+ - [Fix issue with Android browser](https://github.com/Stuk/jszip/pull/60)
+
+ - The compression/decompression methods now give their input type with the `compressInputType` and `uncompressInputType` attributes.
+ - Lazily decompress data when needed and [improve performance in general](https://github.com/Stuk/jszip/pull/56)
+ - [Add support for `Buffer` in Node.js](https://github.com/Stuk/jszip/pull/57).
+ - Package for CommonJS/npm.
+
+### v1.0.1, 2013-03-04
+
+ - Fixed an issue when generating a compressed zip file with empty files or folders, see #33.
+ - With bad data (null or undefined), asText/asBinary/asUint8Array/asArrayBuffer methods now return an empty string, see #36.
+
+# v1.0.0, 2013-02-14
+
+- First release after a long period without version.
+
diff --git a/afb-client/bower_components/jszip/Gruntfile.js b/afb-client/bower_components/jszip/Gruntfile.js
new file mode 100644
index 0000000..b52d7c8
--- /dev/null
+++ b/afb-client/bower_components/jszip/Gruntfile.js
@@ -0,0 +1,130 @@
+/*jshint node: true */
+module.exports = function(grunt) {
+ var browsers = [{
+ browserName: "iphone",
+ platform: "OS X 10.8",
+ version: "6"
+ }, {
+ browserName: "android",
+ platform: "Linux",
+ version: "4.0"
+ }, {
+ browserName: "firefox",
+ platform: "XP"
+ }, {
+ browserName: "chrome",
+ platform: "XP"
+ }, {
+ browserName: "internet explorer",
+ platform: "WIN8",
+ version: "10"
+ }, {
+ browserName: "internet explorer",
+ platform: "VISTA",
+ version: "9"
+ }, {
+ browserName: "internet explorer",
+ platform: "Windows 7",
+ version: "8"
+ }, {
+ browserName: "internet explorer",
+ platform: "XP",
+ version: "7"
+ }, {
+ browserName: "opera",
+ platform: "Windows 2008",
+ version: "12"
+ }, {
+ browserName: "safari",
+ platform: "OS X 10.8",
+ version: "6"
+ }];
+
+ var tags = [];
+ if (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST != "false") {
+ tags.push("pr" + process.env.TRAVIS_PULL_REQUEST);
+ } else if (process.env.TRAVIS_BRANCH) {
+ tags.push(process.env.TRAVIS_BRANCH);
+ }
+
+ grunt.initConfig({
+ connect: {
+ server: {
+ options: {
+ base: "",
+ port: 9999
+ }
+ }
+ },
+ 'saucelabs-qunit': {
+ all: {
+ options: {
+ urls: ["http://127.0.0.1:9999/test/index.html"],
+ tunnelTimeout: 5,
+ build: process.env.TRAVIS_JOB_ID,
+ concurrency: 3,
+ browsers: browsers,
+ testname: "qunit tests",
+ tags: tags
+ }
+ }
+ },
+ jshint: {
+ options: {
+ jshintrc: "./.jshintrc"
+ },
+ all: ['./lib/*.js']
+ },
+ browserify: {
+ all: {
+ files: {
+ 'dist/jszip.js': ['lib/index.js']
+ },
+ options: {
+ bundleOptions: {
+ standalone: 'JSZip',
+ insertGlobalVars : {
+ Buffer: function () {
+ // instead of the full polyfill, we just use the raw value
+ // (or undefined).
+ return '(typeof Buffer !== "undefined" ? Buffer : undefined)';
+ }
+ }
+ },
+ postBundleCB: function(err, src, done) {
+ // add the license
+ var license = require('fs').readFileSync('lib/license_header.js');
+ // remove the source mapping of zlib.js, see #75
+ var srcWithoutSourceMapping = src.replace(/\/\/@ sourceMappingURL=raw..flate.min.js.map/g, '');
+ done(err, license + srcWithoutSourceMapping);
+ }
+ }
+ }
+ },
+ uglify: {
+ options: {
+ report: 'gzip',
+ mangle: true,
+ preserveComments: 'some'
+ },
+ all: {
+ src: 'dist/jszip.js',
+ dest: 'dist/jszip.min.js'
+ }
+ }
+ });
+
+ grunt.loadNpmTasks("grunt-saucelabs");
+ grunt.loadNpmTasks("grunt-contrib-connect");
+ grunt.loadNpmTasks('grunt-browserify');
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+
+ if (process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY) {
+ grunt.registerTask("test", ["connect", "saucelabs-qunit"]);
+ } else {
+ grunt.registerTask("test", []);
+ }
+ grunt.registerTask("build", ["browserify", "uglify"]);
+ grunt.registerTask("default", ["jshint", "build"]);
+};
diff --git a/afb-client/bower_components/jszip/LICENSE.markdown b/afb-client/bower_components/jszip/LICENSE.markdown
new file mode 100644
index 0000000..c0b10c0
--- /dev/null
+++ b/afb-client/bower_components/jszip/LICENSE.markdown
@@ -0,0 +1,651 @@
+JSZip is dual licensed. You may use it under the MIT license *or* the GPLv3
+license.
+
+The MIT License
+===============
+
+Copyright (c) 2009-2014 Stuart Knightley, David Duponchel, Franz Buchinger, António Afonso
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+GPL version 3
+=============
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
diff --git a/afb-client/bower_components/jszip/README.markdown b/afb-client/bower_components/jszip/README.markdown
new file mode 100644
index 0000000..5cfa5dd
--- /dev/null
+++ b/afb-client/bower_components/jszip/README.markdown
@@ -0,0 +1,41 @@
+JSZip
+=====
+
+A library for creating, reading and editing .zip files with Javascript, with a
+lovely and simple API.
+
+See http://stuartk.com/jszip for all the documentation.
+
+```javascript
+var zip = new JSZip();
+
+zip.file("Hello.txt", "Hello World\n");
+
+var img = zip.folder("images");
+img.file("smile.gif", imgData, {base64: true});
+
+var content = zip.generate({type:"blob"});
+
+// see FileSaver.js
+saveAs(content, "example.zip");
+
+/*
+Results in a zip containing
+Hello.txt
+images/
+ smile.gif
+*/
+```
+
+Test status
+-----------
+
+[![Build Status](https://api.travis-ci.org/Stuk/jszip.svg?branch=master)](http://travis-ci.org/Stuk/jszip)
+
+[![Selenium Test Status](https://saucelabs.com/browser-matrix/jszip.svg)](https://saucelabs.com/u/jszip)
+
+License
+-------
+
+JSZip is dual-licensed. You may use it under the MIT license *or* the GPLv3
+license. See [LICENSE.markdown](LICENSE.markdown).
diff --git a/afb-client/bower_components/jszip/_config.yml b/afb-client/bower_components/jszip/_config.yml
new file mode 100644
index 0000000..b1959a1
--- /dev/null
+++ b/afb-client/bower_components/jszip/_config.yml
@@ -0,0 +1,25 @@
+# will be overwritten by github, see https://help.github.com/articles/using-jekyll-with-pages
+safe: true
+lsi: false
+pygments: true
+source: ./
+# /overwritten
+
+baseurl: /jszip
+
+layouts: ./documentation/_layouts
+permalink: none
+exclude: ['bin', 'README.md', 'node_modules']
+
+markdown: redcarpet
+redcarpet:
+ extensions: [
+ 'no_intra_emphasis',
+ 'fenced_code_blocks',
+ 'autolink',
+ 'strikethrough',
+ 'superscript',
+ 'with_toc_data',
+ 'tables',
+ 'hardwrap'
+ ]
diff --git a/afb-client/bower_components/jszip/bower.json b/afb-client/bower_components/jszip/bower.json
new file mode 100644
index 0000000..ff9de90
--- /dev/null
+++ b/afb-client/bower_components/jszip/bower.json
@@ -0,0 +1,23 @@
+{
+ "name": "jszip",
+ "version": "2.5.0",
+ "homepage": "http://stuartk.com/jszip",
+ "authors": [
+ "Stuart Knightley <stuart@stuartk.com>"
+ ],
+ "description": "Create, read and edit .zip files with Javascript http://stuartk.com/jszip",
+ "main": "dist/jszip.js",
+ "keywords": [
+ "zip",
+ "deflate",
+ "inflate"
+ ],
+ "license": "MIT or GPLv3",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ]
+}
diff --git a/afb-client/bower_components/jszip/component.json b/afb-client/bower_components/jszip/component.json
new file mode 100644
index 0000000..8c1928f
--- /dev/null
+++ b/afb-client/bower_components/jszip/component.json
@@ -0,0 +1,16 @@
+{
+ "name": "jszip",
+ "repo": "Stuk/jszip",
+ "description": "Create, read and edit .zip files with Javascript http://stuartk.com/jszip",
+ "version": "2.5.0",
+ "keywords": [
+ "zip",
+ "deflate",
+ "inflate"
+ ],
+ "main": "dist/jszip.js",
+ "license": "MIT or GPLv3",
+ "scripts": [
+ "dist/jszip.js"
+ ]
+}
diff --git a/afb-client/bower_components/jszip/dist/jszip.js b/afb-client/bower_components/jszip/dist/jszip.js
new file mode 100644
index 0000000..1546d7f
--- /dev/null
+++ b/afb-client/bower_components/jszip/dist/jszip.js
@@ -0,0 +1,9155 @@
+/*!
+
+JSZip - A Javascript class for generating and reading zip files
+<http://stuartk.com/jszip>
+
+(c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
+Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
+
+JSZip uses the library pako released under the MIT license :
+https://github.com/nodeca/pako/blob/master/LICENSE
+*/
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSZip=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+'use strict';
+// private property
+var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+
+// public method for encoding
+exports.encode = function(input, utf8) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ }
+ else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
+
+ }
+
+ return output;
+};
+
+// public method for decoding
+exports.decode = function(input, utf8) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = _keyStr.indexOf(input.charAt(i++));
+ enc2 = _keyStr.indexOf(input.charAt(i++));
+ enc3 = _keyStr.indexOf(input.charAt(i++));
+ enc4 = _keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ return output;
+
+};
+
+},{}],2:[function(_dereq_,module,exports){
+'use strict';
+function CompressedObject() {
+ this.compressedSize = 0;
+ this.uncompressedSize = 0;
+ this.crc32 = 0;
+ this.compressionMethod = null;
+ this.compressedContent = null;
+}
+
+CompressedObject.prototype = {
+ /**
+ * Return the decompressed content in an unspecified format.
+ * The format will depend on the decompressor.
+ * @return {Object} the decompressed content.
+ */
+ getContent: function() {
+ return null; // see implementation
+ },
+ /**
+ * Return the compressed content in an unspecified format.
+ * The format will depend on the compressed conten source.
+ * @return {Object} the compressed content.
+ */
+ getCompressedContent: function() {
+ return null; // see implementation
+ }
+};
+module.exports = CompressedObject;
+
+},{}],3:[function(_dereq_,module,exports){
+'use strict';
+exports.STORE = {
+ magic: "\x00\x00",
+ compress: function(content, compressionOptions) {
+ return content; // no compression
+ },
+ uncompress: function(content) {
+ return content; // no compression
+ },
+ compressInputType: null,
+ uncompressInputType: null
+};
+exports.DEFLATE = _dereq_('./flate');
+
+},{"./flate":8}],4:[function(_dereq_,module,exports){
+'use strict';
+
+var utils = _dereq_('./utils');
+
+var table = [
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+];
+
+/**
+ *
+ * Javascript crc32
+ * http://www.webtoolkit.info/
+ *
+ */
+module.exports = function crc32(input, crc) {
+ if (typeof input === "undefined" || !input.length) {
+ return 0;
+ }
+
+ var isArray = utils.getTypeOf(input) !== "string";
+
+ if (typeof(crc) == "undefined") {
+ crc = 0;
+ }
+ var x = 0;
+ var y = 0;
+ var b = 0;
+
+ crc = crc ^ (-1);
+ for (var i = 0, iTop = input.length; i < iTop; i++) {
+ b = isArray ? input[i] : input.charCodeAt(i);
+ y = (crc ^ b) & 0xFF;
+ x = table[y];
+ crc = (crc >>> 8) ^ x;
+ }
+
+ return crc ^ (-1);
+};
+// vim: set shiftwidth=4 softtabstop=4:
+
+},{"./utils":21}],5:[function(_dereq_,module,exports){
+'use strict';
+var utils = _dereq_('./utils');
+
+function DataReader(data) {
+ this.data = null; // type : see implementation
+ this.length = 0;
+ this.index = 0;
+}
+DataReader.prototype = {
+ /**
+ * Check that the offset will not go too far.
+ * @param {string} offset the additional offset to check.
+ * @throws {Error} an Error if the offset is out of bounds.
+ */
+ checkOffset: function(offset) {
+ this.checkIndex(this.index + offset);
+ },
+ /**
+ * Check that the specifed index will not be too far.
+ * @param {string} newIndex the index to check.
+ * @throws {Error} an Error if the index is out of bounds.
+ */
+ checkIndex: function(newIndex) {
+ if (this.length < newIndex || newIndex < 0) {
+ throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?");
+ }
+ },
+ /**
+ * Change the index.
+ * @param {number} newIndex The new index.
+ * @throws {Error} if the new index is out of the data.
+ */
+ setIndex: function(newIndex) {
+ this.checkIndex(newIndex);
+ this.index = newIndex;
+ },
+ /**
+ * Skip the next n bytes.
+ * @param {number} n the number of bytes to skip.
+ * @throws {Error} if the new index is out of the data.
+ */
+ skip: function(n) {
+ this.setIndex(this.index + n);
+ },
+ /**
+ * Get the byte at the specified index.
+ * @param {number} i the index to use.
+ * @return {number} a byte.
+ */
+ byteAt: function(i) {
+ // see implementations
+ },
+ /**
+ * Get the next number with a given byte size.
+ * @param {number} size the number of bytes to read.
+ * @return {number} the corresponding number.
+ */
+ readInt: function(size) {
+ var result = 0,
+ i;
+ this.checkOffset(size);
+ for (i = this.index + size - 1; i >= this.index; i--) {
+ result = (result << 8) + this.byteAt(i);
+ }
+ this.index += size;
+ return result;
+ },
+ /**
+ * Get the next string with a given byte size.
+ * @param {number} size the number of bytes to read.
+ * @return {string} the corresponding string.
+ */
+ readString: function(size) {
+ return utils.transformTo("string", this.readData(size));
+ },
+ /**
+ * Get raw data without conversion, <size> bytes.
+ * @param {number} size the number of bytes to read.
+ * @return {Object} the raw data, implementation specific.
+ */
+ readData: function(size) {
+ // see implementations
+ },
+ /**
+ * Find the last occurence of a zip signature (4 bytes).
+ * @param {string} sig the signature to find.
+ * @return {number} the index of the last occurence, -1 if not found.
+ */
+ lastIndexOfSignature: function(sig) {
+ // see implementations
+ },
+ /**
+ * Get the next date.
+ * @return {Date} the date.
+ */
+ readDate: function() {
+ var dostime = this.readInt(4);
+ return new Date(
+ ((dostime >> 25) & 0x7f) + 1980, // year
+ ((dostime >> 21) & 0x0f) - 1, // month
+ (dostime >> 16) & 0x1f, // day
+ (dostime >> 11) & 0x1f, // hour
+ (dostime >> 5) & 0x3f, // minute
+ (dostime & 0x1f) << 1); // second
+ }
+};
+module.exports = DataReader;
+
+},{"./utils":21}],6:[function(_dereq_,module,exports){
+'use strict';
+exports.base64 = false;
+exports.binary = false;
+exports.dir = false;
+exports.createFolders = false;
+exports.date = null;
+exports.compression = null;
+exports.compressionOptions = null;
+exports.comment = null;
+exports.unixPermissions = null;
+exports.dosPermissions = null;
+
+},{}],7:[function(_dereq_,module,exports){
+'use strict';
+var utils = _dereq_('./utils');
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2binary = function(str) {
+ return utils.string2binary(str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2Uint8Array = function(str) {
+ return utils.transformTo("uint8array", str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.uint8Array2String = function(array) {
+ return utils.transformTo("string", array);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2Blob = function(str) {
+ var buffer = utils.transformTo("arraybuffer", str);
+ return utils.arrayBuffer2Blob(buffer);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.arrayBuffer2Blob = function(buffer) {
+ return utils.arrayBuffer2Blob(buffer);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.transformTo = function(outputType, input) {
+ return utils.transformTo(outputType, input);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.getTypeOf = function(input) {
+ return utils.getTypeOf(input);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.checkSupport = function(type) {
+ return utils.checkSupport(type);
+};
+
+/**
+ * @deprecated
+ * This value will be removed in a future version without replacement.
+ */
+exports.MAX_VALUE_16BITS = utils.MAX_VALUE_16BITS;
+
+/**
+ * @deprecated
+ * This value will be removed in a future version without replacement.
+ */
+exports.MAX_VALUE_32BITS = utils.MAX_VALUE_32BITS;
+
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.pretty = function(str) {
+ return utils.pretty(str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.findCompression = function(compressionMethod) {
+ return utils.findCompression(compressionMethod);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.isRegExp = function (object) {
+ return utils.isRegExp(object);
+};
+
+
+},{"./utils":21}],8:[function(_dereq_,module,exports){
+'use strict';
+var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined');
+
+var pako = _dereq_("pako");
+exports.uncompressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
+exports.compressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
+
+exports.magic = "\x08\x00";
+exports.compress = function(input, compressionOptions) {
+ return pako.deflateRaw(input, {
+ level : compressionOptions.level || -1 // default compression
+ });
+};
+exports.uncompress = function(input) {
+ return pako.inflateRaw(input);
+};
+
+},{"pako":24}],9:[function(_dereq_,module,exports){
+'use strict';
+
+var base64 = _dereq_('./base64');
+
+/**
+Usage:
+ zip = new JSZip();
+ zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing");
+ zip.folder("images").file("smile.gif", base64Data, {base64: true});
+ zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
+ zip.remove("tempfile");
+
+ base64zip = zip.generate();
+
+**/
+
+/**
+ * Representation a of zip file in js
+ * @constructor
+ * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional).
+ * @param {Object=} options the options for creating this objects (optional).
+ */
+function JSZip(data, options) {
+ // if this constructor is used without `new`, it adds `new` before itself:
+ if(!(this instanceof JSZip)) return new JSZip(data, options);
+
+ // object containing the files :
+ // {
+ // "folder/" : {...},
+ // "folder/data.txt" : {...}
+ // }
+ this.files = {};
+
+ this.comment = null;
+
+ // Where we are in the hierarchy
+ this.root = "";
+ if (data) {
+ this.load(data, options);
+ }
+ this.clone = function() {
+ var newObj = new JSZip();
+ for (var i in this) {
+ if (typeof this[i] !== "function") {
+ newObj[i] = this[i];
+ }
+ }
+ return newObj;
+ };
+}
+JSZip.prototype = _dereq_('./object');
+JSZip.prototype.load = _dereq_('./load');
+JSZip.support = _dereq_('./support');
+JSZip.defaults = _dereq_('./defaults');
+
+/**
+ * @deprecated
+ * This namespace will be removed in a future version without replacement.
+ */
+JSZip.utils = _dereq_('./deprecatedPublicUtils');
+
+JSZip.base64 = {
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ encode : function(input) {
+ return base64.encode(input);
+ },
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ decode : function(input) {
+ return base64.decode(input);
+ }
+};
+JSZip.compressions = _dereq_('./compressions');
+module.exports = JSZip;
+
+},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(_dereq_,module,exports){
+'use strict';
+var base64 = _dereq_('./base64');
+var ZipEntries = _dereq_('./zipEntries');
+module.exports = function(data, options) {
+ var files, zipEntries, i, input;
+ options = options || {};
+ if (options.base64) {
+ data = base64.decode(data);
+ }
+
+ zipEntries = new ZipEntries(data, options);
+ files = zipEntries.files;
+ for (i = 0; i < files.length; i++) {
+ input = files[i];
+ this.file(input.fileName, input.decompressed, {
+ binary: true,
+ optimizedBinaryString: true,
+ date: input.date,
+ dir: input.dir,
+ comment : input.fileComment.length ? input.fileComment : null,
+ unixPermissions : input.unixPermissions,
+ dosPermissions : input.dosPermissions,
+ createFolders: options.createFolders
+ });
+ }
+ if (zipEntries.zipComment.length) {
+ this.comment = zipEntries.zipComment;
+ }
+
+ return this;
+};
+
+},{"./base64":1,"./zipEntries":22}],11:[function(_dereq_,module,exports){
+(function (Buffer){
+'use strict';
+module.exports = function(data, encoding){
+ return new Buffer(data, encoding);
+};
+module.exports.test = function(b){
+ return Buffer.isBuffer(b);
+};
+
+}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined))
+},{}],12:[function(_dereq_,module,exports){
+'use strict';
+var Uint8ArrayReader = _dereq_('./uint8ArrayReader');
+
+function NodeBufferReader(data) {
+ this.data = data;
+ this.length = this.data.length;
+ this.index = 0;
+}
+NodeBufferReader.prototype = new Uint8ArrayReader();
+
+/**
+ * @see DataReader.readData
+ */
+NodeBufferReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ var result = this.data.slice(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = NodeBufferReader;
+
+},{"./uint8ArrayReader":18}],13:[function(_dereq_,module,exports){
+'use strict';
+var support = _dereq_('./support');
+var utils = _dereq_('./utils');
+var crc32 = _dereq_('./crc32');
+var signature = _dereq_('./signature');
+var defaults = _dereq_('./defaults');
+var base64 = _dereq_('./base64');
+var compressions = _dereq_('./compressions');
+var CompressedObject = _dereq_('./compressedObject');
+var nodeBuffer = _dereq_('./nodeBuffer');
+var utf8 = _dereq_('./utf8');
+var StringWriter = _dereq_('./stringWriter');
+var Uint8ArrayWriter = _dereq_('./uint8ArrayWriter');
+
+/**
+ * Returns the raw data of a ZipObject, decompress the content if necessary.
+ * @param {ZipObject} file the file to use.
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
+ */
+var getRawData = function(file) {
+ if (file._data instanceof CompressedObject) {
+ file._data = file._data.getContent();
+ file.options.binary = true;
+ file.options.base64 = false;
+
+ if (utils.getTypeOf(file._data) === "uint8array") {
+ var copy = file._data;
+ // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
+ // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
+ file._data = new Uint8Array(copy.length);
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
+ if (copy.length !== 0) {
+ file._data.set(copy, 0);
+ }
+ }
+ }
+ return file._data;
+};
+
+/**
+ * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.
+ * @param {ZipObject} file the file to use.
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
+ */
+var getBinaryData = function(file) {
+ var result = getRawData(file),
+ type = utils.getTypeOf(result);
+ if (type === "string") {
+ if (!file.options.binary) {
+ // unicode text !
+ // unicode string => binary string is a painful process, check if we can avoid it.
+ if (support.nodebuffer) {
+ return nodeBuffer(result, "utf-8");
+ }
+ }
+ return file.asBinary();
+ }
+ return result;
+};
+
+/**
+ * Transform this._data into a string.
+ * @param {function} filter a function String -> String, applied if not null on the result.
+ * @return {String} the string representing this._data.
+ */
+var dataToString = function(asUTF8) {
+ var result = getRawData(this);
+ if (result === null || typeof result === "undefined") {
+ return "";
+ }
+ // if the data is a base64 string, we decode it before checking the encoding !
+ if (this.options.base64) {
+ result = base64.decode(result);
+ }
+ if (asUTF8 && this.options.binary) {
+ // JSZip.prototype.utf8decode supports arrays as input
+ // skip to array => string step, utf8decode will do it.
+ result = out.utf8decode(result);
+ }
+ else {
+ // no utf8 transformation, do the array => string step.
+ result = utils.transformTo("string", result);
+ }
+
+ if (!asUTF8 && !this.options.binary) {
+ result = utils.transformTo("string", out.utf8encode(result));
+ }
+ return result;
+};
+/**
+ * A simple object representing a file in the zip file.
+ * @constructor
+ * @param {string} name the name of the file
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data
+ * @param {Object} options the options of the file
+ */
+var ZipObject = function(name, data, options) {
+ this.name = name;
+ this.dir = options.dir;
+ this.date = options.date;
+ this.comment = options.comment;
+ this.unixPermissions = options.unixPermissions;
+ this.dosPermissions = options.dosPermissions;
+
+ this._data = data;
+ this.options = options;
+
+ /*
+ * This object contains initial values for dir and date.
+ * With them, we can check if the user changed the deprecated metadata in
+ * `ZipObject#options` or not.
+ */
+ this._initialMetadata = {
+ dir : options.dir,
+ date : options.date
+ };
+};
+
+ZipObject.prototype = {
+ /**
+ * Return the content as UTF8 string.
+ * @return {string} the UTF8 string.
+ */
+ asText: function() {
+ return dataToString.call(this, true);
+ },
+ /**
+ * Returns the binary content.
+ * @return {string} the content as binary.
+ */
+ asBinary: function() {
+ return dataToString.call(this, false);
+ },
+ /**
+ * Returns the content as a nodejs Buffer.
+ * @return {Buffer} the content as a Buffer.
+ */
+ asNodeBuffer: function() {
+ var result = getBinaryData(this);
+ return utils.transformTo("nodebuffer", result);
+ },
+ /**
+ * Returns the content as an Uint8Array.
+ * @return {Uint8Array} the content as an Uint8Array.
+ */
+ asUint8Array: function() {
+ var result = getBinaryData(this);
+ return utils.transformTo("uint8array", result);
+ },
+ /**
+ * Returns the content as an ArrayBuffer.
+ * @return {ArrayBuffer} the content as an ArrayBufer.
+ */
+ asArrayBuffer: function() {
+ return this.asUint8Array().buffer;
+ }
+};
+
+/**
+ * Transform an integer into a string in hexadecimal.
+ * @private
+ * @param {number} dec the number to convert.
+ * @param {number} bytes the number of bytes to generate.
+ * @returns {string} the result.
+ */
+var decToHex = function(dec, bytes) {
+ var hex = "",
+ i;
+ for (i = 0; i < bytes; i++) {
+ hex += String.fromCharCode(dec & 0xff);
+ dec = dec >>> 8;
+ }
+ return hex;
+};
+
+/**
+ * Merge the objects passed as parameters into a new one.
+ * @private
+ * @param {...Object} var_args All objects to merge.
+ * @return {Object} a new object with the data of the others.
+ */
+var extend = function() {
+ var result = {}, i, attr;
+ for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
+ for (attr in arguments[i]) {
+ if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
+ result[attr] = arguments[i][attr];
+ }
+ }
+ }
+ return result;
+};
+
+/**
+ * Transforms the (incomplete) options from the user into the complete
+ * set of options to create a file.
+ * @private
+ * @param {Object} o the options from the user.
+ * @return {Object} the complete set of options.
+ */
+var prepareFileAttrs = function(o) {
+ o = o || {};
+ if (o.base64 === true && (o.binary === null || o.binary === undefined)) {
+ o.binary = true;
+ }
+ o = extend(o, defaults);
+ o.date = o.date || new Date();
+ if (o.compression !== null) o.compression = o.compression.toUpperCase();
+
+ return o;
+};
+
+/**
+ * Add a file in the current folder.
+ * @private
+ * @param {string} name the name of the file
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file
+ * @param {Object} o the options of the file
+ * @return {Object} the new file.
+ */
+var fileAdd = function(name, data, o) {
+ // be sure sub folders exist
+ var dataType = utils.getTypeOf(data),
+ parent;
+
+ o = prepareFileAttrs(o);
+
+ if (typeof o.unixPermissions === "string") {
+ o.unixPermissions = parseInt(o.unixPermissions, 8);
+ }
+
+ // UNX_IFDIR 0040000 see zipinfo.c
+ if (o.unixPermissions && (o.unixPermissions & 0x4000)) {
+ o.dir = true;
+ }
+ // Bit 4 Directory
+ if (o.dosPermissions && (o.dosPermissions & 0x0010)) {
+ o.dir = true;
+ }
+
+ if (o.dir) {
+ name = forceTrailingSlash(name);
+ }
+
+ if (o.createFolders && (parent = parentFolder(name))) {
+ folderAdd.call(this, parent, true);
+ }
+
+ if (o.dir || data === null || typeof data === "undefined") {
+ o.base64 = false;
+ o.binary = false;
+ data = null;
+ dataType = null;
+ }
+ else if (dataType === "string") {
+ if (o.binary && !o.base64) {
+ // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask
+ if (o.optimizedBinaryString !== true) {
+ // this is a string, not in a base64 format.
+ // Be sure that this is a correct "binary string"
+ data = utils.string2binary(data);
+ }
+ }
+ }
+ else { // arraybuffer, uint8array, ...
+ o.base64 = false;
+ o.binary = true;
+
+ if (!dataType && !(data instanceof CompressedObject)) {
+ throw new Error("The data of '" + name + "' is in an unsupported format !");
+ }
+
+ // special case : it's way easier to work with Uint8Array than with ArrayBuffer
+ if (dataType === "arraybuffer") {
+ data = utils.transformTo("uint8array", data);
+ }
+ }
+
+ var object = new ZipObject(name, data, o);
+ this.files[name] = object;
+ return object;
+};
+
+/**
+ * Find the parent folder of the path.
+ * @private
+ * @param {string} path the path to use
+ * @return {string} the parent folder, or ""
+ */
+var parentFolder = function (path) {
+ if (path.slice(-1) == '/') {
+ path = path.substring(0, path.length - 1);
+ }
+ var lastSlash = path.lastIndexOf('/');
+ return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
+};
+
+
+/**
+ * Returns the path with a slash at the end.
+ * @private
+ * @param {String} path the path to check.
+ * @return {String} the path with a trailing slash.
+ */
+var forceTrailingSlash = function(path) {
+ // Check the name ends with a /
+ if (path.slice(-1) != "/") {
+ path += "/"; // IE doesn't like substr(-1)
+ }
+ return path;
+};
+/**
+ * Add a (sub) folder in the current folder.
+ * @private
+ * @param {string} name the folder's name
+ * @param {boolean=} [createFolders] If true, automatically create sub
+ * folders. Defaults to false.
+ * @return {Object} the new folder.
+ */
+var folderAdd = function(name, createFolders) {
+ createFolders = (typeof createFolders !== 'undefined') ? createFolders : false;
+
+ name = forceTrailingSlash(name);
+
+ // Does this folder already exist?
+ if (!this.files[name]) {
+ fileAdd.call(this, name, null, {
+ dir: true,
+ createFolders: createFolders
+ });
+ }
+ return this.files[name];
+};
+
+/**
+ * Generate a JSZip.CompressedObject for a given zipOject.
+ * @param {ZipObject} file the object to read.
+ * @param {JSZip.compression} compression the compression to use.
+ * @param {Object} compressionOptions the options to use when compressing.
+ * @return {JSZip.CompressedObject} the compressed result.
+ */
+var generateCompressedObjectFrom = function(file, compression, compressionOptions) {
+ var result = new CompressedObject(),
+ content;
+
+ // the data has not been decompressed, we might reuse things !
+ if (file._data instanceof CompressedObject) {
+ result.uncompressedSize = file._data.uncompressedSize;
+ result.crc32 = file._data.crc32;
+
+ if (result.uncompressedSize === 0 || file.dir) {
+ compression = compressions['STORE'];
+ result.compressedContent = "";
+ result.crc32 = 0;
+ }
+ else if (file._data.compressionMethod === compression.magic) {
+ result.compressedContent = file._data.getCompressedContent();
+ }
+ else {
+ content = file._data.getContent();
+ // need to decompress / recompress
+ result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions);
+ }
+ }
+ else {
+ // have uncompressed data
+ content = getBinaryData(file);
+ if (!content || content.length === 0 || file.dir) {
+ compression = compressions['STORE'];
+ content = "";
+ }
+ result.uncompressedSize = content.length;
+ result.crc32 = crc32(content);
+ result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions);
+ }
+
+ result.compressedSize = result.compressedContent.length;
+ result.compressionMethod = compression.magic;
+
+ return result;
+};
+
+
+
+
+/**
+ * Generate the UNIX part of the external file attributes.
+ * @param {Object} unixPermissions the unix permissions or null.
+ * @param {Boolean} isDir true if the entry is a directory, false otherwise.
+ * @return {Number} a 32 bit integer.
+ *
+ * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute :
+ *
+ * TTTTsstrwxrwxrwx0000000000ADVSHR
+ * ^^^^____________________________ file type, see zipinfo.c (UNX_*)
+ * ^^^_________________________ setuid, setgid, sticky
+ * ^^^^^^^^^________________ permissions
+ * ^^^^^^^^^^______ not used ?
+ * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only
+ */
+var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
+
+ var result = unixPermissions;
+ if (!unixPermissions) {
+ // I can't use octal values in strict mode, hence the hexa.
+ // 040775 => 0x41fd
+ // 0100664 => 0x81b4
+ result = isDir ? 0x41fd : 0x81b4;
+ }
+
+ return (result & 0xFFFF) << 16;
+};
+
+/**
+ * Generate the DOS part of the external file attributes.
+ * @param {Object} dosPermissions the dos permissions or null.
+ * @param {Boolean} isDir true if the entry is a directory, false otherwise.
+ * @return {Number} a 32 bit integer.
+ *
+ * Bit 0 Read-Only
+ * Bit 1 Hidden
+ * Bit 2 System
+ * Bit 3 Volume Label
+ * Bit 4 Directory
+ * Bit 5 Archive
+ */
+var generateDosExternalFileAttr = function (dosPermissions, isDir) {
+
+ // the dir flag is already set for compatibility
+
+ return (dosPermissions || 0) & 0x3F;
+};
+
+/**
+ * Generate the various parts used in the construction of the final zip file.
+ * @param {string} name the file name.
+ * @param {ZipObject} file the file content.
+ * @param {JSZip.CompressedObject} compressedObject the compressed object.
+ * @param {number} offset the current offset from the start of the zip file.
+ * @param {String} platform let's pretend we are this platform (change platform dependents fields)
+ * @return {object} the zip parts.
+ */
+var generateZipParts = function(name, file, compressedObject, offset, platform) {
+ var data = compressedObject.compressedContent,
+ utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)),
+ comment = file.comment || "",
+ utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)),
+ useUTF8ForFileName = utfEncodedFileName.length !== file.name.length,
+ useUTF8ForComment = utfEncodedComment.length !== comment.length,
+ o = file.options,
+ dosTime,
+ dosDate,
+ extraFields = "",
+ unicodePathExtraField = "",
+ unicodeCommentExtraField = "",
+ dir, date;
+
+
+ // handle the deprecated options.dir
+ if (file._initialMetadata.dir !== file.dir) {
+ dir = file.dir;
+ } else {
+ dir = o.dir;
+ }
+
+ // handle the deprecated options.date
+ if(file._initialMetadata.date !== file.date) {
+ date = file.date;
+ } else {
+ date = o.date;
+ }
+
+ var extFileAttr = 0;
+ var versionMadeBy = 0;
+ if (dir) {
+ // dos or unix, we set the dos dir flag
+ extFileAttr |= 0x00010;
+ }
+ if(platform === "UNIX") {
+ versionMadeBy = 0x031E; // UNIX, version 3.0
+ extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir);
+ } else { // DOS or other, fallback to DOS
+ versionMadeBy = 0x0014; // DOS, version 2.0
+ extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir);
+ }
+
+ // date
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
+
+ dosTime = date.getHours();
+ dosTime = dosTime << 6;
+ dosTime = dosTime | date.getMinutes();
+ dosTime = dosTime << 5;
+ dosTime = dosTime | date.getSeconds() / 2;
+
+ dosDate = date.getFullYear() - 1980;
+ dosDate = dosDate << 4;
+ dosDate = dosDate | (date.getMonth() + 1);
+ dosDate = dosDate << 5;
+ dosDate = dosDate | date.getDate();
+
+ if (useUTF8ForFileName) {
+ // set the unicode path extra field. unzip needs at least one extra
+ // field to correctly handle unicode path, so using the path is as good
+ // as any other information. This could improve the situation with
+ // other archive managers too.
+ // This field is usually used without the utf8 flag, with a non
+ // unicode path in the header (winrar, winzip). This helps (a bit)
+ // with the messy Windows' default compressed folders feature but
+ // breaks on p7zip which doesn't seek the unicode path extra field.
+ // So for now, UTF-8 everywhere !
+ unicodePathExtraField =
+ // Version
+ decToHex(1, 1) +
+ // NameCRC32
+ decToHex(crc32(utfEncodedFileName), 4) +
+ // UnicodeName
+ utfEncodedFileName;
+
+ extraFields +=
+ // Info-ZIP Unicode Path Extra Field
+ "\x75\x70" +
+ // size
+ decToHex(unicodePathExtraField.length, 2) +
+ // content
+ unicodePathExtraField;
+ }
+
+ if(useUTF8ForComment) {
+
+ unicodeCommentExtraField =
+ // Version
+ decToHex(1, 1) +
+ // CommentCRC32
+ decToHex(this.crc32(utfEncodedComment), 4) +
+ // UnicodeName
+ utfEncodedComment;
+
+ extraFields +=
+ // Info-ZIP Unicode Path Extra Field
+ "\x75\x63" +
+ // size
+ decToHex(unicodeCommentExtraField.length, 2) +
+ // content
+ unicodeCommentExtraField;
+ }
+
+ var header = "";
+
+ // version needed to extract
+ header += "\x0A\x00";
+ // general purpose bit flag
+ // set bit 11 if utf8
+ header += (useUTF8ForFileName || useUTF8ForComment) ? "\x00\x08" : "\x00\x00";
+ // compression method
+ header += compressedObject.compressionMethod;
+ // last mod file time
+ header += decToHex(dosTime, 2);
+ // last mod file date
+ header += decToHex(dosDate, 2);
+ // crc-32
+ header += decToHex(compressedObject.crc32, 4);
+ // compressed size
+ header += decToHex(compressedObject.compressedSize, 4);
+ // uncompressed size
+ header += decToHex(compressedObject.uncompressedSize, 4);
+ // file name length
+ header += decToHex(utfEncodedFileName.length, 2);
+ // extra field length
+ header += decToHex(extraFields.length, 2);
+
+
+ var fileRecord = signature.LOCAL_FILE_HEADER + header + utfEncodedFileName + extraFields;
+
+ var dirRecord = signature.CENTRAL_FILE_HEADER +
+ // version made by (00: DOS)
+ decToHex(versionMadeBy, 2) +
+ // file header (common to file and central directory)
+ header +
+ // file comment length
+ decToHex(utfEncodedComment.length, 2) +
+ // disk number start
+ "\x00\x00" +
+ // internal file attributes TODO
+ "\x00\x00" +
+ // external file attributes
+ decToHex(extFileAttr, 4) +
+ // relative offset of local header
+ decToHex(offset, 4) +
+ // file name
+ utfEncodedFileName +
+ // extra field
+ extraFields +
+ // file comment
+ utfEncodedComment;
+
+ return {
+ fileRecord: fileRecord,
+ dirRecord: dirRecord,
+ compressedObject: compressedObject
+ };
+};
+
+
+// return the actual prototype of JSZip
+var out = {
+ /**
+ * Read an existing zip and merge the data in the current JSZip object.
+ * The implementation is in jszip-load.js, don't forget to include it.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load
+ * @param {Object} options Options for loading the stream.
+ * options.base64 : is the stream in base64 ? default : false
+ * @return {JSZip} the current JSZip object
+ */
+ load: function(stream, options) {
+ throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
+ },
+
+ /**
+ * Filter nested files/folders with the specified function.
+ * @param {Function} search the predicate to use :
+ * function (relativePath, file) {...}
+ * It takes 2 arguments : the relative path and the file.
+ * @return {Array} An array of matching elements.
+ */
+ filter: function(search) {
+ var result = [],
+ filename, relativePath, file, fileClone;
+ for (filename in this.files) {
+ if (!this.files.hasOwnProperty(filename)) {
+ continue;
+ }
+ file = this.files[filename];
+ // return a new object, don't let the user mess with our internal objects :)
+ fileClone = new ZipObject(file.name, file._data, extend(file.options));
+ relativePath = filename.slice(this.root.length, filename.length);
+ if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
+ search(relativePath, fileClone)) { // and the file matches the function
+ result.push(fileClone);
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Add a file to the zip file, or search a file.
+ * @param {string|RegExp} name The name of the file to add (if data is defined),
+ * the name of the file to find (if no data) or a regex to match files.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
+ * @param {Object} o File options
+ * @return {JSZip|Object|Array} this JSZip object (when adding a file),
+ * a file (when searching by string) or an array of files (when searching by regex).
+ */
+ file: function(name, data, o) {
+ if (arguments.length === 1) {
+ if (utils.isRegExp(name)) {
+ var regexp = name;
+ return this.filter(function(relativePath, file) {
+ return !file.dir && regexp.test(relativePath);
+ });
+ }
+ else { // text
+ return this.filter(function(relativePath, file) {
+ return !file.dir && relativePath === name;
+ })[0] || null;
+ }
+ }
+ else { // more than one argument : we have data !
+ name = this.root + name;
+ fileAdd.call(this, name, data, o);
+ }
+ return this;
+ },
+
+ /**
+ * Add a directory to the zip file, or search.
+ * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
+ * @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
+ */
+ folder: function(arg) {
+ if (!arg) {
+ return this;
+ }
+
+ if (utils.isRegExp(arg)) {
+ return this.filter(function(relativePath, file) {
+ return file.dir && arg.test(relativePath);
+ });
+ }
+
+ // else, name is a new folder
+ var name = this.root + arg;
+ var newFolder = folderAdd.call(this, name);
+
+ // Allow chaining by returning a new object with this folder as the root
+ var ret = this.clone();
+ ret.root = newFolder.name;
+ return ret;
+ },
+
+ /**
+ * Delete a file, or a directory and all sub-files, from the zip
+ * @param {string} name the name of the file to delete
+ * @return {JSZip} this JSZip object
+ */
+ remove: function(name) {
+ name = this.root + name;
+ var file = this.files[name];
+ if (!file) {
+ // Look for any folders
+ if (name.slice(-1) != "/") {
+ name += "/";
+ }
+ file = this.files[name];
+ }
+
+ if (file && !file.dir) {
+ // file
+ delete this.files[name];
+ } else {
+ // maybe a folder, delete recursively
+ var kids = this.filter(function(relativePath, file) {
+ return file.name.slice(0, name.length) === name;
+ });
+ for (var i = 0; i < kids.length; i++) {
+ delete this.files[kids[i].name];
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * Generate the complete zip file
+ * @param {Object} options the options to generate the zip file :
+ * - base64, (deprecated, use type instead) true to generate base64.
+ * - compression, "STORE" by default.
+ * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
+ * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
+ */
+ generate: function(options) {
+ options = extend(options || {}, {
+ base64: true,
+ compression: "STORE",
+ compressionOptions : null,
+ type: "base64",
+ platform: "DOS",
+ comment: null,
+ mimeType: 'application/zip'
+ });
+
+ utils.checkSupport(options.type);
+
+ // accept nodejs `process.platform`
+ if(
+ options.platform === 'darwin' ||
+ options.platform === 'freebsd' ||
+ options.platform === 'linux' ||
+ options.platform === 'sunos'
+ ) {
+ options.platform = "UNIX";
+ }
+ if (options.platform === 'win32') {
+ options.platform = "DOS";
+ }
+
+ var zipData = [],
+ localDirLength = 0,
+ centralDirLength = 0,
+ writer, i,
+ utfEncodedComment = utils.transformTo("string", this.utf8encode(options.comment || this.comment || ""));
+
+ // first, generate all the zip parts.
+ for (var name in this.files) {
+ if (!this.files.hasOwnProperty(name)) {
+ continue;
+ }
+ var file = this.files[name];
+
+ var compressionName = file.options.compression || options.compression.toUpperCase();
+ var compression = compressions[compressionName];
+ if (!compression) {
+ throw new Error(compressionName + " is not a valid compression method !");
+ }
+ var compressionOptions = file.options.compressionOptions || options.compressionOptions || {};
+
+ var compressedObject = generateCompressedObjectFrom.call(this, file, compression, compressionOptions);
+
+ var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength, options.platform);
+ localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;
+ centralDirLength += zipPart.dirRecord.length;
+ zipData.push(zipPart);
+ }
+
+ var dirEnd = "";
+
+ // end of central dir signature
+ dirEnd = signature.CENTRAL_DIRECTORY_END +
+ // number of this disk
+ "\x00\x00" +
+ // number of the disk with the start of the central directory
+ "\x00\x00" +
+ // total number of entries in the central directory on this disk
+ decToHex(zipData.length, 2) +
+ // total number of entries in the central directory
+ decToHex(zipData.length, 2) +
+ // size of the central directory 4 bytes
+ decToHex(centralDirLength, 4) +
+ // offset of start of central directory with respect to the starting disk number
+ decToHex(localDirLength, 4) +
+ // .ZIP file comment length
+ decToHex(utfEncodedComment.length, 2) +
+ // .ZIP file comment
+ utfEncodedComment;
+
+
+ // we have all the parts (and the total length)
+ // time to create a writer !
+ var typeName = options.type.toLowerCase();
+ if(typeName==="uint8array"||typeName==="arraybuffer"||typeName==="blob"||typeName==="nodebuffer") {
+ writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);
+ }else{
+ writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);
+ }
+
+ for (i = 0; i < zipData.length; i++) {
+ writer.append(zipData[i].fileRecord);
+ writer.append(zipData[i].compressedObject.compressedContent);
+ }
+ for (i = 0; i < zipData.length; i++) {
+ writer.append(zipData[i].dirRecord);
+ }
+
+ writer.append(dirEnd);
+
+ var zip = writer.finalize();
+
+
+
+ switch(options.type.toLowerCase()) {
+ // case "zip is an Uint8Array"
+ case "uint8array" :
+ case "arraybuffer" :
+ case "nodebuffer" :
+ return utils.transformTo(options.type.toLowerCase(), zip);
+ case "blob" :
+ return utils.arrayBuffer2Blob(utils.transformTo("arraybuffer", zip), options.mimeType);
+ // case "zip is a string"
+ case "base64" :
+ return (options.base64) ? base64.encode(zip) : zip;
+ default : // case "string" :
+ return zip;
+ }
+
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ crc32: function (input, crc) {
+ return crc32(input, crc);
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ utf8encode: function (string) {
+ return utils.transformTo("string", utf8.utf8encode(string));
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ utf8decode: function (input) {
+ return utf8.utf8decode(input);
+ }
+};
+module.exports = out;
+
+},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(_dereq_,module,exports){
+'use strict';
+exports.LOCAL_FILE_HEADER = "PK\x03\x04";
+exports.CENTRAL_FILE_HEADER = "PK\x01\x02";
+exports.CENTRAL_DIRECTORY_END = "PK\x05\x06";
+exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07";
+exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06";
+exports.DATA_DESCRIPTOR = "PK\x07\x08";
+
+},{}],15:[function(_dereq_,module,exports){
+'use strict';
+var DataReader = _dereq_('./dataReader');
+var utils = _dereq_('./utils');
+
+function StringReader(data, optimizedBinaryString) {
+ this.data = data;
+ if (!optimizedBinaryString) {
+ this.data = utils.string2binary(this.data);
+ }
+ this.length = this.data.length;
+ this.index = 0;
+}
+StringReader.prototype = new DataReader();
+/**
+ * @see DataReader.byteAt
+ */
+StringReader.prototype.byteAt = function(i) {
+ return this.data.charCodeAt(i);
+};
+/**
+ * @see DataReader.lastIndexOfSignature
+ */
+StringReader.prototype.lastIndexOfSignature = function(sig) {
+ return this.data.lastIndexOf(sig);
+};
+/**
+ * @see DataReader.readData
+ */
+StringReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ // this will work because the constructor applied the "& 0xff" mask.
+ var result = this.data.slice(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = StringReader;
+
+},{"./dataReader":5,"./utils":21}],16:[function(_dereq_,module,exports){
+'use strict';
+
+var utils = _dereq_('./utils');
+
+/**
+ * An object to write any content to a string.
+ * @constructor
+ */
+var StringWriter = function() {
+ this.data = [];
+};
+StringWriter.prototype = {
+ /**
+ * Append any content to the current string.
+ * @param {Object} input the content to add.
+ */
+ append: function(input) {
+ input = utils.transformTo("string", input);
+ this.data.push(input);
+ },
+ /**
+ * Finalize the construction an return the result.
+ * @return {string} the generated string.
+ */
+ finalize: function() {
+ return this.data.join("");
+ }
+};
+
+module.exports = StringWriter;
+
+},{"./utils":21}],17:[function(_dereq_,module,exports){
+(function (Buffer){
+'use strict';
+exports.base64 = true;
+exports.array = true;
+exports.string = true;
+exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
+// contains true if JSZip can read/generate nodejs Buffer, false otherwise.
+// Browserify will provide a Buffer implementation for browsers, which is
+// an augmented Uint8Array (i.e., can be used as either Buffer or U8).
+exports.nodebuffer = typeof Buffer !== "undefined";
+// contains true if JSZip can read/generate Uint8Array, false otherwise.
+exports.uint8array = typeof Uint8Array !== "undefined";
+
+if (typeof ArrayBuffer === "undefined") {
+ exports.blob = false;
+}
+else {
+ var buffer = new ArrayBuffer(0);
+ try {
+ exports.blob = new Blob([buffer], {
+ type: "application/zip"
+ }).size === 0;
+ }
+ catch (e) {
+ try {
+ var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ var builder = new Builder();
+ builder.append(buffer);
+ exports.blob = builder.getBlob('application/zip').size === 0;
+ }
+ catch (e) {
+ exports.blob = false;
+ }
+ }
+}
+
+}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined))
+},{}],18:[function(_dereq_,module,exports){
+'use strict';
+var DataReader = _dereq_('./dataReader');
+
+function Uint8ArrayReader(data) {
+ if (data) {
+ this.data = data;
+ this.length = this.data.length;
+ this.index = 0;
+ }
+}
+Uint8ArrayReader.prototype = new DataReader();
+/**
+ * @see DataReader.byteAt
+ */
+Uint8ArrayReader.prototype.byteAt = function(i) {
+ return this.data[i];
+};
+/**
+ * @see DataReader.lastIndexOfSignature
+ */
+Uint8ArrayReader.prototype.lastIndexOfSignature = function(sig) {
+ var sig0 = sig.charCodeAt(0),
+ sig1 = sig.charCodeAt(1),
+ sig2 = sig.charCodeAt(2),
+ sig3 = sig.charCodeAt(3);
+ for (var i = this.length - 4; i >= 0; --i) {
+ if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) {
+ return i;
+ }
+ }
+
+ return -1;
+};
+/**
+ * @see DataReader.readData
+ */
+Uint8ArrayReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ if(size === 0) {
+ // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of [].
+ return new Uint8Array(0);
+ }
+ var result = this.data.subarray(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = Uint8ArrayReader;
+
+},{"./dataReader":5}],19:[function(_dereq_,module,exports){
+'use strict';
+
+var utils = _dereq_('./utils');
+
+/**
+ * An object to write any content to an Uint8Array.
+ * @constructor
+ * @param {number} length The length of the array.
+ */
+var Uint8ArrayWriter = function(length) {
+ this.data = new Uint8Array(length);
+ this.index = 0;
+};
+Uint8ArrayWriter.prototype = {
+ /**
+ * Append any content to the current array.
+ * @param {Object} input the content to add.
+ */
+ append: function(input) {
+ if (input.length !== 0) {
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
+ input = utils.transformTo("uint8array", input);
+ this.data.set(input, this.index);
+ this.index += input.length;
+ }
+ },
+ /**
+ * Finalize the construction an return the result.
+ * @return {Uint8Array} the generated array.
+ */
+ finalize: function() {
+ return this.data;
+ }
+};
+
+module.exports = Uint8ArrayWriter;
+
+},{"./utils":21}],20:[function(_dereq_,module,exports){
+'use strict';
+
+var utils = _dereq_('./utils');
+var support = _dereq_('./support');
+var nodeBuffer = _dereq_('./nodeBuffer');
+
+/**
+ * The following functions come from pako, from pako/lib/utils/strings
+ * released under the MIT license, see pako https://github.com/nodeca/pako/
+ */
+
+// Table with utf8 lengths (calculated by first byte of sequence)
+// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
+// because max possible codepoint is 0x10ffff
+var _utf8len = new Array(256);
+for (var i=0; i<256; i++) {
+ _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
+}
+_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
+
+// convert string to array (typed, when possible)
+var string2buf = function (str) {
+ var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
+
+ // count binary size
+ for (m_pos = 0; m_pos < str_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
+ }
+
+ // allocate buffer
+ if (support.uint8array) {
+ buf = new Uint8Array(buf_len);
+ } else {
+ buf = new Array(buf_len);
+ }
+
+ // convert
+ for (i=0, m_pos = 0; i < buf_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ if (c < 0x80) {
+ /* one byte */
+ buf[i++] = c;
+ } else if (c < 0x800) {
+ /* two bytes */
+ buf[i++] = 0xC0 | (c >>> 6);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else if (c < 0x10000) {
+ /* three bytes */
+ buf[i++] = 0xE0 | (c >>> 12);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else {
+ /* four bytes */
+ buf[i++] = 0xf0 | (c >>> 18);
+ buf[i++] = 0x80 | (c >>> 12 & 0x3f);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ }
+ }
+
+ return buf;
+};
+
+// Calculate max possible position in utf8 buffer,
+// that will not break sequence. If that's not possible
+// - (very small limits) return max size as is.
+//
+// buf[] - utf8 bytes array
+// max - length limit (mandatory);
+var utf8border = function(buf, max) {
+ var pos;
+
+ max = max || buf.length;
+ if (max > buf.length) { max = buf.length; }
+
+ // go back from last position, until start of sequence found
+ pos = max-1;
+ while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
+
+ // Fuckup - very small and broken sequence,
+ // return max, because we should return something anyway.
+ if (pos < 0) { return max; }
+
+ // If we came to start of buffer - that means vuffer is too small,
+ // return max too.
+ if (pos === 0) { return max; }
+
+ return (pos + _utf8len[buf[pos]] > max) ? pos : max;
+};
+
+// convert array to string
+var buf2string = function (buf) {
+ var str, i, out, c, c_len;
+ var len = buf.length;
+
+ // Reserve max possible length (2 words per char)
+ // NB: by unknown reasons, Array is significantly faster for
+ // String.fromCharCode.apply than Uint16Array.
+ var utf16buf = new Array(len*2);
+
+ for (out=0, i=0; i<len;) {
+ c = buf[i++];
+ // quick process ascii
+ if (c < 0x80) { utf16buf[out++] = c; continue; }
+
+ c_len = _utf8len[c];
+ // skip 5 & 6 byte codes
+ if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
+
+ // apply mask on first byte
+ c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
+ // join the rest
+ while (c_len > 1 && i < len) {
+ c = (c << 6) | (buf[i++] & 0x3f);
+ c_len--;
+ }
+
+ // terminated by end of string?
+ if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
+
+ if (c < 0x10000) {
+ utf16buf[out++] = c;
+ } else {
+ c -= 0x10000;
+ utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
+ utf16buf[out++] = 0xdc00 | (c & 0x3ff);
+ }
+ }
+
+ // shrinkBuf(utf16buf, out)
+ if (utf16buf.length !== out) {
+ if(utf16buf.subarray) {
+ utf16buf = utf16buf.subarray(0, out);
+ } else {
+ utf16buf.length = out;
+ }
+ }
+
+ // return String.fromCharCode.apply(null, utf16buf);
+ return utils.applyFromCharCode(utf16buf);
+};
+
+
+// That's all for the pako functions.
+
+
+/**
+ * Transform a javascript string into an array (typed if possible) of bytes,
+ * UTF-8 encoded.
+ * @param {String} str the string to encode
+ * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string.
+ */
+exports.utf8encode = function utf8encode(str) {
+ if (support.nodebuffer) {
+ return nodeBuffer(str, "utf-8");
+ }
+
+ return string2buf(str);
+};
+
+
+/**
+ * Transform a bytes array (or a representation) representing an UTF-8 encoded
+ * string into a javascript string.
+ * @param {Array|Uint8Array|Buffer} buf the data de decode
+ * @return {String} the decoded string.
+ */
+exports.utf8decode = function utf8decode(buf) {
+ if (support.nodebuffer) {
+ return utils.transformTo("nodebuffer", buf).toString("utf-8");
+ }
+
+ buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf);
+
+ // return buf2string(buf);
+ // Chrome prefers to work with "small" chunks of data
+ // for the method buf2string.
+ // Firefox and Chrome has their own shortcut, IE doesn't seem to really care.
+ var result = [], k = 0, len = buf.length, chunk = 65536;
+ while (k < len) {
+ var nextBoundary = utf8border(buf, Math.min(k + chunk, len));
+ if (support.uint8array) {
+ result.push(buf2string(buf.subarray(k, nextBoundary)));
+ } else {
+ result.push(buf2string(buf.slice(k, nextBoundary)));
+ }
+ k = nextBoundary;
+ }
+ return result.join("");
+
+};
+// vim: set shiftwidth=4 softtabstop=4:
+
+},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(_dereq_,module,exports){
+'use strict';
+var support = _dereq_('./support');
+var compressions = _dereq_('./compressions');
+var nodeBuffer = _dereq_('./nodeBuffer');
+/**
+ * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
+ * @param {string} str the string to transform.
+ * @return {String} the binary string.
+ */
+exports.string2binary = function(str) {
+ var result = "";
+ for (var i = 0; i < str.length; i++) {
+ result += String.fromCharCode(str.charCodeAt(i) & 0xff);
+ }
+ return result;
+};
+exports.arrayBuffer2Blob = function(buffer, mimeType) {
+ exports.checkSupport("blob");
+ mimeType = mimeType || 'application/zip';
+
+ try {
+ // Blob constructor
+ return new Blob([buffer], {
+ type: mimeType
+ });
+ }
+ catch (e) {
+
+ try {
+ // deprecated, browser only, old way
+ var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ var builder = new Builder();
+ builder.append(buffer);
+ return builder.getBlob(mimeType);
+ }
+ catch (e) {
+
+ // well, fuck ?!
+ throw new Error("Bug : can't construct the Blob.");
+ }
+ }
+
+
+};
+/**
+ * The identity function.
+ * @param {Object} input the input.
+ * @return {Object} the same input.
+ */
+function identity(input) {
+ return input;
+}
+
+/**
+ * Fill in an array with a string.
+ * @param {String} str the string to use.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
+ */
+function stringToArrayLike(str, array) {
+ for (var i = 0; i < str.length; ++i) {
+ array[i] = str.charCodeAt(i) & 0xFF;
+ }
+ return array;
+}
+
+/**
+ * Transform an array-like object to a string.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
+ * @return {String} the result.
+ */
+function arrayLikeToString(array) {
+ // Performances notes :
+ // --------------------
+ // String.fromCharCode.apply(null, array) is the fastest, see
+ // see http://jsperf.com/converting-a-uint8array-to-a-string/2
+ // but the stack is limited (and we can get huge arrays !).
+ //
+ // result += String.fromCharCode(array[i]); generate too many strings !
+ //
+ // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
+ var chunk = 65536;
+ var result = [],
+ len = array.length,
+ type = exports.getTypeOf(array),
+ k = 0,
+ canUseApply = true;
+ try {
+ switch(type) {
+ case "uint8array":
+ String.fromCharCode.apply(null, new Uint8Array(0));
+ break;
+ case "nodebuffer":
+ String.fromCharCode.apply(null, nodeBuffer(0));
+ break;
+ }
+ } catch(e) {
+ canUseApply = false;
+ }
+
+ // no apply : slow and painful algorithm
+ // default browser on android 4.*
+ if (!canUseApply) {
+ var resultStr = "";
+ for(var i = 0; i < array.length;i++) {
+ resultStr += String.fromCharCode(array[i]);
+ }
+ return resultStr;
+ }
+ while (k < len && chunk > 1) {
+ try {
+ if (type === "array" || type === "nodebuffer") {
+ result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));
+ }
+ else {
+ result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));
+ }
+ k += chunk;
+ }
+ catch (e) {
+ chunk = Math.floor(chunk / 2);
+ }
+ }
+ return result.join("");
+}
+
+exports.applyFromCharCode = arrayLikeToString;
+
+
+/**
+ * Copy the data from an array-like to an other array-like.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
+ */
+function arrayLikeToArrayLike(arrayFrom, arrayTo) {
+ for (var i = 0; i < arrayFrom.length; i++) {
+ arrayTo[i] = arrayFrom[i];
+ }
+ return arrayTo;
+}
+
+// a matrix containing functions to transform everything into everything.
+var transform = {};
+
+// string to ?
+transform["string"] = {
+ "string": identity,
+ "array": function(input) {
+ return stringToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return transform["string"]["uint8array"](input).buffer;
+ },
+ "uint8array": function(input) {
+ return stringToArrayLike(input, new Uint8Array(input.length));
+ },
+ "nodebuffer": function(input) {
+ return stringToArrayLike(input, nodeBuffer(input.length));
+ }
+};
+
+// array to ?
+transform["array"] = {
+ "string": arrayLikeToString,
+ "array": identity,
+ "arraybuffer": function(input) {
+ return (new Uint8Array(input)).buffer;
+ },
+ "uint8array": function(input) {
+ return new Uint8Array(input);
+ },
+ "nodebuffer": function(input) {
+ return nodeBuffer(input);
+ }
+};
+
+// arraybuffer to ?
+transform["arraybuffer"] = {
+ "string": function(input) {
+ return arrayLikeToString(new Uint8Array(input));
+ },
+ "array": function(input) {
+ return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
+ },
+ "arraybuffer": identity,
+ "uint8array": function(input) {
+ return new Uint8Array(input);
+ },
+ "nodebuffer": function(input) {
+ return nodeBuffer(new Uint8Array(input));
+ }
+};
+
+// uint8array to ?
+transform["uint8array"] = {
+ "string": arrayLikeToString,
+ "array": function(input) {
+ return arrayLikeToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return input.buffer;
+ },
+ "uint8array": identity,
+ "nodebuffer": function(input) {
+ return nodeBuffer(input);
+ }
+};
+
+// nodebuffer to ?
+transform["nodebuffer"] = {
+ "string": arrayLikeToString,
+ "array": function(input) {
+ return arrayLikeToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return transform["nodebuffer"]["uint8array"](input).buffer;
+ },
+ "uint8array": function(input) {
+ return arrayLikeToArrayLike(input, new Uint8Array(input.length));
+ },
+ "nodebuffer": identity
+};
+
+/**
+ * Transform an input into any type.
+ * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
+ * If no output type is specified, the unmodified input will be returned.
+ * @param {String} outputType the output type.
+ * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
+ * @throws {Error} an Error if the browser doesn't support the requested output type.
+ */
+exports.transformTo = function(outputType, input) {
+ if (!input) {
+ // undefined, null, etc
+ // an empty string won't harm.
+ input = "";
+ }
+ if (!outputType) {
+ return input;
+ }
+ exports.checkSupport(outputType);
+ var inputType = exports.getTypeOf(input);
+ var result = transform[inputType][outputType](input);
+ return result;
+};
+
+/**
+ * Return the type of the input.
+ * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
+ * @param {Object} input the input to identify.
+ * @return {String} the (lowercase) type of the input.
+ */
+exports.getTypeOf = function(input) {
+ if (typeof input === "string") {
+ return "string";
+ }
+ if (Object.prototype.toString.call(input) === "[object Array]") {
+ return "array";
+ }
+ if (support.nodebuffer && nodeBuffer.test(input)) {
+ return "nodebuffer";
+ }
+ if (support.uint8array && input instanceof Uint8Array) {
+ return "uint8array";
+ }
+ if (support.arraybuffer && input instanceof ArrayBuffer) {
+ return "arraybuffer";
+ }
+};
+
+/**
+ * Throw an exception if the type is not supported.
+ * @param {String} type the type to check.
+ * @throws {Error} an Error if the browser doesn't support the requested type.
+ */
+exports.checkSupport = function(type) {
+ var supported = support[type.toLowerCase()];
+ if (!supported) {
+ throw new Error(type + " is not supported by this browser");
+ }
+};
+exports.MAX_VALUE_16BITS = 65535;
+exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1
+
+/**
+ * Prettify a string read as binary.
+ * @param {string} str the string to prettify.
+ * @return {string} a pretty string.
+ */
+exports.pretty = function(str) {
+ var res = '',
+ code, i;
+ for (i = 0; i < (str || "").length; i++) {
+ code = str.charCodeAt(i);
+ res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
+ }
+ return res;
+};
+
+/**
+ * Find a compression registered in JSZip.
+ * @param {string} compressionMethod the method magic to find.
+ * @return {Object|null} the JSZip compression object, null if none found.
+ */
+exports.findCompression = function(compressionMethod) {
+ for (var method in compressions) {
+ if (!compressions.hasOwnProperty(method)) {
+ continue;
+ }
+ if (compressions[method].magic === compressionMethod) {
+ return compressions[method];
+ }
+ }
+ return null;
+};
+/**
+* Cross-window, cross-Node-context regular expression detection
+* @param {Object} object Anything
+* @return {Boolean} true if the object is a regular expression,
+* false otherwise
+*/
+exports.isRegExp = function (object) {
+ return Object.prototype.toString.call(object) === "[object RegExp]";
+};
+
+
+},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(_dereq_,module,exports){
+'use strict';
+var StringReader = _dereq_('./stringReader');
+var NodeBufferReader = _dereq_('./nodeBufferReader');
+var Uint8ArrayReader = _dereq_('./uint8ArrayReader');
+var utils = _dereq_('./utils');
+var sig = _dereq_('./signature');
+var ZipEntry = _dereq_('./zipEntry');
+var support = _dereq_('./support');
+var jszipProto = _dereq_('./object');
+// class ZipEntries {{{
+/**
+ * All the entries in the zip file.
+ * @constructor
+ * @param {String|ArrayBuffer|Uint8Array} data the binary stream to load.
+ * @param {Object} loadOptions Options for loading the stream.
+ */
+function ZipEntries(data, loadOptions) {
+ this.files = [];
+ this.loadOptions = loadOptions;
+ if (data) {
+ this.load(data);
+ }
+}
+ZipEntries.prototype = {
+ /**
+ * Check that the reader is on the speficied signature.
+ * @param {string} expectedSignature the expected signature.
+ * @throws {Error} if it is an other signature.
+ */
+ checkSignature: function(expectedSignature) {
+ var signature = this.reader.readString(4);
+ if (signature !== expectedSignature) {
+ throw new Error("Corrupted zip or bug : unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")");
+ }
+ },
+ /**
+ * Read the end of the central directory.
+ */
+ readBlockEndOfCentral: function() {
+ this.diskNumber = this.reader.readInt(2);
+ this.diskWithCentralDirStart = this.reader.readInt(2);
+ this.centralDirRecordsOnThisDisk = this.reader.readInt(2);
+ this.centralDirRecords = this.reader.readInt(2);
+ this.centralDirSize = this.reader.readInt(4);
+ this.centralDirOffset = this.reader.readInt(4);
+
+ this.zipCommentLength = this.reader.readInt(2);
+ // warning : the encoding depends of the system locale
+ // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded.
+ // On a windows machine, this field is encoded with the localized windows code page.
+ this.zipComment = this.reader.readString(this.zipCommentLength);
+ // To get consistent behavior with the generation part, we will assume that
+ // this is utf8 encoded.
+ this.zipComment = jszipProto.utf8decode(this.zipComment);
+ },
+ /**
+ * Read the end of the Zip 64 central directory.
+ * Not merged with the method readEndOfCentral :
+ * The end of central can coexist with its Zip64 brother,
+ * I don't want to read the wrong number of bytes !
+ */
+ readBlockZip64EndOfCentral: function() {
+ this.zip64EndOfCentralSize = this.reader.readInt(8);
+ this.versionMadeBy = this.reader.readString(2);
+ this.versionNeeded = this.reader.readInt(2);
+ this.diskNumber = this.reader.readInt(4);
+ this.diskWithCentralDirStart = this.reader.readInt(4);
+ this.centralDirRecordsOnThisDisk = this.reader.readInt(8);
+ this.centralDirRecords = this.reader.readInt(8);
+ this.centralDirSize = this.reader.readInt(8);
+ this.centralDirOffset = this.reader.readInt(8);
+
+ this.zip64ExtensibleData = {};
+ var extraDataSize = this.zip64EndOfCentralSize - 44,
+ index = 0,
+ extraFieldId,
+ extraFieldLength,
+ extraFieldValue;
+ while (index < extraDataSize) {
+ extraFieldId = this.reader.readInt(2);
+ extraFieldLength = this.reader.readInt(4);
+ extraFieldValue = this.reader.readString(extraFieldLength);
+ this.zip64ExtensibleData[extraFieldId] = {
+ id: extraFieldId,
+ length: extraFieldLength,
+ value: extraFieldValue
+ };
+ }
+ },
+ /**
+ * Read the end of the Zip 64 central directory locator.
+ */
+ readBlockZip64EndOfCentralLocator: function() {
+ this.diskWithZip64CentralDirStart = this.reader.readInt(4);
+ this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);
+ this.disksCount = this.reader.readInt(4);
+ if (this.disksCount > 1) {
+ throw new Error("Multi-volumes zip are not supported");
+ }
+ },
+ /**
+ * Read the local files, based on the offset read in the central part.
+ */
+ readLocalFiles: function() {
+ var i, file;
+ for (i = 0; i < this.files.length; i++) {
+ file = this.files[i];
+ this.reader.setIndex(file.localHeaderOffset);
+ this.checkSignature(sig.LOCAL_FILE_HEADER);
+ file.readLocalPart(this.reader);
+ file.handleUTF8();
+ file.processAttributes();
+ }
+ },
+ /**
+ * Read the central directory.
+ */
+ readCentralDir: function() {
+ var file;
+
+ this.reader.setIndex(this.centralDirOffset);
+ while (this.reader.readString(4) === sig.CENTRAL_FILE_HEADER) {
+ file = new ZipEntry({
+ zip64: this.zip64
+ }, this.loadOptions);
+ file.readCentralPart(this.reader);
+ this.files.push(file);
+ }
+ },
+ /**
+ * Read the end of central directory.
+ */
+ readEndOfCentral: function() {
+ var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END);
+ if (offset === -1) {
+ // Check if the content is a truncated zip or complete garbage.
+ // A "LOCAL_FILE_HEADER" is not required at the beginning (auto
+ // extractible zip for example) but it can give a good hint.
+ // If an ajax request was used without responseType, we will also
+ // get unreadable data.
+ var isGarbage = true;
+ try {
+ this.reader.setIndex(0);
+ this.checkSignature(sig.LOCAL_FILE_HEADER);
+ isGarbage = false;
+ } catch (e) {}
+
+ if (isGarbage) {
+ throw new Error("Can't find end of central directory : is this a zip file ? " +
+ "If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html");
+ } else {
+ throw new Error("Corrupted zip : can't find end of central directory");
+ }
+ }
+ this.reader.setIndex(offset);
+ this.checkSignature(sig.CENTRAL_DIRECTORY_END);
+ this.readBlockEndOfCentral();
+
+
+ /* extract from the zip spec :
+ 4) If one of the fields in the end of central directory
+ record is too small to hold required data, the field
+ should be set to -1 (0xFFFF or 0xFFFFFFFF) and the
+ ZIP64 format record should be created.
+ 5) The end of central directory record and the
+ Zip64 end of central directory locator record must
+ reside on the same disk when splitting or spanning
+ an archive.
+ */
+ if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) {
+ this.zip64 = true;
+
+ /*
+ Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from
+ the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents
+ all numbers as 64-bit double precision IEEE 754 floating point numbers.
+ So, we have 53bits for integers and bitwise operations treat everything as 32bits.
+ see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
+ and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5
+ */
+
+ // should look for a zip64 EOCD locator
+ offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
+ if (offset === -1) {
+ throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");
+ }
+ this.reader.setIndex(offset);
+ this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
+ this.readBlockZip64EndOfCentralLocator();
+
+ // now the zip64 EOCD record
+ this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);
+ this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END);
+ this.readBlockZip64EndOfCentral();
+ }
+ },
+ prepareReader: function(data) {
+ var type = utils.getTypeOf(data);
+ if (type === "string" && !support.uint8array) {
+ this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString);
+ }
+ else if (type === "nodebuffer") {
+ this.reader = new NodeBufferReader(data);
+ }
+ else {
+ this.reader = new Uint8ArrayReader(utils.transformTo("uint8array", data));
+ }
+ },
+ /**
+ * Read a zip file and create ZipEntries.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.
+ */
+ load: function(data) {
+ this.prepareReader(data);
+ this.readEndOfCentral();
+ this.readCentralDir();
+ this.readLocalFiles();
+ }
+};
+// }}} end of ZipEntries
+module.exports = ZipEntries;
+
+},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(_dereq_,module,exports){
+'use strict';
+var StringReader = _dereq_('./stringReader');
+var utils = _dereq_('./utils');
+var CompressedObject = _dereq_('./compressedObject');
+var jszipProto = _dereq_('./object');
+
+var MADE_BY_DOS = 0x00;
+var MADE_BY_UNIX = 0x03;
+
+// class ZipEntry {{{
+/**
+ * An entry in the zip file.
+ * @constructor
+ * @param {Object} options Options of the current file.
+ * @param {Object} loadOptions Options for loading the stream.
+ */
+function ZipEntry(options, loadOptions) {
+ this.options = options;
+ this.loadOptions = loadOptions;
+}
+ZipEntry.prototype = {
+ /**
+ * say if the file is encrypted.
+ * @return {boolean} true if the file is encrypted, false otherwise.
+ */
+ isEncrypted: function() {
+ // bit 1 is set
+ return (this.bitFlag & 0x0001) === 0x0001;
+ },
+ /**
+ * say if the file has utf-8 filename/comment.
+ * @return {boolean} true if the filename/comment is in utf-8, false otherwise.
+ */
+ useUTF8: function() {
+ // bit 11 is set
+ return (this.bitFlag & 0x0800) === 0x0800;
+ },
+ /**
+ * Prepare the function used to generate the compressed content from this ZipFile.
+ * @param {DataReader} reader the reader to use.
+ * @param {number} from the offset from where we should read the data.
+ * @param {number} length the length of the data to read.
+ * @return {Function} the callback to get the compressed content (the type depends of the DataReader class).
+ */
+ prepareCompressedContent: function(reader, from, length) {
+ return function() {
+ var previousIndex = reader.index;
+ reader.setIndex(from);
+ var compressedFileData = reader.readData(length);
+ reader.setIndex(previousIndex);
+
+ return compressedFileData;
+ };
+ },
+ /**
+ * Prepare the function used to generate the uncompressed content from this ZipFile.
+ * @param {DataReader} reader the reader to use.
+ * @param {number} from the offset from where we should read the data.
+ * @param {number} length the length of the data to read.
+ * @param {JSZip.compression} compression the compression used on this file.
+ * @param {number} uncompressedSize the uncompressed size to expect.
+ * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class).
+ */
+ prepareContent: function(reader, from, length, compression, uncompressedSize) {
+ return function() {
+
+ var compressedFileData = utils.transformTo(compression.uncompressInputType, this.getCompressedContent());
+ var uncompressedFileData = compression.uncompress(compressedFileData);
+
+ if (uncompressedFileData.length !== uncompressedSize) {
+ throw new Error("Bug : uncompressed data size mismatch");
+ }
+
+ return uncompressedFileData;
+ };
+ },
+ /**
+ * Read the local part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readLocalPart: function(reader) {
+ var compression, localExtraFieldsLength;
+
+ // we already know everything from the central dir !
+ // If the central dir data are false, we are doomed.
+ // On the bright side, the local part is scary : zip64, data descriptors, both, etc.
+ // The less data we get here, the more reliable this should be.
+ // Let's skip the whole header and dash to the data !
+ reader.skip(22);
+ // in some zip created on windows, the filename stored in the central dir contains \ instead of /.
+ // Strangely, the filename here is OK.
+ // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes
+ // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators...
+ // Search "unzip mismatching "local" filename continuing with "central" filename version" on
+ // the internet.
+ //
+ // I think I see the logic here : the central directory is used to display
+ // content and the local directory is used to extract the files. Mixing / and \
+ // may be used to display \ to windows users and use / when extracting the files.
+ // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394
+ this.fileNameLength = reader.readInt(2);
+ localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir
+ this.fileName = reader.readString(this.fileNameLength);
+ reader.skip(localExtraFieldsLength);
+
+ if (this.compressedSize == -1 || this.uncompressedSize == -1) {
+ throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize == -1 || uncompressedSize == -1)");
+ }
+
+ compression = utils.findCompression(this.compressionMethod);
+ if (compression === null) { // no compression found
+ throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")");
+ }
+ this.decompressed = new CompressedObject();
+ this.decompressed.compressedSize = this.compressedSize;
+ this.decompressed.uncompressedSize = this.uncompressedSize;
+ this.decompressed.crc32 = this.crc32;
+ this.decompressed.compressionMethod = this.compressionMethod;
+ this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression);
+ this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize);
+
+ // we need to compute the crc32...
+ if (this.loadOptions.checkCRC32) {
+ this.decompressed = utils.transformTo("string", this.decompressed.getContent());
+ if (jszipProto.crc32(this.decompressed) !== this.crc32) {
+ throw new Error("Corrupted zip : CRC32 mismatch");
+ }
+ }
+ },
+
+ /**
+ * Read the central part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readCentralPart: function(reader) {
+ this.versionMadeBy = reader.readInt(2);
+ this.versionNeeded = reader.readInt(2);
+ this.bitFlag = reader.readInt(2);
+ this.compressionMethod = reader.readString(2);
+ this.date = reader.readDate();
+ this.crc32 = reader.readInt(4);
+ this.compressedSize = reader.readInt(4);
+ this.uncompressedSize = reader.readInt(4);
+ this.fileNameLength = reader.readInt(2);
+ this.extraFieldsLength = reader.readInt(2);
+ this.fileCommentLength = reader.readInt(2);
+ this.diskNumberStart = reader.readInt(2);
+ this.internalFileAttributes = reader.readInt(2);
+ this.externalFileAttributes = reader.readInt(4);
+ this.localHeaderOffset = reader.readInt(4);
+
+ if (this.isEncrypted()) {
+ throw new Error("Encrypted zip are not supported");
+ }
+
+ this.fileName = reader.readString(this.fileNameLength);
+ this.readExtraFields(reader);
+ this.parseZIP64ExtraField(reader);
+ this.fileComment = reader.readString(this.fileCommentLength);
+ },
+
+ /**
+ * Parse the external file attributes and get the unix/dos permissions.
+ */
+ processAttributes: function () {
+ this.unixPermissions = null;
+ this.dosPermissions = null;
+ var madeBy = this.versionMadeBy >> 8;
+
+ // Check if we have the DOS directory flag set.
+ // We look for it in the DOS and UNIX permissions
+ // but some unknown platform could set it as a compatibility flag.
+ this.dir = this.externalFileAttributes & 0x0010 ? true : false;
+
+ if(madeBy === MADE_BY_DOS) {
+ // first 6 bits (0 to 5)
+ this.dosPermissions = this.externalFileAttributes & 0x3F;
+ }
+
+ if(madeBy === MADE_BY_UNIX) {
+ this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;
+ // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);
+ }
+
+ // fail safe : if the name ends with a / it probably means a folder
+ if (!this.dir && this.fileName.slice(-1) === '/') {
+ this.dir = true;
+ }
+ },
+
+ /**
+ * Parse the ZIP64 extra field and merge the info in the current ZipEntry.
+ * @param {DataReader} reader the reader to use.
+ */
+ parseZIP64ExtraField: function(reader) {
+
+ if (!this.extraFields[0x0001]) {
+ return;
+ }
+
+ // should be something, preparing the extra reader
+ var extraReader = new StringReader(this.extraFields[0x0001].value);
+
+ // I really hope that these 64bits integer can fit in 32 bits integer, because js
+ // won't let us have more.
+ if (this.uncompressedSize === utils.MAX_VALUE_32BITS) {
+ this.uncompressedSize = extraReader.readInt(8);
+ }
+ if (this.compressedSize === utils.MAX_VALUE_32BITS) {
+ this.compressedSize = extraReader.readInt(8);
+ }
+ if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) {
+ this.localHeaderOffset = extraReader.readInt(8);
+ }
+ if (this.diskNumberStart === utils.MAX_VALUE_32BITS) {
+ this.diskNumberStart = extraReader.readInt(4);
+ }
+ },
+ /**
+ * Read the central part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readExtraFields: function(reader) {
+ var start = reader.index,
+ extraFieldId,
+ extraFieldLength,
+ extraFieldValue;
+
+ this.extraFields = this.extraFields || {};
+
+ while (reader.index < start + this.extraFieldsLength) {
+ extraFieldId = reader.readInt(2);
+ extraFieldLength = reader.readInt(2);
+ extraFieldValue = reader.readString(extraFieldLength);
+
+ this.extraFields[extraFieldId] = {
+ id: extraFieldId,
+ length: extraFieldLength,
+ value: extraFieldValue
+ };
+ }
+ },
+ /**
+ * Apply an UTF8 transformation if needed.
+ */
+ handleUTF8: function() {
+ if (this.useUTF8()) {
+ this.fileName = jszipProto.utf8decode(this.fileName);
+ this.fileComment = jszipProto.utf8decode(this.fileComment);
+ } else {
+ var upath = this.findExtraFieldUnicodePath();
+ if (upath !== null) {
+ this.fileName = upath;
+ }
+ var ucomment = this.findExtraFieldUnicodeComment();
+ if (ucomment !== null) {
+ this.fileComment = ucomment;
+ }
+ }
+ },
+
+ /**
+ * Find the unicode path declared in the extra field, if any.
+ * @return {String} the unicode path, null otherwise.
+ */
+ findExtraFieldUnicodePath: function() {
+ var upathField = this.extraFields[0x7075];
+ if (upathField) {
+ var extraReader = new StringReader(upathField.value);
+
+ // wrong version
+ if (extraReader.readInt(1) !== 1) {
+ return null;
+ }
+
+ // the crc of the filename changed, this field is out of date.
+ if (jszipProto.crc32(this.fileName) !== extraReader.readInt(4)) {
+ return null;
+ }
+
+ return jszipProto.utf8decode(extraReader.readString(upathField.length - 5));
+ }
+ return null;
+ },
+
+ /**
+ * Find the unicode comment declared in the extra field, if any.
+ * @return {String} the unicode comment, null otherwise.
+ */
+ findExtraFieldUnicodeComment: function() {
+ var ucommentField = this.extraFields[0x6375];
+ if (ucommentField) {
+ var extraReader = new StringReader(ucommentField.value);
+
+ // wrong version
+ if (extraReader.readInt(1) !== 1) {
+ return null;
+ }
+
+ // the crc of the comment changed, this field is out of date.
+ if (jszipProto.crc32(this.fileComment) !== extraReader.readInt(4)) {
+ return null;
+ }
+
+ return jszipProto.utf8decode(extraReader.readString(ucommentField.length - 5));
+ }
+ return null;
+ }
+};
+module.exports = ZipEntry;
+
+},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(_dereq_,module,exports){
+// Top level file is just a mixin of submodules & constants
+'use strict';
+
+var assign = _dereq_('./lib/utils/common').assign;
+
+var deflate = _dereq_('./lib/deflate');
+var inflate = _dereq_('./lib/inflate');
+var constants = _dereq_('./lib/zlib/constants');
+
+var pako = {};
+
+assign(pako, deflate, inflate, constants);
+
+module.exports = pako;
+},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(_dereq_,module,exports){
+'use strict';
+
+
+var zlib_deflate = _dereq_('./zlib/deflate.js');
+var utils = _dereq_('./utils/common');
+var strings = _dereq_('./utils/strings');
+var msg = _dereq_('./zlib/messages');
+var zstream = _dereq_('./zlib/zstream');
+
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+var Z_NO_FLUSH = 0;
+var Z_FINISH = 4;
+
+var Z_OK = 0;
+var Z_STREAM_END = 1;
+
+var Z_DEFAULT_COMPRESSION = -1;
+
+var Z_DEFAULT_STRATEGY = 0;
+
+var Z_DEFLATED = 8;
+
+/* ===========================================================================*/
+
+
+/**
+ * class Deflate
+ *
+ * Generic JS-style wrapper for zlib calls. If you don't need
+ * streaming behaviour - use more simple functions: [[deflate]],
+ * [[deflateRaw]] and [[gzip]].
+ **/
+
+/* internal
+ * Deflate.chunks -> Array
+ *
+ * Chunks of output data, if [[Deflate#onData]] not overriden.
+ **/
+
+/**
+ * Deflate.result -> Uint8Array|Array
+ *
+ * Compressed result, generated by default [[Deflate#onData]]
+ * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
+ * (call [[Deflate#push]] with `Z_FINISH` / `true` param).
+ **/
+
+/**
+ * Deflate.err -> Number
+ *
+ * Error code after deflate finished. 0 (Z_OK) on success.
+ * You will not need it in real life, because deflate errors
+ * are possible only on wrong options or bad `onData` / `onEnd`
+ * custom handlers.
+ **/
+
+/**
+ * Deflate.msg -> String
+ *
+ * Error message, if [[Deflate.err]] != 0
+ **/
+
+
+/**
+ * new Deflate(options)
+ * - options (Object): zlib deflate options.
+ *
+ * Creates new deflator instance with specified params. Throws exception
+ * on bad params. Supported options:
+ *
+ * - `level`
+ * - `windowBits`
+ * - `memLevel`
+ * - `strategy`
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Additional options, for internal needs:
+ *
+ * - `chunkSize` - size of generated data chunks (16K by default)
+ * - `raw` (Boolean) - do raw deflate
+ * - `gzip` (Boolean) - create gzip wrapper
+ * - `to` (String) - if equal to 'string', then result will be "binary string"
+ * (each char code [0..255])
+ * - `header` (Object) - custom header for gzip
+ * - `text` (Boolean) - true if compressed data believed to be text
+ * - `time` (Number) - modification time, unix timestamp
+ * - `os` (Number) - operation system code
+ * - `extra` (Array) - array of bytes with extra data (max 65536)
+ * - `name` (String) - file name (binary string)
+ * - `comment` (String) - comment (binary string)
+ * - `hcrc` (Boolean) - true if header crc should be added
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
+ * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
+ *
+ * var deflate = new pako.Deflate({ level: 3});
+ *
+ * deflate.push(chunk1, false);
+ * deflate.push(chunk2, true); // true -> last chunk
+ *
+ * if (deflate.err) { throw new Error(deflate.err); }
+ *
+ * console.log(deflate.result);
+ * ```
+ **/
+var Deflate = function(options) {
+
+ this.options = utils.assign({
+ level: Z_DEFAULT_COMPRESSION,
+ method: Z_DEFLATED,
+ chunkSize: 16384,
+ windowBits: 15,
+ memLevel: 8,
+ strategy: Z_DEFAULT_STRATEGY,
+ to: ''
+ }, options || {});
+
+ var opt = this.options;
+
+ if (opt.raw && (opt.windowBits > 0)) {
+ opt.windowBits = -opt.windowBits;
+ }
+
+ else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
+ opt.windowBits += 16;
+ }
+
+ this.err = 0; // error code, if happens (0 = Z_OK)
+ this.msg = ''; // error message
+ this.ended = false; // used to avoid multiple onEnd() calls
+ this.chunks = []; // chunks of compressed data
+
+ this.strm = new zstream();
+ this.strm.avail_out = 0;
+
+ var status = zlib_deflate.deflateInit2(
+ this.strm,
+ opt.level,
+ opt.method,
+ opt.windowBits,
+ opt.memLevel,
+ opt.strategy
+ );
+
+ if (status !== Z_OK) {
+ throw new Error(msg[status]);
+ }
+
+ if (opt.header) {
+ zlib_deflate.deflateSetHeader(this.strm, opt.header);
+ }
+};
+
+/**
+ * Deflate#push(data[, mode]) -> Boolean
+ * - data (Uint8Array|Array|String): input data. Strings will be converted to
+ * utf8 byte sequence.
+ * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
+ * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
+ *
+ * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
+ * new compressed chunks. Returns `true` on success. The last data block must have
+ * mode Z_FINISH (or `true`). That flush internal pending buffers and call
+ * [[Deflate#onEnd]].
+ *
+ * On fail call [[Deflate#onEnd]] with error code and return false.
+ *
+ * We strongly recommend to use `Uint8Array` on input for best speed (output
+ * array format is detected automatically). Also, don't skip last param and always
+ * use the same type in your code (boolean or number). That will improve JS speed.
+ *
+ * For regular `Array`-s make sure all elements are [0..255].
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * push(chunk, false); // push one of data chunks
+ * ...
+ * push(chunk, true); // push last chunk
+ * ```
+ **/
+Deflate.prototype.push = function(data, mode) {
+ var strm = this.strm;
+ var chunkSize = this.options.chunkSize;
+ var status, _mode;
+
+ if (this.ended) { return false; }
+
+ _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);
+
+ // Convert data if needed
+ if (typeof data === 'string') {
+ // If we need to compress text, change encoding to utf8.
+ strm.input = strings.string2buf(data);
+ } else {
+ strm.input = data;
+ }
+
+ strm.next_in = 0;
+ strm.avail_in = strm.input.length;
+
+ do {
+ if (strm.avail_out === 0) {
+ strm.output = new utils.Buf8(chunkSize);
+ strm.next_out = 0;
+ strm.avail_out = chunkSize;
+ }
+ status = zlib_deflate.deflate(strm, _mode); /* no bad return value */
+
+ if (status !== Z_STREAM_END && status !== Z_OK) {
+ this.onEnd(status);
+ this.ended = true;
+ return false;
+ }
+ if (strm.avail_out === 0 || (strm.avail_in === 0 && _mode === Z_FINISH)) {
+ if (this.options.to === 'string') {
+ this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
+ } else {
+ this.onData(utils.shrinkBuf(strm.output, strm.next_out));
+ }
+ }
+ } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);
+
+ // Finalize on the last chunk.
+ if (_mode === Z_FINISH) {
+ status = zlib_deflate.deflateEnd(this.strm);
+ this.onEnd(status);
+ this.ended = true;
+ return status === Z_OK;
+ }
+
+ return true;
+};
+
+
+/**
+ * Deflate#onData(chunk) -> Void
+ * - chunk (Uint8Array|Array|String): ouput data. Type of array depends
+ * on js engine support. When string output requested, each chunk
+ * will be string.
+ *
+ * By default, stores data blocks in `chunks[]` property and glue
+ * those in `onEnd`. Override this handler, if you need another behaviour.
+ **/
+Deflate.prototype.onData = function(chunk) {
+ this.chunks.push(chunk);
+};
+
+
+/**
+ * Deflate#onEnd(status) -> Void
+ * - status (Number): deflate status. 0 (Z_OK) on success,
+ * other if not.
+ *
+ * Called once after you tell deflate that input stream complete
+ * or error happenned. By default - join collected chunks,
+ * free memory and fill `results` / `err` properties.
+ **/
+Deflate.prototype.onEnd = function(status) {
+ // On success - join
+ if (status === Z_OK) {
+ if (this.options.to === 'string') {
+ this.result = this.chunks.join('');
+ } else {
+ this.result = utils.flattenChunks(this.chunks);
+ }
+ }
+ this.chunks = [];
+ this.err = status;
+ this.msg = this.strm.msg;
+};
+
+
+/**
+ * deflate(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * Compress `data` with deflate alrorythm and `options`.
+ *
+ * Supported options are:
+ *
+ * - level
+ * - windowBits
+ * - memLevel
+ * - strategy
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Sugar (options):
+ *
+ * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
+ * negative windowBits implicitly.
+ * - `to` (String) - if equal to 'string', then result will be "binary string"
+ * (each char code [0..255])
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ * , data = Uint8Array([1,2,3,4,5,6,7,8,9]);
+ *
+ * console.log(pako.deflate(data));
+ * ```
+ **/
+function deflate(input, options) {
+ var deflator = new Deflate(options);
+
+ deflator.push(input, true);
+
+ // That will never happens, if you don't cheat with options :)
+ if (deflator.err) { throw deflator.msg; }
+
+ return deflator.result;
+}
+
+
+/**
+ * deflateRaw(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * The same as [[deflate]], but creates raw data, without wrapper
+ * (header and adler32 crc).
+ **/
+function deflateRaw(input, options) {
+ options = options || {};
+ options.raw = true;
+ return deflate(input, options);
+}
+
+
+/**
+ * gzip(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * The same as [[deflate]], but create gzip wrapper instead of
+ * deflate one.
+ **/
+function gzip(input, options) {
+ options = options || {};
+ options.gzip = true;
+ return deflate(input, options);
+}
+
+
+exports.Deflate = Deflate;
+exports.deflate = deflate;
+exports.deflateRaw = deflateRaw;
+exports.gzip = gzip;
+},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(_dereq_,module,exports){
+'use strict';
+
+
+var zlib_inflate = _dereq_('./zlib/inflate.js');
+var utils = _dereq_('./utils/common');
+var strings = _dereq_('./utils/strings');
+var c = _dereq_('./zlib/constants');
+var msg = _dereq_('./zlib/messages');
+var zstream = _dereq_('./zlib/zstream');
+var gzheader = _dereq_('./zlib/gzheader');
+
+
+/**
+ * class Inflate
+ *
+ * Generic JS-style wrapper for zlib calls. If you don't need
+ * streaming behaviour - use more simple functions: [[inflate]]
+ * and [[inflateRaw]].
+ **/
+
+/* internal
+ * inflate.chunks -> Array
+ *
+ * Chunks of output data, if [[Inflate#onData]] not overriden.
+ **/
+
+/**
+ * Inflate.result -> Uint8Array|Array|String
+ *
+ * Uncompressed result, generated by default [[Inflate#onData]]
+ * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
+ * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
+ **/
+
+/**
+ * Inflate.err -> Number
+ *
+ * Error code after inflate finished. 0 (Z_OK) on success.
+ * Should be checked if broken data possible.
+ **/
+
+/**
+ * Inflate.msg -> String
+ *
+ * Error message, if [[Inflate.err]] != 0
+ **/
+
+
+/**
+ * new Inflate(options)
+ * - options (Object): zlib inflate options.
+ *
+ * Creates new inflator instance with specified params. Throws exception
+ * on bad params. Supported options:
+ *
+ * - `windowBits`
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Additional options, for internal needs:
+ *
+ * - `chunkSize` - size of generated data chunks (16K by default)
+ * - `raw` (Boolean) - do raw inflate
+ * - `to` (String) - if equal to 'string', then result will be converted
+ * from utf8 to utf16 (javascript) string. When string output requested,
+ * chunk length can differ from `chunkSize`, depending on content.
+ *
+ * By default, when no options set, autodetect deflate/gzip data format via
+ * wrapper header.
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
+ * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
+ *
+ * var inflate = new pako.Inflate({ level: 3});
+ *
+ * inflate.push(chunk1, false);
+ * inflate.push(chunk2, true); // true -> last chunk
+ *
+ * if (inflate.err) { throw new Error(inflate.err); }
+ *
+ * console.log(inflate.result);
+ * ```
+ **/
+var Inflate = function(options) {
+
+ this.options = utils.assign({
+ chunkSize: 16384,
+ windowBits: 0,
+ to: ''
+ }, options || {});
+
+ var opt = this.options;
+
+ // Force window size for `raw` data, if not set directly,
+ // because we have no header for autodetect.
+ if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
+ opt.windowBits = -opt.windowBits;
+ if (opt.windowBits === 0) { opt.windowBits = -15; }
+ }
+
+ // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
+ if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
+ !(options && options.windowBits)) {
+ opt.windowBits += 32;
+ }
+
+ // Gzip header has no info about windows size, we can do autodetect only
+ // for deflate. So, if window size not set, force it to max when gzip possible
+ if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
+ // bit 3 (16) -> gzipped data
+ // bit 4 (32) -> autodetect gzip/deflate
+ if ((opt.windowBits & 15) === 0) {
+ opt.windowBits |= 15;
+ }
+ }
+
+ this.err = 0; // error code, if happens (0 = Z_OK)
+ this.msg = ''; // error message
+ this.ended = false; // used to avoid multiple onEnd() calls
+ this.chunks = []; // chunks of compressed data
+
+ this.strm = new zstream();
+ this.strm.avail_out = 0;
+
+ var status = zlib_inflate.inflateInit2(
+ this.strm,
+ opt.windowBits
+ );
+
+ if (status !== c.Z_OK) {
+ throw new Error(msg[status]);
+ }
+
+ this.header = new gzheader();
+
+ zlib_inflate.inflateGetHeader(this.strm, this.header);
+};
+
+/**
+ * Inflate#push(data[, mode]) -> Boolean
+ * - data (Uint8Array|Array|String): input data
+ * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
+ * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
+ *
+ * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
+ * new output chunks. Returns `true` on success. The last data block must have
+ * mode Z_FINISH (or `true`). That flush internal pending buffers and call
+ * [[Inflate#onEnd]].
+ *
+ * On fail call [[Inflate#onEnd]] with error code and return false.
+ *
+ * We strongly recommend to use `Uint8Array` on input for best speed (output
+ * format is detected automatically). Also, don't skip last param and always
+ * use the same type in your code (boolean or number). That will improve JS speed.
+ *
+ * For regular `Array`-s make sure all elements are [0..255].
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * push(chunk, false); // push one of data chunks
+ * ...
+ * push(chunk, true); // push last chunk
+ * ```
+ **/
+Inflate.prototype.push = function(data, mode) {
+ var strm = this.strm;
+ var chunkSize = this.options.chunkSize;
+ var status, _mode;
+ var next_out_utf8, tail, utf8str;
+
+ if (this.ended) { return false; }
+ _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH);
+
+ // Convert data if needed
+ if (typeof data === 'string') {
+ // Only binary strings can be decompressed on practice
+ strm.input = strings.binstring2buf(data);
+ } else {
+ strm.input = data;
+ }
+
+ strm.next_in = 0;
+ strm.avail_in = strm.input.length;
+
+ do {
+ if (strm.avail_out === 0) {
+ strm.output = new utils.Buf8(chunkSize);
+ strm.next_out = 0;
+ strm.avail_out = chunkSize;
+ }
+
+ status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */
+
+ if (status !== c.Z_STREAM_END && status !== c.Z_OK) {
+ this.onEnd(status);
+ this.ended = true;
+ return false;
+ }
+
+ if (strm.next_out) {
+ if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) {
+
+ if (this.options.to === 'string') {
+
+ next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
+
+ tail = strm.next_out - next_out_utf8;
+ utf8str = strings.buf2string(strm.output, next_out_utf8);
+
+ // move tail
+ strm.next_out = tail;
+ strm.avail_out = chunkSize - tail;
+ if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }
+
+ this.onData(utf8str);
+
+ } else {
+ this.onData(utils.shrinkBuf(strm.output, strm.next_out));
+ }
+ }
+ }
+ } while ((strm.avail_in > 0) && status !== c.Z_STREAM_END);
+
+ if (status === c.Z_STREAM_END) {
+ _mode = c.Z_FINISH;
+ }
+ // Finalize on the last chunk.
+ if (_mode === c.Z_FINISH) {
+ status = zlib_inflate.inflateEnd(this.strm);
+ this.onEnd(status);
+ this.ended = true;
+ return status === c.Z_OK;
+ }
+
+ return true;
+};
+
+
+/**
+ * Inflate#onData(chunk) -> Void
+ * - chunk (Uint8Array|Array|String): ouput data. Type of array depends
+ * on js engine support. When string output requested, each chunk
+ * will be string.
+ *
+ * By default, stores data blocks in `chunks[]` property and glue
+ * those in `onEnd`. Override this handler, if you need another behaviour.
+ **/
+Inflate.prototype.onData = function(chunk) {
+ this.chunks.push(chunk);
+};
+
+
+/**
+ * Inflate#onEnd(status) -> Void
+ * - status (Number): inflate status. 0 (Z_OK) on success,
+ * other if not.
+ *
+ * Called once after you tell inflate that input stream complete
+ * or error happenned. By default - join collected chunks,
+ * free memory and fill `results` / `err` properties.
+ **/
+Inflate.prototype.onEnd = function(status) {
+ // On success - join
+ if (status === c.Z_OK) {
+ if (this.options.to === 'string') {
+ // Glue & convert here, until we teach pako to send
+ // utf8 alligned strings to onData
+ this.result = this.chunks.join('');
+ } else {
+ this.result = utils.flattenChunks(this.chunks);
+ }
+ }
+ this.chunks = [];
+ this.err = status;
+ this.msg = this.strm.msg;
+};
+
+
+/**
+ * inflate(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * Decompress `data` with inflate/ungzip and `options`. Autodetect
+ * format via wrapper header by default. That's why we don't provide
+ * separate `ungzip` method.
+ *
+ * Supported options are:
+ *
+ * - windowBits
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information.
+ *
+ * Sugar (options):
+ *
+ * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
+ * negative windowBits implicitly.
+ * - `to` (String) - if equal to 'string', then result will be converted
+ * from utf8 to utf16 (javascript) string. When string output requested,
+ * chunk length can differ from `chunkSize`, depending on content.
+ *
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ * , input = pako.deflate([1,2,3,4,5,6,7,8,9])
+ * , output;
+ *
+ * try {
+ * output = pako.inflate(input);
+ * } catch (err)
+ * console.log(err);
+ * }
+ * ```
+ **/
+function inflate(input, options) {
+ var inflator = new Inflate(options);
+
+ inflator.push(input, true);
+
+ // That will never happens, if you don't cheat with options :)
+ if (inflator.err) { throw inflator.msg; }
+
+ return inflator.result;
+}
+
+
+/**
+ * inflateRaw(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * The same as [[inflate]], but creates raw data, without wrapper
+ * (header and adler32 crc).
+ **/
+function inflateRaw(input, options) {
+ options = options || {};
+ options.raw = true;
+ return inflate(input, options);
+}
+
+
+/**
+ * ungzip(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * Just shortcut to [[inflate]], because it autodetects format
+ * by header.content. Done for convenience.
+ **/
+
+
+exports.Inflate = Inflate;
+exports.inflate = inflate;
+exports.inflateRaw = inflateRaw;
+exports.ungzip = inflate;
+
+},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(_dereq_,module,exports){
+'use strict';
+
+
+var TYPED_OK = (typeof Uint8Array !== 'undefined') &&
+ (typeof Uint16Array !== 'undefined') &&
+ (typeof Int32Array !== 'undefined');
+
+
+exports.assign = function (obj /*from1, from2, from3, ...*/) {
+ var sources = Array.prototype.slice.call(arguments, 1);
+ while (sources.length) {
+ var source = sources.shift();
+ if (!source) { continue; }
+
+ if (typeof(source) !== 'object') {
+ throw new TypeError(source + 'must be non-object');
+ }
+
+ for (var p in source) {
+ if (source.hasOwnProperty(p)) {
+ obj[p] = source[p];
+ }
+ }
+ }
+
+ return obj;
+};
+
+
+// reduce buffer size, avoiding mem copy
+exports.shrinkBuf = function (buf, size) {
+ if (buf.length === size) { return buf; }
+ if (buf.subarray) { return buf.subarray(0, size); }
+ buf.length = size;
+ return buf;
+};
+
+
+var fnTyped = {
+ arraySet: function (dest, src, src_offs, len, dest_offs) {
+ if (src.subarray && dest.subarray) {
+ dest.set(src.subarray(src_offs, src_offs+len), dest_offs);
+ return;
+ }
+ // Fallback to ordinary array
+ for(var i=0; i<len; i++) {
+ dest[dest_offs + i] = src[src_offs + i];
+ }
+ },
+ // Join array of chunks to single array.
+ flattenChunks: function(chunks) {
+ var i, l, len, pos, chunk, result;
+
+ // calculate data length
+ len = 0;
+ for (i=0, l=chunks.length; i<l; i++) {
+ len += chunks[i].length;
+ }
+
+ // join chunks
+ result = new Uint8Array(len);
+ pos = 0;
+ for (i=0, l=chunks.length; i<l; i++) {
+ chunk = chunks[i];
+ result.set(chunk, pos);
+ pos += chunk.length;
+ }
+
+ return result;
+ }
+};
+
+var fnUntyped = {
+ arraySet: function (dest, src, src_offs, len, dest_offs) {
+ for(var i=0; i<len; i++) {
+ dest[dest_offs + i] = src[src_offs + i];
+ }
+ },
+ // Join array of chunks to single array.
+ flattenChunks: function(chunks) {
+ return [].concat.apply([], chunks);
+ }
+};
+
+
+// Enable/Disable typed arrays use, for testing
+//
+exports.setTyped = function (on) {
+ if (on) {
+ exports.Buf8 = Uint8Array;
+ exports.Buf16 = Uint16Array;
+ exports.Buf32 = Int32Array;
+ exports.assign(exports, fnTyped);
+ } else {
+ exports.Buf8 = Array;
+ exports.Buf16 = Array;
+ exports.Buf32 = Array;
+ exports.assign(exports, fnUntyped);
+ }
+};
+
+exports.setTyped(TYPED_OK);
+},{}],28:[function(_dereq_,module,exports){
+// String encode/decode helpers
+'use strict';
+
+
+var utils = _dereq_('./common');
+
+
+// Quick check if we can use fast array to bin string conversion
+//
+// - apply(Array) can fail on Android 2.2
+// - apply(Uint8Array) can fail on iOS 5.1 Safary
+//
+var STR_APPLY_OK = true;
+var STR_APPLY_UIA_OK = true;
+
+try { String.fromCharCode.apply(null, [0]); } catch(__) { STR_APPLY_OK = false; }
+try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch(__) { STR_APPLY_UIA_OK = false; }
+
+
+// Table with utf8 lengths (calculated by first byte of sequence)
+// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
+// because max possible codepoint is 0x10ffff
+var _utf8len = new utils.Buf8(256);
+for (var i=0; i<256; i++) {
+ _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
+}
+_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
+
+
+// convert string to array (typed, when possible)
+exports.string2buf = function (str) {
+ var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
+
+ // count binary size
+ for (m_pos = 0; m_pos < str_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
+ }
+
+ // allocate buffer
+ buf = new utils.Buf8(buf_len);
+
+ // convert
+ for (i=0, m_pos = 0; i < buf_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ if (c < 0x80) {
+ /* one byte */
+ buf[i++] = c;
+ } else if (c < 0x800) {
+ /* two bytes */
+ buf[i++] = 0xC0 | (c >>> 6);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else if (c < 0x10000) {
+ /* three bytes */
+ buf[i++] = 0xE0 | (c >>> 12);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else {
+ /* four bytes */
+ buf[i++] = 0xf0 | (c >>> 18);
+ buf[i++] = 0x80 | (c >>> 12 & 0x3f);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ }
+ }
+
+ return buf;
+};
+
+// Helper (used in 2 places)
+function buf2binstring(buf, len) {
+ // use fallback for big arrays to avoid stack overflow
+ if (len < 65537) {
+ if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {
+ return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len));
+ }
+ }
+
+ var result = '';
+ for(var i=0; i < len; i++) {
+ result += String.fromCharCode(buf[i]);
+ }
+ return result;
+}
+
+
+// Convert byte array to binary string
+exports.buf2binstring = function(buf) {
+ return buf2binstring(buf, buf.length);
+};
+
+
+// Convert binary string (typed, when possible)
+exports.binstring2buf = function(str) {
+ var buf = new utils.Buf8(str.length);
+ for(var i=0, len=buf.length; i < len; i++) {
+ buf[i] = str.charCodeAt(i);
+ }
+ return buf;
+};
+
+
+// convert array to string
+exports.buf2string = function (buf, max) {
+ var i, out, c, c_len;
+ var len = max || buf.length;
+
+ // Reserve max possible length (2 words per char)
+ // NB: by unknown reasons, Array is significantly faster for
+ // String.fromCharCode.apply than Uint16Array.
+ var utf16buf = new Array(len*2);
+
+ for (out=0, i=0; i<len;) {
+ c = buf[i++];
+ // quick process ascii
+ if (c < 0x80) { utf16buf[out++] = c; continue; }
+
+ c_len = _utf8len[c];
+ // skip 5 & 6 byte codes
+ if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
+
+ // apply mask on first byte
+ c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
+ // join the rest
+ while (c_len > 1 && i < len) {
+ c = (c << 6) | (buf[i++] & 0x3f);
+ c_len--;
+ }
+
+ // terminated by end of string?
+ if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
+
+ if (c < 0x10000) {
+ utf16buf[out++] = c;
+ } else {
+ c -= 0x10000;
+ utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
+ utf16buf[out++] = 0xdc00 | (c & 0x3ff);
+ }
+ }
+
+ return buf2binstring(utf16buf, out);
+};
+
+
+// Calculate max possible position in utf8 buffer,
+// that will not break sequence. If that's not possible
+// - (very small limits) return max size as is.
+//
+// buf[] - utf8 bytes array
+// max - length limit (mandatory);
+exports.utf8border = function(buf, max) {
+ var pos;
+
+ max = max || buf.length;
+ if (max > buf.length) { max = buf.length; }
+
+ // go back from last position, until start of sequence found
+ pos = max-1;
+ while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
+
+ // Fuckup - very small and broken sequence,
+ // return max, because we should return something anyway.
+ if (pos < 0) { return max; }
+
+ // If we came to start of buffer - that means vuffer is too small,
+ // return max too.
+ if (pos === 0) { return max; }
+
+ return (pos + _utf8len[buf[pos]] > max) ? pos : max;
+};
+
+},{"./common":27}],29:[function(_dereq_,module,exports){
+'use strict';
+
+// Note: adler32 takes 12% for level 0 and 2% for level 6.
+// It doesn't worth to make additional optimizationa as in original.
+// Small size is preferable.
+
+function adler32(adler, buf, len, pos) {
+ var s1 = (adler & 0xffff) |0
+ , s2 = ((adler >>> 16) & 0xffff) |0
+ , n = 0;
+
+ while (len !== 0) {
+ // Set limit ~ twice less than 5552, to keep
+ // s2 in 31-bits, because we force signed ints.
+ // in other case %= will fail.
+ n = len > 2000 ? 2000 : len;
+ len -= n;
+
+ do {
+ s1 = (s1 + buf[pos++]) |0;
+ s2 = (s2 + s1) |0;
+ } while (--n);
+
+ s1 %= 65521;
+ s2 %= 65521;
+ }
+
+ return (s1 | (s2 << 16)) |0;
+}
+
+
+module.exports = adler32;
+},{}],30:[function(_dereq_,module,exports){
+module.exports = {
+
+ /* Allowed flush values; see deflate() and inflate() below for details */
+ Z_NO_FLUSH: 0,
+ Z_PARTIAL_FLUSH: 1,
+ Z_SYNC_FLUSH: 2,
+ Z_FULL_FLUSH: 3,
+ Z_FINISH: 4,
+ Z_BLOCK: 5,
+ Z_TREES: 6,
+
+ /* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+ Z_OK: 0,
+ Z_STREAM_END: 1,
+ Z_NEED_DICT: 2,
+ Z_ERRNO: -1,
+ Z_STREAM_ERROR: -2,
+ Z_DATA_ERROR: -3,
+ //Z_MEM_ERROR: -4,
+ Z_BUF_ERROR: -5,
+ //Z_VERSION_ERROR: -6,
+
+ /* compression levels */
+ Z_NO_COMPRESSION: 0,
+ Z_BEST_SPEED: 1,
+ Z_BEST_COMPRESSION: 9,
+ Z_DEFAULT_COMPRESSION: -1,
+
+
+ Z_FILTERED: 1,
+ Z_HUFFMAN_ONLY: 2,
+ Z_RLE: 3,
+ Z_FIXED: 4,
+ Z_DEFAULT_STRATEGY: 0,
+
+ /* Possible values of the data_type field (though see inflate()) */
+ Z_BINARY: 0,
+ Z_TEXT: 1,
+ //Z_ASCII: 1, // = Z_TEXT (deprecated)
+ Z_UNKNOWN: 2,
+
+ /* The deflate compression method */
+ Z_DEFLATED: 8
+ //Z_NULL: null // Use -1 or null inline, depending on var type
+};
+},{}],31:[function(_dereq_,module,exports){
+'use strict';
+
+// Note: we can't get significant speed boost here.
+// So write code to minimize size - no pregenerated tables
+// and array tools dependencies.
+
+
+// Use ordinary array, since untyped makes no boost here
+function makeTable() {
+ var c, table = [];
+
+ for(var n =0; n < 256; n++){
+ c = n;
+ for(var k =0; k < 8; k++){
+ c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
+ }
+ table[n] = c;
+ }
+
+ return table;
+}
+
+// Create table on load. Just 255 signed longs. Not a problem.
+var crcTable = makeTable();
+
+
+function crc32(crc, buf, len, pos) {
+ var t = crcTable
+ , end = pos + len;
+
+ crc = crc ^ (-1);
+
+ for (var i = pos; i < end; i++ ) {
+ crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
+ }
+
+ return (crc ^ (-1)); // >>> 0;
+}
+
+
+module.exports = crc32;
+},{}],32:[function(_dereq_,module,exports){
+'use strict';
+
+var utils = _dereq_('../utils/common');
+var trees = _dereq_('./trees');
+var adler32 = _dereq_('./adler32');
+var crc32 = _dereq_('./crc32');
+var msg = _dereq_('./messages');
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+/* Allowed flush values; see deflate() and inflate() below for details */
+var Z_NO_FLUSH = 0;
+var Z_PARTIAL_FLUSH = 1;
+//var Z_SYNC_FLUSH = 2;
+var Z_FULL_FLUSH = 3;
+var Z_FINISH = 4;
+var Z_BLOCK = 5;
+//var Z_TREES = 6;
+
+
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+var Z_OK = 0;
+var Z_STREAM_END = 1;
+//var Z_NEED_DICT = 2;
+//var Z_ERRNO = -1;
+var Z_STREAM_ERROR = -2;
+var Z_DATA_ERROR = -3;
+//var Z_MEM_ERROR = -4;
+var Z_BUF_ERROR = -5;
+//var Z_VERSION_ERROR = -6;
+
+
+/* compression levels */
+//var Z_NO_COMPRESSION = 0;
+//var Z_BEST_SPEED = 1;
+//var Z_BEST_COMPRESSION = 9;
+var Z_DEFAULT_COMPRESSION = -1;
+
+
+var Z_FILTERED = 1;
+var Z_HUFFMAN_ONLY = 2;
+var Z_RLE = 3;
+var Z_FIXED = 4;
+var Z_DEFAULT_STRATEGY = 0;
+
+/* Possible values of the data_type field (though see inflate()) */
+//var Z_BINARY = 0;
+//var Z_TEXT = 1;
+//var Z_ASCII = 1; // = Z_TEXT
+var Z_UNKNOWN = 2;
+
+
+/* The deflate compression method */
+var Z_DEFLATED = 8;
+
+/*============================================================================*/
+
+
+var MAX_MEM_LEVEL = 9;
+/* Maximum value for memLevel in deflateInit2 */
+var MAX_WBITS = 15;
+/* 32K LZ77 window */
+var DEF_MEM_LEVEL = 8;
+
+
+var LENGTH_CODES = 29;
+/* number of length codes, not counting the special END_BLOCK code */
+var LITERALS = 256;
+/* number of literal bytes 0..255 */
+var L_CODES = LITERALS + 1 + LENGTH_CODES;
+/* number of Literal or Length codes, including the END_BLOCK code */
+var D_CODES = 30;
+/* number of distance codes */
+var BL_CODES = 19;
+/* number of codes used to transfer the bit lengths */
+var HEAP_SIZE = 2*L_CODES + 1;
+/* maximum heap size */
+var MAX_BITS = 15;
+/* All codes must not exceed MAX_BITS bits */
+
+var MIN_MATCH = 3;
+var MAX_MATCH = 258;
+var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+var PRESET_DICT = 0x20;
+
+var INIT_STATE = 42;
+var EXTRA_STATE = 69;
+var NAME_STATE = 73;
+var COMMENT_STATE = 91;
+var HCRC_STATE = 103;
+var BUSY_STATE = 113;
+var FINISH_STATE = 666;
+
+var BS_NEED_MORE = 1; /* block not completed, need more input or more output */
+var BS_BLOCK_DONE = 2; /* block flush performed */
+var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
+var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
+
+var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
+
+function err(strm, errorCode) {
+ strm.msg = msg[errorCode];
+ return errorCode;
+}
+
+function rank(f) {
+ return ((f) << 1) - ((f) > 4 ? 9 : 0);
+}
+
+function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
+
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->output buffer and copying into it.
+ * (See also read_buf()).
+ */
+function flush_pending(strm) {
+ var s = strm.state;
+
+ //_tr_flush_bits(s);
+ var len = s.pending;
+ if (len > strm.avail_out) {
+ len = strm.avail_out;
+ }
+ if (len === 0) { return; }
+
+ utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
+ strm.next_out += len;
+ s.pending_out += len;
+ strm.total_out += len;
+ strm.avail_out -= len;
+ s.pending -= len;
+ if (s.pending === 0) {
+ s.pending_out = 0;
+ }
+}
+
+
+function flush_block_only (s, last) {
+ trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
+ s.block_start = s.strstart;
+ flush_pending(s.strm);
+}
+
+
+function put_byte(s, b) {
+ s.pending_buf[s.pending++] = b;
+}
+
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+function putShortMSB(s, b) {
+// put_byte(s, (Byte)(b >> 8));
+// put_byte(s, (Byte)(b & 0xff));
+ s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
+ s.pending_buf[s.pending++] = b & 0xff;
+}
+
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->input buffer and copying from it.
+ * (See also flush_pending()).
+ */
+function read_buf(strm, buf, start, size) {
+ var len = strm.avail_in;
+
+ if (len > size) { len = size; }
+ if (len === 0) { return 0; }
+
+ strm.avail_in -= len;
+
+ utils.arraySet(buf, strm.input, strm.next_in, len, start);
+ if (strm.state.wrap === 1) {
+ strm.adler = adler32(strm.adler, buf, len, start);
+ }
+
+ else if (strm.state.wrap === 2) {
+ strm.adler = crc32(strm.adler, buf, len, start);
+ }
+
+ strm.next_in += len;
+ strm.total_in += len;
+
+ return len;
+}
+
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+function longest_match(s, cur_match) {
+ var chain_length = s.max_chain_length; /* max hash chain length */
+ var scan = s.strstart; /* current string */
+ var match; /* matched string */
+ var len; /* length of current match */
+ var best_len = s.prev_length; /* best match length so far */
+ var nice_match = s.nice_match; /* stop if match long enough */
+ var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
+ s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
+
+ var _win = s.window; // shortcut
+
+ var wmask = s.w_mask;
+ var prev = s.prev;
+
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+
+ var strend = s.strstart + MAX_MATCH;
+ var scan_end1 = _win[scan + best_len - 1];
+ var scan_end = _win[scan + best_len];
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s.prev_length >= s.good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if (nice_match > s.lookahead) { nice_match = s.lookahead; }
+
+ // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ // Assert(cur_match < s->strstart, "no future");
+ match = cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+
+ if (_win[match + best_len] !== scan_end ||
+ _win[match + best_len - 1] !== scan_end1 ||
+ _win[match] !== _win[scan] ||
+ _win[++match] !== _win[scan + 1]) {
+ continue;
+ }
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2;
+ match++;
+ // Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ /*jshint noempty:false*/
+ } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+ _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+ _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+ _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+ scan < strend);
+
+ // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len) {
+ s.match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) {
+ break;
+ }
+ scan_end1 = _win[scan + best_len - 1];
+ scan_end = _win[scan + best_len];
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
+
+ if (best_len <= s.lookahead) {
+ return best_len;
+ }
+ return s.lookahead;
+}
+
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+function fill_window(s) {
+ var _w_size = s.w_size;
+ var p, n, m, more, str;
+
+ //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+ do {
+ more = s.window_size - s.lookahead - s.strstart;
+
+ // JS ints have 32 bit, block below not needed
+ /* Deal with !@#$% 64K limit: */
+ //if (sizeof(int) <= 2) {
+ // if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ // more = wsize;
+ //
+ // } else if (more == (unsigned)(-1)) {
+ // /* Very unlikely, but possible on 16 bit machine if
+ // * strstart == 0 && lookahead == 1 (input done a byte at time)
+ // */
+ // more--;
+ // }
+ //}
+
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
+
+ utils.arraySet(s.window, s.window, _w_size, _w_size, 0);
+ s.match_start -= _w_size;
+ s.strstart -= _w_size;
+ /* we now have strstart >= MAX_DIST */
+ s.block_start -= _w_size;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+
+ n = s.hash_size;
+ p = n;
+ do {
+ m = s.head[--p];
+ s.head[p] = (m >= _w_size ? m - _w_size : 0);
+ } while (--n);
+
+ n = _w_size;
+ p = n;
+ do {
+ m = s.prev[--p];
+ s.prev[p] = (m >= _w_size ? m - _w_size : 0);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+
+ more += _w_size;
+ }
+ if (s.strm.avail_in === 0) {
+ break;
+ }
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ //Assert(more >= 2, "more < 2");
+ n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
+ s.lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s.lookahead + s.insert >= MIN_MATCH) {
+ str = s.strstart - s.insert;
+ s.ins_h = s.window[str];
+
+ /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;
+//#if MIN_MATCH != 3
+// Call update_hash() MIN_MATCH-3 more times
+//#endif
+ while (s.insert) {
+ /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH-1]) & s.hash_mask;
+
+ s.prev[str & s.w_mask] = s.head[s.ins_h];
+ s.head[s.ins_h] = str;
+ str++;
+ s.insert--;
+ if (s.lookahead + s.insert < MIN_MATCH) {
+ break;
+ }
+ }
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+// if (s.high_water < s.window_size) {
+// var curr = s.strstart + s.lookahead;
+// var init = 0;
+//
+// if (s.high_water < curr) {
+// /* Previous high water mark below current data -- zero WIN_INIT
+// * bytes or up to end of window, whichever is less.
+// */
+// init = s.window_size - curr;
+// if (init > WIN_INIT)
+// init = WIN_INIT;
+// zmemzero(s->window + curr, (unsigned)init);
+// s->high_water = curr + init;
+// }
+// else if (s->high_water < (ulg)curr + WIN_INIT) {
+// /* High water mark at or above current data, but below current data
+// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+// * to end of window, whichever is less.
+// */
+// init = (ulg)curr + WIN_INIT - s->high_water;
+// if (init > s->window_size - s->high_water)
+// init = s->window_size - s->high_water;
+// zmemzero(s->window + s->high_water, (unsigned)init);
+// s->high_water += init;
+// }
+// }
+//
+// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+// "not enough room for search");
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+function deflate_stored(s, flush) {
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ var max_block_size = 0xffff;
+
+ if (max_block_size > s.pending_buf_size - 5) {
+ max_block_size = s.pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s.lookahead <= 1) {
+
+ //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ // s->block_start >= (long)s->w_size, "slide too late");
+// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
+// s.block_start >= s.w_size)) {
+// throw new Error("slide too late");
+// }
+
+ fill_window(s);
+ if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
+ return BS_NEED_MORE;
+ }
+
+ if (s.lookahead === 0) {
+ break;
+ }
+ /* flush the current block */
+ }
+ //Assert(s->block_start >= 0L, "block gone");
+// if (s.block_start < 0) throw new Error("block gone");
+
+ s.strstart += s.lookahead;
+ s.lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ var max_start = s.block_start + max_block_size;
+
+ if (s.strstart === 0 || s.strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s.lookahead = s.strstart - max_start;
+ s.strstart = max_start;
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+
+
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ }
+
+ s.insert = 0;
+
+ if (flush === Z_FINISH) {
+ /*** FLUSH_BLOCK(s, 1); ***/
+ flush_block_only(s, true);
+ if (s.strm.avail_out === 0) {
+ return BS_FINISH_STARTED;
+ }
+ /***/
+ return BS_FINISH_DONE;
+ }
+
+ if (s.strstart > s.block_start) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+
+ return BS_NEED_MORE;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+function deflate_fast(s, flush) {
+ var hash_head; /* head of the hash chain */
+ var bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s.lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
+ return BS_NEED_MORE;
+ }
+ if (s.lookahead === 0) {
+ break; /* flush the current block */
+ }
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = 0/*NIL*/;
+ if (s.lookahead >= MIN_MATCH) {
+ /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+ hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+ s.head[s.ins_h] = s.strstart;
+ /***/
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s.match_length = longest_match(s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s.match_length >= MIN_MATCH) {
+ // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
+
+ /*** _tr_tally_dist(s, s.strstart - s.match_start,
+ s.match_length - MIN_MATCH, bflush); ***/
+ bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
+
+ s.lookahead -= s.match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
+ s.match_length--; /* string at strstart already in table */
+ do {
+ s.strstart++;
+ /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+ hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+ s.head[s.ins_h] = s.strstart;
+ /***/
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s.match_length !== 0);
+ s.strstart++;
+ } else
+ {
+ s.strstart += s.match_length;
+ s.match_length = 0;
+ s.ins_h = s.window[s.strstart];
+ /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;
+
+//#if MIN_MATCH != 3
+// Call UPDATE_HASH() MIN_MATCH-3 more times
+//#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ //Tracevv((stderr,"%c", s.window[s.strstart]));
+ /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+ bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+
+ s.lookahead--;
+ s.strstart++;
+ }
+ if (bflush) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ }
+ s.insert = ((s.strstart < (MIN_MATCH-1)) ? s.strstart : MIN_MATCH-1);
+ if (flush === Z_FINISH) {
+ /*** FLUSH_BLOCK(s, 1); ***/
+ flush_block_only(s, true);
+ if (s.strm.avail_out === 0) {
+ return BS_FINISH_STARTED;
+ }
+ /***/
+ return BS_FINISH_DONE;
+ }
+ if (s.last_lit) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ return BS_BLOCK_DONE;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+function deflate_slow(s, flush) {
+ var hash_head; /* head of hash chain */
+ var bflush; /* set if current block must be flushed */
+
+ var max_insert;
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s.lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
+ return BS_NEED_MORE;
+ }
+ if (s.lookahead === 0) { break; } /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = 0/*NIL*/;
+ if (s.lookahead >= MIN_MATCH) {
+ /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+ hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+ s.head[s.ins_h] = s.strstart;
+ /***/
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s.prev_length = s.match_length;
+ s.prev_match = s.match_start;
+ s.match_length = MIN_MATCH-1;
+
+ if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
+ s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s.match_length = longest_match(s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s.match_length <= 5 &&
+ (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s.match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
+ max_insert = s.strstart + s.lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
+
+ /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
+ s.prev_length - MIN_MATCH, bflush);***/
+ bflush = trees._tr_tally(s, s.strstart - 1- s.prev_match, s.prev_length - MIN_MATCH);
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s.lookahead -= s.prev_length-1;
+ s.prev_length -= 2;
+ do {
+ if (++s.strstart <= max_insert) {
+ /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+ s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+ hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+ s.head[s.ins_h] = s.strstart;
+ /***/
+ }
+ } while (--s.prev_length !== 0);
+ s.match_available = 0;
+ s.match_length = MIN_MATCH-1;
+ s.strstart++;
+
+ if (bflush) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+
+ } else if (s.match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ //Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
+ bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]);
+
+ if (bflush) {
+ /*** FLUSH_BLOCK_ONLY(s, 0) ***/
+ flush_block_only(s, false);
+ /***/
+ }
+ s.strstart++;
+ s.lookahead--;
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s.match_available = 1;
+ s.strstart++;
+ s.lookahead--;
+ }
+ }
+ //Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s.match_available) {
+ //Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
+ bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]);
+
+ s.match_available = 0;
+ }
+ s.insert = s.strstart < MIN_MATCH-1 ? s.strstart : MIN_MATCH-1;
+ if (flush === Z_FINISH) {
+ /*** FLUSH_BLOCK(s, 1); ***/
+ flush_block_only(s, true);
+ if (s.strm.avail_out === 0) {
+ return BS_FINISH_STARTED;
+ }
+ /***/
+ return BS_FINISH_DONE;
+ }
+ if (s.last_lit) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+
+ return BS_BLOCK_DONE;
+}
+
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+function deflate_rle(s, flush) {
+ var bflush; /* set if current block must be flushed */
+ var prev; /* byte at distance one to match */
+ var scan, strend; /* scan goes up to strend for length of run */
+
+ var _win = s.window;
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest run, plus one for the unrolled loop.
+ */
+ if (s.lookahead <= MAX_MATCH) {
+ fill_window(s);
+ if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) {
+ return BS_NEED_MORE;
+ }
+ if (s.lookahead === 0) { break; } /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s.match_length = 0;
+ if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
+ scan = s.strstart - 1;
+ prev = _win[scan];
+ if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
+ strend = s.strstart + MAX_MATCH;
+ do {
+ /*jshint noempty:false*/
+ } while (prev === _win[++scan] && prev === _win[++scan] &&
+ prev === _win[++scan] && prev === _win[++scan] &&
+ prev === _win[++scan] && prev === _win[++scan] &&
+ prev === _win[++scan] && prev === _win[++scan] &&
+ scan < strend);
+ s.match_length = MAX_MATCH - (strend - scan);
+ if (s.match_length > s.lookahead) {
+ s.match_length = s.lookahead;
+ }
+ }
+ //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s.match_length >= MIN_MATCH) {
+ //check_match(s, s.strstart, s.strstart - 1, s.match_length);
+
+ /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
+ bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH);
+
+ s.lookahead -= s.match_length;
+ s.strstart += s.match_length;
+ s.match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ //Tracevv((stderr,"%c", s->window[s->strstart]));
+ /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+ bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+
+ s.lookahead--;
+ s.strstart++;
+ }
+ if (bflush) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ }
+ s.insert = 0;
+ if (flush === Z_FINISH) {
+ /*** FLUSH_BLOCK(s, 1); ***/
+ flush_block_only(s, true);
+ if (s.strm.avail_out === 0) {
+ return BS_FINISH_STARTED;
+ }
+ /***/
+ return BS_FINISH_DONE;
+ }
+ if (s.last_lit) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ return BS_BLOCK_DONE;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+function deflate_huff(s, flush) {
+ var bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s.lookahead === 0) {
+ fill_window(s);
+ if (s.lookahead === 0) {
+ if (flush === Z_NO_FLUSH) {
+ return BS_NEED_MORE;
+ }
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s.match_length = 0;
+ //Tracevv((stderr,"%c", s->window[s->strstart]));
+ /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+ bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+ s.lookahead--;
+ s.strstart++;
+ if (bflush) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ }
+ s.insert = 0;
+ if (flush === Z_FINISH) {
+ /*** FLUSH_BLOCK(s, 1); ***/
+ flush_block_only(s, true);
+ if (s.strm.avail_out === 0) {
+ return BS_FINISH_STARTED;
+ }
+ /***/
+ return BS_FINISH_DONE;
+ }
+ if (s.last_lit) {
+ /*** FLUSH_BLOCK(s, 0); ***/
+ flush_block_only(s, false);
+ if (s.strm.avail_out === 0) {
+ return BS_NEED_MORE;
+ }
+ /***/
+ }
+ return BS_BLOCK_DONE;
+}
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+var Config = function (good_length, max_lazy, nice_length, max_chain, func) {
+ this.good_length = good_length;
+ this.max_lazy = max_lazy;
+ this.nice_length = nice_length;
+ this.max_chain = max_chain;
+ this.func = func;
+};
+
+var configuration_table;
+
+configuration_table = [
+ /* good lazy nice chain */
+ new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */
+ new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */
+ new Config(4, 5, 16, 8, deflate_fast), /* 2 */
+ new Config(4, 6, 32, 32, deflate_fast), /* 3 */
+
+ new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */
+ new Config(8, 16, 32, 32, deflate_slow), /* 5 */
+ new Config(8, 16, 128, 128, deflate_slow), /* 6 */
+ new Config(8, 32, 128, 256, deflate_slow), /* 7 */
+ new Config(32, 128, 258, 1024, deflate_slow), /* 8 */
+ new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */
+];
+
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+function lm_init(s) {
+ s.window_size = 2 * s.w_size;
+
+ /*** CLEAR_HASH(s); ***/
+ zero(s.head); // Fill with NIL (= 0);
+
+ /* Set the default configuration parameters:
+ */
+ s.max_lazy_match = configuration_table[s.level].max_lazy;
+ s.good_match = configuration_table[s.level].good_length;
+ s.nice_match = configuration_table[s.level].nice_length;
+ s.max_chain_length = configuration_table[s.level].max_chain;
+
+ s.strstart = 0;
+ s.block_start = 0;
+ s.lookahead = 0;
+ s.insert = 0;
+ s.match_length = s.prev_length = MIN_MATCH - 1;
+ s.match_available = 0;
+ s.ins_h = 0;
+}
+
+
+function DeflateState() {
+ this.strm = null; /* pointer back to this zlib stream */
+ this.status = 0; /* as the name implies */
+ this.pending_buf = null; /* output still pending */
+ this.pending_buf_size = 0; /* size of pending_buf */
+ this.pending_out = 0; /* next pending byte to output to the stream */
+ this.pending = 0; /* nb of bytes in the pending buffer */
+ this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
+ this.gzhead = null; /* gzip header information to write */
+ this.gzindex = 0; /* where in extra, name, or comment */
+ this.method = Z_DEFLATED; /* can only be DEFLATED */
+ this.last_flush = -1; /* value of flush param for previous deflate call */
+
+ this.w_size = 0; /* LZ77 window size (32K by default) */
+ this.w_bits = 0; /* log2(w_size) (8..16) */
+ this.w_mask = 0; /* w_size - 1 */
+
+ this.window = null;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size.
+ */
+
+ this.window_size = 0;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ this.prev = null;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ this.head = null; /* Heads of the hash chains or NIL. */
+
+ this.ins_h = 0; /* hash index of string to be inserted */
+ this.hash_size = 0; /* number of elements in hash table */
+ this.hash_bits = 0; /* log2(hash_size) */
+ this.hash_mask = 0; /* hash_size-1 */
+
+ this.hash_shift = 0;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ this.block_start = 0;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ this.match_length = 0; /* length of best match */
+ this.prev_match = 0; /* previous match */
+ this.match_available = 0; /* set if previous match exists */
+ this.strstart = 0; /* start of string to insert */
+ this.match_start = 0; /* start of matching string */
+ this.lookahead = 0; /* number of valid bytes ahead in window */
+
+ this.prev_length = 0;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ this.max_chain_length = 0;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ this.max_lazy_match = 0;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+ // That's alias to max_lazy_match, don't use directly
+ //this.max_insert_length = 0;
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ this.level = 0; /* compression level (1..9) */
+ this.strategy = 0; /* favor or force Huffman coding*/
+
+ this.good_match = 0;
+ /* Use a faster search when the previous match is longer than this */
+
+ this.nice_match = 0; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+
+ // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ // Use flat array of DOUBLE size, with interleaved fata,
+ // because JS does not support effective
+ this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2);
+ this.dyn_dtree = new utils.Buf16((2*D_CODES+1) * 2);
+ this.bl_tree = new utils.Buf16((2*BL_CODES+1) * 2);
+ zero(this.dyn_ltree);
+ zero(this.dyn_dtree);
+ zero(this.bl_tree);
+
+ this.l_desc = null; /* desc. for literal tree */
+ this.d_desc = null; /* desc. for distance tree */
+ this.bl_desc = null; /* desc. for bit length tree */
+
+ //ush bl_count[MAX_BITS+1];
+ this.bl_count = new utils.Buf16(MAX_BITS+1);
+ /* number of codes at each bit length for an optimal tree */
+
+ //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ this.heap = new utils.Buf16(2*L_CODES+1); /* heap used to build the Huffman trees */
+ zero(this.heap);
+
+ this.heap_len = 0; /* number of elements in the heap */
+ this.heap_max = 0; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ this.depth = new utils.Buf16(2*L_CODES+1); //uch depth[2*L_CODES+1];
+ zero(this.depth);
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ this.l_buf = 0; /* buffer index for literals or lengths */
+
+ this.lit_bufsize = 0;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ this.last_lit = 0; /* running index in l_buf */
+
+ this.d_buf = 0;
+ /* Buffer index for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ this.opt_len = 0; /* bit length of current block with optimal trees */
+ this.static_len = 0; /* bit length of current block with static trees */
+ this.matches = 0; /* number of string matches in current block */
+ this.insert = 0; /* bytes at end of window left to insert */
+
+
+ this.bi_buf = 0;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ this.bi_valid = 0;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ // Used for window memory init. We safely ignore it for JS. That makes
+ // sense only for pointers and memory check tools.
+ //this.high_water = 0;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+}
+
+
+function deflateResetKeep(strm) {
+ var s;
+
+ if (!strm || !strm.state) {
+ return err(strm, Z_STREAM_ERROR);
+ }
+
+ strm.total_in = strm.total_out = 0;
+ strm.data_type = Z_UNKNOWN;
+
+ s = strm.state;
+ s.pending = 0;
+ s.pending_out = 0;
+
+ if (s.wrap < 0) {
+ s.wrap = -s.wrap;
+ /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
+ strm.adler = (s.wrap === 2) ?
+ 0 // crc32(0, Z_NULL, 0)
+ :
+ 1; // adler32(0, Z_NULL, 0)
+ s.last_flush = Z_NO_FLUSH;
+ trees._tr_init(s);
+ return Z_OK;
+}
+
+
+function deflateReset(strm) {
+ var ret = deflateResetKeep(strm);
+ if (ret === Z_OK) {
+ lm_init(strm.state);
+ }
+ return ret;
+}
+
+
+function deflateSetHeader(strm, head) {
+ if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+ if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
+ strm.state.gzhead = head;
+ return Z_OK;
+}
+
+
+function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
+ if (!strm) { // === Z_NULL
+ return Z_STREAM_ERROR;
+ }
+ var wrap = 1;
+
+ if (level === Z_DEFAULT_COMPRESSION) {
+ level = 6;
+ }
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return err(strm, Z_STREAM_ERROR);
+ }
+
+
+ if (windowBits === 8) {
+ windowBits = 9;
+ }
+ /* until 256-byte window bug fixed */
+
+ var s = new DeflateState();
+
+ strm.state = s;
+ s.strm = strm;
+
+ s.wrap = wrap;
+ s.gzhead = null;
+ s.w_bits = windowBits;
+ s.w_size = 1 << s.w_bits;
+ s.w_mask = s.w_size - 1;
+
+ s.hash_bits = memLevel + 7;
+ s.hash_size = 1 << s.hash_bits;
+ s.hash_mask = s.hash_size - 1;
+ s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
+
+ s.window = new utils.Buf8(s.w_size * 2);
+ s.head = new utils.Buf16(s.hash_size);
+ s.prev = new utils.Buf16(s.w_size);
+
+ // Don't need mem init magic for JS.
+ //s.high_water = 0; /* nothing written to s->window yet */
+
+ s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ s.pending_buf_size = s.lit_bufsize * 4;
+ s.pending_buf = new utils.Buf8(s.pending_buf_size);
+
+ s.d_buf = s.lit_bufsize >> 1;
+ s.l_buf = (1 + 2) * s.lit_bufsize;
+
+ s.level = level;
+ s.strategy = strategy;
+ s.method = method;
+
+ return deflateReset(strm);
+}
+
+function deflateInit(strm, level) {
+ return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+}
+
+
+function deflate(strm, flush) {
+ var old_flush, s;
+ var beg, val; // for gzip header write only
+
+ if (!strm || !strm.state ||
+ flush > Z_BLOCK || flush < 0) {
+ return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
+ }
+
+ s = strm.state;
+
+ if (!strm.output ||
+ (!strm.input && strm.avail_in !== 0) ||
+ (s.status === FINISH_STATE && flush !== Z_FINISH)) {
+ return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
+ }
+
+ s.strm = strm; /* just in case */
+ old_flush = s.last_flush;
+ s.last_flush = flush;
+
+ /* Write the header */
+ if (s.status === INIT_STATE) {
+
+ if (s.wrap === 2) { // GZIP header
+ strm.adler = 0; //crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (!s.gzhead) { // s->gzhead == Z_NULL
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s.level === 9 ? 2 :
+ (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s.status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s.gzhead.text ? 1 : 0) +
+ (s.gzhead.hcrc ? 2 : 0) +
+ (!s.gzhead.extra ? 0 : 4) +
+ (!s.gzhead.name ? 0 : 8) +
+ (!s.gzhead.comment ? 0 : 16)
+ );
+ put_byte(s, s.gzhead.time & 0xff);
+ put_byte(s, (s.gzhead.time >> 8) & 0xff);
+ put_byte(s, (s.gzhead.time >> 16) & 0xff);
+ put_byte(s, (s.gzhead.time >> 24) & 0xff);
+ put_byte(s, s.level === 9 ? 2 :
+ (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
+ 4 : 0));
+ put_byte(s, s.gzhead.os & 0xff);
+ if (s.gzhead.extra && s.gzhead.extra.length) {
+ put_byte(s, s.gzhead.extra.length & 0xff);
+ put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
+ }
+ if (s.gzhead.hcrc) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
+ }
+ s.gzindex = 0;
+ s.status = EXTRA_STATE;
+ }
+ }
+ else // DEFLATE header
+ {
+ var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
+ var level_flags = -1;
+
+ if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
+ level_flags = 0;
+ } else if (s.level < 6) {
+ level_flags = 1;
+ } else if (s.level === 6) {
+ level_flags = 2;
+ } else {
+ level_flags = 3;
+ }
+ header |= (level_flags << 6);
+ if (s.strstart !== 0) { header |= PRESET_DICT; }
+ header += 31 - (header % 31);
+
+ s.status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s.strstart !== 0) {
+ putShortMSB(s, strm.adler >>> 16);
+ putShortMSB(s, strm.adler & 0xffff);
+ }
+ strm.adler = 1; // adler32(0L, Z_NULL, 0);
+ }
+ }
+
+//#ifdef GZIP
+ if (s.status === EXTRA_STATE) {
+ if (s.gzhead.extra/* != Z_NULL*/) {
+ beg = s.pending; /* start of bytes to update crc */
+
+ while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
+ if (s.pending === s.pending_buf_size) {
+ if (s.gzhead.hcrc && s.pending > beg) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ flush_pending(strm);
+ beg = s.pending;
+ if (s.pending === s.pending_buf_size) {
+ break;
+ }
+ }
+ put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
+ s.gzindex++;
+ }
+ if (s.gzhead.hcrc && s.pending > beg) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ if (s.gzindex === s.gzhead.extra.length) {
+ s.gzindex = 0;
+ s.status = NAME_STATE;
+ }
+ }
+ else {
+ s.status = NAME_STATE;
+ }
+ }
+ if (s.status === NAME_STATE) {
+ if (s.gzhead.name/* != Z_NULL*/) {
+ beg = s.pending; /* start of bytes to update crc */
+ //int val;
+
+ do {
+ if (s.pending === s.pending_buf_size) {
+ if (s.gzhead.hcrc && s.pending > beg) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ flush_pending(strm);
+ beg = s.pending;
+ if (s.pending === s.pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ // JS specific: little magic to add zero terminator to end of string
+ if (s.gzindex < s.gzhead.name.length) {
+ val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
+ } else {
+ val = 0;
+ }
+ put_byte(s, val);
+ } while (val !== 0);
+
+ if (s.gzhead.hcrc && s.pending > beg){
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ if (val === 0) {
+ s.gzindex = 0;
+ s.status = COMMENT_STATE;
+ }
+ }
+ else {
+ s.status = COMMENT_STATE;
+ }
+ }
+ if (s.status === COMMENT_STATE) {
+ if (s.gzhead.comment/* != Z_NULL*/) {
+ beg = s.pending; /* start of bytes to update crc */
+ //int val;
+
+ do {
+ if (s.pending === s.pending_buf_size) {
+ if (s.gzhead.hcrc && s.pending > beg) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ flush_pending(strm);
+ beg = s.pending;
+ if (s.pending === s.pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ // JS specific: little magic to add zero terminator to end of string
+ if (s.gzindex < s.gzhead.comment.length) {
+ val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
+ } else {
+ val = 0;
+ }
+ put_byte(s, val);
+ } while (val !== 0);
+
+ if (s.gzhead.hcrc && s.pending > beg) {
+ strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+ }
+ if (val === 0) {
+ s.status = HCRC_STATE;
+ }
+ }
+ else {
+ s.status = HCRC_STATE;
+ }
+ }
+ if (s.status === HCRC_STATE) {
+ if (s.gzhead.hcrc) {
+ if (s.pending + 2 > s.pending_buf_size) {
+ flush_pending(strm);
+ }
+ if (s.pending + 2 <= s.pending_buf_size) {
+ put_byte(s, strm.adler & 0xff);
+ put_byte(s, (strm.adler >> 8) & 0xff);
+ strm.adler = 0; //crc32(0L, Z_NULL, 0);
+ s.status = BUSY_STATE;
+ }
+ }
+ else {
+ s.status = BUSY_STATE;
+ }
+ }
+//#endif
+
+ /* Flush as much pending output as possible */
+ if (s.pending !== 0) {
+ flush_pending(strm);
+ if (strm.avail_out === 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s.last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
+ flush !== Z_FINISH) {
+ return err(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s.status === FINISH_STATE && strm.avail_in !== 0) {
+ return err(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm.avail_in !== 0 || s.lookahead !== 0 ||
+ (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
+ var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
+ (s.strategy === Z_RLE ? deflate_rle(s, flush) :
+ configuration_table[s.level].func(s, flush));
+
+ if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
+ s.status = FINISH_STATE;
+ }
+ if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
+ if (strm.avail_out === 0) {
+ s.last_flush = -1;
+ /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate === BS_BLOCK_DONE) {
+ if (flush === Z_PARTIAL_FLUSH) {
+ trees._tr_align(s);
+ }
+ else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+
+ trees._tr_stored_block(s, 0, 0, false);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush === Z_FULL_FLUSH) {
+ /*** CLEAR_HASH(s); ***/ /* forget history */
+ zero(s.head); // Fill with NIL (= 0);
+
+ if (s.lookahead === 0) {
+ s.strstart = 0;
+ s.block_start = 0;
+ s.insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm.avail_out === 0) {
+ s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ //Assert(strm->avail_out > 0, "bug2");
+ //if (strm.avail_out <= 0) { throw new Error("bug2");}
+
+ if (flush !== Z_FINISH) { return Z_OK; }
+ if (s.wrap <= 0) { return Z_STREAM_END; }
+
+ /* Write the trailer */
+ if (s.wrap === 2) {
+ put_byte(s, strm.adler & 0xff);
+ put_byte(s, (strm.adler >> 8) & 0xff);
+ put_byte(s, (strm.adler >> 16) & 0xff);
+ put_byte(s, (strm.adler >> 24) & 0xff);
+ put_byte(s, strm.total_in & 0xff);
+ put_byte(s, (strm.total_in >> 8) & 0xff);
+ put_byte(s, (strm.total_in >> 16) & 0xff);
+ put_byte(s, (strm.total_in >> 24) & 0xff);
+ }
+ else
+ {
+ putShortMSB(s, strm.adler >>> 16);
+ putShortMSB(s, strm.adler & 0xffff);
+ }
+
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s.wrap > 0) { s.wrap = -s.wrap; }
+ /* write the trailer only once! */
+ return s.pending !== 0 ? Z_OK : Z_STREAM_END;
+}
+
+function deflateEnd(strm) {
+ var status;
+
+ if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
+ return Z_STREAM_ERROR;
+ }
+
+ status = strm.state.status;
+ if (status !== INIT_STATE &&
+ status !== EXTRA_STATE &&
+ status !== NAME_STATE &&
+ status !== COMMENT_STATE &&
+ status !== HCRC_STATE &&
+ status !== BUSY_STATE &&
+ status !== FINISH_STATE
+ ) {
+ return err(strm, Z_STREAM_ERROR);
+ }
+
+ strm.state = null;
+
+ return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state
+ */
+//function deflateCopy(dest, source) {
+//
+//}
+
+exports.deflateInit = deflateInit;
+exports.deflateInit2 = deflateInit2;
+exports.deflateReset = deflateReset;
+exports.deflateResetKeep = deflateResetKeep;
+exports.deflateSetHeader = deflateSetHeader;
+exports.deflate = deflate;
+exports.deflateEnd = deflateEnd;
+exports.deflateInfo = 'pako deflate (from Nodeca project)';
+
+/* Not implemented
+exports.deflateBound = deflateBound;
+exports.deflateCopy = deflateCopy;
+exports.deflateSetDictionary = deflateSetDictionary;
+exports.deflateParams = deflateParams;
+exports.deflatePending = deflatePending;
+exports.deflatePrime = deflatePrime;
+exports.deflateTune = deflateTune;
+*/
+},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(_dereq_,module,exports){
+'use strict';
+
+
+function GZheader() {
+ /* true if compressed data believed to be text */
+ this.text = 0;
+ /* modification time */
+ this.time = 0;
+ /* extra flags (not used when writing a gzip file) */
+ this.xflags = 0;
+ /* operating system */
+ this.os = 0;
+ /* pointer to extra field or Z_NULL if none */
+ this.extra = null;
+ /* extra field length (valid if extra != Z_NULL) */
+ this.extra_len = 0; // Actually, we don't need it in JS,
+ // but leave for few code modifications
+
+ //
+ // Setup limits is not necessary because in js we should not preallocate memory
+ // for inflate use constant limit in 65536 bytes
+ //
+
+ /* space at extra (only when reading header) */
+ // this.extra_max = 0;
+ /* pointer to zero-terminated file name or Z_NULL */
+ this.name = '';
+ /* space at name (only when reading header) */
+ // this.name_max = 0;
+ /* pointer to zero-terminated comment or Z_NULL */
+ this.comment = '';
+ /* space at comment (only when reading header) */
+ // this.comm_max = 0;
+ /* true if there was or will be a header crc */
+ this.hcrc = 0;
+ /* true when done reading gzip header (not used when writing a gzip file) */
+ this.done = false;
+}
+
+module.exports = GZheader;
+},{}],34:[function(_dereq_,module,exports){
+'use strict';
+
+// See state defs from inflate.js
+var BAD = 30; /* got a data error -- remain here until reset */
+var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state.mode === LEN
+ strm.avail_in >= 6
+ strm.avail_out >= 258
+ start >= strm.avail_out
+ state.bits < 8
+
+ On return, state.mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm.avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm.avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+module.exports = function inflate_fast(strm, start) {
+ var state;
+ var _in; /* local strm.input */
+ var last; /* have enough input while in < last */
+ var _out; /* local strm.output */
+ var beg; /* inflate()'s initial strm.output */
+ var end; /* while out < end, enough space available */
+//#ifdef INFLATE_STRICT
+ var dmax; /* maximum distance from zlib header */
+//#endif
+ var wsize; /* window size or zero if not using window */
+ var whave; /* valid bytes in the window */
+ var wnext; /* window write index */
+ var window; /* allocated sliding window, if wsize != 0 */
+ var hold; /* local strm.hold */
+ var bits; /* local strm.bits */
+ var lcode; /* local strm.lencode */
+ var dcode; /* local strm.distcode */
+ var lmask; /* mask for first level of length codes */
+ var dmask; /* mask for first level of distance codes */
+ var here; /* retrieved table entry */
+ var op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ var len; /* match length, unused bytes */
+ var dist; /* match distance */
+ var from; /* where to copy match from */
+ var from_source;
+
+
+ var input, output; // JS specific, because we have no pointers
+
+ /* copy state to local variables */
+ state = strm.state;
+ //here = state.here;
+ _in = strm.next_in;
+ input = strm.input;
+ last = _in + (strm.avail_in - 5);
+ _out = strm.next_out;
+ output = strm.output;
+ beg = _out - (start - strm.avail_out);
+ end = _out + (strm.avail_out - 257);
+//#ifdef INFLATE_STRICT
+ dmax = state.dmax;
+//#endif
+ wsize = state.wsize;
+ whave = state.whave;
+ wnext = state.wnext;
+ window = state.window;
+ hold = state.hold;
+ bits = state.bits;
+ lcode = state.lencode;
+ dcode = state.distcode;
+ lmask = (1 << state.lenbits) - 1;
+ dmask = (1 << state.distbits) - 1;
+
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+
+ top:
+ do {
+ if (bits < 15) {
+ hold += input[_in++] << bits;
+ bits += 8;
+ hold += input[_in++] << bits;
+ bits += 8;
+ }
+
+ here = lcode[hold & lmask];
+
+ dolen:
+ for (;;) { // Goto emulation
+ op = here >>> 24/*here.bits*/;
+ hold >>>= op;
+ bits -= op;
+ op = (here >>> 16) & 0xff/*here.op*/;
+ if (op === 0) { /* literal */
+ //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ // "inflate: literal '%c'\n" :
+ // "inflate: literal 0x%02x\n", here.val));
+ output[_out++] = here & 0xffff/*here.val*/;
+ }
+ else if (op & 16) { /* length base */
+ len = here & 0xffff/*here.val*/;
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += input[_in++] << bits;
+ bits += 8;
+ }
+ len += hold & ((1 << op) - 1);
+ hold >>>= op;
+ bits -= op;
+ }
+ //Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += input[_in++] << bits;
+ bits += 8;
+ hold += input[_in++] << bits;
+ bits += 8;
+ }
+ here = dcode[hold & dmask];
+
+ dodist:
+ for (;;) { // goto emulation
+ op = here >>> 24/*here.bits*/;
+ hold >>>= op;
+ bits -= op;
+ op = (here >>> 16) & 0xff/*here.op*/;
+
+ if (op & 16) { /* distance base */
+ dist = here & 0xffff/*here.val*/;
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += input[_in++] << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += input[_in++] << bits;
+ bits += 8;
+ }
+ }
+ dist += hold & ((1 << op) - 1);
+//#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break top;
+ }
+//#endif
+ hold >>>= op;
+ bits -= op;
+ //Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = _out - beg; /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state.sane) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break top;
+ }
+
+// (!) This block is disabled in zlib defailts,
+// don't enable it for binary compatibility
+//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+// if (len <= op - whave) {
+// do {
+// output[_out++] = 0;
+// } while (--len);
+// continue top;
+// }
+// len -= op - whave;
+// do {
+// output[_out++] = 0;
+// } while (--op > whave);
+// if (op === 0) {
+// from = _out - dist;
+// do {
+// output[_out++] = output[from++];
+// } while (--len);
+// continue top;
+// }
+//#endif
+ }
+ from = 0; // window index
+ from_source = window;
+ if (wnext === 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ output[_out++] = window[from++];
+ } while (--op);
+ from = _out - dist; /* rest from output */
+ from_source = output;
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ output[_out++] = window[from++];
+ } while (--op);
+ from = 0;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ output[_out++] = window[from++];
+ } while (--op);
+ from = _out - dist; /* rest from output */
+ from_source = output;
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ output[_out++] = window[from++];
+ } while (--op);
+ from = _out - dist; /* rest from output */
+ from_source = output;
+ }
+ }
+ while (len > 2) {
+ output[_out++] = from_source[from++];
+ output[_out++] = from_source[from++];
+ output[_out++] = from_source[from++];
+ len -= 3;
+ }
+ if (len) {
+ output[_out++] = from_source[from++];
+ if (len > 1) {
+ output[_out++] = from_source[from++];
+ }
+ }
+ }
+ else {
+ from = _out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ output[_out++] = output[from++];
+ output[_out++] = output[from++];
+ output[_out++] = output[from++];
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ output[_out++] = output[from++];
+ if (len > 1) {
+ output[_out++] = output[from++];
+ }
+ }
+ }
+ }
+ else if ((op & 64) === 0) { /* 2nd level distance code */
+ here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
+ continue dodist;
+ }
+ else {
+ strm.msg = 'invalid distance code';
+ state.mode = BAD;
+ break top;
+ }
+
+ break; // need to emulate goto via "continue"
+ }
+ }
+ else if ((op & 64) === 0) { /* 2nd level length code */
+ here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
+ continue dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ //Tracevv((stderr, "inflate: end of block\n"));
+ state.mode = TYPE;
+ break top;
+ }
+ else {
+ strm.msg = 'invalid literal/length code';
+ state.mode = BAD;
+ break top;
+ }
+
+ break; // need to emulate goto via "continue"
+ }
+ } while (_in < last && _out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ _in -= len;
+ bits -= len << 3;
+ hold &= (1 << bits) - 1;
+
+ /* update state and return */
+ strm.next_in = _in;
+ strm.next_out = _out;
+ strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
+ strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
+ state.hold = hold;
+ state.bits = bits;
+ return;
+};
+
+},{}],35:[function(_dereq_,module,exports){
+'use strict';
+
+
+var utils = _dereq_('../utils/common');
+var adler32 = _dereq_('./adler32');
+var crc32 = _dereq_('./crc32');
+var inflate_fast = _dereq_('./inffast');
+var inflate_table = _dereq_('./inftrees');
+
+var CODES = 0;
+var LENS = 1;
+var DISTS = 2;
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+/* Allowed flush values; see deflate() and inflate() below for details */
+//var Z_NO_FLUSH = 0;
+//var Z_PARTIAL_FLUSH = 1;
+//var Z_SYNC_FLUSH = 2;
+//var Z_FULL_FLUSH = 3;
+var Z_FINISH = 4;
+var Z_BLOCK = 5;
+var Z_TREES = 6;
+
+
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+var Z_OK = 0;
+var Z_STREAM_END = 1;
+var Z_NEED_DICT = 2;
+//var Z_ERRNO = -1;
+var Z_STREAM_ERROR = -2;
+var Z_DATA_ERROR = -3;
+var Z_MEM_ERROR = -4;
+var Z_BUF_ERROR = -5;
+//var Z_VERSION_ERROR = -6;
+
+/* The deflate compression method */
+var Z_DEFLATED = 8;
+
+
+/* STATES ====================================================================*/
+/* ===========================================================================*/
+
+
+var HEAD = 1; /* i: waiting for magic header */
+var FLAGS = 2; /* i: waiting for method and flags (gzip) */
+var TIME = 3; /* i: waiting for modification time (gzip) */
+var OS = 4; /* i: waiting for extra flags and operating system (gzip) */
+var EXLEN = 5; /* i: waiting for extra length (gzip) */
+var EXTRA = 6; /* i: waiting for extra bytes (gzip) */
+var NAME = 7; /* i: waiting for end of file name (gzip) */
+var COMMENT = 8; /* i: waiting for end of comment (gzip) */
+var HCRC = 9; /* i: waiting for header crc (gzip) */
+var DICTID = 10; /* i: waiting for dictionary check value */
+var DICT = 11; /* waiting for inflateSetDictionary() call */
+var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
+var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */
+var STORED = 14; /* i: waiting for stored size (length and complement) */
+var COPY_ = 15; /* i/o: same as COPY below, but only first time in */
+var COPY = 16; /* i/o: waiting for input or output to copy stored block */
+var TABLE = 17; /* i: waiting for dynamic block table lengths */
+var LENLENS = 18; /* i: waiting for code length code lengths */
+var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */
+var LEN_ = 20; /* i: same as LEN below, but only first time in */
+var LEN = 21; /* i: waiting for length/lit/eob code */
+var LENEXT = 22; /* i: waiting for length extra bits */
+var DIST = 23; /* i: waiting for distance code */
+var DISTEXT = 24; /* i: waiting for distance extra bits */
+var MATCH = 25; /* o: waiting for output space to copy string */
+var LIT = 26; /* o: waiting for output space to write literal */
+var CHECK = 27; /* i: waiting for 32-bit check value */
+var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */
+var DONE = 29; /* finished check, done -- remain here until reset */
+var BAD = 30; /* got a data error -- remain here until reset */
+var MEM = 31; /* got an inflate() memory error -- remain here until reset */
+var SYNC = 32; /* looking for synchronization bytes to restart inflate() */
+
+/* ===========================================================================*/
+
+
+
+var ENOUGH_LENS = 852;
+var ENOUGH_DISTS = 592;
+//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
+
+var MAX_WBITS = 15;
+/* 32K LZ77 window */
+var DEF_WBITS = MAX_WBITS;
+
+
+function ZSWAP32(q) {
+ return (((q >>> 24) & 0xff) +
+ ((q >>> 8) & 0xff00) +
+ ((q & 0xff00) << 8) +
+ ((q & 0xff) << 24));
+}
+
+
+function InflateState() {
+ this.mode = 0; /* current inflate mode */
+ this.last = false; /* true if processing last block */
+ this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
+ this.havedict = false; /* true if dictionary provided */
+ this.flags = 0; /* gzip header method and flags (0 if zlib) */
+ this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
+ this.check = 0; /* protected copy of check value */
+ this.total = 0; /* protected copy of output count */
+ // TODO: may be {}
+ this.head = null; /* where to save gzip header information */
+
+ /* sliding window */
+ this.wbits = 0; /* log base 2 of requested window size */
+ this.wsize = 0; /* window size or zero if not using window */
+ this.whave = 0; /* valid bytes in the window */
+ this.wnext = 0; /* window write index */
+ this.window = null; /* allocated sliding window, if needed */
+
+ /* bit accumulator */
+ this.hold = 0; /* input bit accumulator */
+ this.bits = 0; /* number of bits in "in" */
+
+ /* for string and stored block copying */
+ this.length = 0; /* literal or length of data to copy */
+ this.offset = 0; /* distance back to copy string from */
+
+ /* for table and code decoding */
+ this.extra = 0; /* extra bits needed */
+
+ /* fixed and dynamic code tables */
+ this.lencode = null; /* starting table for length/literal codes */
+ this.distcode = null; /* starting table for distance codes */
+ this.lenbits = 0; /* index bits for lencode */
+ this.distbits = 0; /* index bits for distcode */
+
+ /* dynamic table building */
+ this.ncode = 0; /* number of code length code lengths */
+ this.nlen = 0; /* number of length code lengths */
+ this.ndist = 0; /* number of distance code lengths */
+ this.have = 0; /* number of code lengths in lens[] */
+ this.next = null; /* next available space in codes[] */
+
+ this.lens = new utils.Buf16(320); /* temporary storage for code lengths */
+ this.work = new utils.Buf16(288); /* work area for code table building */
+
+ /*
+ because we don't have pointers in js, we use lencode and distcode directly
+ as buffers so we don't need codes
+ */
+ //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */
+ this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */
+ this.distdyn = null; /* dynamic table for distance codes (JS specific) */
+ this.sane = 0; /* if false, allow invalid distance too far */
+ this.back = 0; /* bits back of last unprocessed length/lit */
+ this.was = 0; /* initial length of match */
+}
+
+function inflateResetKeep(strm) {
+ var state;
+
+ if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+ state = strm.state;
+ strm.total_in = strm.total_out = state.total = 0;
+ strm.msg = ''; /*Z_NULL*/
+ if (state.wrap) { /* to support ill-conceived Java test suite */
+ strm.adler = state.wrap & 1;
+ }
+ state.mode = HEAD;
+ state.last = 0;
+ state.havedict = 0;
+ state.dmax = 32768;
+ state.head = null/*Z_NULL*/;
+ state.hold = 0;
+ state.bits = 0;
+ //state.lencode = state.distcode = state.next = state.codes;
+ state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS);
+ state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS);
+
+ state.sane = 1;
+ state.back = -1;
+ //Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+function inflateReset(strm) {
+ var state;
+
+ if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+ state = strm.state;
+ state.wsize = 0;
+ state.whave = 0;
+ state.wnext = 0;
+ return inflateResetKeep(strm);
+
+}
+
+function inflateReset2(strm, windowBits) {
+ var wrap;
+ var state;
+
+ /* get the state */
+ if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+ state = strm.state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 1;
+ if (windowBits < 48) {
+ windowBits &= 15;
+ }
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15)) {
+ return Z_STREAM_ERROR;
+ }
+ if (state.window !== null && state.wbits !== windowBits) {
+ state.window = null;
+ }
+
+ /* update state and reset the rest of it */
+ state.wrap = wrap;
+ state.wbits = windowBits;
+ return inflateReset(strm);
+}
+
+function inflateInit2(strm, windowBits) {
+ var ret;
+ var state;
+
+ if (!strm) { return Z_STREAM_ERROR; }
+ //strm.msg = Z_NULL; /* in case we return an error */
+
+ state = new InflateState();
+
+ //if (state === Z_NULL) return Z_MEM_ERROR;
+ //Tracev((stderr, "inflate: allocated\n"));
+ strm.state = state;
+ state.window = null/*Z_NULL*/;
+ ret = inflateReset2(strm, windowBits);
+ if (ret !== Z_OK) {
+ strm.state = null/*Z_NULL*/;
+ }
+ return ret;
+}
+
+function inflateInit(strm) {
+ return inflateInit2(strm, DEF_WBITS);
+}
+
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+var virgin = true;
+
+var lenfix, distfix; // We have no pointers in JS, so keep tables separate
+
+function fixedtables(state) {
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ var sym;
+
+ lenfix = new utils.Buf32(512);
+ distfix = new utils.Buf32(32);
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) { state.lens[sym++] = 8; }
+ while (sym < 256) { state.lens[sym++] = 9; }
+ while (sym < 280) { state.lens[sym++] = 7; }
+ while (sym < 288) { state.lens[sym++] = 8; }
+
+ inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9});
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) { state.lens[sym++] = 5; }
+
+ inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5});
+
+ /* do this just once */
+ virgin = false;
+ }
+
+ state.lencode = lenfix;
+ state.lenbits = 9;
+ state.distcode = distfix;
+ state.distbits = 5;
+}
+
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+function updatewindow(strm, src, end, copy) {
+ var dist;
+ var state = strm.state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state.window === null) {
+ state.wsize = 1 << state.wbits;
+ state.wnext = 0;
+ state.whave = 0;
+
+ state.window = new utils.Buf8(state.wsize);
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state.wsize) {
+ utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0);
+ state.wnext = 0;
+ state.whave = state.wsize;
+ }
+ else {
+ dist = state.wsize - state.wnext;
+ if (dist > copy) {
+ dist = copy;
+ }
+ //zmemcpy(state->window + state->wnext, end - copy, dist);
+ utils.arraySet(state.window,src, end - copy, dist, state.wnext);
+ copy -= dist;
+ if (copy) {
+ //zmemcpy(state->window, end - copy, copy);
+ utils.arraySet(state.window,src, end - copy, copy, 0);
+ state.wnext = copy;
+ state.whave = state.wsize;
+ }
+ else {
+ state.wnext += dist;
+ if (state.wnext === state.wsize) { state.wnext = 0; }
+ if (state.whave < state.wsize) { state.whave += dist; }
+ }
+ }
+ return 0;
+}
+
+function inflate(strm, flush) {
+ var state;
+ var input, output; // input/output buffers
+ var next; /* next input INDEX */
+ var put; /* next output INDEX */
+ var have, left; /* available input and output */
+ var hold; /* bit buffer */
+ var bits; /* bits in bit buffer */
+ var _in, _out; /* save starting available input and output */
+ var copy; /* number of stored or match bytes to copy */
+ var from; /* where to copy match bytes from */
+ var from_source;
+ var here = 0; /* current decoding table entry */
+ var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
+ //var last; /* parent table entry */
+ var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
+ var len; /* length to copy for repeats, bits to drop */
+ var ret; /* return code */
+ var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */
+ var opts;
+
+ var n; // temporary var for NEED_BITS
+
+ var order = /* permutation of code lengths */
+ [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
+
+
+ if (!strm || !strm.state || !strm.output ||
+ (!strm.input && strm.avail_in !== 0)) {
+ return Z_STREAM_ERROR;
+ }
+
+ state = strm.state;
+ if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */
+
+
+ //--- LOAD() ---
+ put = strm.next_out;
+ output = strm.output;
+ left = strm.avail_out;
+ next = strm.next_in;
+ input = strm.input;
+ have = strm.avail_in;
+ hold = state.hold;
+ bits = state.bits;
+ //---
+
+ _in = have;
+ _out = left;
+ ret = Z_OK;
+
+ inf_leave: // goto emulation
+ for (;;) {
+ switch (state.mode) {
+ case HEAD:
+ if (state.wrap === 0) {
+ state.mode = TYPEDO;
+ break;
+ }
+ //=== NEEDBITS(16);
+ while (bits < 16) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */
+ state.check = 0/*crc32(0L, Z_NULL, 0)*/;
+ //=== CRC2(state.check, hold);
+ hbuf[0] = hold & 0xff;
+ hbuf[1] = (hold >>> 8) & 0xff;
+ state.check = crc32(state.check, hbuf, 2, 0);
+ //===//
+
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = FLAGS;
+ break;
+ }
+ state.flags = 0; /* expect zlib header */
+ if (state.head) {
+ state.head.done = false;
+ }
+ if (!(state.wrap & 1) || /* check if zlib header allowed */
+ (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
+ strm.msg = 'incorrect header check';
+ state.mode = BAD;
+ break;
+ }
+ if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
+ strm.msg = 'unknown compression method';
+ state.mode = BAD;
+ break;
+ }
+ //--- DROPBITS(4) ---//
+ hold >>>= 4;
+ bits -= 4;
+ //---//
+ len = (hold & 0x0f)/*BITS(4)*/ + 8;
+ if (state.wbits === 0) {
+ state.wbits = len;
+ }
+ else if (len > state.wbits) {
+ strm.msg = 'invalid window size';
+ state.mode = BAD;
+ break;
+ }
+ state.dmax = 1 << len;
+ //Tracev((stderr, "inflate: zlib header ok\n"));
+ strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
+ state.mode = hold & 0x200 ? DICTID : TYPE;
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ break;
+ case FLAGS:
+ //=== NEEDBITS(16); */
+ while (bits < 16) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.flags = hold;
+ if ((state.flags & 0xff) !== Z_DEFLATED) {
+ strm.msg = 'unknown compression method';
+ state.mode = BAD;
+ break;
+ }
+ if (state.flags & 0xe000) {
+ strm.msg = 'unknown header flags set';
+ state.mode = BAD;
+ break;
+ }
+ if (state.head) {
+ state.head.text = ((hold >> 8) & 1);
+ }
+ if (state.flags & 0x0200) {
+ //=== CRC2(state.check, hold);
+ hbuf[0] = hold & 0xff;
+ hbuf[1] = (hold >>> 8) & 0xff;
+ state.check = crc32(state.check, hbuf, 2, 0);
+ //===//
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = TIME;
+ /* falls through */
+ case TIME:
+ //=== NEEDBITS(32); */
+ while (bits < 32) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if (state.head) {
+ state.head.time = hold;
+ }
+ if (state.flags & 0x0200) {
+ //=== CRC4(state.check, hold)
+ hbuf[0] = hold & 0xff;
+ hbuf[1] = (hold >>> 8) & 0xff;
+ hbuf[2] = (hold >>> 16) & 0xff;
+ hbuf[3] = (hold >>> 24) & 0xff;
+ state.check = crc32(state.check, hbuf, 4, 0);
+ //===
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = OS;
+ /* falls through */
+ case OS:
+ //=== NEEDBITS(16); */
+ while (bits < 16) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if (state.head) {
+ state.head.xflags = (hold & 0xff);
+ state.head.os = (hold >> 8);
+ }
+ if (state.flags & 0x0200) {
+ //=== CRC2(state.check, hold);
+ hbuf[0] = hold & 0xff;
+ hbuf[1] = (hold >>> 8) & 0xff;
+ state.check = crc32(state.check, hbuf, 2, 0);
+ //===//
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = EXLEN;
+ /* falls through */
+ case EXLEN:
+ if (state.flags & 0x0400) {
+ //=== NEEDBITS(16); */
+ while (bits < 16) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.length = hold;
+ if (state.head) {
+ state.head.extra_len = hold;
+ }
+ if (state.flags & 0x0200) {
+ //=== CRC2(state.check, hold);
+ hbuf[0] = hold & 0xff;
+ hbuf[1] = (hold >>> 8) & 0xff;
+ state.check = crc32(state.check, hbuf, 2, 0);
+ //===//
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ }
+ else if (state.head) {
+ state.head.extra = null/*Z_NULL*/;
+ }
+ state.mode = EXTRA;
+ /* falls through */
+ case EXTRA:
+ if (state.flags & 0x0400) {
+ copy = state.length;
+ if (copy > have) { copy = have; }
+ if (copy) {
+ if (state.head) {
+ len = state.head.extra_len - state.length;
+ if (!state.head.extra) {
+ // Use untyped array for more conveniend processing later
+ state.head.extra = new Array(state.head.extra_len);
+ }
+ utils.arraySet(
+ state.head.extra,
+ input,
+ next,
+ // extra field is limited to 65536 bytes
+ // - no need for additional size check
+ copy,
+ /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
+ len
+ );
+ //zmemcpy(state.head.extra + len, next,
+ // len + copy > state.head.extra_max ?
+ // state.head.extra_max - len : copy);
+ }
+ if (state.flags & 0x0200) {
+ state.check = crc32(state.check, input, copy, next);
+ }
+ have -= copy;
+ next += copy;
+ state.length -= copy;
+ }
+ if (state.length) { break inf_leave; }
+ }
+ state.length = 0;
+ state.mode = NAME;
+ /* falls through */
+ case NAME:
+ if (state.flags & 0x0800) {
+ if (have === 0) { break inf_leave; }
+ copy = 0;
+ do {
+ // TODO: 2 or 1 bytes?
+ len = input[next + copy++];
+ /* use constant limit because in js we should not preallocate memory */
+ if (state.head && len &&
+ (state.length < 65536 /*state.head.name_max*/)) {
+ state.head.name += String.fromCharCode(len);
+ }
+ } while (len && copy < have);
+
+ if (state.flags & 0x0200) {
+ state.check = crc32(state.check, input, copy, next);
+ }
+ have -= copy;
+ next += copy;
+ if (len) { break inf_leave; }
+ }
+ else if (state.head) {
+ state.head.name = null;
+ }
+ state.length = 0;
+ state.mode = COMMENT;
+ /* falls through */
+ case COMMENT:
+ if (state.flags & 0x1000) {
+ if (have === 0) { break inf_leave; }
+ copy = 0;
+ do {
+ len = input[next + copy++];
+ /* use constant limit because in js we should not preallocate memory */
+ if (state.head && len &&
+ (state.length < 65536 /*state.head.comm_max*/)) {
+ state.head.comment += String.fromCharCode(len);
+ }
+ } while (len && copy < have);
+ if (state.flags & 0x0200) {
+ state.check = crc32(state.check, input, copy, next);
+ }
+ have -= copy;
+ next += copy;
+ if (len) { break inf_leave; }
+ }
+ else if (state.head) {
+ state.head.comment = null;
+ }
+ state.mode = HCRC;
+ /* falls through */
+ case HCRC:
+ if (state.flags & 0x0200) {
+ //=== NEEDBITS(16); */
+ while (bits < 16) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if (hold !== (state.check & 0xffff)) {
+ strm.msg = 'header crc mismatch';
+ state.mode = BAD;
+ break;
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ }
+ if (state.head) {
+ state.head.hcrc = ((state.flags >> 9) & 1);
+ state.head.done = true;
+ }
+ strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/;
+ state.mode = TYPE;
+ break;
+ case DICTID:
+ //=== NEEDBITS(32); */
+ while (bits < 32) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ strm.adler = state.check = ZSWAP32(hold);
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = DICT;
+ /* falls through */
+ case DICT:
+ if (state.havedict === 0) {
+ //--- RESTORE() ---
+ strm.next_out = put;
+ strm.avail_out = left;
+ strm.next_in = next;
+ strm.avail_in = have;
+ state.hold = hold;
+ state.bits = bits;
+ //---
+ return Z_NEED_DICT;
+ }
+ strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
+ state.mode = TYPE;
+ /* falls through */
+ case TYPE:
+ if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
+ /* falls through */
+ case TYPEDO:
+ if (state.last) {
+ //--- BYTEBITS() ---//
+ hold >>>= bits & 7;
+ bits -= bits & 7;
+ //---//
+ state.mode = CHECK;
+ break;
+ }
+ //=== NEEDBITS(3); */
+ while (bits < 3) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.last = (hold & 0x01)/*BITS(1)*/;
+ //--- DROPBITS(1) ---//
+ hold >>>= 1;
+ bits -= 1;
+ //---//
+
+ switch ((hold & 0x03)/*BITS(2)*/) {
+ case 0: /* stored block */
+ //Tracev((stderr, "inflate: stored block%s\n",
+ // state.last ? " (last)" : ""));
+ state.mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ //Tracev((stderr, "inflate: fixed codes block%s\n",
+ // state.last ? " (last)" : ""));
+ state.mode = LEN_; /* decode codes */
+ if (flush === Z_TREES) {
+ //--- DROPBITS(2) ---//
+ hold >>>= 2;
+ bits -= 2;
+ //---//
+ break inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ //Tracev((stderr, "inflate: dynamic codes block%s\n",
+ // state.last ? " (last)" : ""));
+ state.mode = TABLE;
+ break;
+ case 3:
+ strm.msg = 'invalid block type';
+ state.mode = BAD;
+ }
+ //--- DROPBITS(2) ---//
+ hold >>>= 2;
+ bits -= 2;
+ //---//
+ break;
+ case STORED:
+ //--- BYTEBITS() ---// /* go to byte boundary */
+ hold >>>= bits & 7;
+ bits -= bits & 7;
+ //---//
+ //=== NEEDBITS(32); */
+ while (bits < 32) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
+ strm.msg = 'invalid stored block lengths';
+ state.mode = BAD;
+ break;
+ }
+ state.length = hold & 0xffff;
+ //Tracev((stderr, "inflate: stored length %u\n",
+ // state.length));
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ state.mode = COPY_;
+ if (flush === Z_TREES) { break inf_leave; }
+ /* falls through */
+ case COPY_:
+ state.mode = COPY;
+ /* falls through */
+ case COPY:
+ copy = state.length;
+ if (copy) {
+ if (copy > have) { copy = have; }
+ if (copy > left) { copy = left; }
+ if (copy === 0) { break inf_leave; }
+ //--- zmemcpy(put, next, copy); ---
+ utils.arraySet(output, input, next, copy, put);
+ //---//
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state.length -= copy;
+ break;
+ }
+ //Tracev((stderr, "inflate: stored end\n"));
+ state.mode = TYPE;
+ break;
+ case TABLE:
+ //=== NEEDBITS(14); */
+ while (bits < 14) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
+ //--- DROPBITS(5) ---//
+ hold >>>= 5;
+ bits -= 5;
+ //---//
+ state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
+ //--- DROPBITS(5) ---//
+ hold >>>= 5;
+ bits -= 5;
+ //---//
+ state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
+ //--- DROPBITS(4) ---//
+ hold >>>= 4;
+ bits -= 4;
+ //---//
+//#ifndef PKZIP_BUG_WORKAROUND
+ if (state.nlen > 286 || state.ndist > 30) {
+ strm.msg = 'too many length or distance symbols';
+ state.mode = BAD;
+ break;
+ }
+//#endif
+ //Tracev((stderr, "inflate: table sizes ok\n"));
+ state.have = 0;
+ state.mode = LENLENS;
+ /* falls through */
+ case LENLENS:
+ while (state.have < state.ncode) {
+ //=== NEEDBITS(3);
+ while (bits < 3) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
+ //--- DROPBITS(3) ---//
+ hold >>>= 3;
+ bits -= 3;
+ //---//
+ }
+ while (state.have < 19) {
+ state.lens[order[state.have++]] = 0;
+ }
+ // We have separate tables & no pointers. 2 commented lines below not needed.
+ //state.next = state.codes;
+ //state.lencode = state.next;
+ // Switch to use dynamic table
+ state.lencode = state.lendyn;
+ state.lenbits = 7;
+
+ opts = {bits: state.lenbits};
+ ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
+ state.lenbits = opts.bits;
+
+ if (ret) {
+ strm.msg = 'invalid code lengths set';
+ state.mode = BAD;
+ break;
+ }
+ //Tracev((stderr, "inflate: code lengths ok\n"));
+ state.have = 0;
+ state.mode = CODELENS;
+ /* falls through */
+ case CODELENS:
+ while (state.have < state.nlen + state.ndist) {
+ for (;;) {
+ here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
+ here_bits = here >>> 24;
+ here_op = (here >>> 16) & 0xff;
+ here_val = here & 0xffff;
+
+ if ((here_bits) <= bits) { break; }
+ //--- PULLBYTE() ---//
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ //---//
+ }
+ if (here_val < 16) {
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ state.lens[state.have++] = here_val;
+ }
+ else {
+ if (here_val === 16) {
+ //=== NEEDBITS(here.bits + 2);
+ n = here_bits + 2;
+ while (bits < n) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ if (state.have === 0) {
+ strm.msg = 'invalid bit length repeat';
+ state.mode = BAD;
+ break;
+ }
+ len = state.lens[state.have - 1];
+ copy = 3 + (hold & 0x03);//BITS(2);
+ //--- DROPBITS(2) ---//
+ hold >>>= 2;
+ bits -= 2;
+ //---//
+ }
+ else if (here_val === 17) {
+ //=== NEEDBITS(here.bits + 3);
+ n = here_bits + 3;
+ while (bits < n) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ len = 0;
+ copy = 3 + (hold & 0x07);//BITS(3);
+ //--- DROPBITS(3) ---//
+ hold >>>= 3;
+ bits -= 3;
+ //---//
+ }
+ else {
+ //=== NEEDBITS(here.bits + 7);
+ n = here_bits + 7;
+ while (bits < n) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ len = 0;
+ copy = 11 + (hold & 0x7f);//BITS(7);
+ //--- DROPBITS(7) ---//
+ hold >>>= 7;
+ bits -= 7;
+ //---//
+ }
+ if (state.have + copy > state.nlen + state.ndist) {
+ strm.msg = 'invalid bit length repeat';
+ state.mode = BAD;
+ break;
+ }
+ while (copy--) {
+ state.lens[state.have++] = len;
+ }
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state.mode === BAD) { break; }
+
+ /* check for end-of-block code (better have one) */
+ if (state.lens[256] === 0) {
+ strm.msg = 'invalid code -- missing end-of-block';
+ state.mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state.lenbits = 9;
+
+ opts = {bits: state.lenbits};
+ ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
+ // We have separate tables & no pointers. 2 commented lines below not needed.
+ // state.next_index = opts.table_index;
+ state.lenbits = opts.bits;
+ // state.lencode = state.next;
+
+ if (ret) {
+ strm.msg = 'invalid literal/lengths set';
+ state.mode = BAD;
+ break;
+ }
+
+ state.distbits = 6;
+ //state.distcode.copy(state.codes);
+ // Switch to use dynamic table
+ state.distcode = state.distdyn;
+ opts = {bits: state.distbits};
+ ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
+ // We have separate tables & no pointers. 2 commented lines below not needed.
+ // state.next_index = opts.table_index;
+ state.distbits = opts.bits;
+ // state.distcode = state.next;
+
+ if (ret) {
+ strm.msg = 'invalid distances set';
+ state.mode = BAD;
+ break;
+ }
+ //Tracev((stderr, 'inflate: codes ok\n'));
+ state.mode = LEN_;
+ if (flush === Z_TREES) { break inf_leave; }
+ /* falls through */
+ case LEN_:
+ state.mode = LEN;
+ /* falls through */
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ //--- RESTORE() ---
+ strm.next_out = put;
+ strm.avail_out = left;
+ strm.next_in = next;
+ strm.avail_in = have;
+ state.hold = hold;
+ state.bits = bits;
+ //---
+ inflate_fast(strm, _out);
+ //--- LOAD() ---
+ put = strm.next_out;
+ output = strm.output;
+ left = strm.avail_out;
+ next = strm.next_in;
+ input = strm.input;
+ have = strm.avail_in;
+ hold = state.hold;
+ bits = state.bits;
+ //---
+
+ if (state.mode === TYPE) {
+ state.back = -1;
+ }
+ break;
+ }
+ state.back = 0;
+ for (;;) {
+ here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/
+ here_bits = here >>> 24;
+ here_op = (here >>> 16) & 0xff;
+ here_val = here & 0xffff;
+
+ if (here_bits <= bits) { break; }
+ //--- PULLBYTE() ---//
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ //---//
+ }
+ if (here_op && (here_op & 0xf0) === 0) {
+ last_bits = here_bits;
+ last_op = here_op;
+ last_val = here_val;
+ for (;;) {
+ here = state.lencode[last_val +
+ ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)];
+ here_bits = here >>> 24;
+ here_op = (here >>> 16) & 0xff;
+ here_val = here & 0xffff;
+
+ if ((last_bits + here_bits) <= bits) { break; }
+ //--- PULLBYTE() ---//
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ //---//
+ }
+ //--- DROPBITS(last.bits) ---//
+ hold >>>= last_bits;
+ bits -= last_bits;
+ //---//
+ state.back += last_bits;
+ }
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ state.back += here_bits;
+ state.length = here_val;
+ if (here_op === 0) {
+ //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ // "inflate: literal '%c'\n" :
+ // "inflate: literal 0x%02x\n", here.val));
+ state.mode = LIT;
+ break;
+ }
+ if (here_op & 32) {
+ //Tracevv((stderr, "inflate: end of block\n"));
+ state.back = -1;
+ state.mode = TYPE;
+ break;
+ }
+ if (here_op & 64) {
+ strm.msg = 'invalid literal/length code';
+ state.mode = BAD;
+ break;
+ }
+ state.extra = here_op & 15;
+ state.mode = LENEXT;
+ /* falls through */
+ case LENEXT:
+ if (state.extra) {
+ //=== NEEDBITS(state.extra);
+ n = state.extra;
+ while (bits < n) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/;
+ //--- DROPBITS(state.extra) ---//
+ hold >>>= state.extra;
+ bits -= state.extra;
+ //---//
+ state.back += state.extra;
+ }
+ //Tracevv((stderr, "inflate: length %u\n", state.length));
+ state.was = state.length;
+ state.mode = DIST;
+ /* falls through */
+ case DIST:
+ for (;;) {
+ here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/
+ here_bits = here >>> 24;
+ here_op = (here >>> 16) & 0xff;
+ here_val = here & 0xffff;
+
+ if ((here_bits) <= bits) { break; }
+ //--- PULLBYTE() ---//
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ //---//
+ }
+ if ((here_op & 0xf0) === 0) {
+ last_bits = here_bits;
+ last_op = here_op;
+ last_val = here_val;
+ for (;;) {
+ here = state.distcode[last_val +
+ ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)];
+ here_bits = here >>> 24;
+ here_op = (here >>> 16) & 0xff;
+ here_val = here & 0xffff;
+
+ if ((last_bits + here_bits) <= bits) { break; }
+ //--- PULLBYTE() ---//
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ //---//
+ }
+ //--- DROPBITS(last.bits) ---//
+ hold >>>= last_bits;
+ bits -= last_bits;
+ //---//
+ state.back += last_bits;
+ }
+ //--- DROPBITS(here.bits) ---//
+ hold >>>= here_bits;
+ bits -= here_bits;
+ //---//
+ state.back += here_bits;
+ if (here_op & 64) {
+ strm.msg = 'invalid distance code';
+ state.mode = BAD;
+ break;
+ }
+ state.offset = here_val;
+ state.extra = (here_op) & 15;
+ state.mode = DISTEXT;
+ /* falls through */
+ case DISTEXT:
+ if (state.extra) {
+ //=== NEEDBITS(state.extra);
+ n = state.extra;
+ while (bits < n) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/;
+ //--- DROPBITS(state.extra) ---//
+ hold >>>= state.extra;
+ bits -= state.extra;
+ //---//
+ state.back += state.extra;
+ }
+//#ifdef INFLATE_STRICT
+ if (state.offset > state.dmax) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break;
+ }
+//#endif
+ //Tracevv((stderr, "inflate: distance %u\n", state.offset));
+ state.mode = MATCH;
+ /* falls through */
+ case MATCH:
+ if (left === 0) { break inf_leave; }
+ copy = _out - left;
+ if (state.offset > copy) { /* copy from window */
+ copy = state.offset - copy;
+ if (copy > state.whave) {
+ if (state.sane) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break;
+ }
+// (!) This block is disabled in zlib defailts,
+// don't enable it for binary compatibility
+//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+// Trace((stderr, "inflate.c too far\n"));
+// copy -= state.whave;
+// if (copy > state.length) { copy = state.length; }
+// if (copy > left) { copy = left; }
+// left -= copy;
+// state.length -= copy;
+// do {
+// output[put++] = 0;
+// } while (--copy);
+// if (state.length === 0) { state.mode = LEN; }
+// break;
+//#endif
+ }
+ if (copy > state.wnext) {
+ copy -= state.wnext;
+ from = state.wsize - copy;
+ }
+ else {
+ from = state.wnext - copy;
+ }
+ if (copy > state.length) { copy = state.length; }
+ from_source = state.window;
+ }
+ else { /* copy from output */
+ from_source = output;
+ from = put - state.offset;
+ copy = state.length;
+ }
+ if (copy > left) { copy = left; }
+ left -= copy;
+ state.length -= copy;
+ do {
+ output[put++] = from_source[from++];
+ } while (--copy);
+ if (state.length === 0) { state.mode = LEN; }
+ break;
+ case LIT:
+ if (left === 0) { break inf_leave; }
+ output[put++] = state.length;
+ left--;
+ state.mode = LEN;
+ break;
+ case CHECK:
+ if (state.wrap) {
+ //=== NEEDBITS(32);
+ while (bits < 32) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ // Use '|' insdead of '+' to make sure that result is signed
+ hold |= input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ _out -= left;
+ strm.total_out += _out;
+ state.total += _out;
+ if (_out) {
+ strm.adler = state.check =
+ /*UPDATE(state.check, put - _out, _out);*/
+ (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));
+
+ }
+ _out = left;
+ // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too
+ if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) {
+ strm.msg = 'incorrect data check';
+ state.mode = BAD;
+ break;
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ //Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+ state.mode = LENGTH;
+ /* falls through */
+ case LENGTH:
+ if (state.wrap && state.flags) {
+ //=== NEEDBITS(32);
+ while (bits < 32) {
+ if (have === 0) { break inf_leave; }
+ have--;
+ hold += input[next++] << bits;
+ bits += 8;
+ }
+ //===//
+ if (hold !== (state.total & 0xffffffff)) {
+ strm.msg = 'incorrect length check';
+ state.mode = BAD;
+ break;
+ }
+ //=== INITBITS();
+ hold = 0;
+ bits = 0;
+ //===//
+ //Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+ state.mode = DONE;
+ /* falls through */
+ case DONE:
+ ret = Z_STREAM_END;
+ break inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ break inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ /* falls through */
+ default:
+ return Z_STREAM_ERROR;
+ }
+ }
+
+ // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+
+ //--- RESTORE() ---
+ strm.next_out = put;
+ strm.avail_out = left;
+ strm.next_in = next;
+ strm.avail_in = have;
+ state.hold = hold;
+ state.bits = bits;
+ //---
+
+ if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
+ (state.mode < CHECK || flush !== Z_FINISH))) {
+ if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
+ state.mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ }
+ _in -= strm.avail_in;
+ _out -= strm.avail_out;
+ strm.total_in += _in;
+ strm.total_out += _out;
+ state.total += _out;
+ if (state.wrap && _out) {
+ strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
+ (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));
+ }
+ strm.data_type = state.bits + (state.last ? 64 : 0) +
+ (state.mode === TYPE ? 128 : 0) +
+ (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
+ if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) {
+ ret = Z_BUF_ERROR;
+ }
+ return ret;
+}
+
+function inflateEnd(strm) {
+
+ if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
+ return Z_STREAM_ERROR;
+ }
+
+ var state = strm.state;
+ if (state.window) {
+ state.window = null;
+ }
+ strm.state = null;
+ return Z_OK;
+}
+
+function inflateGetHeader(strm, head) {
+ var state;
+
+ /* check state */
+ if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+ state = strm.state;
+ if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }
+
+ /* save header structure */
+ state.head = head;
+ head.done = false;
+ return Z_OK;
+}
+
+
+exports.inflateReset = inflateReset;
+exports.inflateReset2 = inflateReset2;
+exports.inflateResetKeep = inflateResetKeep;
+exports.inflateInit = inflateInit;
+exports.inflateInit2 = inflateInit2;
+exports.inflate = inflate;
+exports.inflateEnd = inflateEnd;
+exports.inflateGetHeader = inflateGetHeader;
+exports.inflateInfo = 'pako inflate (from Nodeca project)';
+
+/* Not implemented
+exports.inflateCopy = inflateCopy;
+exports.inflateGetDictionary = inflateGetDictionary;
+exports.inflateMark = inflateMark;
+exports.inflatePrime = inflatePrime;
+exports.inflateSetDictionary = inflateSetDictionary;
+exports.inflateSync = inflateSync;
+exports.inflateSyncPoint = inflateSyncPoint;
+exports.inflateUndermine = inflateUndermine;
+*/
+},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(_dereq_,module,exports){
+'use strict';
+
+
+var utils = _dereq_('../utils/common');
+
+var MAXBITS = 15;
+var ENOUGH_LENS = 852;
+var ENOUGH_DISTS = 592;
+//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
+
+var CODES = 0;
+var LENS = 1;
+var DISTS = 2;
+
+var lbase = [ /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+];
+
+var lext = [ /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
+];
+
+var dbase = [ /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0
+];
+
+var dext = [ /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64
+];
+
+module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
+{
+ var bits = opts.bits;
+ //here = opts.here; /* table entry for duplication */
+
+ var len = 0; /* a code's length in bits */
+ var sym = 0; /* index of code symbols */
+ var min = 0, max = 0; /* minimum and maximum code lengths */
+ var root = 0; /* number of index bits for root table */
+ var curr = 0; /* number of index bits for current table */
+ var drop = 0; /* code bits to drop for sub-table */
+ var left = 0; /* number of prefix codes available */
+ var used = 0; /* code entries in table used */
+ var huff = 0; /* Huffman code */
+ var incr; /* for incrementing code, index */
+ var fill; /* index for replicating entries */
+ var low; /* low bits for current root entry */
+ var mask; /* mask for low root bits */
+ var next; /* next available space in table */
+ var base = null; /* base value table to use */
+ var base_index = 0;
+// var shoextra; /* extra bits table to use */
+ var end; /* use base and extra for symbol > end */
+ var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */
+ var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */
+ var extra = null;
+ var extra_index = 0;
+
+ var here_bits, here_op, here_val;
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++) {
+ count[len] = 0;
+ }
+ for (sym = 0; sym < codes; sym++) {
+ count[lens[lens_index + sym]]++;
+ }
+
+ /* bound code lengths, force root to be within code lengths */
+ root = bits;
+ for (max = MAXBITS; max >= 1; max--) {
+ if (count[max] !== 0) { break; }
+ }
+ if (root > max) {
+ root = max;
+ }
+ if (max === 0) { /* no symbols to code at all */
+ //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
+ //table.bits[opts.table_index] = 1; //here.bits = (var char)1;
+ //table.val[opts.table_index++] = 0; //here.val = (var short)0;
+ table[table_index++] = (1 << 24) | (64 << 16) | 0;
+
+
+ //table.op[opts.table_index] = 64;
+ //table.bits[opts.table_index] = 1;
+ //table.val[opts.table_index++] = 0;
+ table[table_index++] = (1 << 24) | (64 << 16) | 0;
+
+ opts.bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++) {
+ if (count[min] !== 0) { break; }
+ }
+ if (root < min) {
+ root = min;
+ }
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) {
+ return -1;
+ } /* over-subscribed */
+ }
+ if (left > 0 && (type === CODES || max !== 1)) {
+ return -1; /* incomplete set */
+ }
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++) {
+ offs[len + 1] = offs[len] + count[len];
+ }
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++) {
+ if (lens[lens_index + sym] !== 0) {
+ work[offs[lens[lens_index + sym]]++] = sym;
+ }
+ }
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ // poor man optimization - use if-else instead of switch,
+ // to avoid deopts in old v8
+ if (type === CODES) {
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ } else if (type === LENS) {
+ base = lbase;
+ base_index -= 257;
+ extra = lext;
+ extra_index -= 257;
+ end = 256;
+ } else { /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize opts for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = table_index; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = -1; /* trigger new sub-table when len > root */
+ used = 1 << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type === LENS && used > ENOUGH_LENS) ||
+ (type === DISTS && used > ENOUGH_DISTS)) {
+ return 1;
+ }
+
+ var i=0;
+ /* process all codes and make table entries */
+ for (;;) {
+ i++;
+ /* create table entry */
+ here_bits = len - drop;
+ if (work[sym] < end) {
+ here_op = 0;
+ here_val = work[sym];
+ }
+ else if (work[sym] > end) {
+ here_op = extra[extra_index + work[sym]];
+ here_val = base[base_index + work[sym]];
+ }
+ else {
+ here_op = 32 + 64; /* end of block */
+ here_val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1 << (len - drop);
+ fill = 1 << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
+ } while (fill !== 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1 << (len - 1);
+ while (huff & incr) {
+ incr >>= 1;
+ }
+ if (incr !== 0) {
+ huff &= incr - 1;
+ huff += incr;
+ } else {
+ huff = 0;
+ }
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--count[len] === 0) {
+ if (len === max) { break; }
+ len = lens[lens_index + work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) !== low) {
+ /* if first time, transition to sub-tables */
+ if (drop === 0) {
+ drop = root;
+ }
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = 1 << curr;
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) { break; }
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1 << curr;
+ if ((type === LENS && used > ENOUGH_LENS) ||
+ (type === DISTS && used > ENOUGH_DISTS)) {
+ return 1;
+ }
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ /*table.op[low] = curr;
+ table.bits[low] = root;
+ table.val[low] = next - opts.table_index;*/
+ table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff !== 0) {
+ //table.op[next + huff] = 64; /* invalid code marker */
+ //table.bits[next + huff] = len - drop;
+ //table.val[next + huff] = 0;
+ table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
+ }
+
+ /* set return parameters */
+ //opts.table_index += used;
+ opts.bits = root;
+ return 0;
+};
+
+},{"../utils/common":27}],37:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = {
+ '2': 'need dictionary', /* Z_NEED_DICT 2 */
+ '1': 'stream end', /* Z_STREAM_END 1 */
+ '0': '', /* Z_OK 0 */
+ '-1': 'file error', /* Z_ERRNO (-1) */
+ '-2': 'stream error', /* Z_STREAM_ERROR (-2) */
+ '-3': 'data error', /* Z_DATA_ERROR (-3) */
+ '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */
+ '-5': 'buffer error', /* Z_BUF_ERROR (-5) */
+ '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
+};
+},{}],38:[function(_dereq_,module,exports){
+'use strict';
+
+
+var utils = _dereq_('../utils/common');
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+//var Z_FILTERED = 1;
+//var Z_HUFFMAN_ONLY = 2;
+//var Z_RLE = 3;
+var Z_FIXED = 4;
+//var Z_DEFAULT_STRATEGY = 0;
+
+/* Possible values of the data_type field (though see inflate()) */
+var Z_BINARY = 0;
+var Z_TEXT = 1;
+//var Z_ASCII = 1; // = Z_TEXT
+var Z_UNKNOWN = 2;
+
+/*============================================================================*/
+
+
+function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
+
+// From zutil.h
+
+var STORED_BLOCK = 0;
+var STATIC_TREES = 1;
+var DYN_TREES = 2;
+/* The three kinds of block type */
+
+var MIN_MATCH = 3;
+var MAX_MATCH = 258;
+/* The minimum and maximum match lengths */
+
+// From deflate.h
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+var LENGTH_CODES = 29;
+/* number of length codes, not counting the special END_BLOCK code */
+
+var LITERALS = 256;
+/* number of literal bytes 0..255 */
+
+var L_CODES = LITERALS + 1 + LENGTH_CODES;
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+var D_CODES = 30;
+/* number of distance codes */
+
+var BL_CODES = 19;
+/* number of codes used to transfer the bit lengths */
+
+var HEAP_SIZE = 2*L_CODES + 1;
+/* maximum heap size */
+
+var MAX_BITS = 15;
+/* All codes must not exceed MAX_BITS bits */
+
+var Buf_size = 16;
+/* size of bit buffer in bi_buf */
+
+
+/* ===========================================================================
+ * Constants
+ */
+
+var MAX_BL_BITS = 7;
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+var END_BLOCK = 256;
+/* end of block literal code */
+
+var REP_3_6 = 16;
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+var REPZ_3_10 = 17;
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+var REPZ_11_138 = 18;
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+var extra_lbits = /* extra bits for each length code */
+ [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
+
+var extra_dbits = /* extra bits for each distance code */
+ [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
+
+var extra_blbits = /* extra bits for each bit length code */
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];
+
+var bl_order =
+ [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+// We pre-fill arrays with 0 to avoid uninitialized gaps
+
+var DIST_CODE_LEN = 512; /* see definition of array dist_code below */
+
+// !!!! Use flat array insdead of structure, Freq = i*2, Len = i*2+1
+var static_ltree = new Array((L_CODES+2) * 2);
+zero(static_ltree);
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+var static_dtree = new Array(D_CODES * 2);
+zero(static_dtree);
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+var _dist_code = new Array(DIST_CODE_LEN);
+zero(_dist_code);
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+var _length_code = new Array(MAX_MATCH-MIN_MATCH+1);
+zero(_length_code);
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+var base_length = new Array(LENGTH_CODES);
+zero(base_length);
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+var base_dist = new Array(D_CODES);
+zero(base_dist);
+/* First normalized distance for each code (0 = distance of 1) */
+
+
+var StaticTreeDesc = function (static_tree, extra_bits, extra_base, elems, max_length) {
+
+ this.static_tree = static_tree; /* static tree or NULL */
+ this.extra_bits = extra_bits; /* extra bits for each code or NULL */
+ this.extra_base = extra_base; /* base index for extra_bits */
+ this.elems = elems; /* max number of elements in the tree */
+ this.max_length = max_length; /* max bit length for the codes */
+
+ // show if `static_tree` has data or dummy - needed for monomorphic objects
+ this.has_stree = static_tree && static_tree.length;
+};
+
+
+var static_l_desc;
+var static_d_desc;
+var static_bl_desc;
+
+
+var TreeDesc = function(dyn_tree, stat_desc) {
+ this.dyn_tree = dyn_tree; /* the dynamic tree */
+ this.max_code = 0; /* largest code with non zero frequency */
+ this.stat_desc = stat_desc; /* the corresponding static tree */
+};
+
+
+
+function d_code(dist) {
+ return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
+}
+
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+function put_short (s, w) {
+// put_byte(s, (uch)((w) & 0xff));
+// put_byte(s, (uch)((ush)(w) >> 8));
+ s.pending_buf[s.pending++] = (w) & 0xff;
+ s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
+}
+
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+function send_bits(s, value, length) {
+ if (s.bi_valid > (Buf_size - length)) {
+ s.bi_buf |= (value << s.bi_valid) & 0xffff;
+ put_short(s, s.bi_buf);
+ s.bi_buf = value >> (Buf_size - s.bi_valid);
+ s.bi_valid += length - Buf_size;
+ } else {
+ s.bi_buf |= (value << s.bi_valid) & 0xffff;
+ s.bi_valid += length;
+ }
+}
+
+
+function send_code(s, c, tree) {
+ send_bits(s, tree[c*2]/*.Code*/, tree[c*2 + 1]/*.Len*/);
+}
+
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+function bi_reverse(code, len) {
+ var res = 0;
+ do {
+ res |= code & 1;
+ code >>>= 1;
+ res <<= 1;
+ } while (--len > 0);
+ return res >>> 1;
+}
+
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+function bi_flush(s) {
+ if (s.bi_valid === 16) {
+ put_short(s, s.bi_buf);
+ s.bi_buf = 0;
+ s.bi_valid = 0;
+
+ } else if (s.bi_valid >= 8) {
+ s.pending_buf[s.pending++] = s.bi_buf & 0xff;
+ s.bi_buf >>= 8;
+ s.bi_valid -= 8;
+ }
+}
+
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+function gen_bitlen(s, desc)
+// deflate_state *s;
+// tree_desc *desc; /* the tree descriptor */
+{
+ var tree = desc.dyn_tree;
+ var max_code = desc.max_code;
+ var stree = desc.stat_desc.static_tree;
+ var has_stree = desc.stat_desc.has_stree;
+ var extra = desc.stat_desc.extra_bits;
+ var base = desc.stat_desc.extra_base;
+ var max_length = desc.stat_desc.max_length;
+ var h; /* heap index */
+ var n, m; /* iterate over the tree elements */
+ var bits; /* bit length */
+ var xbits; /* extra bits */
+ var f; /* frequency */
+ var overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) {
+ s.bl_count[bits] = 0;
+ }
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s.heap[s.heap_max]*2 + 1]/*.Len*/ = 0; /* root of the heap */
+
+ for (h = s.heap_max+1; h < HEAP_SIZE; h++) {
+ n = s.heap[h];
+ bits = tree[tree[n*2 +1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
+ if (bits > max_length) {
+ bits = max_length;
+ overflow++;
+ }
+ tree[n*2 + 1]/*.Len*/ = bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) { continue; } /* not a leaf node */
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) {
+ xbits = extra[n-base];
+ }
+ f = tree[n * 2]/*.Freq*/;
+ s.opt_len += f * (bits + xbits);
+ if (has_stree) {
+ s.static_len += f * (stree[n*2 + 1]/*.Len*/ + xbits);
+ }
+ }
+ if (overflow === 0) { return; }
+
+ // Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s.bl_count[bits] === 0) { bits--; }
+ s.bl_count[bits]--; /* move one leaf down the tree */
+ s.bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s.bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits !== 0; bits--) {
+ n = s.bl_count[bits];
+ while (n !== 0) {
+ m = s.heap[--h];
+ if (m > max_code) { continue; }
+ if (tree[m*2 + 1]/*.Len*/ !== bits) {
+ // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s.opt_len += (bits - tree[m*2 + 1]/*.Len*/)*tree[m*2]/*.Freq*/;
+ tree[m*2 + 1]/*.Len*/ = bits;
+ }
+ n--;
+ }
+ }
+}
+
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+function gen_codes(tree, max_code, bl_count)
+// ct_data *tree; /* the tree to decorate */
+// int max_code; /* largest code with non zero frequency */
+// ushf *bl_count; /* number of codes at each bit length */
+{
+ var next_code = new Array(MAX_BITS+1); /* next code value for each bit length */
+ var code = 0; /* running code value */
+ var bits; /* bit index */
+ var n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ // "inconsistent bit counts");
+ //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ var len = tree[n*2 + 1]/*.Len*/;
+ if (len === 0) { continue; }
+ /* Now reverse the bits */
+ tree[n*2]/*.Code*/ = bi_reverse(next_code[len]++, len);
+
+ //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ // n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+function tr_static_init() {
+ var n; /* iterates over tree elements */
+ var bits; /* bit counter */
+ var length; /* length value */
+ var code; /* code value */
+ var dist; /* distance index */
+ var bl_count = new Array(MAX_BITS+1);
+ /* number of codes at each bit length for an optimal tree */
+
+ // do check in _tr_init()
+ //if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+/*#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif*/
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = code;
+ }
+ }
+ //Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = code;
+ }
+ }
+ //Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = code;
+ }
+ }
+ //Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) {
+ bl_count[bits] = 0;
+ }
+
+ n = 0;
+ while (n <= 143) {
+ static_ltree[n*2 + 1]/*.Len*/ = 8;
+ n++;
+ bl_count[8]++;
+ }
+ while (n <= 255) {
+ static_ltree[n*2 + 1]/*.Len*/ = 9;
+ n++;
+ bl_count[9]++;
+ }
+ while (n <= 279) {
+ static_ltree[n*2 + 1]/*.Len*/ = 7;
+ n++;
+ bl_count[7]++;
+ }
+ while (n <= 287) {
+ static_ltree[n*2 + 1]/*.Len*/ = 8;
+ n++;
+ bl_count[8]++;
+ }
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes(static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n*2 + 1]/*.Len*/ = 5;
+ static_dtree[n*2]/*.Code*/ = bi_reverse(n, 5);
+ }
+
+ // Now data ready and we can init static trees
+ static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS);
+ static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS);
+ static_bl_desc =new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ //static_init_done = true;
+}
+
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+function init_block(s) {
+ var n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n*2]/*.Freq*/ = 0; }
+ for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n*2]/*.Freq*/ = 0; }
+ for (n = 0; n < BL_CODES; n++) { s.bl_tree[n*2]/*.Freq*/ = 0; }
+
+ s.dyn_ltree[END_BLOCK*2]/*.Freq*/ = 1;
+ s.opt_len = s.static_len = 0;
+ s.last_lit = s.matches = 0;
+}
+
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+function bi_windup(s)
+{
+ if (s.bi_valid > 8) {
+ put_short(s, s.bi_buf);
+ } else if (s.bi_valid > 0) {
+ //put_byte(s, (Byte)s->bi_buf);
+ s.pending_buf[s.pending++] = s.bi_buf;
+ }
+ s.bi_buf = 0;
+ s.bi_valid = 0;
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+function copy_block(s, buf, len, header)
+//DeflateState *s;
+//charf *buf; /* the input data */
+//unsigned len; /* its length */
+//int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+
+ if (header) {
+ put_short(s, len);
+ put_short(s, ~len);
+ }
+// while (len--) {
+// put_byte(s, *buf++);
+// }
+ utils.arraySet(s.pending_buf, s.window, buf, len, s.pending);
+ s.pending += len;
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+function smaller(tree, n, m, depth) {
+ var _n2 = n*2;
+ var _m2 = m*2;
+ return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
+ (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
+}
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+function pqdownheap(s, tree, k)
+// deflate_state *s;
+// ct_data *tree; /* the tree to restore */
+// int k; /* node to move down */
+{
+ var v = s.heap[k];
+ var j = k << 1; /* left son of k */
+ while (j <= s.heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s.heap_len &&
+ smaller(tree, s.heap[j+1], s.heap[j], s.depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s.heap[j], s.depth)) { break; }
+
+ /* Exchange v with the smallest son */
+ s.heap[k] = s.heap[j];
+ k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s.heap[k] = v;
+}
+
+
+// inlined manually
+// var SMALLEST = 1;
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+function compress_block(s, ltree, dtree)
+// deflate_state *s;
+// const ct_data *ltree; /* literal tree */
+// const ct_data *dtree; /* distance tree */
+{
+ var dist; /* distance of matched string */
+ var lc; /* match length or unmatched char (if dist == 0) */
+ var lx = 0; /* running index in l_buf */
+ var code; /* the code to send */
+ var extra; /* number of extra bits to send */
+
+ if (s.last_lit !== 0) {
+ do {
+ dist = (s.pending_buf[s.d_buf + lx*2] << 8) | (s.pending_buf[s.d_buf + lx*2 + 1]);
+ lc = s.pending_buf[s.l_buf + lx];
+ lx++;
+
+ if (dist === 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra !== 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ //Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra !== 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ // "pendingBuf overflow");
+
+ } while (lx < s.last_lit);
+ }
+
+ send_code(s, END_BLOCK, ltree);
+}
+
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+function build_tree(s, desc)
+// deflate_state *s;
+// tree_desc *desc; /* the tree descriptor */
+{
+ var tree = desc.dyn_tree;
+ var stree = desc.stat_desc.static_tree;
+ var has_stree = desc.stat_desc.has_stree;
+ var elems = desc.stat_desc.elems;
+ var n, m; /* iterate over heap elements */
+ var max_code = -1; /* largest code with non zero frequency */
+ var node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n * 2]/*.Freq*/ !== 0) {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+
+ } else {
+ tree[n*2 + 1]/*.Len*/ = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s.heap_len < 2) {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2]/*.Freq*/ = 1;
+ s.depth[node] = 0;
+ s.opt_len--;
+
+ if (has_stree) {
+ s.static_len -= stree[node*2 + 1]/*.Len*/;
+ }
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc.max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ //pqremove(s, tree, n); /* n = node of least frequency */
+ /*** pqremove ***/
+ n = s.heap[1/*SMALLEST*/];
+ s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
+ pqdownheap(s, tree, 1/*SMALLEST*/);
+ /***/
+
+ m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
+
+ s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
+ s.heap[--s.heap_max] = m;
+
+ /* Create a new node father of n and m */
+ tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
+ s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
+ tree[n*2 + 1]/*.Dad*/ = tree[m*2 + 1]/*.Dad*/ = node;
+
+ /* and insert the new node in the heap */
+ s.heap[1/*SMALLEST*/] = node++;
+ pqdownheap(s, tree, 1/*SMALLEST*/);
+
+ } while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes(tree, max_code, s.bl_count);
+}
+
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+function scan_tree(s, tree, max_code)
+// deflate_state *s;
+// ct_data *tree; /* the tree to be scanned */
+// int max_code; /* and its largest code of non zero frequency */
+{
+ var n; /* iterates over all tree elements */
+ var prevlen = -1; /* last emitted length */
+ var curlen; /* length of current code */
+
+ var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */
+
+ var count = 0; /* repeat count of the current code */
+ var max_count = 7; /* max repeat count */
+ var min_count = 4; /* min repeat count */
+
+ if (nextlen === 0) {
+ max_count = 138;
+ min_count = 3;
+ }
+ tree[(max_code+1)*2 + 1]/*.Len*/ = 0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen;
+ nextlen = tree[(n+1)*2 + 1]/*.Len*/;
+
+ if (++count < max_count && curlen === nextlen) {
+ continue;
+
+ } else if (count < min_count) {
+ s.bl_tree[curlen * 2]/*.Freq*/ += count;
+
+ } else if (curlen !== 0) {
+
+ if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
+ s.bl_tree[REP_3_6*2]/*.Freq*/++;
+
+ } else if (count <= 10) {
+ s.bl_tree[REPZ_3_10*2]/*.Freq*/++;
+
+ } else {
+ s.bl_tree[REPZ_11_138*2]/*.Freq*/++;
+ }
+
+ count = 0;
+ prevlen = curlen;
+
+ if (nextlen === 0) {
+ max_count = 138;
+ min_count = 3;
+
+ } else if (curlen === nextlen) {
+ max_count = 6;
+ min_count = 3;
+
+ } else {
+ max_count = 7;
+ min_count = 4;
+ }
+ }
+}
+
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+function send_tree(s, tree, max_code)
+// deflate_state *s;
+// ct_data *tree; /* the tree to be scanned */
+// int max_code; /* and its largest code of non zero frequency */
+{
+ var n; /* iterates over all tree elements */
+ var prevlen = -1; /* last emitted length */
+ var curlen; /* length of current code */
+
+ var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */
+
+ var count = 0; /* repeat count of the current code */
+ var max_count = 7; /* max repeat count */
+ var min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen === 0) {
+ max_count = 138;
+ min_count = 3;
+ }
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen;
+ nextlen = tree[(n+1)*2 + 1]/*.Len*/;
+
+ if (++count < max_count && curlen === nextlen) {
+ continue;
+
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
+
+ } else if (curlen !== 0) {
+ if (curlen !== prevlen) {
+ send_code(s, curlen, s.bl_tree);
+ count--;
+ }
+ //Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s.bl_tree);
+ send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s.bl_tree);
+ send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s.bl_tree);
+ send_bits(s, count-11, 7);
+ }
+
+ count = 0;
+ prevlen = curlen;
+ if (nextlen === 0) {
+ max_count = 138;
+ min_count = 3;
+
+ } else if (curlen === nextlen) {
+ max_count = 6;
+ min_count = 3;
+
+ } else {
+ max_count = 7;
+ min_count = 4;
+ }
+ }
+}
+
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+function build_bl_tree(s) {
+ var max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
+ scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, s.bl_desc);
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s.bl_tree[bl_order[max_blindex]*2 + 1]/*.Len*/ !== 0) {
+ break;
+ }
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s.opt_len += 3*(max_blindex+1) + 5+5+4;
+ //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ // s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+function send_all_trees(s, lcodes, dcodes, blcodes)
+// deflate_state *s;
+// int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ var rank; /* index in bl_order */
+
+ //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ // "too many codes");
+ //Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s.bl_tree[bl_order[rank]*2 + 1]/*.Len*/, 3);
+ }
+ //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, s.dyn_ltree, lcodes-1); /* literal tree */
+ //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, s.dyn_dtree, dcodes-1); /* distance tree */
+ //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "black list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+function detect_data_type(s) {
+ /* black_mask is the bit mask of black-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ var black_mask = 0xf3ffc07f;
+ var n;
+
+ /* Check for non-textual ("black-listed") bytes. */
+ for (n = 0; n <= 31; n++, black_mask >>>= 1) {
+ if ((black_mask & 1) && (s.dyn_ltree[n*2]/*.Freq*/ !== 0)) {
+ return Z_BINARY;
+ }
+ }
+
+ /* Check for textual ("white-listed") bytes. */
+ if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
+ s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
+ return Z_TEXT;
+ }
+ for (n = 32; n < LITERALS; n++) {
+ if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
+ return Z_TEXT;
+ }
+ }
+
+ /* There are no "black-listed" or "white-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+
+var static_init_done = false;
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+function _tr_init(s)
+{
+
+ if (!static_init_done) {
+ tr_static_init();
+ static_init_done = true;
+ }
+
+ s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);
+ s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);
+ s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
+
+ s.bi_buf = 0;
+ s.bi_valid = 0;
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+
+/* ===========================================================================
+ * Send a stored block
+ */
+function _tr_stored_block(s, buf, stored_len, last)
+//DeflateState *s;
+//charf *buf; /* input block */
+//ulg stored_len; /* length of input block */
+//int last; /* one if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+(last ? 1 : 0), 3); /* send block type */
+ copy_block(s, buf, stored_len, true); /* with header */
+}
+
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+function _tr_align(s) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ bi_flush(s);
+}
+
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+function _tr_flush_block(s, buf, stored_len, last)
+//DeflateState *s;
+//charf *buf; /* input block, or NULL if too old */
+//ulg stored_len; /* length of input block */
+//int last; /* one if this is the last block for a file */
+{
+ var opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ var max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s.level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s.strm.data_type === Z_UNKNOWN) {
+ s.strm.data_type = detect_data_type(s);
+ }
+
+ /* Construct the literal and distance trees */
+ build_tree(s, s.l_desc);
+ // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ // s->static_len));
+
+ build_tree(s, s.d_desc);
+ // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ // s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s.opt_len+3+7) >>> 3;
+ static_lenb = (s.static_len+3+7) >>> 3;
+
+ // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ // s->last_lit));
+
+ if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
+
+ } else {
+ // Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+ if ((stored_len+4 <= opt_lenb) && (buf !== -1)) {
+ /* 4: two words for the lengths */
+
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+ } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {
+
+ send_bits(s, (STATIC_TREES<<1) + (last ? 1 : 0), 3);
+ compress_block(s, static_ltree, static_dtree);
+
+ } else {
+ send_bits(s, (DYN_TREES<<1) + (last ? 1 : 0), 3);
+ send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, max_blindex+1);
+ compress_block(s, s.dyn_ltree, s.dyn_dtree);
+ }
+ // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+ }
+ // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ // s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+function _tr_tally(s, dist, lc)
+// deflate_state *s;
+// unsigned dist; /* distance of matched string */
+// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ //var out_length, in_length, dcode;
+
+ s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff;
+ s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
+
+ s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
+ s.last_lit++;
+
+ if (dist === 0) {
+ /* lc is the unmatched char */
+ s.dyn_ltree[lc*2]/*.Freq*/++;
+ } else {
+ s.matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ //Assert((ush)dist < (ush)MAX_DIST(s) &&
+ // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s.dyn_ltree[(_length_code[lc]+LITERALS+1) * 2]/*.Freq*/++;
+ s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
+ }
+
+// (!) This block is disabled in zlib defailts,
+// don't enable it for binary compatibility
+
+//#ifdef TRUNCATE_BLOCK
+// /* Try to guess if it is profitable to stop the current block here */
+// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
+// /* Compute an upper bound for the compressed length */
+// out_length = s.last_lit*8;
+// in_length = s.strstart - s.block_start;
+//
+// for (dcode = 0; dcode < D_CODES; dcode++) {
+// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
+// }
+// out_length >>>= 3;
+// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+// // s->last_lit, in_length, out_length,
+// // 100L - out_length*100L/in_length));
+// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
+// return true;
+// }
+// }
+//#endif
+
+ return (s.last_lit === s.lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+exports._tr_init = _tr_init;
+exports._tr_stored_block = _tr_stored_block;
+exports._tr_flush_block = _tr_flush_block;
+exports._tr_tally = _tr_tally;
+exports._tr_align = _tr_align;
+},{"../utils/common":27}],39:[function(_dereq_,module,exports){
+'use strict';
+
+
+function ZStream() {
+ /* next input byte */
+ this.input = null; // JS specific, because we have no pointers
+ this.next_in = 0;
+ /* number of bytes available at input */
+ this.avail_in = 0;
+ /* total number of input bytes read so far */
+ this.total_in = 0;
+ /* next output byte should be put there */
+ this.output = null; // JS specific, because we have no pointers
+ this.next_out = 0;
+ /* remaining free space at output */
+ this.avail_out = 0;
+ /* total number of bytes output so far */
+ this.total_out = 0;
+ /* last error message, NULL if no error */
+ this.msg = ''/*Z_NULL*/;
+ /* not visible by applications */
+ this.state = null;
+ /* best guess about the data type: binary or text */
+ this.data_type = 2/*Z_UNKNOWN*/;
+ /* adler32 value of the uncompressed data */
+ this.adler = 0;
+}
+
+module.exports = ZStream;
+},{}]},{},[9])
+(9)
+}); \ No newline at end of file
diff --git a/afb-client/bower_components/jszip/dist/jszip.min.js b/afb-client/bower_components/jszip/dist/jszip.min.js
new file mode 100644
index 0000000..a09f35b
--- /dev/null
+++ b/afb-client/bower_components/jszip/dist/jszip.min.js
@@ -0,0 +1,14 @@
+/*!
+
+JSZip - A Javascript class for generating and reading zip files
+<http://stuartk.com/jszip>
+
+(c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
+Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
+
+JSZip uses the library pako released under the MIT license :
+https://github.com/nodeca/pako/blob/master/LICENSE
+*/
+!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.compressionOptions=null,c.comment=null,c.unixPermissions=null,c.dosPermissions=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a,b){return e.deflateRaw(a,{level:b.level||-1})},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,unixPermissions:h.unixPermissions,dosPermissions:h.dosPermissions,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?D.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",D.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this.unixPermissions=c.unixPermissions,this.dosPermissions=c.dosPermissions,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),"string"==typeof c.unixPermissions&&(c.unixPermissions=parseInt(c.unixPermissions,8)),c.unixPermissions&&16384&c.unixPermissions&&(c.dir=!0),c.dosPermissions&&16&c.dosPermissions&&(c.dir=!0),c.dir&&(a=x(a)),c.createFolders&&(e=w(a))&&y.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null,f=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a){return"/"!=a.slice(-1)&&(a+="/"),a},y=function(a,b){return b="undefined"!=typeof b?b:!1,a=x(a),this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},z=function(a,b,c){var f,g=new j;return a._data instanceof j?(g.uncompressedSize=a._data.uncompressedSize,g.crc32=a._data.crc32,0===g.uncompressedSize||a.dir?(b=i.STORE,g.compressedContent="",g.crc32=0):a._data.compressionMethod===b.magic?g.compressedContent=a._data.getCompressedContent():(f=a._data.getContent(),g.compressedContent=b.compress(d.transformTo(b.compressInputType,f),c))):(f=p(a),(!f||0===f.length||a.dir)&&(b=i.STORE,f=""),g.uncompressedSize=f.length,g.crc32=e(f),g.compressedContent=b.compress(d.transformTo(b.compressInputType,f),c)),g.compressedSize=g.compressedContent.length,g.compressionMethod=b.magic,g},A=function(a,b){var c=a;return a||(c=b?16893:33204),(65535&c)<<16},B=function(a){return 63&(a||0)},C=function(a,b,c,g,h){var i,j,k,m,n=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),o=b.comment||"",p=d.transformTo("string",l.utf8encode(o)),q=n.length!==b.name.length,r=p.length!==o.length,t=b.options,u="",v="",w="";k=b._initialMetadata.dir!==b.dir?b.dir:t.dir,m=b._initialMetadata.date!==b.date?b.date:t.date;var x=0,y=0;k&&(x|=16),"UNIX"===h?(y=798,x|=A(b.unixPermissions,k)):(y=20,x|=B(b.dosPermissions,k)),i=m.getHours(),i<<=6,i|=m.getMinutes(),i<<=5,i|=m.getSeconds()/2,j=m.getFullYear()-1980,j<<=4,j|=m.getMonth()+1,j<<=5,j|=m.getDate(),q&&(v=s(1,1)+s(e(n),4)+n,u+="up"+s(v.length,2)+v),r&&(w=s(1,1)+s(this.crc32(p),4)+p,u+="uc"+s(w.length,2)+w);var z="";z+="\n\x00",z+=q||r?"\x00\b":"\x00\x00",z+=c.compressionMethod,z+=s(i,2),z+=s(j,2),z+=s(c.crc32,4),z+=s(c.compressedSize,4),z+=s(c.uncompressedSize,4),z+=s(n.length,2),z+=s(u.length,2);var C=f.LOCAL_FILE_HEADER+z+n+u,D=f.CENTRAL_FILE_HEADER+s(y,2)+z+s(p.length,2)+"\x00\x00\x00\x00"+s(x,4)+s(g,4)+n+u+p;return{fileRecord:C,dirRecord:D,compressedObject:c}},D={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=y.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",compressionOptions:null,type:"base64",platform:"DOS",comment:null,mimeType:"application/zip"}),d.checkSupport(a.type),("darwin"===a.platform||"freebsd"===a.platform||"linux"===a.platform||"sunos"===a.platform)&&(a.platform="UNIX"),"win32"===a.platform&&(a.platform="DOS");var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=o.options.compressionOptions||a.compressionOptions||{},u=z.call(this,o,q,r),v=C.call(this,l,o,u,g,a.platform);g+=v.fileRecord.length+u.compressedSize,j+=v.dirRecord.length,e.push(v)}var w="";w=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var x=a.type.toLowerCase();for(b="uint8array"===x||"arraybuffer"===x||"blob"===x||"nodebuffer"===x?new n(g+j+w.length):new m(g+j+w.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(w);var y=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),y);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",y),a.mimeType);case"base64":return a.base64?h.encode(y):y;default:return y}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=D},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a,b){c.checkSupport("blob"),b=b||"application/zip";try{return new Blob([a],{type:b})}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;return f.append(a),f.getBlob(b)}catch(d){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8(),b.processAttributes()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a){var b=!0;try{this.reader.setIndex(0),this.checkSignature(h.LOCAL_FILE_HEADER),b=!1}catch(c){}throw new Error(b?"Can't find end of central directory : is this a zip file ? If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html":"Corrupted zip : can't find end of central directory")}if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object"),h=0,i=3;c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readInt(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var a=this.versionMadeBy>>8;this.dir=16&this.externalFileAttributes?!0:!1,a===h&&(this.dosPermissions=63&this.externalFileAttributes),a===i&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileName.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))
+}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);
+break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}); \ No newline at end of file
diff --git a/afb-client/bower_components/jszip/docs/APPNOTE.TXT b/afb-client/bower_components/jszip/docs/APPNOTE.TXT
new file mode 100644
index 0000000..1565e77
--- /dev/null
+++ b/afb-client/bower_components/jszip/docs/APPNOTE.TXT
@@ -0,0 +1,3217 @@
+File: APPNOTE.TXT - .ZIP File Format Specification
+Version: 6.3.2
+Revised: September 28, 2007
+Copyright (c) 1989 - 2007 PKWARE Inc., All Rights Reserved.
+
+The use of certain technological aspects disclosed in the current
+APPNOTE is available pursuant to the below section entitled
+"Incorporating PKWARE Proprietary Technology into Your Product".
+
+I. Purpose
+----------
+
+This specification is intended to define a cross-platform,
+interoperable file storage and transfer format. Since its
+first publication in 1989, PKWARE has remained committed to
+ensuring the interoperability of the .ZIP file format through
+publication and maintenance of this specification. We trust that
+all .ZIP compatible vendors and application developers that have
+adopted and benefited from this format will share and support
+this commitment to interoperability.
+
+II. Contacting PKWARE
+---------------------
+
+ PKWARE, Inc.
+ 648 N. Plankinton Avenue, Suite 220
+ Milwaukee, WI 53203
+ +1-414-289-9788
+ +1-414-289-9789 FAX
+ zipformat@pkware.com
+
+III. Disclaimer
+---------------
+
+Although PKWARE will attempt to supply current and accurate
+information relating to its file formats, algorithms, and the
+subject programs, the possibility of error or omission cannot
+be eliminated. PKWARE therefore expressly disclaims any warranty
+that the information contained in the associated materials relating
+to the subject programs and/or the format of the files created or
+accessed by the subject programs and/or the algorithms used by
+the subject programs, or any other matter, is current, correct or
+accurate as delivered. Any risk of damage due to any possible
+inaccurate information is assumed by the user of the information.
+Furthermore, the information relating to the subject programs
+and/or the file formats created or accessed by the subject
+programs and/or the algorithms used by the subject programs is
+subject to change without notice.
+
+If the version of this file is marked as a NOTIFICATION OF CHANGE,
+the content defines an Early Feature Specification (EFS) change
+to the .ZIP file format that may be subject to modification prior
+to publication of the Final Feature Specification (FFS). This
+document may also contain information on Planned Feature
+Specifications (PFS) defining recognized future extensions.
+
+IV. Change Log
+--------------
+
+Version Change Description Date
+------- ------------------ ----------
+5.2 -Single Password Symmetric Encryption 06/02/2003
+ storage
+
+6.1.0 -Smartcard compatibility 01/20/2004
+ -Documentation on certificate storage
+
+6.2.0 -Introduction of Central Directory 04/26/2004
+ Encryption for encrypting metadata
+ -Added OS/X to Version Made By values
+
+6.2.1 -Added Extra Field placeholder for 04/01/2005
+ POSZIP using ID 0x4690
+
+ -Clarified size field on
+ "zip64 end of central directory record"
+
+6.2.2 -Documented Final Feature Specification 01/06/2006
+ for Strong Encryption
+
+ -Clarifications and typographical
+ corrections
+
+6.3.0 -Added tape positioning storage 09/29/2006
+ parameters
+
+ -Expanded list of supported hash algorithms
+
+ -Expanded list of supported compression
+ algorithms
+
+ -Expanded list of supported encryption
+ algorithms
+
+ -Added option for Unicode filename
+ storage
+
+ -Clarifications for consistent use
+ of Data Descriptor records
+
+ -Added additional "Extra Field"
+ definitions
+
+6.3.1 -Corrected standard hash values for 04/11/2007
+ SHA-256/384/512
+
+6.3.2 -Added compression method 97 09/28/2007
+
+ -Documented InfoZIP "Extra Field"
+ values for UTF-8 file name and
+ file comment storage
+
+V. General Format of a .ZIP file
+--------------------------------
+
+ Files stored in arbitrary order. Large .ZIP files can span multiple
+ volumes or be split into user-defined segment sizes. All values
+ are stored in little-endian byte order unless otherwise specified.
+
+ Overall .ZIP file format:
+
+ [local file header 1]
+ [file data 1]
+ [data descriptor 1]
+ .
+ .
+ .
+ [local file header n]
+ [file data n]
+ [data descriptor n]
+ [archive decryption header]
+ [archive extra data record]
+ [central directory]
+ [zip64 end of central directory record]
+ [zip64 end of central directory locator]
+ [end of central directory record]
+
+
+ A. Local file header:
+
+ local file header signature 4 bytes (0x04034b50)
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+
+ file name (variable size)
+ extra field (variable size)
+
+ B. File data
+
+ Immediately following the local header for a file
+ is the compressed or stored data for the file.
+ The series of [local file header][file data][data
+ descriptor] repeats for each file in the .ZIP archive.
+
+ C. Data descriptor:
+
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+
+ This descriptor exists only if bit 3 of the general
+ purpose bit flag is set (see below). It is byte aligned
+ and immediately follows the last byte of compressed data.
+ This descriptor is used only when it was not possible to
+ seek in the output .ZIP file, e.g., when the output .ZIP file
+ was standard output or a non-seekable device. For ZIP64(tm) format
+ archives, the compressed and uncompressed sizes are 8 bytes each.
+
+ When compressing files, compressed and uncompressed sizes
+ should be stored in ZIP64 format (as 8 byte values) when a
+ files size exceeds 0xFFFFFFFF. However ZIP64 format may be
+ used regardless of the size of a file. When extracting, if
+ the zip64 extended information extra field is present for
+ the file the compressed and uncompressed sizes will be 8
+ byte values.
+
+ Although not originally assigned a signature, the value
+ 0x08074b50 has commonly been adopted as a signature value
+ for the data descriptor record. Implementers should be
+ aware that ZIP files may be encountered with or without this
+ signature marking data descriptors and should account for
+ either case when reading ZIP files to ensure compatibility.
+ When writing ZIP files, it is recommended to include the
+ signature value marking the data descriptor record. When
+ the signature is used, the fields currently defined for
+ the data descriptor record will immediately follow the
+ signature.
+
+ An extensible data descriptor will be released in a future
+ version of this APPNOTE. This new record is intended to
+ resolve conflicts with the use of this record going forward,
+ and to provide better support for streamed file processing.
+
+ When the Central Directory Encryption method is used, the data
+ descriptor record is not required, but may be used. If present,
+ and bit 3 of the general purpose bit field is set to indicate
+ its presence, the values in fields of the data descriptor
+ record should be set to binary zeros.
+
+ D. Archive decryption header:
+
+ The Archive Decryption Header is introduced in version 6.2
+ of the ZIP format specification. This record exists in support
+ of the Central Directory Encryption Feature implemented as part of
+ the Strong Encryption Specification as described in this document.
+ When the Central Directory Structure is encrypted, this decryption
+ header will precede the encrypted data segment. The encrypted
+ data segment will consist of the Archive extra data record (if
+ present) and the encrypted Central Directory Structure data.
+ The format of this data record is identical to the Decryption
+ header record preceding compressed file data. If the central
+ directory structure is encrypted, the location of the start of
+ this data record is determined using the Start of Central Directory
+ field in the Zip64 End of Central Directory record. Refer to the
+ section on the Strong Encryption Specification for information
+ on the fields used in the Archive Decryption Header record.
+
+
+ E. Archive extra data record:
+
+ archive extra data signature 4 bytes (0x08064b50)
+ extra field length 4 bytes
+ extra field data (variable size)
+
+ The Archive Extra Data Record is introduced in version 6.2
+ of the ZIP format specification. This record exists in support
+ of the Central Directory Encryption Feature implemented as part of
+ the Strong Encryption Specification as described in this document.
+ When present, this record immediately precedes the central
+ directory data structure. The size of this data record will be
+ included in the Size of the Central Directory field in the
+ End of Central Directory record. If the central directory structure
+ is compressed, but not encrypted, the location of the start of
+ this data record is determined using the Start of Central Directory
+ field in the Zip64 End of Central Directory record.
+
+
+ F. Central directory structure:
+
+ [file header 1]
+ .
+ .
+ .
+ [file header n]
+ [digital signature]
+
+ File header:
+
+ central file header signature 4 bytes (0x02014b50)
+ version made by 2 bytes
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+ file comment length 2 bytes
+ disk number start 2 bytes
+ internal file attributes 2 bytes
+ external file attributes 4 bytes
+ relative offset of local header 4 bytes
+
+ file name (variable size)
+ extra field (variable size)
+ file comment (variable size)
+
+ Digital signature:
+
+ header signature 4 bytes (0x05054b50)
+ size of data 2 bytes
+ signature data (variable size)
+
+ With the introduction of the Central Directory Encryption
+ feature in version 6.2 of this specification, the Central
+ Directory Structure may be stored both compressed and encrypted.
+ Although not required, it is assumed when encrypting the
+ Central Directory Structure, that it will be compressed
+ for greater storage efficiency. Information on the
+ Central Directory Encryption feature can be found in the section
+ describing the Strong Encryption Specification. The Digital
+ Signature record will be neither compressed nor encrypted.
+
+ G. Zip64 end of central directory record
+
+ zip64 end of central dir
+ signature 4 bytes (0x06064b50)
+ size of zip64 end of central
+ directory record 8 bytes
+ version made by 2 bytes
+ version needed to extract 2 bytes
+ number of this disk 4 bytes
+ number of the disk with the
+ start of the central directory 4 bytes
+ total number of entries in the
+ central directory on this disk 8 bytes
+ total number of entries in the
+ central directory 8 bytes
+ size of the central directory 8 bytes
+ offset of start of central
+ directory with respect to
+ the starting disk number 8 bytes
+ zip64 extensible data sector (variable size)
+
+ The value stored into the "size of zip64 end of central
+ directory record" should be the size of the remaining
+ record and should not include the leading 12 bytes.
+
+ Size = SizeOfFixedFields + SizeOfVariableData - 12.
+
+ The above record structure defines Version 1 of the
+ zip64 end of central directory record. Version 1 was
+ implemented in versions of this specification preceding
+ 6.2 in support of the ZIP64 large file feature. The
+ introduction of the Central Directory Encryption feature
+ implemented in version 6.2 as part of the Strong Encryption
+ Specification defines Version 2 of this record structure.
+ Refer to the section describing the Strong Encryption
+ Specification for details on the version 2 format for
+ this record.
+
+ Special purpose data may reside in the zip64 extensible data
+ sector field following either a V1 or V2 version of this
+ record. To ensure identification of this special purpose data
+ it must include an identifying header block consisting of the
+ following:
+
+ Header ID - 2 bytes
+ Data Size - 4 bytes
+
+ The Header ID field indicates the type of data that is in the
+ data block that follows.
+
+ Data Size identifies the number of bytes that follow for this
+ data block type.
+
+ Multiple special purpose data blocks may be present, but each
+ must be preceded by a Header ID and Data Size field. Current
+ mappings of Header ID values supported in this field are as
+ defined in APPENDIX C.
+
+ H. Zip64 end of central directory locator
+
+ zip64 end of central dir locator
+ signature 4 bytes (0x07064b50)
+ number of the disk with the
+ start of the zip64 end of
+ central directory 4 bytes
+ relative offset of the zip64
+ end of central directory record 8 bytes
+ total number of disks 4 bytes
+
+ I. End of central directory record:
+
+ end of central dir signature 4 bytes (0x06054b50)
+ number of this disk 2 bytes
+ number of the disk with the
+ start of the central directory 2 bytes
+ total number of entries in the
+ central directory on this disk 2 bytes
+ total number of entries in
+ the central directory 2 bytes
+ size of the central directory 4 bytes
+ offset of start of central
+ directory with respect to
+ the starting disk number 4 bytes
+ .ZIP file comment length 2 bytes
+ .ZIP file comment (variable size)
+
+ J. Explanation of fields:
+
+ version made by (2 bytes)
+
+ The upper byte indicates the compatibility of the file
+ attribute information. If the external file attributes
+ are compatible with MS-DOS and can be read by PKZIP for
+ DOS version 2.04g then this value will be zero. If these
+ attributes are not compatible, then this value will
+ identify the host system on which the attributes are
+ compatible. Software can use this information to determine
+ the line record format for text files etc. The current
+ mappings are:
+
+ 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
+ 1 - Amiga 2 - OpenVMS
+ 3 - UNIX 4 - VM/CMS
+ 5 - Atari ST 6 - OS/2 H.P.F.S.
+ 7 - Macintosh 8 - Z-System
+ 9 - CP/M 10 - Windows NTFS
+ 11 - MVS (OS/390 - Z/OS) 12 - VSE
+ 13 - Acorn Risc 14 - VFAT
+ 15 - alternate MVS 16 - BeOS
+ 17 - Tandem 18 - OS/400
+ 19 - OS/X (Darwin) 20 thru 255 - unused
+
+ The lower byte indicates the ZIP specification version
+ (the version of this document) supported by the software
+ used to encode the file. The value/10 indicates the major
+ version number, and the value mod 10 is the minor version
+ number.
+
+ version needed to extract (2 bytes)
+
+ The minimum supported ZIP specification version needed to
+ extract the file, mapped as above. This value is based on
+ the specific format features a ZIP program must support to
+ be able to extract the file. If multiple features are
+ applied to a file, the minimum version should be set to the
+ feature having the highest value. New features or feature
+ changes affecting the published format specification will be
+ implemented using higher version numbers than the last
+ published value to avoid conflict.
+
+ Current minimum feature versions are as defined below:
+
+ 1.0 - Default value
+ 1.1 - File is a volume label
+ 2.0 - File is a folder (directory)
+ 2.0 - File is compressed using Deflate compression
+ 2.0 - File is encrypted using traditional PKWARE encryption
+ 2.1 - File is compressed using Deflate64(tm)
+ 2.5 - File is compressed using PKWARE DCL Implode
+ 2.7 - File is a patch data set
+ 4.5 - File uses ZIP64 format extensions
+ 4.6 - File is compressed using BZIP2 compression*
+ 5.0 - File is encrypted using DES
+ 5.0 - File is encrypted using 3DES
+ 5.0 - File is encrypted using original RC2 encryption
+ 5.0 - File is encrypted using RC4 encryption
+ 5.1 - File is encrypted using AES encryption
+ 5.1 - File is encrypted using corrected RC2 encryption**
+ 5.2 - File is encrypted using corrected RC2-64 encryption**
+ 6.1 - File is encrypted using non-OAEP key wrapping***
+ 6.2 - Central directory encryption
+ 6.3 - File is compressed using LZMA
+ 6.3 - File is compressed using PPMd+
+ 6.3 - File is encrypted using Blowfish
+ 6.3 - File is encrypted using Twofish
+
+
+ * Early 7.x (pre-7.2) versions of PKZIP incorrectly set the
+ version needed to extract for BZIP2 compression to be 50
+ when it should have been 46.
+
+ ** Refer to the section on Strong Encryption Specification
+ for additional information regarding RC2 corrections.
+
+ *** Certificate encryption using non-OAEP key wrapping is the
+ intended mode of operation for all versions beginning with 6.1.
+ Support for OAEP key wrapping should only be used for
+ backward compatibility when sending ZIP files to be opened by
+ versions of PKZIP older than 6.1 (5.0 or 6.0).
+
+ + Files compressed using PPMd should set the version
+ needed to extract field to 6.3, however, not all ZIP
+ programs enforce this and may be unable to decompress
+ data files compressed using PPMd if this value is set.
+
+ When using ZIP64 extensions, the corresponding value in the
+ zip64 end of central directory record should also be set.
+ This field should be set appropriately to indicate whether
+ Version 1 or Version 2 format is in use.
+
+ general purpose bit flag: (2 bytes)
+
+ Bit 0: If set, indicates that the file is encrypted.
+
+ (For Method 6 - Imploding)
+ Bit 1: If the compression method used was type 6,
+ Imploding, then this bit, if set, indicates
+ an 8K sliding dictionary was used. If clear,
+ then a 4K sliding dictionary was used.
+ Bit 2: If the compression method used was type 6,
+ Imploding, then this bit, if set, indicates
+ 3 Shannon-Fano trees were used to encode the
+ sliding dictionary output. If clear, then 2
+ Shannon-Fano trees were used.
+
+ (For Methods 8 and 9 - Deflating)
+ Bit 2 Bit 1
+ 0 0 Normal (-en) compression option was used.
+ 0 1 Maximum (-exx/-ex) compression option was used.
+ 1 0 Fast (-ef) compression option was used.
+ 1 1 Super Fast (-es) compression option was used.
+
+ (For Method 14 - LZMA)
+ Bit 1: If the compression method used was type 14,
+ LZMA, then this bit, if set, indicates
+ an end-of-stream (EOS) marker is used to
+ mark the end of the compressed data stream.
+ If clear, then an EOS marker is not present
+ and the compressed data size must be known
+ to extract.
+
+ Note: Bits 1 and 2 are undefined if the compression
+ method is any other.
+
+ Bit 3: If this bit is set, the fields crc-32, compressed
+ size and uncompressed size are set to zero in the
+ local header. The correct values are put in the
+ data descriptor immediately following the compressed
+ data. (Note: PKZIP version 2.04g for DOS only
+ recognizes this bit for method 8 compression, newer
+ versions of PKZIP recognize this bit for any
+ compression method.)
+
+ Bit 4: Reserved for use with method 8, for enhanced
+ deflating.
+
+ Bit 5: If this bit is set, this indicates that the file is
+ compressed patched data. (Note: Requires PKZIP
+ version 2.70 or greater)
+
+ Bit 6: Strong encryption. If this bit is set, you should
+ set the version needed to extract value to at least
+ 50 and you must also set bit 0. If AES encryption
+ is used, the version needed to extract value must
+ be at least 51.
+
+ Bit 7: Currently unused.
+
+ Bit 8: Currently unused.
+
+ Bit 9: Currently unused.
+
+ Bit 10: Currently unused.
+
+ Bit 11: Language encoding flag (EFS). If this bit is set,
+ the filename and comment fields for this file
+ must be encoded using UTF-8. (see APPENDIX D)
+
+ Bit 12: Reserved by PKWARE for enhanced compression.
+
+ Bit 13: Used when encrypting the Central Directory to indicate
+ selected data values in the Local Header are masked to
+ hide their actual values. See the section describing
+ the Strong Encryption Specification for details.
+
+ Bit 14: Reserved by PKWARE.
+
+ Bit 15: Reserved by PKWARE.
+
+ compression method: (2 bytes)
+
+ (see accompanying documentation for algorithm
+ descriptions)
+
+ 0 - The file is stored (no compression)
+ 1 - The file is Shrunk
+ 2 - The file is Reduced with compression factor 1
+ 3 - The file is Reduced with compression factor 2
+ 4 - The file is Reduced with compression factor 3
+ 5 - The file is Reduced with compression factor 4
+ 6 - The file is Imploded
+ 7 - Reserved for Tokenizing compression algorithm
+ 8 - The file is Deflated
+ 9 - Enhanced Deflating using Deflate64(tm)
+ 10 - PKWARE Data Compression Library Imploding (old IBM TERSE)
+ 11 - Reserved by PKWARE
+ 12 - File is compressed using BZIP2 algorithm
+ 13 - Reserved by PKWARE
+ 14 - LZMA (EFS)
+ 15 - Reserved by PKWARE
+ 16 - Reserved by PKWARE
+ 17 - Reserved by PKWARE
+ 18 - File is compressed using IBM TERSE (new)
+ 19 - IBM LZ77 z Architecture (PFS)
+ 97 - WavPack compressed data
+ 98 - PPMd version I, Rev 1
+
+ date and time fields: (2 bytes each)
+
+ The date and time are encoded in standard MS-DOS format.
+ If input came from standard input, the date and time are
+ those at which compression was started for this data.
+ If encrypting the central directory and general purpose bit
+ flag 13 is set indicating masking, the value stored in the
+ Local Header will be zero.
+
+ CRC-32: (4 bytes)
+
+ The CRC-32 algorithm was generously contributed by
+ David Schwaderer and can be found in his excellent
+ book "C Programmers Guide to NetBIOS" published by
+ Howard W. Sams & Co. Inc. The 'magic number' for
+ the CRC is 0xdebb20e3. The proper CRC pre and post
+ conditioning is used, meaning that the CRC register
+ is pre-conditioned with all ones (a starting value
+ of 0xffffffff) and the value is post-conditioned by
+ taking the one's complement of the CRC residual.
+ If bit 3 of the general purpose flag is set, this
+ field is set to zero in the local header and the correct
+ value is put in the data descriptor and in the central
+ directory. When encrypting the central directory, if the
+ local header is not in ZIP64 format and general purpose
+ bit flag 13 is set indicating masking, the value stored
+ in the Local Header will be zero.
+
+ compressed size: (4 bytes)
+ uncompressed size: (4 bytes)
+
+ The size of the file compressed and uncompressed,
+ respectively. When a decryption header is present it will
+ be placed in front of the file data and the value of the
+ compressed file size will include the bytes of the decryption
+ header. If bit 3 of the general purpose bit flag is set,
+ these fields are set to zero in the local header and the
+ correct values are put in the data descriptor and
+ in the central directory. If an archive is in ZIP64 format
+ and the value in this field is 0xFFFFFFFF, the size will be
+ in the corresponding 8 byte ZIP64 extended information
+ extra field. When encrypting the central directory, if the
+ local header is not in ZIP64 format and general purpose bit
+ flag 13 is set indicating masking, the value stored for the
+ uncompressed size in the Local Header will be zero.
+
+ file name length: (2 bytes)
+ extra field length: (2 bytes)
+ file comment length: (2 bytes)
+
+ The length of the file name, extra field, and comment
+ fields respectively. The combined length of any
+ directory record and these three fields should not
+ generally exceed 65,535 bytes. If input came from standard
+ input, the file name length is set to zero.
+
+ disk number start: (2 bytes)
+
+ The number of the disk on which this file begins. If an
+ archive is in ZIP64 format and the value in this field is
+ 0xFFFF, the size will be in the corresponding 4 byte zip64
+ extended information extra field.
+
+ internal file attributes: (2 bytes)
+
+ Bits 1 and 2 are reserved for use by PKWARE.
+
+ The lowest bit of this field indicates, if set, that
+ the file is apparently an ASCII or text file. If not
+ set, that the file apparently contains binary data.
+ The remaining bits are unused in version 1.0.
+
+ The 0x0002 bit of this field indicates, if set, that a
+ 4 byte variable record length control field precedes each
+ logical record indicating the length of the record. The
+ record length control field is stored in little-endian byte
+ order. This flag is independent of text control characters,
+ and if used in conjunction with text data, includes any
+ control characters in the total length of the record. This
+ value is provided for mainframe data transfer support.
+
+ external file attributes: (4 bytes)
+
+ The mapping of the external attributes is
+ host-system dependent (see 'version made by'). For
+ MS-DOS, the low order byte is the MS-DOS directory
+ attribute byte. If input came from standard input, this
+ field is set to zero.
+
+ relative offset of local header: (4 bytes)
+
+ This is the offset from the start of the first disk on
+ which this file appears, to where the local header should
+ be found. If an archive is in ZIP64 format and the value
+ in this field is 0xFFFFFFFF, the size will be in the
+ corresponding 8 byte zip64 extended information extra field.
+
+ file name: (Variable)
+
+ The name of the file, with optional relative path.
+ The path stored should not contain a drive or
+ device letter, or a leading slash. All slashes
+ should be forward slashes '/' as opposed to
+ backwards slashes '\' for compatibility with Amiga
+ and UNIX file systems etc. If input came from standard
+ input, there is no file name field. If encrypting
+ the central directory and general purpose bit flag 13 is set
+ indicating masking, the file name stored in the Local Header
+ will not be the actual file name. A masking value consisting
+ of a unique hexadecimal value will be stored. This value will
+ be sequentially incremented for each file in the archive. See
+ the section on the Strong Encryption Specification for details
+ on retrieving the encrypted file name.
+
+ extra field: (Variable)
+
+ This is for expansion. If additional information
+ needs to be stored for special needs or for specific
+ platforms, it should be stored here. Earlier versions
+ of the software can then safely skip this file, and
+ find the next file or header. This field will be 0
+ length in version 1.0.
+
+ In order to allow different programs and different types
+ of information to be stored in the 'extra' field in .ZIP
+ files, the following structure should be used for all
+ programs storing data in this field:
+
+ header1+data1 + header2+data2 . . .
+
+ Each header should consist of:
+
+ Header ID - 2 bytes
+ Data Size - 2 bytes
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ The Header ID field indicates the type of data that is in
+ the following data block.
+
+ Header ID's of 0 thru 31 are reserved for use by PKWARE.
+ The remaining ID's can be used by third party vendors for
+ proprietary usage.
+
+ The current Header ID mappings defined by PKWARE are:
+
+ 0x0001 Zip64 extended information extra field
+ 0x0007 AV Info
+ 0x0008 Reserved for extended language encoding data (PFS)
+ (see APPENDIX D)
+ 0x0009 OS/2
+ 0x000a NTFS
+ 0x000c OpenVMS
+ 0x000d UNIX
+ 0x000e Reserved for file stream and fork descriptors
+ 0x000f Patch Descriptor
+ 0x0014 PKCS#7 Store for X.509 Certificates
+ 0x0015 X.509 Certificate ID and Signature for
+ individual file
+ 0x0016 X.509 Certificate ID for Central Directory
+ 0x0017 Strong Encryption Header
+ 0x0018 Record Management Controls
+ 0x0019 PKCS#7 Encryption Recipient Certificate List
+ 0x0065 IBM S/390 (Z390), AS/400 (I400) attributes
+ - uncompressed
+ 0x0066 Reserved for IBM S/390 (Z390), AS/400 (I400)
+ attributes - compressed
+ 0x4690 POSZIP 4690 (reserved)
+
+ Third party mappings commonly used are:
+
+
+ 0x07c8 Macintosh
+ 0x2605 ZipIt Macintosh
+ 0x2705 ZipIt Macintosh 1.3.5+
+ 0x2805 ZipIt Macintosh 1.3.5+
+ 0x334d Info-ZIP Macintosh
+ 0x4341 Acorn/SparkFS
+ 0x4453 Windows NT security descriptor (binary ACL)
+ 0x4704 VM/CMS
+ 0x470f MVS
+ 0x4b46 FWKCS MD5 (see below)
+ 0x4c41 OS/2 access control list (text ACL)
+ 0x4d49 Info-ZIP OpenVMS
+ 0x4f4c Xceed original location extra field
+ 0x5356 AOS/VS (ACL)
+ 0x5455 extended timestamp
+ 0x554e Xceed unicode extra field
+ 0x5855 Info-ZIP UNIX (original, also OS/2, NT, etc)
+ 0x6375 Info-ZIP Unicode Comment Extra Field
+ 0x6542 BeOS/BeBox
+ 0x7075 Info-ZIP Unicode Path Extra Field
+ 0x756e ASi UNIX
+ 0x7855 Info-ZIP UNIX (new)
+ 0xa220 Microsoft Open Packaging Growth Hint
+ 0xfd4a SMS/QDOS
+
+ Detailed descriptions of Extra Fields defined by third
+ party mappings will be documented as information on
+ these data structures is made available to PKWARE.
+ PKWARE does not guarantee the accuracy of any published
+ third party data.
+
+ The Data Size field indicates the size of the following
+ data block. Programs can use this value to skip to the
+ next header block, passing over any data blocks that are
+ not of interest.
+
+ Note: As stated above, the size of the entire .ZIP file
+ header, including the file name, comment, and extra
+ field should not exceed 64K in size.
+
+ In case two different programs should appropriate the same
+ Header ID value, it is strongly recommended that each
+ program place a unique signature of at least two bytes in
+ size (and preferably 4 bytes or bigger) at the start of
+ each data area. Every program should verify that its
+ unique signature is present, in addition to the Header ID
+ value being correct, before assuming that it is a block of
+ known type.
+
+ -Zip64 Extended Information Extra Field (0x0001):
+
+ The following is the layout of the zip64 extended
+ information "extra" block. If one of the size or
+ offset fields in the Local or Central directory
+ record is too small to hold the required data,
+ a Zip64 extended information record is created.
+ The order of the fields in the zip64 extended
+ information record is fixed, but the fields will
+ only appear if the corresponding Local or Central
+ directory record field is set to 0xFFFF or 0xFFFFFFFF.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (ZIP64) 0x0001 2 bytes Tag for this "extra" block type
+ Size 2 bytes Size of this "extra" block
+ Original
+ Size 8 bytes Original uncompressed file size
+ Compressed
+ Size 8 bytes Size of compressed data
+ Relative Header
+ Offset 8 bytes Offset of local header record
+ Disk Start
+ Number 4 bytes Number of the disk on which
+ this file starts
+
+ This entry in the Local header must include BOTH original
+ and compressed file size fields. If encrypting the
+ central directory and bit 13 of the general purpose bit
+ flag is set indicating masking, the value stored in the
+ Local Header for the original file size will be zero.
+
+
+ -OS/2 Extra Field (0x0009):
+
+ The following is the layout of the OS/2 attributes "extra"
+ block. (Last Revision 09/05/95)
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (OS/2) 0x0009 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size for the following data block
+ BSize 4 bytes Uncompressed Block Size
+ CType 2 bytes Compression type
+ EACRC 4 bytes CRC value for uncompress block
+ (var) variable Compressed block
+
+ The OS/2 extended attribute structure (FEA2LIST) is
+ compressed and then stored in it's entirety within this
+ structure. There will only ever be one "block" of data in
+ VarFields[].
+
+ -NTFS Extra Field (0x000a):
+
+ The following is the layout of the NTFS attributes
+ "extra" block. (Note: At this time the Mtime, Atime
+ and Ctime values may be used on any WIN32 system.)
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (NTFS) 0x000a 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of the total "extra" block
+ Reserved 4 bytes Reserved for future use
+ Tag1 2 bytes NTFS attribute tag value #1
+ Size1 2 bytes Size of attribute #1, in bytes
+ (var.) Size1 Attribute #1 data
+ .
+ .
+ .
+ TagN 2 bytes NTFS attribute tag value #N
+ SizeN 2 bytes Size of attribute #N, in bytes
+ (var.) SizeN Attribute #N data
+
+ For NTFS, values for Tag1 through TagN are as follows:
+ (currently only one set of attributes is defined for NTFS)
+
+ Tag Size Description
+ ----- ---- -----------
+ 0x0001 2 bytes Tag for attribute #1
+ Size1 2 bytes Size of attribute #1, in bytes
+ Mtime 8 bytes File last modification time
+ Atime 8 bytes File last access time
+ Ctime 8 bytes File creation time
+
+ -OpenVMS Extra Field (0x000c):
+
+ The following is the layout of the OpenVMS attributes
+ "extra" block.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (VMS) 0x000c 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of the total "extra" block
+ CRC 4 bytes 32-bit CRC for remainder of the block
+ Tag1 2 bytes OpenVMS attribute tag value #1
+ Size1 2 bytes Size of attribute #1, in bytes
+ (var.) Size1 Attribute #1 data
+ .
+ .
+ .
+ TagN 2 bytes OpenVMS attribute tag value #N
+ SizeN 2 bytes Size of attribute #N, in bytes
+ (var.) SizeN Attribute #N data
+
+ Rules:
+
+ 1. There will be one or more of attributes present, which
+ will each be preceded by the above TagX & SizeX values.
+ These values are identical to the ATR$C_XXXX and
+ ATR$S_XXXX constants which are defined in ATR.H under
+ OpenVMS C. Neither of these values will ever be zero.
+
+ 2. No word alignment or padding is performed.
+
+ 3. A well-behaved PKZIP/OpenVMS program should never produce
+ more than one sub-block with the same TagX value. Also,
+ there will never be more than one "extra" block of type
+ 0x000c in a particular directory record.
+
+ -UNIX Extra Field (0x000d):
+
+ The following is the layout of the UNIX "extra" block.
+ Note: all fields are stored in Intel low-byte/high-byte
+ order.
+
+ Value Size Description
+ ----- ---- -----------
+ (UNIX) 0x000d 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size for the following data block
+ Atime 4 bytes File last access time
+ Mtime 4 bytes File last modification time
+ Uid 2 bytes File user ID
+ Gid 2 bytes File group ID
+ (var) variable Variable length data field
+
+ The variable length data field will contain file type
+ specific data. Currently the only values allowed are
+ the original "linked to" file names for hard or symbolic
+ links, and the major and minor device node numbers for
+ character and block device nodes. Since device nodes
+ cannot be either symbolic or hard links, only one set of
+ variable length data is stored. Link files will have the
+ name of the original file stored. This name is NOT NULL
+ terminated. Its size can be determined by checking TSize -
+ 12. Device entries will have eight bytes stored as two 4
+ byte entries (in little endian format). The first entry
+ will be the major device number, and the second the minor
+ device number.
+
+ -PATCH Descriptor Extra Field (0x000f):
+
+ The following is the layout of the Patch Descriptor "extra"
+ block.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (Patch) 0x000f 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of the total "extra" block
+ Version 2 bytes Version of the descriptor
+ Flags 4 bytes Actions and reactions (see below)
+ OldSize 4 bytes Size of the file about to be patched
+ OldCRC 4 bytes 32-bit CRC of the file to be patched
+ NewSize 4 bytes Size of the resulting file
+ NewCRC 4 bytes 32-bit CRC of the resulting file
+
+ Actions and reactions
+
+ Bits Description
+ ---- ----------------
+ 0 Use for auto detection
+ 1 Treat as a self-patch
+ 2-3 RESERVED
+ 4-5 Action (see below)
+ 6-7 RESERVED
+ 8-9 Reaction (see below) to absent file
+ 10-11 Reaction (see below) to newer file
+ 12-13 Reaction (see below) to unknown file
+ 14-15 RESERVED
+ 16-31 RESERVED
+
+ Actions
+
+ Action Value
+ ------ -----
+ none 0
+ add 1
+ delete 2
+ patch 3
+
+ Reactions
+
+ Reaction Value
+ -------- -----
+ ask 0
+ skip 1
+ ignore 2
+ fail 3
+
+ Patch support is provided by PKPatchMaker(tm) technology and is
+ covered under U.S. Patents and Patents Pending. The use or
+ implementation in a product of certain technological aspects set
+ forth in the current APPNOTE, including those with regard to
+ strong encryption, patching, or extended tape operations requires
+ a license from PKWARE. Please contact PKWARE with regard to
+ acquiring a license.
+
+ -PKCS#7 Store for X.509 Certificates (0x0014):
+
+ This field contains information about each of the certificates
+ files may be signed with. When the Central Directory Encryption
+ feature is enabled for a ZIP file, this record will appear in
+ the Archive Extra Data Record, otherwise it will appear in the
+ first central directory record and will be ignored in any
+ other record.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (Store) 0x0014 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of the store data
+ TData TSize Data about the store
+
+
+ -X.509 Certificate ID and Signature for individual file (0x0015):
+
+ This field contains the information about which certificate in
+ the PKCS#7 store was used to sign a particular file. It also
+ contains the signature data. This field can appear multiple
+ times, but can only appear once per certificate.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (CID) 0x0015 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of data that follows
+ TData TSize Signature Data
+
+ -X.509 Certificate ID and Signature for central directory (0x0016):
+
+ This field contains the information about which certificate in
+ the PKCS#7 store was used to sign the central directory structure.
+ When the Central Directory Encryption feature is enabled for a
+ ZIP file, this record will appear in the Archive Extra Data Record,
+ otherwise it will appear in the first central directory record.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (CDID) 0x0016 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of data that follows
+ TData TSize Data
+
+ -Strong Encryption Header (0x0017):
+
+ Value Size Description
+ ----- ---- -----------
+ 0x0017 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of data that follows
+ Format 2 bytes Format definition for this record
+ AlgID 2 bytes Encryption algorithm identifier
+ Bitlen 2 bytes Bit length of encryption key
+ Flags 2 bytes Processing flags
+ CertData TSize-8 Certificate decryption extra field data
+ (refer to the explanation for CertData
+ in the section describing the
+ Certificate Processing Method under
+ the Strong Encryption Specification)
+
+
+ -Record Management Controls (0x0018):
+
+ Value Size Description
+ ----- ---- -----------
+(Rec-CTL) 0x0018 2 bytes Tag for this "extra" block type
+ CSize 2 bytes Size of total extra block data
+ Tag1 2 bytes Record control attribute 1
+ Size1 2 bytes Size of attribute 1, in bytes
+ Data1 Size1 Attribute 1 data
+ .
+ .
+ .
+ TagN 2 bytes Record control attribute N
+ SizeN 2 bytes Size of attribute N, in bytes
+ DataN SizeN Attribute N data
+
+
+ -PKCS#7 Encryption Recipient Certificate List (0x0019):
+
+ This field contains information about each of the certificates
+ used in encryption processing and it can be used to identify who is
+ allowed to decrypt encrypted files. This field should only appear
+ in the archive extra data record. This field is not required and
+ serves only to aide archive modifications by preserving public
+ encryption key data. Individual security requirements may dictate
+ that this data be omitted to deter information exposure.
+
+ Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ (CStore) 0x0019 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size of the store data
+ TData TSize Data about the store
+
+ TData:
+
+ Value Size Description
+ ----- ---- -----------
+ Version 2 bytes Format version number - must 0x0001 at this time
+ CStore (var) PKCS#7 data blob
+
+
+ -MVS Extra Field (0x0065):
+
+ The following is the layout of the MVS "extra" block.
+ Note: Some fields are stored in Big Endian format.
+ All text is in EBCDIC format unless otherwise specified.
+
+ Value Size Description
+ ----- ---- -----------
+ (MVS) 0x0065 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size for the following data block
+ ID 4 bytes EBCDIC "Z390" 0xE9F3F9F0 or
+ "T4MV" for TargetFour
+ (var) TSize-4 Attribute data (see APPENDIX B)
+
+
+ -OS/400 Extra Field (0x0065):
+
+ The following is the layout of the OS/400 "extra" block.
+ Note: Some fields are stored in Big Endian format.
+ All text is in EBCDIC format unless otherwise specified.
+
+ Value Size Description
+ ----- ---- -----------
+ (OS400) 0x0065 2 bytes Tag for this "extra" block type
+ TSize 2 bytes Size for the following data block
+ ID 4 bytes EBCDIC "I400" 0xC9F4F0F0 or
+ "T4MV" for TargetFour
+ (var) TSize-4 Attribute data (see APPENDIX A)
+
+
+ Third-party Mappings:
+
+ -ZipIt Macintosh Extra Field (long) (0x2605):
+
+ The following is the layout of the ZipIt extra block
+ for Macintosh. The local-header and central-header versions
+ are identical. This block must be present if the file is
+ stored MacBinary-encoded and it should not be used if the file
+ is not stored MacBinary-encoded.
+
+ Value Size Description
+ ----- ---- -----------
+ (Mac2) 0x2605 Short tag for this extra block type
+ TSize Short total data size for this block
+ "ZPIT" beLong extra-field signature
+ FnLen Byte length of FileName
+ FileName variable full Macintosh filename
+ FileType Byte[4] four-byte Mac file type string
+ Creator Byte[4] four-byte Mac creator string
+
+
+ -ZipIt Macintosh Extra Field (short, for files) (0x2705):
+
+ The following is the layout of a shortened variant of the
+ ZipIt extra block for Macintosh (without "full name" entry).
+ This variant is used by ZipIt 1.3.5 and newer for entries of
+ files (not directories) that do not have a MacBinary encoded
+ file. The local-header and central-header versions are identical.
+
+ Value Size Description
+ ----- ---- -----------
+ (Mac2b) 0x2705 Short tag for this extra block type
+ TSize Short total data size for this block (12)
+ "ZPIT" beLong extra-field signature
+ FileType Byte[4] four-byte Mac file type string
+ Creator Byte[4] four-byte Mac creator string
+ fdFlags beShort attributes from FInfo.frFlags,
+ may be omitted
+ 0x0000 beShort reserved, may be omitted
+
+
+ -ZipIt Macintosh Extra Field (short, for directories) (0x2805):
+
+ The following is the layout of a shortened variant of the
+ ZipIt extra block for Macintosh used only for directory
+ entries. This variant is used by ZipIt 1.3.5 and newer to
+ save some optional Mac-specific information about directories.
+ The local-header and central-header versions are identical.
+
+ Value Size Description
+ ----- ---- -----------
+ (Mac2c) 0x2805 Short tag for this extra block type
+ TSize Short total data size for this block (12)
+ "ZPIT" beLong extra-field signature
+ frFlags beShort attributes from DInfo.frFlags, may
+ be omitted
+ View beShort ZipIt view flag, may be omitted
+
+
+ The View field specifies ZipIt-internal settings as follows:
+
+ Bits of the Flags:
+ bit 0 if set, the folder is shown expanded (open)
+ when the archive contents are viewed in ZipIt.
+ bits 1-15 reserved, zero;
+
+
+ -FWKCS MD5 Extra Field (0x4b46):
+
+ The FWKCS Contents_Signature System, used in
+ automatically identifying files independent of file name,
+ optionally adds and uses an extra field to support the
+ rapid creation of an enhanced contents_signature:
+
+ Header ID = 0x4b46
+ Data Size = 0x0013
+ Preface = 'M','D','5'
+ followed by 16 bytes containing the uncompressed file's
+ 128_bit MD5 hash(1), low byte first.
+
+ When FWKCS revises a .ZIP file central directory to add
+ this extra field for a file, it also replaces the
+ central directory entry for that file's uncompressed
+ file length with a measured value.
+
+ FWKCS provides an option to strip this extra field, if
+ present, from a .ZIP file central directory. In adding
+ this extra field, FWKCS preserves .ZIP file Authenticity
+ Verification; if stripping this extra field, FWKCS
+ preserves all versions of AV through PKZIP version 2.04g.
+
+ FWKCS, and FWKCS Contents_Signature System, are
+ trademarks of Frederick W. Kantor.
+
+ (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer
+ Science and RSA Data Security, Inc., April 1992.
+ ll.76-77: "The MD5 algorithm is being placed in the
+ public domain for review and possible adoption as a
+ standard."
+
+
+ -Info-ZIP Unicode Comment Extra Field (0x6375):
+
+ Stores the UTF-8 version of the file comment as stored in the
+ central directory header. (Last Revision 20070912)
+
+ Value Size Description
+ ----- ---- -----------
+ (UCom) 0x6375 Short tag for this extra block type ("uc")
+ TSize Short total data size for this block
+ Version 1 byte version of this extra field, currently 1
+ ComCRC32 4 bytes Comment Field CRC32 Checksum
+ UnicodeCom Variable UTF-8 version of the entry comment
+
+ Currently Version is set to the number 1. If there is a need
+ to change this field, the version will be incremented. Changes
+ may not be backward compatible so this extra field should not be
+ used if the version is not recognized.
+
+ The ComCRC32 is the standard zip CRC32 checksum of the File Comment
+ field in the central directory header. This is used to verify that
+ the comment field has not changed since the Unicode Comment extra field
+ was created. This can happen if a utility changes the File Comment
+ field but does not update the UTF-8 Comment extra field. If the CRC
+ check fails, this Unicode Comment extra field should be ignored and
+ the File Comment field in the header should be used instead.
+
+ The UnicodeCom field is the UTF-8 version of the File Comment field
+ in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte
+ order mark (BOM) is used. The length of this field is determined by
+ subtracting the size of the previous fields from TSize. If both the
+ File Name and Comment fields are UTF-8, the new General Purpose Bit
+ Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate
+ both the header File Name and Comment fields are UTF-8 and, in this
+ case, the Unicode Path and Unicode Comment extra fields are not
+ needed and should not be created. Note that, for backward
+ compatibility, bit 11 should only be used if the native character set
+ of the paths and comments being zipped up are already in UTF-8. It is
+ expected that the same file comment storage method, either general
+ purpose bit 11 or extra fields, be used in both the Local and Central
+ Directory Header for a file.
+
+
+ -Info-ZIP Unicode Path Extra Field (0x7075):
+
+ Stores the UTF-8 version of the file name field as stored in the
+ local header and central directory header. (Last Revision 20070912)
+
+ Value Size Description
+ ----- ---- -----------
+ (UPath) 0x7075 Short tag for this extra block type ("up")
+ TSize Short total data size for this block
+ Version 1 byte version of this extra field, currently 1
+ NameCRC32 4 bytes File Name Field CRC32 Checksum
+ UnicodeName Variable UTF-8 version of the entry File Name
+
+ Currently Version is set to the number 1. If there is a need
+ to change this field, the version will be incremented. Changes
+ may not be backward compatible so this extra field should not be
+ used if the version is not recognized.
+
+ The NameCRC32 is the standard zip CRC32 checksum of the File Name
+ field in the header. This is used to verify that the header
+ File Name field has not changed since the Unicode Path extra field
+ was created. This can happen if a utility renames the File Name but
+ does not update the UTF-8 path extra field. If the CRC check fails,
+ this UTF-8 Path Extra Field should be ignored and the File Name field
+ in the header should be used instead.
+
+ The UnicodeName is the UTF-8 version of the contents of the File Name
+ field in the header. As UnicodeName is defined to be UTF-8, no UTF-8
+ byte order mark (BOM) is used. The length of this field is determined
+ by subtracting the size of the previous fields from TSize. If both
+ the File Name and Comment fields are UTF-8, the new General Purpose
+ Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to
+ indicate that both the header File Name and Comment fields are UTF-8
+ and, in this case, the Unicode Path and Unicode Comment extra fields
+ are not needed and should not be created. Note that, for backward
+ compatibility, bit 11 should only be used if the native character set
+ of the paths and comments being zipped up are already in UTF-8. It is
+ expected that the same file name storage method, either general
+ purpose bit 11 or extra fields, be used in both the Local and Central
+ Directory Header for a file.
+
+
+ -Microsoft Open Packaging Growth Hint (0xa220):
+
+ Value Size Description
+ ----- ---- -----------
+ 0xa220 Short tag for this extra block type
+ TSize Short size of Sig + PadVal + Padding
+ Sig Short verification signature (A028)
+ PadVal Short Initial padding value
+ Padding variable filled with NULL characters
+
+
+ file comment: (Variable)
+
+ The comment for this file.
+
+ number of this disk: (2 bytes)
+
+ The number of this disk, which contains central
+ directory end record. If an archive is in ZIP64 format
+ and the value in this field is 0xFFFF, the size will
+ be in the corresponding 4 byte zip64 end of central
+ directory field.
+
+
+ number of the disk with the start of the central
+ directory: (2 bytes)
+
+ The number of the disk on which the central
+ directory starts. If an archive is in ZIP64 format
+ and the value in this field is 0xFFFF, the size will
+ be in the corresponding 4 byte zip64 end of central
+ directory field.
+
+ total number of entries in the central dir on
+ this disk: (2 bytes)
+
+ The number of central directory entries on this disk.
+ If an archive is in ZIP64 format and the value in
+ this field is 0xFFFF, the size will be in the
+ corresponding 8 byte zip64 end of central
+ directory field.
+
+ total number of entries in the central dir: (2 bytes)
+
+ The total number of files in the .ZIP file. If an
+ archive is in ZIP64 format and the value in this field
+ is 0xFFFF, the size will be in the corresponding 8 byte
+ zip64 end of central directory field.
+
+ size of the central directory: (4 bytes)
+
+ The size (in bytes) of the entire central directory.
+ If an archive is in ZIP64 format and the value in
+ this field is 0xFFFFFFFF, the size will be in the
+ corresponding 8 byte zip64 end of central
+ directory field.
+
+ offset of start of central directory with respect to
+ the starting disk number: (4 bytes)
+
+ Offset of the start of the central directory on the
+ disk on which the central directory starts. If an
+ archive is in ZIP64 format and the value in this
+ field is 0xFFFFFFFF, the size will be in the
+ corresponding 8 byte zip64 end of central
+ directory field.
+
+ .ZIP file comment length: (2 bytes)
+
+ The length of the comment for this .ZIP file.
+
+ .ZIP file comment: (Variable)
+
+ The comment for this .ZIP file. ZIP file comment data
+ is stored unsecured. No encryption or data authentication
+ is applied to this area at this time. Confidential information
+ should not be stored in this section.
+
+ zip64 extensible data sector (variable size)
+
+ (currently reserved for use by PKWARE)
+
+
+ K. Splitting and Spanning ZIP files
+
+ Spanning is the process of segmenting a ZIP file across
+ multiple removable media. This support has typically only
+ been provided for DOS formatted floppy diskettes.
+
+ File splitting is a newer derivative of spanning.
+ Splitting follows the same segmentation process as
+ spanning, however, it does not require writing each
+ segment to a unique removable medium and instead supports
+ placing all pieces onto local or non-removable locations
+ such as file systems, local drives, folders, etc...
+
+ A key difference between spanned and split ZIP files is
+ that all pieces of a spanned ZIP file have the same name.
+ Since each piece is written to a separate volume, no name
+ collisions occur and each segment can reuse the original
+ .ZIP file name given to the archive.
+
+ Sequence ordering for DOS spanned archives uses the DOS
+ volume label to determine segment numbers. Volume labels
+ for each segment are written using the form PKBACK#xxx,
+ where xxx is the segment number written as a decimal
+ value from 001 - nnn.
+
+ Split ZIP files are typically written to the same location
+ and are subject to name collisions if the spanned name
+ format is used since each segment will reside on the same
+ drive. To avoid name collisions, split archives are named
+ as follows.
+
+ Segment 1 = filename.z01
+ Segment n-1 = filename.z(n-1)
+ Segment n = filename.zip
+
+ The .ZIP extension is used on the last segment to support
+ quickly reading the central directory. The segment number
+ n should be a decimal value.
+
+ Spanned ZIP files may be PKSFX Self-extracting ZIP files.
+ PKSFX files may also be split, however, in this case
+ the first segment must be named filename.exe. The first
+ segment of a split PKSFX archive must be large enough to
+ include the entire executable program.
+
+ Capacities for split archives are as follows.
+
+ Maximum number of segments = 4,294,967,295 - 1
+ Maximum .ZIP segment size = 4,294,967,295 bytes
+ Minimum segment size = 64K
+ Maximum PKSFX segment size = 2,147,483,647 bytes
+
+ Segment sizes may be different however by convention, all
+ segment sizes should be the same with the exception of the
+ last, which may be smaller. Local and central directory
+ header records must never be split across a segment boundary.
+ When writing a header record, if the number of bytes remaining
+ within a segment is less than the size of the header record,
+ end the current segment and write the header at the start
+ of the next segment. The central directory may span segment
+ boundaries, but no single record in the central directory
+ should be split across segments.
+
+ Spanned/Split archives created using PKZIP for Windows
+ (V2.50 or greater), PKZIP Command Line (V2.50 or greater),
+ or PKZIP Explorer will include a special spanning
+ signature as the first 4 bytes of the first segment of
+ the archive. This signature (0x08074b50) will be
+ followed immediately by the local header signature for
+ the first file in the archive.
+
+ A special spanning marker may also appear in spanned/split
+ archives if the spanning or splitting process starts but
+ only requires one segment. In this case the 0x08074b50
+ signature will be replaced with the temporary spanning
+ marker signature of 0x30304b50. Split archives can
+ only be uncompressed by other versions of PKZIP that
+ know how to create a split archive.
+
+ The signature value 0x08074b50 is also used by some
+ ZIP implementations as a marker for the Data Descriptor
+ record. Conflict in this alternate assignment can be
+ avoided by ensuring the position of the signature
+ within the ZIP file to determine the use for which it
+ is intended.
+
+ L. General notes:
+
+ 1) All fields unless otherwise noted are unsigned and stored
+ in Intel low-byte:high-byte, low-word:high-word order.
+
+ 2) String fields are not null terminated, since the
+ length is given explicitly.
+
+ 3) The entries in the central directory may not necessarily
+ be in the same order that files appear in the .ZIP file.
+
+ 4) If one of the fields in the end of central directory
+ record is too small to hold required data, the field
+ should be set to -1 (0xFFFF or 0xFFFFFFFF) and the
+ ZIP64 format record should be created.
+
+ 5) The end of central directory record and the
+ Zip64 end of central directory locator record must
+ reside on the same disk when splitting or spanning
+ an archive.
+
+VI. Explanation of compression methods
+--------------------------------------
+
+UnShrinking - Method 1
+----------------------
+
+Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
+with partial clearing. The initial code size is 9 bits, and
+the maximum code size is 13 bits. Shrinking differs from
+conventional Dynamic Ziv-Lempel-Welch implementations in several
+respects:
+
+1) The code size is controlled by the compressor, and is not
+ automatically increased when codes larger than the current
+ code size are created (but not necessarily used). When
+ the decompressor encounters the code sequence 256
+ (decimal) followed by 1, it should increase the code size
+ read from the input stream to the next bit size. No
+ blocking of the codes is performed, so the next code at
+ the increased size should be read from the input stream
+ immediately after where the previous code at the smaller
+ bit size was read. Again, the decompressor should not
+ increase the code size used until the sequence 256,1 is
+ encountered.
+
+2) When the table becomes full, total clearing is not
+ performed. Rather, when the compressor emits the code
+ sequence 256,2 (decimal), the decompressor should clear
+ all leaf nodes from the Ziv-Lempel tree, and continue to
+ use the current code size. The nodes that are cleared
+ from the Ziv-Lempel tree are then re-used, with the lowest
+ code value re-used first, and the highest code value
+ re-used last. The compressor can emit the sequence 256,2
+ at any time.
+
+Expanding - Methods 2-5
+-----------------------
+
+The Reducing algorithm is actually a combination of two
+distinct algorithms. The first algorithm compresses repeated
+byte sequences, and the second algorithm takes the compressed
+stream from the first algorithm and applies a probabilistic
+compression method.
+
+The probabilistic compression stores an array of 'follower
+sets' S(j), for j=0 to 255, corresponding to each possible
+ASCII character. Each set contains between 0 and 32
+characters, to be denoted as S(j)[0],...,S(j)[m], where m<32.
+The sets are stored at the beginning of the data area for a
+Reduced file, in reverse order, with S(255) first, and S(0)
+last.
+
+The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] },
+where N(j) is the size of set S(j). N(j) can be 0, in which
+case the follower set for S(j) is empty. Each N(j) value is
+encoded in 6 bits, followed by N(j) eight bit character values
+corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If
+N(j) is 0, then no values for S(j) are stored, and the value
+for N(j-1) immediately follows.
+
+Immediately after the follower sets, is the compressed data
+stream. The compressed data stream can be interpreted for the
+probabilistic decompression as follows:
+
+let Last-Character <- 0.
+loop until done
+ if the follower set S(Last-Character) is empty then
+ read 8 bits from the input stream, and copy this
+ value to the output stream.
+ otherwise if the follower set S(Last-Character) is non-empty then
+ read 1 bit from the input stream.
+ if this bit is not zero then
+ read 8 bits from the input stream, and copy this
+ value to the output stream.
+ otherwise if this bit is zero then
+ read B(N(Last-Character)) bits from the input
+ stream, and assign this value to I.
+ Copy the value of S(Last-Character)[I] to the
+ output stream.
+
+ assign the last value placed on the output stream to
+ Last-Character.
+end loop
+
+B(N(j)) is defined as the minimal number of bits required to
+encode the value N(j)-1.
+
+The decompressed stream from above can then be expanded to
+re-create the original file as follows:
+
+let State <- 0.
+
+loop until done
+ read 8 bits from the input stream into C.
+ case State of
+ 0: if C is not equal to DLE (144 decimal) then
+ copy C to the output stream.
+ otherwise if C is equal to DLE then
+ let State <- 1.
+
+ 1: if C is non-zero then
+ let V <- C.
+ let Len <- L(V)
+ let State <- F(Len).
+ otherwise if C is zero then
+ copy the value 144 (decimal) to the output stream.
+ let State <- 0
+
+ 2: let Len <- Len + C
+ let State <- 3.
+
+ 3: move backwards D(V,C) bytes in the output stream
+ (if this position is before the start of the output
+ stream, then assume that all the data before the
+ start of the output stream is filled with zeros).
+ copy Len+3 bytes from this position to the output stream.
+ let State <- 0.
+ end case
+end loop
+
+The functions F,L, and D are dependent on the 'compression
+factor', 1 through 4, and are defined as follows:
+
+For compression factor 1:
+ L(X) equals the lower 7 bits of X.
+ F(X) equals 2 if X equals 127 otherwise F(X) equals 3.
+ D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1.
+For compression factor 2:
+ L(X) equals the lower 6 bits of X.
+ F(X) equals 2 if X equals 63 otherwise F(X) equals 3.
+ D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1.
+For compression factor 3:
+ L(X) equals the lower 5 bits of X.
+ F(X) equals 2 if X equals 31 otherwise F(X) equals 3.
+ D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1.
+For compression factor 4:
+ L(X) equals the lower 4 bits of X.
+ F(X) equals 2 if X equals 15 otherwise F(X) equals 3.
+ D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1.
+
+Imploding - Method 6
+--------------------
+
+The Imploding algorithm is actually a combination of two distinct
+algorithms. The first algorithm compresses repeated byte
+sequences using a sliding dictionary. The second algorithm is
+used to compress the encoding of the sliding dictionary output,
+using multiple Shannon-Fano trees.
+
+The Imploding algorithm can use a 4K or 8K sliding dictionary
+size. The dictionary size used can be determined by bit 1 in the
+general purpose flag word; a 0 bit indicates a 4K dictionary
+while a 1 bit indicates an 8K dictionary.
+
+The Shannon-Fano trees are stored at the start of the compressed
+file. The number of trees stored is defined by bit 2 in the
+general purpose flag word; a 0 bit indicates two trees stored, a
+1 bit indicates three trees are stored. If 3 trees are stored,
+the first Shannon-Fano tree represents the encoding of the
+Literal characters, the second tree represents the encoding of
+the Length information, the third represents the encoding of the
+Distance information. When 2 Shannon-Fano trees are stored, the
+Length tree is stored first, followed by the Distance tree.
+
+The Literal Shannon-Fano tree, if present is used to represent
+the entire ASCII character set, and contains 256 values. This
+tree is used to compress any data not compressed by the sliding
+dictionary algorithm. When this tree is present, the Minimum
+Match Length for the sliding dictionary is 3. If this tree is
+not present, the Minimum Match Length is 2.
+
+The Length Shannon-Fano tree is used to compress the Length part
+of the (length,distance) pairs from the sliding dictionary
+output. The Length tree contains 64 values, ranging from the
+Minimum Match Length, to 63 plus the Minimum Match Length.
+
+The Distance Shannon-Fano tree is used to compress the Distance
+part of the (length,distance) pairs from the sliding dictionary
+output. The Distance tree contains 64 values, ranging from 0 to
+63, representing the upper 6 bits of the distance value. The
+distance values themselves will be between 0 and the sliding
+dictionary size, either 4K or 8K.
+
+The Shannon-Fano trees themselves are stored in a compressed
+format. The first byte of the tree data represents the number of
+bytes of data representing the (compressed) Shannon-Fano tree
+minus 1. The remaining bytes represent the Shannon-Fano tree
+data encoded as:
+
+ High 4 bits: Number of values at this bit length + 1. (1 - 16)
+ Low 4 bits: Bit Length needed to represent value + 1. (1 - 16)
+
+The Shannon-Fano codes can be constructed from the bit lengths
+using the following algorithm:
+
+1) Sort the Bit Lengths in ascending order, while retaining the
+ order of the original lengths stored in the file.
+
+2) Generate the Shannon-Fano trees:
+
+ Code <- 0
+ CodeIncrement <- 0
+ LastBitLength <- 0
+ i <- number of Shannon-Fano codes - 1 (either 255 or 63)
+
+ loop while i >= 0
+ Code = Code + CodeIncrement
+ if BitLength(i) <> LastBitLength then
+ LastBitLength=BitLength(i)
+ CodeIncrement = 1 shifted left (16 - LastBitLength)
+ ShannonCode(i) = Code
+ i <- i - 1
+ end loop
+
+3) Reverse the order of all the bits in the above ShannonCode()
+ vector, so that the most significant bit becomes the least
+ significant bit. For example, the value 0x1234 (hex) would
+ become 0x2C48 (hex).
+
+4) Restore the order of Shannon-Fano codes as originally stored
+ within the file.
+
+Example:
+
+ This example will show the encoding of a Shannon-Fano tree
+ of size 8. Notice that the actual Shannon-Fano trees used
+ for Imploding are either 64 or 256 entries in size.
+
+Example: 0x02, 0x42, 0x01, 0x13
+
+ The first byte indicates 3 values in this table. Decoding the
+ bytes:
+ 0x42 = 5 codes of 3 bits long
+ 0x01 = 1 code of 2 bits long
+ 0x13 = 2 codes of 4 bits long
+
+ This would generate the original bit length array of:
+ (3, 3, 3, 3, 3, 2, 4, 4)
+
+ There are 8 codes in this table for the values 0 thru 7. Using
+ the algorithm to obtain the Shannon-Fano codes produces:
+
+ Reversed Order Original
+Val Sorted Constructed Code Value Restored Length
+--- ------ ----------------- -------- -------- ------
+0: 2 1100000000000000 11 101 3
+1: 3 1010000000000000 101 001 3
+2: 3 1000000000000000 001 110 3
+3: 3 0110000000000000 110 010 3
+4: 3 0100000000000000 010 100 3
+5: 3 0010000000000000 100 11 2
+6: 4 0001000000000000 1000 1000 4
+7: 4 0000000000000000 0000 0000 4
+
+The values in the Val, Order Restored and Original Length columns
+now represent the Shannon-Fano encoding tree that can be used for
+decoding the Shannon-Fano encoded data. How to parse the
+variable length Shannon-Fano values from the data stream is beyond
+the scope of this document. (See the references listed at the end of
+this document for more information.) However, traditional decoding
+schemes used for Huffman variable length decoding, such as the
+Greenlaw algorithm, can be successfully applied.
+
+The compressed data stream begins immediately after the
+compressed Shannon-Fano data. The compressed data stream can be
+interpreted as follows:
+
+loop until done
+ read 1 bit from input stream.
+
+ if this bit is non-zero then (encoded data is literal data)
+ if Literal Shannon-Fano tree is present
+ read and decode character using Literal Shannon-Fano tree.
+ otherwise
+ read 8 bits from input stream.
+ copy character to the output stream.
+ otherwise (encoded data is sliding dictionary match)
+ if 8K dictionary size
+ read 7 bits for offset Distance (lower 7 bits of offset).
+ otherwise
+ read 6 bits for offset Distance (lower 6 bits of offset).
+
+ using the Distance Shannon-Fano tree, read and decode the
+ upper 6 bits of the Distance value.
+
+ using the Length Shannon-Fano tree, read and decode
+ the Length value.
+
+ Length <- Length + Minimum Match Length
+
+ if Length = 63 + Minimum Match Length
+ read 8 bits from the input stream,
+ add this value to Length.
+
+ move backwards Distance+1 bytes in the output stream, and
+ copy Length characters from this position to the output
+ stream. (if this position is before the start of the output
+ stream, then assume that all the data before the start of
+ the output stream is filled with zeros).
+end loop
+
+Tokenizing - Method 7
+---------------------
+
+This method is not used by PKZIP.
+
+Deflating - Method 8
+--------------------
+
+The Deflate algorithm is similar to the Implode algorithm using
+a sliding dictionary of up to 32K with secondary compression
+from Huffman/Shannon-Fano codes.
+
+The compressed data is stored in blocks with a header describing
+the block and the Huffman codes used in the data block. The header
+format is as follows:
+
+ Bit 0: Last Block bit This bit is set to 1 if this is the last
+ compressed block in the data.
+ Bits 1-2: Block type
+ 00 (0) - Block is stored - All stored data is byte aligned.
+ Skip bits until next byte, then next word = block
+ length, followed by the ones compliment of the block
+ length word. Remaining data in block is the stored
+ data.
+
+ 01 (1) - Use fixed Huffman codes for literal and distance codes.
+ Lit Code Bits Dist Code Bits
+ --------- ---- --------- ----
+ 0 - 143 8 0 - 31 5
+ 144 - 255 9
+ 256 - 279 7
+ 280 - 287 8
+
+ Literal codes 286-287 and distance codes 30-31 are
+ never used but participate in the huffman construction.
+
+ 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes)
+
+ 11 (3) - Reserved - Flag a "Error in compressed data" if seen.
+
+Expanding Huffman Codes
+-----------------------
+If the data block is stored with dynamic Huffman codes, the Huffman
+codes are sent in the following compressed format:
+
+ 5 Bits: # of Literal codes sent - 256 (256 - 286)
+ All other codes are never sent.
+ 5 Bits: # of Dist codes - 1 (1 - 32)
+ 4 Bits: # of Bit Length codes - 3 (3 - 19)
+
+The Huffman codes are sent as bit lengths and the codes are built as
+described in the implode algorithm. The bit lengths themselves are
+compressed with Huffman codes. There are 19 bit length codes:
+
+ 0 - 15: Represent bit lengths of 0 - 15
+ 16: Copy the previous bit length 3 - 6 times.
+ The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6)
+ Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will
+ expand to 12 bit lengths of 8 (1 + 6 + 5)
+ 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length)
+ 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length)
+
+The lengths of the bit length codes are sent packed 3 bits per value
+(0 - 7) in the following order:
+
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+
+The Huffman codes should be built as described in the Implode algorithm
+except codes are assigned starting at the shortest bit length, i.e. the
+shortest code should be all 0's rather than all 1's. Also, codes with
+a bit length of zero do not participate in the tree construction. The
+codes are then used to decode the bit lengths for the literal and
+distance tables.
+
+The bit lengths for the literal tables are sent first with the number
+of entries sent described by the 5 bits sent earlier. There are up
+to 286 literal characters; the first 256 represent the respective 8
+bit character, code 256 represents the End-Of-Block code, the remaining
+29 codes represent copy lengths of 3 thru 258. There are up to 30
+distance codes representing distances from 1 thru 32k as described
+below.
+
+ Length Codes
+ ------------
+ Extra Extra Extra Extra
+ Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s)
+ ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- ---------
+ 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162
+ 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194
+ 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226
+ 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257
+ 261 0 7 269 2 19-22 277 4 67-82 285 0 258
+ 262 0 8 270 2 23-26 278 4 83-98
+ 263 0 9 271 2 27-30 279 4 99-114
+ 264 0 10 272 2 31-34 280 4 115-130
+
+ Distance Codes
+ --------------
+ Extra Extra Extra Extra
+ Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance
+ ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- --------
+ 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144
+ 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192
+ 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288
+ 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384
+ 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576
+ 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768
+ 6 2 9-12 14 6 129-192 22 10 2049-3072
+ 7 2 13-16 15 6 193-256 23 10 3073-4096
+
+The compressed data stream begins immediately after the
+compressed header data. The compressed data stream can be
+interpreted as follows:
+
+do
+ read header from input stream.
+
+ if stored block
+ skip bits until byte aligned
+ read count and 1's compliment of count
+ copy count bytes data block
+ otherwise
+ loop until end of block code sent
+ decode literal character from input stream
+ if literal < 256
+ copy character to the output stream
+ otherwise
+ if literal = end of block
+ break from loop
+ otherwise
+ decode distance from input stream
+
+ move backwards distance bytes in the output stream, and
+ copy length characters from this position to the output
+ stream.
+ end loop
+while not last block
+
+if data descriptor exists
+ skip bits until byte aligned
+ read crc and sizes
+endif
+
+Enhanced Deflating - Method 9
+-----------------------------
+
+The Enhanced Deflating algorithm is similar to Deflate but
+uses a sliding dictionary of up to 64K. Deflate64(tm) is supported
+by the Deflate extractor.
+
+BZIP2 - Method 12
+-----------------
+
+BZIP2 is an open-source data compression algorithm developed by
+Julian Seward. Information and source code for this algorithm
+can be found on the internet.
+
+LZMA - Method 14 (EFS)
+----------------------
+
+LZMA is a block-oriented, general purpose data compression algorithm
+developed and maintained by Igor Pavlov. It is a derivative of LZ77
+that utilizes Markov chains and a range coder. Information and
+source code for this algorithm can be found on the internet. Consult
+with the author of this algorithm for information on terms or
+restrictions on use.
+
+Support for LZMA within the ZIP format is defined as follows:
+
+The Compression method field within the ZIP Local and Central
+Header records will be set to the value 14 to indicate data was
+compressed using LZMA.
+
+The Version needed to extract field within the ZIP Local and
+Central Header records will be set to 6.3 to indicate the
+minimum ZIP format version supporting this feature.
+
+File data compressed using the LZMA algorithm must be placed
+immediately following the Local Header for the file. If a
+standard ZIP encryption header is required, it will follow
+the Local Header and will precede the LZMA compressed file
+data segment. The location of LZMA compressed data segment
+within the ZIP format will be as shown:
+
+ [local header file 1]
+ [encryption header file 1]
+ [LZMA compressed data segment for file 1]
+ [data descriptor 1]
+ [local header file 2]
+
+The encryption header and data descriptor records may
+be conditionally present. The LZMA Compressed Data Segment
+will consist of an LZMA Properties Header followed by the
+LZMA Compressed Data as shown:
+
+ [LZMA properties header for file 1]
+ [LZMA compressed data for file 1]
+
+The LZMA Compressed Data will be stored as provided by the
+LZMA compression library. Compressed size, uncompressed
+size and other file characteristics about the file being
+compressed must be stored in standard ZIP storage format.
+
+The LZMA Properties Header will store specific data required to
+decompress the LZMA compressed Data. This data is set by the
+LZMA compression engine using the function WriteCoderProperties()
+as documented within the LZMA SDK.
+
+Storage fields for the property information within the LZMA
+Properties Header are as follows:
+
+ LZMA Version Information 2 bytes
+ LZMA Properties Size 2 bytes
+ LZMA Properties Data variable, defined by "LZMA Properties Size"
+
+LZMA Version Information - this field identifies which version of
+ the LZMA SDK was used to compress a file. The first byte will
+ store the major version number of the LZMA SDK and the second
+ byte will store the minor number.
+
+LZMA Properties Size - this field defines the size of the remaining
+ property data. Typically this size should be determined by the
+ version of the SDK. This size field is included as a convenience
+ and to help avoid any ambiguity should it arise in the future due
+ to changes in this compression algorithm.
+
+LZMA Property Data - this variable sized field records the required
+ values for the decompressor as defined by the LZMA SDK. The
+ data stored in this field should be obtained using the
+ WriteCoderProperties() in the version of the SDK defined by
+ the "LZMA Version Information" field.
+
+The layout of the "LZMA Properties Data" field is a function of the
+LZMA compression algorithm. It is possible that this layout may be
+changed by the author over time. The data layout in version 4.32
+of the LZMA SDK defines a 5 byte array that uses 4 bytes to store
+the dictionary size in little-endian order. This is preceded by a
+single packed byte as the first element of the array that contains
+the following fields:
+
+ PosStateBits
+ LiteralPosStateBits
+ LiteralContextBits
+
+Refer to the LZMA documentation for a more detailed explanation of
+these fields.
+
+Data compressed with method 14, LZMA, may include an end-of-stream
+(EOS) marker ending the compressed data stream. This marker is not
+required, but its use is highly recommended to facilitate processing
+and implementers should include the EOS marker whenever possible.
+When the EOS marker is used, general purpose bit 1 must be set. If
+general purpose bit 1 is not set, the EOS marker is not present.
+
+WavPack - Method 97
+-------------------
+
+Information describing the use of compression method 97 is
+provided by WinZIP International, LLC. This method relies on the
+open source WavPack audio compression utility developed by David Bryant.
+Information on WavPack is available at www.wavpack.com. Please consult
+with the author of this algorithm for information on terms and
+restrictions on use.
+
+WavPack data for a file begins immediately after the end of the
+local header data. This data is the output from WavPack compression
+routines. Within the ZIP file, the use of WavPack compression is
+indicated by setting the compression method field to a value of 97
+in both the local header and the central directory header. The Version
+needed to extract and version made by fields use the same values as are
+used for data compressed using the Deflate algorithm.
+
+An implementation note for storing digital sample data when using
+WavPack compression within ZIP files is that all of the bytes of
+the sample data should be compressed. This includes any unused
+bits up to the byte boundary. An example is a 2 byte sample that
+uses only 12 bits for the sample data with 4 unused bits. If only
+12 bits are passed as the sample size to the WavPack routines, the 4
+unused bits will be set to 0 on extraction regardless of their original
+state. To avoid this, the full 16 bits of the sample data size
+should be provided.
+
+PPMd - Method 98
+----------------
+
+PPMd is a data compression algorithm developed by Dmitry Shkarin
+which includes a carryless rangecoder developed by Dmitry Subbotin.
+This algorithm is based on predictive phrase matching on multiple
+order contexts. Information and source code for this algorithm
+can be found on the internet. Consult with the author of this
+algorithm for information on terms or restrictions on use.
+
+Support for PPMd within the ZIP format currently is provided only
+for version I, revision 1 of the algorithm. Storage requirements
+for using this algorithm are as follows:
+
+Parameters needed to control the algorithm are stored in the two
+bytes immediately preceding the compressed data. These bytes are
+used to store the following fields:
+
+Model order - sets the maximum model order, default is 8, possible
+ values are from 2 to 16 inclusive
+
+Sub-allocator size - sets the size of sub-allocator in MB, default is 50,
+ possible values are from 1MB to 256MB inclusive
+
+Model restoration method - sets the method used to restart context
+ model at memory insufficiency, values are:
+
+ 0 - restarts model from scratch - default
+ 1 - cut off model - decreases performance by as much as 2x
+ 2 - freeze context tree - not recommended
+
+An example for packing these fields into the 2 byte storage field is
+illustrated below. These values are stored in Intel low-byte/high-byte
+order.
+
+wPPMd = (Model order - 1) +
+ ((Sub-allocator size - 1) << 4) +
+ (Model restoration method << 12)
+
+
+VII. Traditional PKWARE Encryption
+----------------------------------
+
+The following information discusses the decryption steps
+required to support traditional PKWARE encryption. This
+form of encryption is considered weak by today's standards
+and its use is recommended only for situations with
+low security needs or for compatibility with older .ZIP
+applications.
+
+Decryption
+----------
+
+PKWARE is grateful to Mr. Roger Schlafly for his expert contribution
+towards the development of PKWARE's traditional encryption.
+
+PKZIP encrypts the compressed data stream. Encrypted files must
+be decrypted before they can be extracted.
+
+Each encrypted file has an extra 12 bytes stored at the start of
+the data area defining the encryption header for that file. The
+encryption header is originally set to random values, and then
+itself encrypted, using three, 32-bit keys. The key values are
+initialized using the supplied encryption password. After each byte
+is encrypted, the keys are then updated using pseudo-random number
+generation techniques in combination with the same CRC-32 algorithm
+used in PKZIP and described elsewhere in this document.
+
+The following is the basic steps required to decrypt a file:
+
+1) Initialize the three 32-bit keys with the password.
+2) Read and decrypt the 12-byte encryption header, further
+ initializing the encryption keys.
+3) Read and decrypt the compressed data stream using the
+ encryption keys.
+
+Step 1 - Initializing the encryption keys
+-----------------------------------------
+
+Key(0) <- 305419896
+Key(1) <- 591751049
+Key(2) <- 878082192
+
+loop for i <- 0 to length(password)-1
+ update_keys(password(i))
+end loop
+
+Where update_keys() is defined as:
+
+update_keys(char):
+ Key(0) <- crc32(key(0),char)
+ Key(1) <- Key(1) + (Key(0) & 000000ffH)
+ Key(1) <- Key(1) * 134775813 + 1
+ Key(2) <- crc32(key(2),key(1) >> 24)
+end update_keys
+
+Where crc32(old_crc,char) is a routine that given a CRC value and a
+character, returns an updated CRC value after applying the CRC-32
+algorithm described elsewhere in this document.
+
+Step 2 - Decrypting the encryption header
+-----------------------------------------
+
+The purpose of this step is to further initialize the encryption
+keys, based on random data, to render a plaintext attack on the
+data ineffective.
+
+Read the 12-byte encryption header into Buffer, in locations
+Buffer(0) thru Buffer(11).
+
+loop for i <- 0 to 11
+ C <- buffer(i) ^ decrypt_byte()
+ update_keys(C)
+ buffer(i) <- C
+end loop
+
+Where decrypt_byte() is defined as:
+
+unsigned char decrypt_byte()
+ local unsigned short temp
+ temp <- Key(2) | 2
+ decrypt_byte <- (temp * (temp ^ 1)) >> 8
+end decrypt_byte
+
+After the header is decrypted, the last 1 or 2 bytes in Buffer
+should be the high-order word/byte of the CRC for the file being
+decrypted, stored in Intel low-byte/high-byte order. Versions of
+PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is
+used on versions after 2.0. This can be used to test if the password
+supplied is correct or not.
+
+Step 3 - Decrypting the compressed data stream
+----------------------------------------------
+
+The compressed data stream can be decrypted as follows:
+
+loop until done
+ read a character into C
+ Temp <- C ^ decrypt_byte()
+ update_keys(temp)
+ output Temp
+end loop
+
+
+VIII. Strong Encryption Specification
+-------------------------------------
+
+The Strong Encryption technology defined in this specification is
+covered under a pending patent application. The use or implementation
+in a product of certain technological aspects set forth in the current
+APPNOTE, including those with regard to strong encryption, patching,
+or extended tape operations requires a license from PKWARE. Portions
+of this Strong Encryption technology are available for use at no charge.
+Contact PKWARE for licensing terms and conditions. Refer to section II
+of this APPNOTE (Contacting PKWARE) for information on how to
+contact PKWARE.
+
+Version 5.x of this specification introduced support for strong
+encryption algorithms. These algorithms can be used with either
+a password or an X.509v3 digital certificate to encrypt each file.
+This format specification supports either password or certificate
+based encryption to meet the security needs of today, to enable
+interoperability between users within both PKI and non-PKI
+environments, and to ensure interoperability between different
+computing platforms that are running a ZIP program.
+
+Password based encryption is the most common form of encryption
+people are familiar with. However, inherent weaknesses with
+passwords (e.g. susceptibility to dictionary/brute force attack)
+as well as password management and support issues make certificate
+based encryption a more secure and scalable option. Industry
+efforts and support are defining and moving towards more advanced
+security solutions built around X.509v3 digital certificates and
+Public Key Infrastructures(PKI) because of the greater scalability,
+administrative options, and more robust security over traditional
+password based encryption.
+
+Most standard encryption algorithms are supported with this
+specification. Reference implementations for many of these
+algorithms are available from either commercial or open source
+distributors. Readily available cryptographic toolkits make
+implementation of the encryption features straight-forward.
+This document is not intended to provide a treatise on data
+encryption principles or theory. Its purpose is to document the
+data structures required for implementing interoperable data
+encryption within the .ZIP format. It is strongly recommended that
+you have a good understanding of data encryption before reading
+further.
+
+The algorithms introduced in Version 5.0 of this specification
+include:
+
+ RC2 40 bit, 64 bit, and 128 bit
+ RC4 40 bit, 64 bit, and 128 bit
+ DES
+ 3DES 112 bit and 168 bit
+
+Version 5.1 adds support for the following:
+
+ AES 128 bit, 192 bit, and 256 bit
+
+
+Version 6.1 introduces encryption data changes to support
+interoperability with Smartcard and USB Token certificate storage
+methods which do not support the OAEP strengthening standard.
+
+Version 6.2 introduces support for encrypting metadata by compressing
+and encrypting the central directory data structure to reduce information
+leakage. Information leakage can occur in legacy ZIP applications
+through exposure of information about a file even though that file is
+stored encrypted. The information exposed consists of file
+characteristics stored within the records and fields defined by this
+specification. This includes data such as a files name, its original
+size, timestamp and CRC32 value.
+
+Version 6.3 introduces support for encrypting data using the Blowfish
+and Twofish algorithms. These are symmetric block ciphers developed
+by Bruce Schneier. Blowfish supports using a variable length key from
+32 to 448 bits. Block size is 64 bits. Implementations should use 16
+rounds and the only mode supported within ZIP files is CBC. Twofish
+supports key sizes 128, 192 and 256 bits. Block size is 128 bits.
+Implementations should use 16 rounds and the only mode supported within
+ZIP files is CBC. Information and source code for both Blowfish and
+Twofish algorithms can be found on the internet. Consult with the author
+of these algorithms for information on terms or restrictions on use.
+
+Central Directory Encryption provides greater protection against
+information leakage by encrypting the Central Directory structure and
+by masking key values that are replicated in the unencrypted Local
+Header. ZIP compatible programs that cannot interpret an encrypted
+Central Directory structure cannot rely on the data in the corresponding
+Local Header for decompression information.
+
+Extra Field records that may contain information about a file that should
+not be exposed should not be stored in the Local Header and should only
+be written to the Central Directory where they can be encrypted. This
+design currently does not support streaming. Information in the End of
+Central Directory record, the Zip64 End of Central Directory Locator,
+and the Zip64 End of Central Directory records are not encrypted. Access
+to view data on files within a ZIP file with an encrypted Central Directory
+requires the appropriate password or private key for decryption prior to
+viewing any files, or any information about the files, in the archive.
+
+Older ZIP compatible programs not familiar with the Central Directory
+Encryption feature will no longer be able to recognize the Central
+Directory and may assume the ZIP file is corrupt. Programs that
+attempt streaming access using Local Headers will see invalid
+information for each file. Central Directory Encryption need not be
+used for every ZIP file. Its use is recommended for greater security.
+ZIP files not using Central Directory Encryption should operate as
+in the past.
+
+This strong encryption feature specification is intended to provide for
+scalable, cross-platform encryption needs ranging from simple password
+encryption to authenticated public/private key encryption.
+
+Encryption provides data confidentiality and privacy. It is
+recommended that you combine X.509 digital signing with encryption
+to add authentication and non-repudiation.
+
+
+Single Password Symmetric Encryption Method:
+-------------------------------------------
+
+The Single Password Symmetric Encryption Method using strong
+encryption algorithms operates similarly to the traditional
+PKWARE encryption defined in this format. Additional data
+structures are added to support the processing needs of the
+strong algorithms.
+
+The Strong Encryption data structures are:
+
+1. General Purpose Bits - Bits 0 and 6 of the General Purpose bit
+flag in both local and central header records. Both bits set
+indicates strong encryption. Bit 13, when set indicates the Central
+Directory is encrypted and that selected fields in the Local Header
+are masked to hide their actual value.
+
+
+2. Extra Field 0x0017 in central header only.
+
+ Fields to consider in this record are:
+
+ Format - the data format identifier for this record. The only
+ value allowed at this time is the integer value 2.
+
+ AlgId - integer identifier of the encryption algorithm from the
+ following range
+
+ 0x6601 - DES
+ 0x6602 - RC2 (version needed to extract < 5.2)
+ 0x6603 - 3DES 168
+ 0x6609 - 3DES 112
+ 0x660E - AES 128
+ 0x660F - AES 192
+ 0x6610 - AES 256
+ 0x6702 - RC2 (version needed to extract >= 5.2)
+ 0x6720 - Blowfish
+ 0x6721 - Twofish
+ 0x6801 - RC4
+ 0xFFFF - Unknown algorithm
+
+ Bitlen - Explicit bit length of key
+
+ 32 - 448 bits
+
+ Flags - Processing flags needed for decryption
+
+ 0x0001 - Password is required to decrypt
+ 0x0002 - Certificates only
+ 0x0003 - Password or certificate required to decrypt
+
+ Values > 0x0003 reserved for certificate processing
+
+
+3. Decryption header record preceding compressed file data.
+
+ -Decryption Header:
+
+ Value Size Description
+ ----- ---- -----------
+ IVSize 2 bytes Size of initialization vector (IV)
+ IVData IVSize Initialization vector for this file
+ Size 4 bytes Size of remaining decryption header data
+ Format 2 bytes Format definition for this record
+ AlgID 2 bytes Encryption algorithm identifier
+ Bitlen 2 bytes Bit length of encryption key
+ Flags 2 bytes Processing flags
+ ErdSize 2 bytes Size of Encrypted Random Data
+ ErdData ErdSize Encrypted Random Data
+ Reserved1 4 bytes Reserved certificate processing data
+ Reserved2 (var) Reserved for certificate processing data
+ VSize 2 bytes Size of password validation data
+ VData VSize-4 Password validation data
+ VCRC32 4 bytes Standard ZIP CRC32 of password validation data
+
+ IVData - The size of the IV should match the algorithm block size.
+ The IVData can be completely random data. If the size of
+ the randomly generated data does not match the block size
+ it should be complemented with zero's or truncated as
+ necessary. If IVSize is 0,then IV = CRC32 + Uncompressed
+ File Size (as a 64 bit little-endian, unsigned integer value).
+
+ Format - the data format identifier for this record. The only
+ value allowed at this time is the integer value 3.
+
+ AlgId - integer identifier of the encryption algorithm from the
+ following range
+
+ 0x6601 - DES
+ 0x6602 - RC2 (version needed to extract < 5.2)
+ 0x6603 - 3DES 168
+ 0x6609 - 3DES 112
+ 0x660E - AES 128
+ 0x660F - AES 192
+ 0x6610 - AES 256
+ 0x6702 - RC2 (version needed to extract >= 5.2)
+ 0x6720 - Blowfish
+ 0x6721 - Twofish
+ 0x6801 - RC4
+ 0xFFFF - Unknown algorithm
+
+ Bitlen - Explicit bit length of key
+
+ 32 - 448 bits
+
+ Flags - Processing flags needed for decryption
+
+ 0x0001 - Password is required to decrypt
+ 0x0002 - Certificates only
+ 0x0003 - Password or certificate required to decrypt
+
+ Values > 0x0003 reserved for certificate processing
+
+ ErdData - Encrypted random data is used to store random data that
+ is used to generate a file session key for encrypting
+ each file. SHA1 is used to calculate hash data used to
+ derive keys. File session keys are derived from a master
+ session key generated from the user-supplied password.
+ If the Flags field in the decryption header contains
+ the value 0x4000, then the ErdData field must be
+ decrypted using 3DES. If the value 0x4000 is not set,
+ then the ErdData field must be decrypted using AlgId.
+
+
+ Reserved1 - Reserved for certificate processing, if value is
+ zero, then Reserved2 data is absent. See the explanation
+ under the Certificate Processing Method for details on
+ this data structure.
+
+ Reserved2 - If present, the size of the Reserved2 data structure
+ is located by skipping the first 4 bytes of this field
+ and using the next 2 bytes as the remaining size. See
+ the explanation under the Certificate Processing Method
+ for details on this data structure.
+
+ VSize - This size value will always include the 4 bytes of the
+ VCRC32 data and will be greater than 4 bytes.
+
+ VData - Random data for password validation. This data is VSize
+ in length and VSize must be a multiple of the encryption
+ block size. VCRC32 is a checksum value of VData.
+ VData and VCRC32 are stored encrypted and start the
+ stream of encrypted data for a file.
+
+
+4. Useful Tips
+
+Strong Encryption is always applied to a file after compression. The
+block oriented algorithms all operate in Cypher Block Chaining (CBC)
+mode. The block size used for AES encryption is 16. All other block
+algorithms use a block size of 8. Two ID's are defined for RC2 to
+account for a discrepancy found in the implementation of the RC2
+algorithm in the cryptographic library on Windows XP SP1 and all
+earlier versions of Windows. It is recommended that zero length files
+not be encrypted, however programs should be prepared to extract them
+if they are found within a ZIP file.
+
+A pseudo-code representation of the encryption process is as follows:
+
+Password = GetUserPassword()
+MasterSessionKey = DeriveKey(SHA1(Password))
+RD = CryptographicStrengthRandomData()
+For Each File
+ IV = CryptographicStrengthRandomData()
+ VData = CryptographicStrengthRandomData()
+ VCRC32 = CRC32(VData)
+ FileSessionKey = DeriveKey(SHA1(IV + RD)
+ ErdData = Encrypt(RD,MasterSessionKey,IV)
+ Encrypt(VData + VCRC32 + FileData, FileSessionKey,IV)
+Done
+
+The function names and parameter requirements will depend on
+the choice of the cryptographic toolkit selected. Almost any
+toolkit supporting the reference implementations for each
+algorithm can be used. The RSA BSAFE(r), OpenSSL, and Microsoft
+CryptoAPI libraries are all known to work well.
+
+
+Single Password - Central Directory Encryption:
+-----------------------------------------------
+
+Central Directory Encryption is achieved within the .ZIP format by
+encrypting the Central Directory structure. This encapsulates the metadata
+most often used for processing .ZIP files. Additional metadata is stored for
+redundancy in the Local Header for each file. The process of concealing
+metadata by encrypting the Central Directory does not protect the data within
+the Local Header. To avoid information leakage from the exposed metadata
+in the Local Header, the fields containing information about a file are masked.
+
+Local Header:
+
+Masking replaces the true content of the fields for a file in the Local
+Header with false information. When masked, the Local Header is not
+suitable for streaming access and the options for data recovery of damaged
+archives is reduced. Extra Data fields that may contain confidential
+data should not be stored within the Local Header. The value set into
+the Version needed to extract field should be the correct value needed to
+extract the file without regard to Central Directory Encryption. The fields
+within the Local Header targeted for masking when the Central Directory is
+encrypted are:
+
+ Field Name Mask Value
+ ------------------ ---------------------------
+ compression method 0
+ last mod file time 0
+ last mod file date 0
+ crc-32 0
+ compressed size 0
+ uncompressed size 0
+ file name (variable size) Base 16 value from the
+ range 1 - 0xFFFFFFFFFFFFFFFF
+ represented as a string whose
+ size will be set into the
+ file name length field
+
+The Base 16 value assigned as a masked file name is simply a sequentially
+incremented value for each file starting with 1 for the first file.
+Modifications to a ZIP file may cause different values to be stored for
+each file. For compatibility, the file name field in the Local Header
+should never be left blank. As of Version 6.2 of this specification,
+the Compression Method and Compressed Size fields are not yet masked.
+Fields having a value of 0xFFFF or 0xFFFFFFFF for the ZIP64 format
+should not be masked.
+
+Encrypting the Central Directory:
+
+Encryption of the Central Directory does not include encryption of the
+Central Directory Signature data, the Zip64 End of Central Directory
+record, the Zip64 End of Central Directory Locator, or the End
+of Central Directory record. The ZIP file comment data is never
+encrypted.
+
+Before encrypting the Central Directory, it may optionally be compressed.
+Compression is not required, but for storage efficiency it is assumed
+this structure will be compressed before encrypting. Similarly, this
+specification supports compressing the Central Directory without
+requiring that it also be encrypted. Early implementations of this
+feature will assume the encryption method applied to files matches the
+encryption applied to the Central Directory.
+
+Encryption of the Central Directory is done in a manner similar to
+that of file encryption. The encrypted data is preceded by a
+decryption header. The decryption header is known as the Archive
+Decryption Header. The fields of this record are identical to
+the decryption header preceding each encrypted file. The location
+of the Archive Decryption Header is determined by the value in the
+Start of the Central Directory field in the Zip64 End of Central
+Directory record. When the Central Directory is encrypted, the
+Zip64 End of Central Directory record will always be present.
+
+The layout of the Zip64 End of Central Directory record for all
+versions starting with 6.2 of this specification will follow the
+Version 2 format. The Version 2 format is as follows:
+
+The leading fixed size fields within the Version 1 format for this
+record remain unchanged. The record signature for both Version 1
+and Version 2 will be 0x06064b50. Immediately following the last
+byte of the field known as the Offset of Start of Central
+Directory With Respect to the Starting Disk Number will begin the
+new fields defining Version 2 of this record.
+
+New fields for Version 2:
+
+Note: all fields stored in Intel low-byte/high-byte order.
+
+ Value Size Description
+ ----- ---- -----------
+ Compression Method 2 bytes Method used to compress the
+ Central Directory
+ Compressed Size 8 bytes Size of the compressed data
+ Original Size 8 bytes Original uncompressed size
+ AlgId 2 bytes Encryption algorithm ID
+ BitLen 2 bytes Encryption key length
+ Flags 2 bytes Encryption flags
+ HashID 2 bytes Hash algorithm identifier
+ Hash Length 2 bytes Length of hash data
+ Hash Data (variable) Hash data
+
+The Compression Method accepts the same range of values as the
+corresponding field in the Central Header.
+
+The Compressed Size and Original Size values will not include the
+data of the Central Directory Signature which is compressed or
+encrypted.
+
+The AlgId, BitLen, and Flags fields accept the same range of values
+the corresponding fields within the 0x0017 record.
+
+Hash ID identifies the algorithm used to hash the Central Directory
+data. This data does not have to be hashed, in which case the
+values for both the HashID and Hash Length will be 0. Possible
+values for HashID are:
+
+ Value Algorithm
+ ------ ---------
+ 0x0000 none
+ 0x0001 CRC32
+ 0x8003 MD5
+ 0x8004 SHA1
+ 0x8007 RIPEMD160
+ 0x800C SHA256
+ 0x800D SHA384
+ 0x800E SHA512
+
+When the Central Directory data is signed, the same hash algorithm
+used to hash the Central Directory for signing should be used.
+This is recommended for processing efficiency, however, it is
+permissible for any of the above algorithms to be used independent
+of the signing process.
+
+The Hash Data will contain the hash data for the Central Directory.
+The length of this data will vary depending on the algorithm used.
+
+The Version Needed to Extract should be set to 62.
+
+The value for the Total Number of Entries on the Current Disk will
+be 0. These records will no longer support random access when
+encrypting the Central Directory.
+
+When the Central Directory is compressed and/or encrypted, the
+End of Central Directory record will store the value 0xFFFFFFFF
+as the value for the Total Number of Entries in the Central
+Directory. The value stored in the Total Number of Entries in
+the Central Directory on this Disk field will be 0. The actual
+values will be stored in the equivalent fields of the Zip64
+End of Central Directory record.
+
+Decrypting and decompressing the Central Directory is accomplished
+in the same manner as decrypting and decompressing a file.
+
+Certificate Processing Method:
+-----------------------------
+
+The Certificate Processing Method of for ZIP file encryption
+defines the following additional data fields:
+
+1. Certificate Flag Values
+
+Additional processing flags that can be present in the Flags field of both
+the 0x0017 field of the central directory Extra Field and the Decryption
+header record preceding compressed file data are:
+
+ 0x0007 - reserved for future use
+ 0x000F - reserved for future use
+ 0x0100 - Indicates non-OAEP key wrapping was used. If this
+ this field is set, the version needed to extract must
+ be at least 61. This means OAEP key wrapping is not
+ used when generating a Master Session Key using
+ ErdData.
+ 0x4000 - ErdData must be decrypted using 3DES-168, otherwise use the
+ same algorithm used for encrypting the file contents.
+ 0x8000 - reserved for future use
+
+
+2. CertData - Extra Field 0x0017 record certificate data structure
+
+The data structure used to store certificate data within the section
+of the Extra Field defined by the CertData field of the 0x0017
+record are as shown:
+
+ Value Size Description
+ ----- ---- -----------
+ RCount 4 bytes Number of recipients.
+ HashAlg 2 bytes Hash algorithm identifier
+ HSize 2 bytes Hash size
+ SRList (var) Simple list of recipients hashed public keys
+
+
+ RCount This defines the number intended recipients whose
+ public keys were used for encryption. This identifies
+ the number of elements in the SRList.
+
+ HashAlg This defines the hash algorithm used to calculate
+ the public key hash of each public key used
+ for encryption. This field currently supports
+ only the following value for SHA-1
+
+ 0x8004 - SHA1
+
+ HSize This defines the size of a hashed public key.
+
+ SRList This is a variable length list of the hashed
+ public keys for each intended recipient. Each
+ element in this list is HSize. The total size of
+ SRList is determined using RCount * HSize.
+
+
+3. Reserved1 - Certificate Decryption Header Reserved1 Data:
+
+ Value Size Description
+ ----- ---- -----------
+ RCount 4 bytes Number of recipients.
+
+ RCount This defines the number intended recipients whose
+ public keys were used for encryption. This defines
+ the number of elements in the REList field defined below.
+
+
+4. Reserved2 - Certificate Decryption Header Reserved2 Data Structures:
+
+
+ Value Size Description
+ ----- ---- -----------
+ HashAlg 2 bytes Hash algorithm identifier
+ HSize 2 bytes Hash size
+ REList (var) List of recipient data elements
+
+
+ HashAlg This defines the hash algorithm used to calculate
+ the public key hash of each public key used
+ for encryption. This field currently supports
+ only the following value for SHA-1
+
+ 0x8004 - SHA1
+
+ HSize This defines the size of a hashed public key
+ defined in REHData.
+
+ REList This is a variable length of list of recipient data.
+ Each element in this list consists of a Recipient
+ Element data structure as follows:
+
+
+ Recipient Element (REList) Data Structure:
+
+ Value Size Description
+ ----- ---- -----------
+ RESize 2 bytes Size of REHData + REKData
+ REHData HSize Hash of recipients public key
+ REKData (var) Simple key blob
+
+
+ RESize This defines the size of an individual REList
+ element. This value is the combined size of the
+ REHData field + REKData field. REHData is defined by
+ HSize. REKData is variable and can be calculated
+ for each REList element using RESize and HSize.
+
+ REHData Hashed public key for this recipient.
+
+ REKData Simple Key Blob. The format of this data structure
+ is identical to that defined in the Microsoft
+ CryptoAPI and generated using the CryptExportKey()
+ function. The version of the Simple Key Blob
+ supported at this time is 0x02 as defined by
+ Microsoft.
+
+Certificate Processing - Central Directory Encryption:
+------------------------------------------------------
+
+Central Directory Encryption using Digital Certificates will
+operate in a manner similar to that of Single Password Central
+Directory Encryption. This record will only be present when there
+is data to place into it. Currently, data is placed into this
+record when digital certificates are used for either encrypting
+or signing the files within a ZIP file. When only password
+encryption is used with no certificate encryption or digital
+signing, this record is not currently needed. When present, this
+record will appear before the start of the actual Central Directory
+data structure and will be located immediately after the Archive
+Decryption Header if the Central Directory is encrypted.
+
+The Archive Extra Data record will be used to store the following
+information. Additional data may be added in future versions.
+
+Extra Data Fields:
+
+0x0014 - PKCS#7 Store for X.509 Certificates
+0x0016 - X.509 Certificate ID and Signature for central directory
+0x0019 - PKCS#7 Encryption Recipient Certificate List
+
+The 0x0014 and 0x0016 Extra Data records that otherwise would be
+located in the first record of the Central Directory for digital
+certificate processing. When encrypting or compressing the Central
+Directory, the 0x0014 and 0x0016 records must be located in the
+Archive Extra Data record and they should not remain in the first
+Central Directory record. The Archive Extra Data record will also
+be used to store the 0x0019 data.
+
+When present, the size of the Archive Extra Data record will be
+included in the size of the Central Directory. The data of the
+Archive Extra Data record will also be compressed and encrypted
+along with the Central Directory data structure.
+
+Certificate Processing Differences:
+
+The Certificate Processing Method of encryption differs from the
+Single Password Symmetric Encryption Method as follows. Instead
+of using a user-defined password to generate a master session key,
+cryptographically random data is used. The key material is then
+wrapped using standard key-wrapping techniques. This key material
+is wrapped using the public key of each recipient that will need
+to decrypt the file using their corresponding private key.
+
+This specification currently assumes digital certificates will follow
+the X.509 V3 format for 1024 bit and higher RSA format digital
+certificates. Implementation of this Certificate Processing Method
+requires supporting logic for key access and management. This logic
+is outside the scope of this specification.
+
+OAEP Processing with Certificate-based Encryption:
+
+OAEP stands for Optimal Asymmetric Encryption Padding. It is a
+strengthening technique used for small encoded items such as decryption
+keys. This is commonly applied in cryptographic key-wrapping techniques
+and is supported by PKCS #1. Versions 5.0 and 6.0 of this specification
+were designed to support OAEP key-wrapping for certificate-based
+decryption keys for additional security.
+
+Support for private keys stored on Smartcards or Tokens introduced
+a conflict with this OAEP logic. Most card and token products do
+not support the additional strengthening applied to OAEP key-wrapped
+data. In order to resolve this conflict, versions 6.1 and above of this
+specification will no longer support OAEP when encrypting using
+digital certificates.
+
+Versions of PKZIP available during initial development of the
+certificate processing method set a value of 61 into the
+version needed to extract field for a file. This indicates that
+non-OAEP key wrapping is used. This affects certificate encryption
+only, and password encryption functions should not be affected by
+this value. This means values of 61 may be found on files encrypted
+with certificates only, or on files encrypted with both password
+encryption and certificate encryption. Files encrypted with both
+methods can safely be decrypted using the password methods documented.
+
+IX. Change Process
+------------------
+
+In order for the .ZIP file format to remain a viable definition, this
+specification should be considered as open for periodic review and
+revision. Although this format was originally designed with a
+certain level of extensibility, not all changes in technology
+(present or future) were or will be necessarily considered in its
+design. If your application requires new definitions to the
+extensible sections in this format, or if you would like to
+submit new data structures, please forward your request to
+zipformat@pkware.com. All submissions will be reviewed by the
+ZIP File Specification Committee for possible inclusion into
+future versions of this specification. Periodic revisions
+to this specification will be published to ensure interoperability.
+We encourage comments and feedback that may help improve clarity
+or content.
+
+X. Incorporating PKWARE Proprietary Technology into Your Product
+----------------------------------------------------------------
+
+PKWARE is committed to the interoperability and advancement of the
+.ZIP format. PKWARE offers a free license for certain technological
+aspects described above under certain restrictions and conditions.
+However, the use or implementation in a product of certain technological
+aspects set forth in the current APPNOTE, including those with regard to
+strong encryption, patching, or extended tape operations requires a
+license from PKWARE. Please contact PKWARE with regard to acquiring
+a license.
+
+XI. Acknowledgements
+---------------------
+
+In addition to the above mentioned contributors to PKZIP and PKUNZIP,
+I would like to extend special thanks to Robert Mahoney for suggesting
+the extension .ZIP for this software.
+
+XII. References
+---------------
+
+ Fiala, Edward R., and Greene, Daniel H., "Data compression with
+ finite windows", Communications of the ACM, Volume 32, Number 4,
+ April 1989, pages 490-505.
+
+ Held, Gilbert, "Data Compression, Techniques and Applications,
+ Hardware and Software Considerations", John Wiley & Sons, 1987.
+
+ Huffman, D.A., "A method for the construction of minimum-redundancy
+ codes", Proceedings of the IRE, Volume 40, Number 9, September 1952,
+ pages 1098-1101.
+
+ Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14,
+ Number 10, October 1989, pages 29-37.
+
+ Nelson, Mark, "The Data Compression Book", M&T Books, 1991.
+
+ Storer, James A., "Data Compression, Methods and Theory",
+ Computer Science Press, 1988
+
+ Welch, Terry, "A Technique for High-Performance Data Compression",
+ IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19.
+
+ Ziv, J. and Lempel, A., "A universal algorithm for sequential data
+ compression", Communications of the ACM, Volume 30, Number 6,
+ June 1987, pages 520-540.
+
+ Ziv, J. and Lempel, A., "Compression of individual sequences via
+ variable-rate coding", IEEE Transactions on Information Theory,
+ Volume 24, Number 5, September 1978, pages 530-536.
+
+
+APPENDIX A - AS/400 Extra Field (0x0065) Attribute Definitions
+--------------------------------------------------------------
+
+Field Definition Structure:
+
+ a. field length including length 2 bytes
+ b. field code 2 bytes
+ c. data x bytes
+
+Field Code Description
+ 4001 Source type i.e. CLP etc
+ 4002 The text description of the library
+ 4003 The text description of the file
+ 4004 The text description of the member
+ 4005 x'F0' or 0 is PF-DTA, x'F1' or 1 is PF_SRC
+ 4007 Database Type Code 1 byte
+ 4008 Database file and fields definition
+ 4009 GZIP file type 2 bytes
+ 400B IFS code page 2 bytes
+ 400C IFS Creation Time 4 bytes
+ 400D IFS Access Time 4 bytes
+ 400E IFS Modification time 4 bytes
+ 005C Length of the records in the file 2 bytes
+ 0068 GZIP two words 8 bytes
+
+APPENDIX B - z/OS Extra Field (0x0065) Attribute Definitions
+------------------------------------------------------------
+
+Field Definition Structure:
+
+ a. field length including length 2 bytes
+ b. field code 2 bytes
+ c. data x bytes
+
+Field Code Description
+ 0001 File Type 2 bytes
+ 0002 NonVSAM Record Format 1 byte
+ 0003 Reserved
+ 0004 NonVSAM Block Size 2 bytes Big Endian
+ 0005 Primary Space Allocation 3 bytes Big Endian
+ 0006 Secondary Space Allocation 3 bytes Big Endian
+ 0007 Space Allocation Type1 byte flag
+ 0008 Modification Date Retired with PKZIP 5.0 +
+ 0009 Expiration Date Retired with PKZIP 5.0 +
+ 000A PDS Directory Block Allocation 3 bytes Big Endian binary value
+ 000B NonVSAM Volume List variable
+ 000C UNIT Reference Retired with PKZIP 5.0 +
+ 000D DF/SMS Management Class 8 bytes EBCDIC Text Value
+ 000E DF/SMS Storage Class 8 bytes EBCDIC Text Value
+ 000F DF/SMS Data Class 8 bytes EBCDIC Text Value
+ 0010 PDS/PDSE Member Info. 30 bytes
+ 0011 VSAM sub-filetype 2 bytes
+ 0012 VSAM LRECL 13 bytes EBCDIC "(num_avg num_max)"
+ 0013 VSAM Cluster Name Retired with PKZIP 5.0 +
+ 0014 VSAM KSDS Key Information 13 bytes EBCDIC "(num_length num_position)"
+ 0015 VSAM Average LRECL 5 bytes EBCDIC num_value padded with blanks
+ 0016 VSAM Maximum LRECL 5 bytes EBCDIC num_value padded with blanks
+ 0017 VSAM KSDS Key Length 5 bytes EBCDIC num_value padded with blanks
+ 0018 VSAM KSDS Key Position 5 bytes EBCDIC num_value padded with blanks
+ 0019 VSAM Data Name 1-44 bytes EBCDIC text string
+ 001A VSAM KSDS Index Name 1-44 bytes EBCDIC text string
+ 001B VSAM Catalog Name 1-44 bytes EBCDIC text string
+ 001C VSAM Data Space Type 9 bytes EBCDIC text string
+ 001D VSAM Data Space Primary 9 bytes EBCDIC num_value left-justified
+ 001E VSAM Data Space Secondary 9 bytes EBCDIC num_value left-justified
+ 001F VSAM Data Volume List variable EBCDIC text list of 6-character Volume IDs
+ 0020 VSAM Data Buffer Space 8 bytes EBCDIC num_value left-justified
+ 0021 VSAM Data CISIZE 5 bytes EBCDIC num_value left-justified
+ 0022 VSAM Erase Flag 1 byte flag
+ 0023 VSAM Free CI % 3 bytes EBCDIC num_value left-justified
+ 0024 VSAM Free CA % 3 bytes EBCDIC num_value left-justified
+ 0025 VSAM Index Volume List variable EBCDIC text list of 6-character Volume IDs
+ 0026 VSAM Ordered Flag 1 byte flag
+ 0027 VSAM REUSE Flag 1 byte flag
+ 0028 VSAM SPANNED Flag 1 byte flag
+ 0029 VSAM Recovery Flag 1 byte flag
+ 002A VSAM WRITECHK Flag 1 byte flag
+ 002B VSAM Cluster/Data SHROPTS 3 bytes EBCDIC "n,y"
+ 002C VSAM Index SHROPTS 3 bytes EBCDIC "n,y"
+ 002D VSAM Index Space Type 9 bytes EBCDIC text string
+ 002E VSAM Index Space Primary 9 bytes EBCDIC num_value left-justified
+ 002F VSAM Index Space Secondary 9 bytes EBCDIC num_value left-justified
+ 0030 VSAM Index CISIZE 5 bytes EBCDIC num_value left-justified
+ 0031 VSAM Index IMBED 1 byte flag
+ 0032 VSAM Index Ordered Flag 1 byte flag
+ 0033 VSAM REPLICATE Flag 1 byte flag
+ 0034 VSAM Index REUSE Flag 1 byte flag
+ 0035 VSAM Index WRITECHK Flag 1 byte flag Retired with PKZIP 5.0 +
+ 0036 VSAM Owner 8 bytes EBCDIC text string
+ 0037 VSAM Index Owner 8 bytes EBCDIC text string
+ 0038 Reserved
+ 0039 Reserved
+ 003A Reserved
+ 003B Reserved
+ 003C Reserved
+ 003D Reserved
+ 003E Reserved
+ 003F Reserved
+ 0040 Reserved
+ 0041 Reserved
+ 0042 Reserved
+ 0043 Reserved
+ 0044 Reserved
+ 0045 Reserved
+ 0046 Reserved
+ 0047 Reserved
+ 0048 Reserved
+ 0049 Reserved
+ 004A Reserved
+ 004B Reserved
+ 004C Reserved
+ 004D Reserved
+ 004E Reserved
+ 004F Reserved
+ 0050 Reserved
+ 0051 Reserved
+ 0052 Reserved
+ 0053 Reserved
+ 0054 Reserved
+ 0055 Reserved
+ 0056 Reserved
+ 0057 Reserved
+ 0058 PDS/PDSE Member TTR Info. 6 bytes Big Endian
+ 0059 PDS 1st LMOD Text TTR 3 bytes Big Endian
+ 005A PDS LMOD EP Rec # 4 bytes Big Endian
+ 005B Reserved
+ 005C Max Length of records 2 bytes Big Endian
+ 005D PDSE Flag 1 byte flag
+ 005E Reserved
+ 005F Reserved
+ 0060 Reserved
+ 0061 Reserved
+ 0062 Reserved
+ 0063 Reserved
+ 0064 Reserved
+ 0065 Last Date Referenced 4 bytes Packed Hex "yyyymmdd"
+ 0066 Date Created 4 bytes Packed Hex "yyyymmdd"
+ 0068 GZIP two words 8 bytes
+ 0071 Extended NOTE Location 12 bytes Big Endian
+ 0072 Archive device UNIT 6 bytes EBCDIC
+ 0073 Archive 1st Volume 6 bytes EBCDIC
+ 0074 Archive 1st VOL File Seq# 2 bytes Binary
+
+APPENDIX C - Zip64 Extensible Data Sector Mappings (EFS)
+--------------------------------------------------------
+
+ -Z390 Extra Field:
+
+ The following is the general layout of the attributes for the
+ ZIP 64 "extra" block for extended tape operations. Portions of
+ this extended tape processing technology is covered under a
+ pending patent application. The use or implementation in a
+ product of certain technological aspects set forth in the
+ current APPNOTE, including those with regard to strong encryption,
+ patching or extended tape operations, requires a license from
+ PKWARE. Please contact PKWARE with regard to acquiring a license.
+
+
+ Note: some fields stored in Big Endian format. All text is
+ in EBCDIC format unless otherwise specified.
+
+ Value Size Description
+ ----- ---- -----------
+ (Z390) 0x0065 2 bytes Tag for this "extra" block type
+ Size 4 bytes Size for the following data block
+ Tag 4 bytes EBCDIC "Z390"
+ Length71 2 bytes Big Endian
+ Subcode71 2 bytes Enote type code
+ FMEPos 1 byte
+ Length72 2 bytes Big Endian
+ Subcode72 2 bytes Unit type code
+ Unit 1 byte Unit
+ Length73 2 bytes Big Endian
+ Subcode73 2 bytes Volume1 type code
+ FirstVol 1 byte Volume
+ Length74 2 bytes Big Endian
+ Subcode74 2 bytes FirstVol file sequence
+ FileSeq 2 bytes Sequence
+
+APPENDIX D - Language Encoding (EFS)
+------------------------------------
+
+The ZIP format has historically supported only the original IBM PC character
+encoding set, commonly referred to as IBM Code Page 437. This limits storing
+file name characters to only those within the original MS-DOS range of values
+and does not properly support file names in other character encodings, or
+languages. To address this limitation, this specification will support the
+following change.
+
+If general purpose bit 11 is unset, the file name and comment should conform
+to the original ZIP character encoding. If general purpose bit 11 is set, the
+filename and comment must support The Unicode Standard, Version 4.1.0 or
+greater using the character encoding form defined by the UTF-8 storage
+specification. The Unicode Standard is published by the The Unicode
+Consortium (www.unicode.org). UTF-8 encoded data stored within ZIP files
+is expected to not include a byte order mark (BOM).
+
+Applications may choose to supplement this file name storage through the use
+of the 0x0008 Extra Field. Storage for this optional field is currently
+undefined, however it will be used to allow storing extended information
+on source or target encoding that may further assist applications with file
+name, or file content encoding tasks. Please contact PKWARE with any
+requirements on how this field should be used.
+
+The 0x0008 Extra Field storage may be used with either setting for general
+purpose bit 11. Examples of the intended usage for this field is to store
+whether "modified-UTF-8" (JAVA) is used, or UTF-8-MAC. Similarly, other
+commonly used character encoding (code page) designations can be indicated
+through this field. Formalized values for use of the 0x0008 record remain
+undefined at this time. The definition for the layout of the 0x0008 field
+will be published when available. Use of the 0x0008 Extra Field provides
+for storing data within a ZIP file in an encoding other than IBM Code
+Page 437 or UTF-8.
+
+General purpose bit 11 will not imply any encoding of file content or
+password. Values defining character encoding for file content or
+password must be stored within the 0x0008 Extended Language Encoding
+Extra Field.
+
+Ed Gordon of the Info-ZIP group has defined a pair of "extra field" records
+that can be used to store UTF-8 file name and file comment fields. These
+records can be used for cases when the general purpose bit 11 method
+for storing UTF-8 data in the standard file name and comment fields is
+not desirable. A common case for this alternate method is if backward
+compatibility with older programs is required.
+
+Definitions for the record structure of these fields are included above
+in the section on 3rd party mappings for "extra field" records. These
+records are identified by Header ID's 0x6375 (Info-ZIP Unicode Comment
+Extra Field) and 0x7075 (Info-ZIP Unicode Path Extra Field).
+
+The choice of which storage method to use when writing a ZIP file is left
+to the implementation. Developers should expect that a ZIP file may
+contain either method and should provide support for reading data in
+either format. Use of general purpose bit 11 reduces storage requirements
+for file name data by not requiring additional "extra field" data for
+each file, but can result in older ZIP programs not being able to extract
+files. Use of the 0x6375 and 0x7075 records will result in a ZIP file
+that should always be readable by older ZIP programs, but requires more
+storage per file to write file name and/or file comment fields.
+
+
+
+
diff --git a/afb-client/bower_components/jszip/docs/ZIP spec.txt b/afb-client/bower_components/jszip/docs/ZIP spec.txt
new file mode 100644
index 0000000..bb1485e
--- /dev/null
+++ b/afb-client/bower_components/jszip/docs/ZIP spec.txt
@@ -0,0 +1,66 @@
+Here are the notes I made while working through the ZIP file specification.
+
+For each file:
+
+ local file header signature 4 bytes (0x04034b50)
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+
+|sig |v |g |c |t |d |crc |csz |usz |n |x |
+ PK.. ## 00 00 ?? ?? xxxx ???? ???? ?? 00
+<file name><file data>
+
+Central directory:
+
+ central file header signature 4 bytes (0x02014b50)
+ version made by 2 bytes
+ version needed to extract 2 bytes *
+ general purpose bit flag 2 bytes *
+ compression method 2 bytes *
+ last mod file time 2 bytes *
+ last mod file date 2 bytes *
+ crc-32 4 bytes *
+ compressed size 4 bytes *
+ uncompressed size 4 bytes *
+ file name length 2 bytes *
+ extra field length 2 bytes *
+ file comment length 2 bytes
+ disk number start 2 bytes
+ internal file attributes 2 bytes
+ external file attributes 4 bytes
+ relative offset of local header 4 bytes
+
+ file name (variable size)
+ extra field (variable size)
+ file comment (variable size)
+
+|sig |vm|vx|g |c |d |t |crc |csz |usz |n |x |cm|dn|ia|xa |roff|
+ PK.. ## ## 00 00 ?? ?? xxxx ???? ???? ?? 00 00 00 00 xxxx ????
+
+End of central directory:
+
+ end of central dir signature 4 bytes (0x06054b50)
+ number of this disk 2 bytes
+ number of the disk with the
+ start of the central directory 2 bytes
+ total number of entries in the
+ central directory on this disk 2 bytes
+ total number of entries in
+ the central directory 2 bytes
+ size of the central directory 4 bytes
+ offset of start of central
+ directory with respect to
+ the starting disk number 4 bytes
+ .ZIP file comment length 2 bytes
+ .ZIP file comment (variable size)
+
+|sig |n1|n2|e |ne|size|off |cm|
+ PK.. 00 00 ?? ?? ???? ???? 00
diff --git a/afb-client/bower_components/jszip/docs/references.txt b/afb-client/bower_components/jszip/docs/references.txt
new file mode 100644
index 0000000..9aab182
--- /dev/null
+++ b/afb-client/bower_components/jszip/docs/references.txt
@@ -0,0 +1,18 @@
+Zip format
+----------
+http://www.pkware.com/support/zip-application-note
+http://www.xxcopy.com/xxcopy06.htm
+
+Data URL
+--------
+https://developer.mozilla.org/en/The_data_URL_scheme
+http://msdn.microsoft.com/en-us/library/cc848897(VS.85).aspx
+http://www.phpied.com/mhtml-when-you-need-data-uris-in-ie7-and-under/
+
+http://www.motobit.com/util/base64-decoder-encoder.asp
+
+Saving files
+------------
+http://msdn.microsoft.com/en-us/library/ms536676(VS.85).aspx
+http://msdn.microsoft.com/en-us/library/ms536419(VS.85).aspx
+http://msdn.microsoft.com/en-us/library/ms537418(VS.85).aspx
diff --git a/afb-client/bower_components/jszip/documentation/_layouts/default.html b/afb-client/bower_components/jszip/documentation/_layouts/default.html
new file mode 100644
index 0000000..d1694cf
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/_layouts/default.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description" content="Create .zip files using Javascript. Provides a simple API to place any content generated by Javascript into a .zip file for your users." />
+ <title>{{page.title}}</title>
+
+ <!-- Latest compiled and minified CSS -->
+ <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
+
+ <!-- Optional theme -->
+ <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
+
+ <!-- Latest compiled and minified JavaScript -->
+ <!-- <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> -->
+
+ <link rel="stylesheet" href="{{site.baseurl}}/documentation/css/pygments.css">
+ <link rel="stylesheet" href="{{site.baseurl}}/documentation/css/main.css">
+
+ <script type="text/javascript" src="{{site.baseurl}}/dist/jszip.js"></script>
+
+ <script type="text/javascript" src="//stuk.github.io/jszip-utils/dist/jszip-utils.js"></script>
+ <!--
+ Mandatory in IE 6, 7, 8 and 9.
+ -->
+ <!--[if IE]>
+ <script type="text/javascript" src="//stuk.github.io/jszip-utils/dist/jszip-utils-ie.js"></script>
+ <![endif]-->
+
+ <!--
+ Any version of jQuery will do (it's just to write some examples), this one
+ happens to be available in our tests.
+ -->
+ <script type="text/javascript" src="{{site.baseurl}}/test/jquery-1.8.3.min.js"></script>
+
+ <script type="text/javascript" src="{{site.baseurl}}/vendor/FileSaver.js"></script>
+ </head>
+ <body>
+ <div class="container">
+ <div class="navbar navbar-default" role="navigation">
+ <div class="container-fluid">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="{{site.baseurl}}/"><strong>JS</strong>Zip</a>
+ </div>
+ <ul class="nav navbar-nav">
+ <li {% if page.section == "api" %}class="active"{% endif %}>
+ <a href="{{site.baseurl}}/documentation/api_jszip.html">API</a>
+ </li>
+ <li {% if page.section == "example" %}class="active"{% endif %}>
+ <a href="{{site.baseurl}}/documentation/examples.html">How to / examples</a>
+ </li>
+ <li {% if page.section == "limitations" %}class="active"{% endif %}>
+ <a href="{{site.baseurl}}/documentation/limitations.html">Performances / limitations</a>
+ </li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li>
+ <a href="https://github.com/Stuk/jszip">JSZip on Github</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ {% if page.section and page.fullpage != true %}
+ <div class="row">
+ <nav class="col-md-3">
+ {% case page.section %}
+ {% when "main" %}
+ <h4>JSZip users :</h4>
+ <ul class="nav">
+ <li><a href="{{site.baseurl}}/">Installation</a></li>
+ <li><a href="{{site.baseurl}}/documentation/faq.html">FAQ</a></li>
+ <li><a href="{{site.baseurl}}/CHANGES.html">Changelog</a></li>
+ <li><a href="{{site.baseurl}}/documentation/upgrade_guide.html">Upgrade guide</a></li>
+ <li><a href="https://github.com/Stuk/jszip/issues">Bug tracker</a></li>
+ </ul>
+ <h4>JSZip developers :</h4>
+ <ul class="nav">
+ <li><a href="{{site.baseurl}}/documentation/contributing.html">How to contribute</a></li>
+ <li><a href="https://github.com/Stuk/jszip/graphs/contributors">Contributors</a></li>
+ </ul>
+ {% when "api" %}
+ <ul class="nav">
+ <li><a href="{{site.baseurl}}/documentation/api_jszip.html">JSZip</a>
+ <ul>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/constructor.html">new JSZip() or JSZip()</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/constructor_load.html">new JSZip(data [,options])</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/file_name.html">JSZip#file(name)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/file_regex.html">JSZip#file(regex)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/file_data.html">JSZip#file(name, data [,options])</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/folder_data.html">JSZip#folder(name)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/folder_regex.html">JSZip#folder(regex)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/filter.html">JSZip#filter(predicate)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/remove.html">JSZip#remove(name)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/generate.html">JSZip#generate(options)</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/load.html">JSZip#load(data [, options])</a></li>
+ <li><a href="{{site.baseurl}}/documentation/api_jszip/support.html">JSZip.support</a></li>
+ </ul>
+ </li>
+ <li><a href="{{site.baseurl}}/documentation/api_zipobject.html">ZipObject</a></li>
+ </ul>
+ {% when "example" %}
+ <h4>How to ...</h4>
+ <ul class="nav">
+ <li><a href="{{site.baseurl}}/documentation/examples.html">Use JSZip</a></li>
+ <li><a href="{{site.baseurl}}/documentation/howto/read_zip.html">Read a file</a></li>
+ <li><a href="{{site.baseurl}}/documentation/howto/write_zip.html">Write a file</a></li>
+ </ul>
+ <h4>Examples</h4>
+ <ul class="nav">
+ <li><a href="{{site.baseurl}}/documentation/examples/read-local-file-api.html">Read local file</a></li>
+ <li><a href="{{site.baseurl}}/documentation/examples/get-binary-files-ajax.html">Read remote file</a></li>
+ <li><a href="{{site.baseurl}}/documentation/examples/download-zip-file.html">Give the user its zip file</a></li>
+ <li><a href="{{site.baseurl}}/documentation/examples/downloader.html">Mini app : downloader</a></li>
+ </ul>
+ {% endcase %}
+ <!-- <ul class="nav"> -->
+ <!-- <li><a href="{{site.baseurl}}/documentation/faq.html">FAQ</a></li> -->
+ <!-- </ul> -->
+ <!-- <li><a href="{{site.baseurl}}/">installation</a></li> -->
+ </nav>
+ {% endif %}
+ <div class="{% if page.section and page.fullpage != true%}col-md-9{% else %}col-md-12{% endif %}">
+ <h1>{{page.title}}</h1>
+ <!-- ===================== -->
+ <!-- === C O N T E N T === -->
+ <!-- ===================== -->
+
+ {{content}}
+
+ <!-- ===================== -->
+ <!-- == / C O N T E N T == -->
+ <!-- ===================== -->
+ </div>
+ </div>
+ </div>
+ <script>
+ // FIXME find how to do that cleanly
+ (function(){
+ var tables = document.getElementsByTagName("table");
+ for(var i = 0; i < tables.length; i++) {
+ tables[i].className += " table table-condensed table-striped table-bordered ";
+ }
+ })();
+ </script>
+ <script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-52085706-1', 'stuk.github.io');
+ ga('send', 'pageview');
+
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip.md b/afb-client/bower_components/jszip/documentation/api_jszip.md
new file mode 100644
index 0000000..1eb759c
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip.md
@@ -0,0 +1,15 @@
+---
+title: "JSZip API"
+layout: default
+section: api
+---
+
+An instance of JSZip represents a set of files. You can add them, remove them,
+modify them. You can also import an existing zip file or generate one.
+
+### Attributes
+
+attribute name | type | description
+---------------------|-------------|-------------
+`files` | object | the [ZipObject]({{site.baseurl}}/documentation/api_zipobject.html)s inside the zip with the name as key. See [file(name)]({{site.baseurl}}/documentation/api_jszip/file_name.html).
+`comment` | string | the comment of the zip file.
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/constructor.md b/afb-client/bower_components/jszip/documentation/api_jszip/constructor.md
new file mode 100644
index 0000000..5564737
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/constructor.md
@@ -0,0 +1,23 @@
+---
+title: "new JSZip() or JSZip()"
+layout: default
+section: api
+---
+
+__Description__ : Create a new JSZip instance.
+
+__Arguments__ : None
+
+__Returns__ : A new JSZip.
+
+__Throws__ : Nothing.
+
+<!-- __Complexity__ : Object creation in **O(1)**. -->
+
+__Example__
+
+```js
+var zip = new JSZip();
+// same as
+var zip = JSZip();
+```
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/constructor_load.md b/afb-client/bower_components/jszip/documentation/api_jszip/constructor_load.md
new file mode 100644
index 0000000..4e6f7ed
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/constructor_load.md
@@ -0,0 +1,22 @@
+---
+title: "new JSZip(data [,options]) or JSZip(data [,options])"
+layout: default
+section: api
+---
+
+This is a shortcut for
+
+```js
+var zip = new JSZip();
+zip.load(data, options);
+```
+
+Please see the documentation of [load]({{site.baseurl}}/documentation/api_jszip/load.html).
+
+__Example__
+
+```js
+var zip = new JSZip(data, options);
+// same as
+var zip = JSZip(data, options);
+```
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/file_data.md b/afb-client/bower_components/jszip/documentation/api_jszip/file_data.md
new file mode 100644
index 0000000..69adecb
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/file_data.md
@@ -0,0 +1,90 @@
+---
+title: "file(name, data [,options])"
+layout: default
+section: api
+---
+
+__Description__ : Add (or update) a file to the zip file.
+
+__Arguments__
+
+name | type | description
+--------------------|---------|------------
+name | string | the name of the file. You can specify folders in the name : the folder separator is a forward slash ("/").
+data | String/ArrayBuffer/Uint8Array/Buffer | the content of the file.
+options | object | the options.
+
+Content of `options` :
+
+name | type | default | description
+------------|---------|---------|------------
+base64 | boolean | `false` | set to `true` if the data is base64 encoded. For example image data from a `<canvas>` element. Plain text and HTML do not need this option.
+binary | boolean | `false` | set to `true` if the data should be treated as raw content, `false` if this is a text. If base64 is used, this defaults to `true`, if the data is not a string, this will be set to `true`.
+date | date | the current date | the last modification date.
+compression | string | null | If set, specifies compression method to use for this specific file. If not, the default file compression will be used, see [generate(options)]({{site.baseurl}}/documentation/api_jszip/generate.html).
+compressionOptions | object | `null` | the options to use when compressing the file, see [generate(options)]({{site.baseurl}}/documentation/api_jszip/generate.html).
+comment | string | null | The comment for this file.
+optimizedBinaryString | boolean | `false` | Set to true if (and only if) the input is a "binary string" and has already been prepared with a 0xFF mask.
+createFolders | boolean | `false` | Set to true if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file.
+unixPermissions | 16 bits number | null | The UNIX permissions of the file, if any.
+dosPermissions | 6 bits number | null | The DOS permissions of the file, if any.
+dir | boolean | false | Set to true if this is a directory and content should be ignored.
+
+You shouldn't update the data given to this method : it is kept as it so any
+update will impact the stored data.
+
+__For the permissions__ :
+
+The field `unixPermissions` also accepts a string representing the octal value :
+"644", "755", etc. On nodejs you can use the `mode` attribute of
+[nodejs' fs.Stats](http://nodejs.org/api/fs.html#fs_class_fs_stats).
+
+See also [the platform option of generate()]({{site.baseurl}}/documentation/api_jszip/generate.html).
+
+__About `dir`__ :
+
+If `dir` is true or if a permission says it's a folder, this entry be flagged
+as a folder and the content will be ignored.
+
+__Returns__ : The current JSZip object, for chaining.
+
+__Throws__ : An exception if the data is not in a supported format.
+
+<!--
+__Complexity__ : **O(1)** for anything but binary strings.
+For binary strings (`data` is a string and `binary` = true), if
+`optimizedBinaryString` is not set, the 0xFF mask will be applied giving a
+complexity in **O(n)** where n is the size of the added data.
+-->
+
+__Example__
+
+```js
+zip.file("Hello.txt", "Hello World\n");
+
+// base64
+zip.file("smile.gif", "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", {base64: true});
+// from an ajax call with xhr.responseType = 'arraybuffer'
+zip.file("smile.gif", arraybufferFromXhr);
+// or on nodejs
+zip.file("smile.gif", fs.readFileSync("smile.gif"));
+
+zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
+zip.file("folder/file.txt", "file in folder");
+
+zip.file("animals.txt", "dog,platypus\n").file("people.txt", "james,sebastian\n");
+
+// result : Hello.txt, smile.gif, Xmas.txt, animals.txt, people.txt,
+// folder/, folder/file.txt
+// In the above case, the "folder" folder will not have a 'D'irectory attribute or Method property. The
+// folder only exists as part of the path to "file.txt".
+
+zip.file("folder/file.txt", "file in folder", {createFolders: true});
+// In this case, the "folder" folder WILL have a 'D'irectory attribute and a Method property of "store".
+// It will exist whether or not "file.txt" is present.
+
+zip.file("script.sh", "echo 'hello world'", {
+ unixPermissions : "755"
+});
+// when generated with platform:UNIX, the script.sh file will be executable
+```
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/file_name.md b/afb-client/bower_components/jszip/documentation/api_jszip/file_name.md
new file mode 100644
index 0000000..88b6d43
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/file_name.md
@@ -0,0 +1,46 @@
+---
+title: "file(name)"
+layout: default
+section: api
+---
+
+__Description__ : Get a file with the specified name. You can specify folders
+in the name : the folder separator is a forward slash ("/").
+
+__Arguments__
+
+name | type | description
+-----|--------|-------------
+name | string | the name of the file.
+
+__Returns__ : An instance of [ZipObject]({{site.baseurl}}/documentation/api_zipobject.html) representing
+the file if any, `null` otherwise.
+
+__Throws__ : Nothing.
+
+<!-- __Complexity__ : This is a simple lookup in **O(1)**. -->
+
+__Examples__
+
+```js
+var zip = new JSZip();
+zip.file("file.txt", "content");
+
+zip.file("file.txt").name // "file.txt"
+zip.file("file.txt").asText() // "content"
+zip.file("file.txt").options.dir // false
+
+// utf8 example
+var zip = new JSZip(zipFromAjaxWithUTF8);
+zip.file("amount.txt").asText() // "€15"
+zip.file("amount.txt").asArrayBuffer() // an ArrayBuffer containing €15 encoded as utf8
+zip.file("amount.txt").asUint8Array() // an Uint8Array containing €15 encoded as utf8
+
+// with folders
+zip.folder("sub").file("file.txt", "content");
+zip.file("sub/file.txt"); // the file
+// or
+zip.folder("sub").file("file.txt") // the file
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/file_regex.md b/afb-client/bower_components/jszip/documentation/api_jszip/file_regex.md
new file mode 100644
index 0000000..5dd2416
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/file_regex.md
@@ -0,0 +1,49 @@
+---
+title: "file(regex)"
+layout: default
+section: api
+---
+
+__Description__ : Search a file in the current folder and subfolders with a
+[regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
+The regex is tested against the relative filename.
+
+__Arguments__
+
+name | type | description
+------|--------|------------
+regex | RegExp | the regex to use.
+
+__Returns__ : An array of matching files (an empty array if none matched). Each
+maching file is an instance of [ZipObject]({{site.baseurl}}/documentation/api_zipobject.html).
+
+__Throws__ : Nothing.
+
+<!--
+__Complexity__ : **O(k)** where k is the number of entries in the current JSZip
+instance.
+-->
+
+__Example__
+
+```js
+var zip = new JSZip();
+zip.file("file1.txt", "content");
+zip.file("file2.txt", "content");
+
+zip.file(/file/); // array of size 2
+
+// example with a relative path :
+var folder = zip.folder("sub");
+folder
+ .file("file3.txt", "content") // relative path from folder : file3.txt
+ .file("file4.txt", "content"); // relative path from folder : file4.txt
+
+folder.file(/file/); // array of size 2
+folder.file(/^file/); // array of size 2, the relative paths start with file
+
+// arrays contain objects in the form:
+// {name: "file2.txt", dir: false, asText : function () {...}, ...}
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/filter.md b/afb-client/bower_components/jszip/documentation/api_jszip/filter.md
new file mode 100644
index 0000000..3afc435
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/filter.md
@@ -0,0 +1,43 @@
+---
+title: "filter(predicate)"
+layout: default
+section: api
+---
+
+__Description__ : Filter nested files/folders with the specified function.
+
+__Arguments__
+
+name | type | description
+----------|----------|------------
+predicate | function | the predicate to use.
+
+The predicate has the following signature : `function (relativePath, file) {...}` :
+
+name | type | description
+-------------|-----------|------------
+relativePath | string | the filename and its path, reliatively to the current folder.
+file | ZipObject | the file being tested. See [ZipObject]({{site.baseurl}}/documentation/api_zipobject.html).
+
+The predicate must return true if the file should be included, false otherwise.
+
+
+__Returns__ : An array of matching ZipObject.
+
+__Throws__ : Nothing.
+
+<!-- __Complexity__ : **O(k)** where k is the number of entries. -->
+
+__Example__
+
+```js
+var zip = new JSZip().folder("dir");
+zip.file("readme.txt", "content");
+zip.filter(function (relativePath, file){
+ // relativePath == "readme.txt"
+ // file = {name:"dir/readme.txt",options:{...},asText:function}
+ return true/false;
+});
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/folder_data.md b/afb-client/bower_components/jszip/documentation/api_jszip/folder_data.md
new file mode 100644
index 0000000..9f8bd44
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/folder_data.md
@@ -0,0 +1,34 @@
+---
+title: "folder(name)"
+layout: default
+section: api
+---
+
+__Description__ : Create a directory if it doesn't exist, return a new JSZip
+object with the new folder as root.
+
+See also [the `dir` option of file()]({{site.baseurl}}/documentation/api_jszip/file_data.html).
+
+__Arguments__
+
+name | type | description
+-----|--------|------------
+name | string | the name of the directory.
+
+__Returns__ : A new JSZip (for chaining), with the new folder as root.
+
+__Throws__ : Nothing.
+
+<!-- __Complexity__ : **O(1)** -->
+
+__Example__
+
+```js
+zip.folder("images");
+zip.folder("css").file("style.css", "body {background: #FF0000}");
+// or specify an absolute path (using forward slashes)
+zip.file("css/font.css", "body {font-family: sans-serif}")
+
+// result : images/, css/, css/style.css, css/font.css
+```
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/folder_regex.md b/afb-client/bower_components/jszip/documentation/api_jszip/folder_regex.md
new file mode 100644
index 0000000..8d9e021
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/folder_regex.md
@@ -0,0 +1,40 @@
+---
+title: "folder(regex)"
+layout: default
+section: api
+---
+
+__Description__ : Search a subdirectory in the current directory with a
+[regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
+The regex is tested against the relative path.
+
+__Arguments__
+
+name | type | description
+------|--------|------------
+regex | RegExp | the regex to use.
+
+__Returns__ : An array of matching folders (an empty array if none matched).
+Each maching folder is an instance of [ZipObject]({{site.baseurl}}/documentation/api_zipobject.html).
+
+__Throws__ : Nothing.
+
+<!--
+__Complexity__ : **O(k)** where k is the number of entries in the current JSZip
+instance.
+-->
+
+__Example__
+
+```js
+var zip = new JSZip();
+zip.folder("home/Pierre/videos");
+zip.folder("home/Pierre/photos");
+zip.folder("home/Jean/videos");
+zip.folder("home/Jean/photos");
+
+zip.folder(/videos/); // array of size 2
+
+zip.folder("home/Jean").folder(/^vid/); // array of 1
+```
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/generate.md b/afb-client/bower_components/jszip/documentation/api_jszip/generate.md
new file mode 100644
index 0000000..7b00f97
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/generate.md
@@ -0,0 +1,139 @@
+---
+title: "generate(options)"
+layout: default
+section: api
+---
+
+__Description__ : Generates the complete zip file.
+
+__Arguments__
+
+name | type | default | description
+--------------------|---------|---------|------------
+options | object | | the options to generate the zip file :
+options.base64 | boolean | false | **deprecated**, use `type` instead. If `type` is not used, set to `false` to get the result as a raw byte string, `true` to encode it as base64.
+options.compression | string | `STORE` (no compression) | the default file compression method to use. Available methods are `STORE` and `DEFLATE`. You can also provide your own compression method.
+options.compressionOptions | object | `null` | the options to use when compressing the file, see below.
+options.type | string | `base64` | The type of zip to return, see below for the other types.
+options.comment | string | | The comment to use for the zip file.
+options.mimeType | string | `application/zip` | mime-type for the generated file. Useful when you need to generate a file with a different extension, ie: ".ods".
+options.platform | string | `DOS` | The platform to use when generating the zip file.
+
+Possible values for `type` :
+
+* `base64` (default) : the result will be a string, the binary in a base64 form.
+* `string` : the result will be a string in "binary" form, using 1 byte per char (2 bytes).
+* `uint8array` : the result will be a Uint8Array containing the zip. This requires a compatible browser.
+* `arraybuffer` : the result will be a ArrayBuffer containing the zip. This requires a compatible browser.
+* `blob` : the result will be a Blob containing the zip. This requires a compatible browser.
+* `nodebuffer` : the result will be a nodejs Buffer containing the zip. This requires nodejs.
+
+Note : when using type = "uint8array", "arraybuffer" or "blob", be sure to
+check if the browser supports it (you can use [`JSZip.support`]({{site.baseurl}}/documentation/api_jszip/support.html)).
+
+The `compressionOptions` parameter depends on the compression type. With
+`STORE` (no compression), this parameter is ignored. With `DEFLATE`, you can
+give the compression level with `compressionOptions : {level:6}` (or any level
+between 1 (best speed) and 9 (best compression)).
+
+Note : if the entry is *already* compressed (coming from a compressed zip file),
+calling `generate()` with a different compression level won't update the entry.
+The reason is simple : JSZip doesn't know how compressed the content was and
+how to match the compression level with the implementation we use.
+
+Note for the `comment` option : the zip format has no flag or field to give the
+encoding of this field and JSZip will use UTF-8. With non ASCII characters you
+might get encoding issues if the file archiver doesn't use UTF-8 to decode the
+comment.
+
+If not set, JSZip will use the field `comment` on its `options`.
+
+Possible values for `platform` : `DOS` and `UNIX`. It also accepts nodejs
+`process.platform` values.
+When using `DOS`, the attribute `dosPermissions` of each file is used.
+When using `UNIX`, the attribute `unixPermissions` of each file is used.
+
+If you set the platform value on nodejs, be sure to use `process.platform`.
+`fs.stats` returns a non executable mode for folders on windows, if you
+force the platform to `UNIX` the generated zip file will have a strange
+behavior on UNIX platforms.
+
+__Returns__ : The generated zip file.
+
+__Throws__ : An exception if the asked `type` is not available in the browser,
+see [JSZip.support]({{site.baseurl}}/documentation/api_jszip/support.html).
+
+<!-- __Complexity__ : TODO : worst case, with/out compression, etc -->
+
+__Example__
+
+```js
+var content = zip.generate({type:"blob"});
+// see FileSaver.js
+saveAs(content, "hello.zip");
+```
+
+```js
+var content = zip.generate({type:"base64"});
+location.href="data:application/zip;base64,"+content;
+```
+
+```js
+var content = zip.generate({type:"nodebuffer"});
+require("fs").writeFile("hello.zip", content, function(err){/*...*/});
+```
+
+```js
+// on nodejs
+zip.file(pathname, content, {
+ date: stat.mtime,
+ unixPermissions: stat.mode
+});
+
+// ...
+
+zip.generate({
+ type: 'nodebuffer',
+ platform: process.platform
+});
+```
+
+```js
+//This example will Generate a Open Document Spreasheet, with the correct mime type
+var zip = new JSZip();
+zip.file("mimetype", "application/vnd.oasis.opendocument.spreadsheet");
+var conf2 = zip.folder("Configurations2");
+conf2.folder("acceleator");
+conf2.folder("images");
+conf2.folder("popupmenu");
+conf2.folder("statusbar");
+conf2.folder("floater");
+conf2.folder("menubar");
+conf2.folder("progressbar");
+conf2.folder("toolbar");
+
+var manifest = "<..."; //xml containing manifest.xml
+var styles = "<..."; //xml containing styles.xml
+var settings = "<..."; //xml containing settings.xml
+var meta = "<..."; //xml containing meta.xml
+var content = "<..."; //xml containing content.xml
+
+var metaInf = zip.folder("META-INF");
+metaInf.file("manifest.xml", manifest);
+zip.file("styles.xml", styles);
+zip.file("settings.xml", settings);
+zip.file("meta.xml", meta);
+zip.file("content.xml", content);
+
+//Generate the file
+var odsFile = zip.generate({type: "blob", mimeType: "application/ods", compression: "DEFLATE"});
+
+var url = window.URL.createObjectURL(odsFile);
+var link = document.getElementById("link"); //I suppose you'll have a link with this id :)
+link.download = "testjs.ods";
+link.href = url;
+
+
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/load.md b/afb-client/bower_components/jszip/documentation/api_jszip/load.md
new file mode 100644
index 0000000..a2f54ad
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/load.md
@@ -0,0 +1,81 @@
+---
+title: "load(data [, options])"
+layout: default
+section: api
+---
+
+__Description__ : Read an existing zip and merge the data in the current JSZip
+object at the current folder level. This technique has some limitations, see
+[here]({{site.baseurl}}/documentation/limitations.html).
+
+__Arguments__
+
+name | type | description
+-------------------|--------|------------
+data | String/ArrayBuffer/Uint8Array/Buffer | the zip file
+options | object | the options to load the zip file
+
+Content of `options` :
+
+name | type | default | description
+------------------------------|---------|---------|------------
+options.base64 | boolean | false | set to `true` if the data is base64 encoded, `false` for binary.
+options.checkCRC32 | boolean | false | set to `true` if the read data should be checked against its CRC32.
+options.optimizedBinaryString | boolean | false | set to true if (and only if) the input is a string and has already been prepared with a 0xFF mask.
+options.createFolders | boolean | false | set to true to create folders in the file path automatically. Leaving it false will result in only virtual folders (i.e. folders that merely represent part of the file path) being created.
+
+You shouldn't update the data given to this method : it is kept as it so any
+update will impact the stored data.
+
+Zip features supported by this method :
+
+* Compression (<code>DEFLATE</code> supported)
+* zip with data descriptor
+* ZIP64
+* UTF8 in file name, UTF8 in file content
+
+Zip features not (yet) supported :
+
+* password protected zip
+* multi-volume zip
+
+__Returns__ : The current JSZip object.
+
+__Throws__ : An exception if the loaded data is not valid zip data or if it
+uses features (multi volume, password protected, etc).
+
+<!--
+__Complexity__ : for k the number of entries in the zip file and n the length
+of the data :
+
+The default use case is **O(k)**.
+If the data is in base64, we must first decode it : **O(k + n)**.
+If the data is a string not in base64 and optimizedBinaryString is false, we
+must apply the 0xFF mask : **O(k + n)**.
+If checkCRC32 is true, it **adds** to the above complexity **O(n)** and the
+complexity of the decompression algorithm.
+-->
+
+__Example__
+
+```js
+var zip = new JSZip();
+zip.load(zipDataFromXHR);
+```
+
+```js
+require("fs").readFile("hello.zip", function (err, data) {
+ if (err) throw err;
+ var zip = new JSZip();
+ zip.load(data);
+}
+```
+
+Using sub folders :
+
+```js
+var zip = new JSZip();
+zip.folder("subfolder").load(data);
+// the content of data will be loaded in subfolder/
+```
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/remove.md b/afb-client/bower_components/jszip/documentation/api_jszip/remove.md
new file mode 100644
index 0000000..af7aa78
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/remove.md
@@ -0,0 +1,37 @@
+---
+title: "remove(name)"
+layout: default
+section: api
+---
+
+__Description__ : Delete a file or folder (recursively).
+
+__Arguments__
+
+name | type | description
+-----|--------|------------
+name | string | the name of the file/folder to delete.
+
+__Returns__ : The current JSZip object.
+
+__Throws__ : Nothing.
+
+<!--
+__Complexity__ : **O(k)** where k is the number of entry to delete (may be > 1
+when removing a folder).
+-->
+
+__Example__
+
+```js
+var zip = new JSZip();
+zip.file("Hello.txt", "Hello World\n");
+zip.file("temp.txt", "nothing").remove("temp.txt");
+// result : Hello.txt
+
+zip.folder("css").file("style.css", "body {background: #FF0000}");
+zip.remove("css");
+//result : empty zip
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_jszip/support.md b/afb-client/bower_components/jszip/documentation/api_jszip/support.md
new file mode 100644
index 0000000..73d076f
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_jszip/support.md
@@ -0,0 +1,16 @@
+---
+title: "JSZip.support"
+layout: default
+section: api
+---
+
+If the browser supports them, JSZip can take advantage of some "new" features :
+ArrayBuffer, Blob, Uint8Array. To know if JSZip can use them, you can check the
+JSZip.support object. It contains the following boolean properties :
+
+* `arraybuffer` : true if JSZip can read and generate ArrayBuffer, false otherwise.
+* `uint8array` : true if JSZip can read and generate Uint8Array, false otherwise.
+* `blob` : true if JSZip can generate Blob, false otherwise.
+* `nodebuffer` : true if JSZip can read and generate nodejs Buffer, false otherwise.
+
+
diff --git a/afb-client/bower_components/jszip/documentation/api_zipobject.md b/afb-client/bower_components/jszip/documentation/api_zipobject.md
new file mode 100644
index 0000000..970fa8f
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/api_zipobject.md
@@ -0,0 +1,37 @@
+---
+title: "ZipObject API"
+layout: default
+section: api
+---
+
+This represents an entry in the zip file. If the entry comes from an existing
+archive previously [loaded]({{site.baseurl}}/documentation/api_jszip/load.html), the content
+will be automatically decompressed/converted first.
+
+### Attributes
+
+attribute name | type | description
+----------------------------|-------------|-------------
+`name` | string | the absolute path of the file
+`dir` | boolean | true if this is a directory
+`date` | date | the last modification date
+`comment` | string | the comment for this file
+`unixPermissions` | 16 bits number | The UNIX permissions of the file, if any.
+`dosPermissions` | 6 bits number | The DOS permissions of the file, if any.
+`options` | object | the options of the file. The available options are :
+`options.base64` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
+`options.binary` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
+`options.dir` | boolean | **Deprecated**, use `dir`. True if this is a directory
+`options.date` | date | **Deprecated**, use `date`. See [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
+`options.compression` | compression | see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
+
+
+### Getters
+
+method | return type | description
+------------------|---------------|-------------
+`asText()` | string | the content as an unicode string.
+`asBinary()` | string | the content as binary string.
+`asArrayBuffer()` | ArrayBuffer | need a [compatible browser]({{site.baseurl}}/documentation/api_jszip/support.html).
+`asUint8Array()` | Uint8Array | need a [compatible browser]({{site.baseurl}}/documentation/api_jszip/support.html).
+`asNodeBuffer()` | nodejs Buffer | need [nodejs]({{site.baseurl}}/documentation/api_jszip/support.html).
diff --git a/afb-client/bower_components/jszip/documentation/contributing.md b/afb-client/bower_components/jszip/documentation/contributing.md
new file mode 100644
index 0000000..f1b5dd3
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/contributing.md
@@ -0,0 +1,62 @@
+---
+title: Contributing
+layout: default
+section: main
+---
+
+
+### Download the sources
+
+You should create a [Github](https://github.com/) account and
+[fork the repository](https://help.github.com/articles/fork-a-repo) (you will
+need one to create the pull request).
+
+If you just want the get the source code, you can use git and do
+`git clone https://github.com/Stuk/jszip.git` to get the sources. You can also
+download the latest sources [here](https://github.com/Stuk/jszip/archive/master.zip).
+
+### Building the project
+
+#### Code
+
+The dependencies are handled by npm, the first step is to run
+`npm install` to get the dependencies.
+JSZip uses Grunt to handle the build, [see here to install its CLI](http://gruntjs.com/getting-started).
+
+Here are the interesting build commands :
+
+* `grunt` will generate the final js file in dist/ and the minified version.
+* `npm run test-node` will run the tests in nodejs.
+* `npm run test-browser` will the tests in some browsers using SauceLabs, see
+ below.
+* `npm run test` will run the tests in nodejs and in the browser.
+* `npm run lint` will use jshint the check the source code.
+
+#### Documentation
+
+The documentation uses jekyll on gh-pages. To render the documentation, you
+need to [install jekyll](http://jekyllrb.com/docs/installation/) and then run
+`jekyll serve --baseurl ''`.
+
+### Testing the project
+
+To test JSZip in nodejs, use `npm run test-node`.
+
+To test JSZip in a browser, you can open the file `test/index.html` in the
+browser you want to test. Don't forget to update the dist/ files with `grunt`.
+
+You can also test JSZip in a lot of browsers at once with
+[SauceLabs](https://saucelabs.com/). You will need a SauceLabs account and two
+variables into your environment. On linux, just use
+
+```bash
+export SAUCE_USERNAME=your-saucelabs-username
+export SAUCE_ACCESS_KEY=your-saucelabs-access-key
+```
+
+before running the `npm run test-browser` command.
+
+### Merging the changes
+
+If you have tested bug fixes or new features, you can open a
+[pull request](https://help.github.com/articles/using-pull-requests) on Github.
diff --git a/afb-client/bower_components/jszip/documentation/css/main.css b/afb-client/bower_components/jszip/documentation/css/main.css
new file mode 100644
index 0000000..f2a368c
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/css/main.css
@@ -0,0 +1,24 @@
+ul.nav ul {
+ list-style:none;
+ margin: 0;
+ padding: 0 0 0 25px;
+}
+
+#downloader_application form {
+ margin-bottom: 10px;
+}
+
+#downloader_application ul {
+ list-style-type: none;
+}
+
+.browser_support th {
+ border-bottom-width: 3px !important;
+}
+
+.support_ie {border-bottom-color: #0275BA !important;}
+.support_ff {border-bottom-color: #DF7215 !important;}
+.support_sf {border-bottom-color: #43B3E9 !important;}
+.support_cr {border-bottom-color: #39B642 !important;}
+.support_op {border-bottom-color: #C42122 !important;}
+.support_nd {border-bottom-color: #8CC84B !important;}
diff --git a/afb-client/bower_components/jszip/documentation/css/pygments.css b/afb-client/bower_components/jszip/documentation/css/pygments.css
new file mode 100644
index 0000000..2086339
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/css/pygments.css
@@ -0,0 +1,64 @@
+/* Generated with :
+ * pygmentize -S default -f html > pygments.css
+ */
+.hll { background-color: #ffffcc }
+.c { color: #408080; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #008000; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.cp { color: #BC7A00 } /* Comment.Preproc */
+.c1 { color: #408080; font-style: italic } /* Comment.Single */
+.cs { color: #408080; font-style: italic } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #888888 } /* Generic.Output */
+.gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0044DD } /* Generic.Traceback */
+.kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.kp { color: #008000 } /* Keyword.Pseudo */
+.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #B00040 } /* Keyword.Type */
+.m { color: #666666 } /* Literal.Number */
+.s { color: #BA2121 } /* Literal.String */
+.na { color: #7D9029 } /* Name.Attribute */
+.nb { color: #008000 } /* Name.Builtin */
+.nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.no { color: #880000 } /* Name.Constant */
+.nd { color: #AA22FF } /* Name.Decorator */
+.ni { color: #999999; font-weight: bold } /* Name.Entity */
+.ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.nf { color: #0000FF } /* Name.Function */
+.nl { color: #A0A000 } /* Name.Label */
+.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.nt { color: #008000; font-weight: bold } /* Name.Tag */
+.nv { color: #19177C } /* Name.Variable */
+.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #666666 } /* Literal.Number.Float */
+.mh { color: #666666 } /* Literal.Number.Hex */
+.mi { color: #666666 } /* Literal.Number.Integer */
+.mo { color: #666666 } /* Literal.Number.Oct */
+.sb { color: #BA2121 } /* Literal.String.Backtick */
+.sc { color: #BA2121 } /* Literal.String.Char */
+.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #BA2121 } /* Literal.String.Double */
+.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #BA2121 } /* Literal.String.Heredoc */
+.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.sx { color: #008000 } /* Literal.String.Other */
+.sr { color: #BB6688 } /* Literal.String.Regex */
+.s1 { color: #BA2121 } /* Literal.String.Single */
+.ss { color: #19177C } /* Literal.String.Symbol */
+.bp { color: #008000 } /* Name.Builtin.Pseudo */
+.vc { color: #19177C } /* Name.Variable.Class */
+.vg { color: #19177C } /* Name.Variable.Global */
+.vi { color: #19177C } /* Name.Variable.Instance */
+.il { color: #666666 } /* Literal.Number.Integer.Long */
diff --git a/afb-client/bower_components/jszip/documentation/examples.md b/afb-client/bower_components/jszip/documentation/examples.md
new file mode 100644
index 0000000..01d6e2d
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples.md
@@ -0,0 +1,115 @@
+---
+title: "How to use JSZip"
+layout: default
+section: example
+---
+
+An instance of JSZip represents a set of files. You can add them, remove them,
+modify them. You can also import an existing zip file or generate one.
+
+### Getting the object
+
+#### In a browser
+
+For a browser, there are two interesting files : `dist/jszip.js` and
+`dist/jszip.min.js` (include just one).
+
+If you use an AMD loader (RequireJS for example) JSZip will register itself :
+you just have to put the js file at the right place, or configure the loader
+(see [here for RequireJS](http://requirejs.org/docs/api.html#config-paths)).
+
+Without any loader, JSZip will declare in the global scope a variable named `JSZip`.
+
+#### In nodejs
+
+In nodejs, you can `require` it :
+
+```js
+var JSZip = require("jszip");
+```
+
+### Basic manipulations
+
+The first step is to create an instance of JSZip :
+
+```js
+var zip = new JSZip();
+```
+
+On this instance, we can add (and update) files and folders with
+`.file(name, content)` and `.folder(name)`.
+They return the current JSZip instance so you can chain the calls.
+
+```js
+// create a file
+zip.file("hello.txt", "Hello[p my)6cxsw2q");
+// oops, cat on keyboard. Fixing !
+zip.file("hello.txt", "Hello World\n");
+
+// create a file and a folder
+zip.file("nested/hello.txt", "Hello World\n");
+// same as
+zip.folder("nested").file("hello.txt", "Hello World\n");
+```
+
+With `.folder(name)`, the returned object has a different root : if you add files
+on this object, you will put them in the created subfolder. This is just a
+view, the added files will also be in the "root" object.
+
+```js
+var photoZip = zip.folder("photos");
+// this call will create photos/README
+photoZip.file("README", "a folder with photos");
+```
+
+You can access the file content with `.file(name)` and
+[its getters]({{site.baseurl}}/documentation/api_zipobject.html) :
+
+```js
+zip.file("hello.txt").asText(); // "Hello World\n"
+
+if (JSZip.support.uint8array) {
+ zip.file("hello.txt").asUint8Array(); // Uint8Array { 0=72, 1=101, 2=108, more...}
+}
+```
+
+You can also remove files or folders with `.remove(name)` :
+
+```js
+zip.remove("photos/README");
+zip.remove("photos");
+// same as
+zip.remove("photos"); // by removing the folder, you also remove its content.
+```
+
+### Generate a zip file
+
+With `.generate(options)` you can generate a zip file (not a real file but its
+representation in memory). Check
+[this page]({{site.baseurl}}/documentation/howto/write_zip.html) for more
+informations on how to write / give the file to the user.
+
+```js
+var content = null;
+if (JSZip.support.uint8array) {
+ content = zip.generate({type : "uint8array"});
+} else {
+ content = zip.generate({type : "string"});
+}
+```
+
+### Read a zip file
+
+With `.load(data)` you can load a zip file. Check
+[this page]({{site.baseurl}}/documentation/howto/read_zip.html) to see how to
+do properly (it's more tricky that it seems).
+
+```js
+var new_zip = new JSZip();
+// more files !
+new_zip.load(content);
+
+// you now have every files contained in the loaded zip
+new_zip.file("hello.txt").asText(); // "Hello World\n"
+```
+
diff --git a/afb-client/bower_components/jszip/documentation/examples/download-zip-file.html b/afb-client/bower_components/jszip/documentation/examples/download-zip-file.html
new file mode 100644
index 0000000..869a54e
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples/download-zip-file.html
@@ -0,0 +1,59 @@
+---
+title: "Download the generated zip file"
+layout: default
+section: example
+---
+
+<p>Tip : check the source of the page !</p>
+<h2>The FileSaver API</h2>
+<div>
+ Works on firefox, chrome , opera &gt;= 15 and IE &gt;= 10 (but NOT in compatibility view).<br/>
+ <button id="blob" class="btn btn-primary">click to download</button>
+</div>
+<h2>The data URL</h2>
+<div>
+ Does not work in IE, has restrictions on the length.<br/>
+ <button id="data_uri" class="btn btn-primary">click to download</button>
+</div>
+<script type="text/javascript">
+(function () {
+ var zip = new JSZip();
+ zip.file("Hello.txt", "Hello world\n");
+
+ function bindEvent(el, eventName, eventHandler) {
+ if (el.addEventListener){
+ // standard way
+ el.addEventListener(eventName, eventHandler, false);
+ } else if (el.attachEvent){
+ // old IE
+ el.attachEvent('on'+eventName, eventHandler);
+ }
+ }
+
+ // Blob
+ var blobLink = document.getElementById('blob');
+ if (JSZip.support.blob) {
+ function downloadWithBlob() {
+ try {
+ var blob = zip.generate({type:"blob"});
+ // see FileSaver.js
+ saveAs(blob, "hello.zip");
+ } catch(e) {
+ blobLink.innerHTML += " " + e;
+ }
+ return false;
+ }
+ bindEvent(blobLink, 'click', downloadWithBlob);
+ } else {
+ blobLink.innerHTML += " (not supported on this browser)";
+ }
+
+ // data URI
+ function downloadWithDataURI() {
+ window.location = "data:application/zip;base64," + zip.generate({type:"base64"});
+ }
+ var dataUriLink = document.getElementById('data_uri');
+ bindEvent(dataUriLink, 'click', downloadWithDataURI);
+
+})();
+</script>
diff --git a/afb-client/bower_components/jszip/documentation/examples/downloader.html b/afb-client/bower_components/jszip/documentation/examples/downloader.html
new file mode 100644
index 0000000..e3589db
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples/downloader.html
@@ -0,0 +1,58 @@
+---
+title: "Mini app : Downloader"
+layout: default
+section: example
+---
+
+<p>Tip : check the source of the page !</p>
+
+<p>
+ This mini application let you choose the files you want in a list, download
+ them, zip them and give the result to the user.
+</p>
+<p>
+ This demo requires a recent browser, see <a href="{{site.baseurl}}/documentation/howto/write_zip.html">
+ the howto</a>.
+</p>
+
+
+
+<div id="downloader_application">
+ <h3>Please select your files</h3>
+ <form action="#" id="download_form">
+ <ul>
+ <li>
+ <label>
+ <input type="checkbox" data-url="{{site.baseurl}}/test/ref/complex_files/Franz Kafka - The Metamorphosis.epub" checked />
+ Franz Kafka - The Metamorphosis.epub
+ </label>
+ </li>
+ <li>
+ <label>
+ <input type="checkbox" data-url="{{site.baseurl}}/documentation/css/pygments.css" checked />
+ pygments.css
+ </label>
+ </li>
+ <li>
+ <label>
+ <input type="checkbox" data-url="{{site.baseurl}}/dist/jszip.js" />
+ jszip.js
+ </label>
+ </li>
+ <li>
+ <label>
+ <input type="checkbox" data-url="{{site.baseurl}}/test/ref/all.zip" />
+ all.zip
+ </label>
+ </li>
+ </ul>
+
+ <button type="submit" class="btn btn-primary">pack them !</button>
+</form>
+
+<p class="hide" id="result"></p>
+
+
+</div>
+
+<script type="text/javascript" src="{{site.baseurl}}/documentation/examples/downloader.js"></script>
diff --git a/afb-client/bower_components/jszip/documentation/examples/downloader.js b/afb-client/bower_components/jszip/documentation/examples/downloader.js
new file mode 100644
index 0000000..13903cc
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples/downloader.js
@@ -0,0 +1,89 @@
+jQuery(function ($) {
+ "use strict";
+
+ /**
+ * Reset the message.
+ */
+ function resetMessage () {
+ $("#result")
+ .removeClass()
+ .text("");
+ }
+ /**
+ * show a successful message.
+ * @param {String} text the text to show.
+ */
+ function showMessage(text) {
+ resetMessage();
+ $("#result")
+ .addClass("alert alert-success")
+ .text(text);
+ }
+ /**
+ * show an error message.
+ * @param {String} text the text to show.
+ */
+ function showError(text) {
+ resetMessage();
+ $("#result")
+ .addClass("alert alert-danger")
+ .text(text);
+ }
+
+ /**
+ * Fetch the content, add it to the JSZip object
+ * and use a jQuery deferred to hold the result.
+ * @param {String} url the url of the content to fetch.
+ * @param {String} filename the filename to use in the JSZip object.
+ * @param {JSZip} zip the JSZip instance.
+ * @return {jQuery.Deferred} the deferred containing the data.
+ */
+ function deferredAddZip(url, filename, zip) {
+ var deferred = $.Deferred();
+ JSZipUtils.getBinaryContent(url, function (err, data) {
+ if(err) {
+ deferred.reject(err);
+ } else {
+ zip.file(filename, data, {binary:true});
+ deferred.resolve(data);
+ }
+ });
+ return deferred;
+ }
+
+ if(!JSZip.support.blob) {
+ showError("This demo works only with a recent browser !");
+ return;
+ }
+
+ var $form = $("#download_form").on("submit", function () {
+
+ resetMessage();
+
+ var zip = new JSZip();
+ var deferreds = [];
+
+ // find every checked item
+ $(this).find(":checked").each(function () {
+ var $this = $(this);
+ var url = $this.data("url");
+ var filename = url.replace(/.*\//g, "");
+ deferreds.push(deferredAddZip(url, filename, zip));
+ });
+
+ // when everything has been downloaded, we can trigger the dl
+ $.when.apply($, deferreds).done(function () {
+ var blob = zip.generate({type:"blob"});
+
+ // see FileSaver.js
+ saveAs(blob, "example.zip");
+
+ showMessage("done !");
+ }).fail(function (err) {
+ showError(err);
+ });
+ return false;
+ });
+});
+
+// vim: set shiftwidth=4 softtabstop=4:
diff --git a/afb-client/bower_components/jszip/documentation/examples/get-binary-files-ajax.html b/afb-client/bower_components/jszip/documentation/examples/get-binary-files-ajax.html
new file mode 100644
index 0000000..ee7594e
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples/get-binary-files-ajax.html
@@ -0,0 +1,43 @@
+---
+title: "Get a file with an ajax call"
+layout: default
+section: example
+---
+
+<p>Tip : check the source of the page !</p>
+
+<h3>With JSZipUtils</h3>
+<div id="jszip_utils"></div>
+
+<script type="text/javascript">
+(function () {
+
+ function showError(elt, err) {
+ elt.innerHTML = "<p class='alert alert-danger'>" + err + "</p>";
+ }
+
+ function showContent(elt, type, content) {
+ elt.innerHTML = "<p class='alert alert-success'>loaded ! (as a " + type + ")<br/>" +
+ "Content = " + content + "</p>";
+ }
+
+ //=========================
+ // JSZipUtils
+ //=========================
+ JSZipUtils.getBinaryContent('{{site.baseurl}}/test/ref/text.zip', function(err, data) {
+ var elt = document.getElementById('jszip_utils');
+ if(err) {
+ showError(elt, err);
+ return;
+ }
+
+ try {
+ var zip = new JSZip(data);
+ showContent(elt, "" + data, zip.file("Hello.txt").asText());
+ } catch(e) {
+ showError(elt, e);
+ }
+ });
+
+})();
+</script>
diff --git a/afb-client/bower_components/jszip/documentation/examples/read-local-file-api.html b/afb-client/bower_components/jszip/documentation/examples/read-local-file-api.html
new file mode 100644
index 0000000..da307c2
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/examples/read-local-file-api.html
@@ -0,0 +1,87 @@
+---
+title: "Reading a local file with the File API"
+layout: default
+section: example
+---
+
+<h3>Choose the local(s) zip file(s)</h3>
+<p class="note">Note : your browser will process the zip file, don't choose a file too big !</p>
+<input type="file" id="file" name="file" multiple /><br />
+
+<div id="error_block" class="alert alert-danger hidden">
+ You will need a recent browser to use this demo :(
+</div>
+
+<div id="result_block" class="hidden">
+ <h3>Content :</h3>
+ <div id="result"></div>
+</div>
+<script type="text/javascript" src="{{site.baseurl}}/test/jquery-1.8.3.min.js"></script>
+<script type="text/javascript">
+(function () {
+ if (!window.FileReader || !window.ArrayBuffer) {
+ $("#error_block").removeClass("hidden").addClass("show");
+ return;
+ }
+
+
+ var $result = $("#result");
+ $("#file").on("change", function(evt) {
+ // remove content
+ $result.html("");
+ // be sure to show the results
+ $("#result_block").removeClass("hidden").addClass("show");
+
+ // see http://www.html5rocks.com/en/tutorials/file/dndfiles/
+
+ var files = evt.target.files;
+ for (var i = 0, f; f = files[i]; i++) {
+
+ var reader = new FileReader();
+
+ // Closure to capture the file information.
+ reader.onload = (function(theFile) {
+ return function(e) {
+ var $title = $("<h4>", {
+ text : theFile.name
+ });
+ $result.append($title);
+ var $fileContent = $("<ul>");
+ try {
+
+ var dateBefore = new Date();
+ // read the content of the file with JSZip
+ var zip = new JSZip(e.target.result);
+ var dateAfter = new Date();
+
+ $title.append($("<span>", {
+ text:" (parsed in " + (dateAfter - dateBefore) + "ms)"
+ }));
+
+ // that, or a good ol' for(var entryName in zip.files)
+ $.each(zip.files, function (index, zipEntry) {
+ $fileContent.append($("<li>", {
+ text : zipEntry.name
+ }));
+ // the content is here : zipEntry.asText()
+ });
+ // end of the magic !
+
+ } catch(e) {
+ $fileContent = $("<div>", {
+ "class" : "alert alert-danger",
+ text : "Error reading " + theFile.name + " : " + e.message
+ });
+ }
+ $result.append($fileContent);
+ }
+ })(f);
+
+ // read the file !
+ // readAsArrayBuffer and readAsBinaryString both produce valid content for JSZip.
+ reader.readAsArrayBuffer(f);
+ // reader.readAsBinaryString(f);
+ }
+ });
+})();
+</script>
diff --git a/afb-client/bower_components/jszip/documentation/faq.md b/afb-client/bower_components/jszip/documentation/faq.md
new file mode 100644
index 0000000..57059e2
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/faq.md
@@ -0,0 +1,19 @@
+---
+title: "Frequently Asked Questions"
+layout: default
+section: main
+---
+
+### "Corrupted zip or bug : unexpected signature"
+
+If you are sure that the zip file is correct, that error often comes from a
+corrupted content. An ajax request, if not prepared correctly, will try to
+decode the binary content as a text and corrupt it. See
+[this page]({{site.baseurl}}/documentation/howto/read_zip.html).
+
+### My browser crashes / becomes unresponsive / never finish the execution
+
+That happens if you try to handle to much data. If possible, try again with a
+small (some KB) zip file to see if your code is correct. See
+[this page]({{site.baseurl}}/documentation/limitations.html) for more
+informations.
diff --git a/afb-client/bower_components/jszip/documentation/howto/read_zip.md b/afb-client/bower_components/jszip/documentation/howto/read_zip.md
new file mode 100644
index 0000000..48a5240
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/howto/read_zip.md
@@ -0,0 +1,152 @@
+---
+title: "How to read a file"
+layout: default
+section: example
+---
+
+This page explains how to read an existing zip file or add a existing file into
+the zip file.
+
+
+### In the browser
+
+#### AJAX request
+
+Getting binary data with an ajax request is hard (mainly because of IE <= 9).
+The easy way is to use [JSZipUtils.getBinaryContent](https://github.com/stuk/jszip-utils).
+With JSZipUtils.getBinaryContent, you can do the following (see the
+documentation for more examples) :
+
+```js
+JSZipUtils.getBinaryContent('path/to/content.zip', function(err, data) {
+ if(err) {
+ throw err; // or handle err
+ }
+
+ var zip = new JSZip(data);
+});
+```
+
+<br>
+
+If you need to adapt an existing solution to what getBinaryContent does, here
+are the details. When doing a XHR request (level 1, without setting the
+`responseType`) the browser will try to interpret the response as a string and
+decode it from its charset. To avoid this on Firefox/Chrome/Opera, you need to
+set mime type : `xhr.overrideMimeType("text/plain; charset=x-user-defined");`.
+On IE <= 9, this is harder. The overrideMimeType trick doesn't work so we need
+to use [vbscript](http://stackoverflow.com/questions/1095102/how-do-i-load-binary-image-data-using-javascript-and-xmlhttprequest)
+and non standard attributes.
+On IE > 9, overrideMimeType doesn't work but xhr2 does.
+
+With [xhr 2](http://caniuse.com/xhr2), you can just set the responseType
+attribute : `xhr.responseType = "arraybuffer";`. With this, the browser will
+return an ArrayBuffer.
+
+#### Local files
+
+If the browser supports the [FileReader API](http://caniuse.com/filereader),
+you can use it to read a zip file. JSZip can read ArrayBuffer, so you can use
+`FileReader.readAsArrayBuffer(Blob)`, see this [example]({{site.baseurl}}/documentation/examples/read-local-file-api.html).
+
+### In nodejs
+
+JSZip can read Buffers so you can do the following :
+
+#### Local file
+
+```js
+"use strict";
+
+var fs = require("fs");
+var JSZip = require("jszip");
+
+// read a zip file
+fs.readFile("test.zip", function(err, data) {
+ if (err) throw err;
+ var zip = new JSZip(data);
+});
+
+// read a file and add it to a zip
+fs.readFile("picture.png", function(err, data) {
+ if (err) throw err;
+ var zip = new JSZip();
+ zip.file("picture.png", data);
+});
+```
+
+#### Remote file
+
+There are a lot of nodejs libraries doing http requests, from the built-in
+[http](http://nodejs.org/docs/latest/api/http.html) to the
+[npm packages](https://www.npmjs.org/browse/keyword/http). Here are two
+examples, one with the default http API, the other with
+[request](https://github.com/mikeal/request) (but you're free to use your
+favorite library !). If possible, download the file as a Buffer (you will get
+better performances). If it's not possible, you can fallback to a binary string
+(the option is likely to be `encoding : "binary"`).
+
+##### With http :
+
+```js
+"use strict";
+
+var http = require("http");
+var url = require("url");
+var JSZip = require("jszip");
+
+var req = http.get(url.parse("http://localhost/.../file.zip"), function (res) {
+ if (res.statusCode !== 200) {
+ console.log(res.statusCode);
+ // handle error
+ return;
+ }
+ var data = [], dataLen = 0;
+
+ // don't set the encoding, it will break everything !
+ // or, if you must, set it to null. In that case the chunk will be a string.
+
+ res.on("data", function (chunk) {
+ data.push(chunk);
+ dataLen += chunk.length;
+ });
+
+ res.on("end", function () {
+ var buf = new Buffer(dataLen);
+ for (var i=0,len=data.length,pos=0; i<len; i++) {
+ data[i].copy(buf, pos);
+ pos += data[i].length;
+ }
+
+ // here we go !
+ var zip = new JSZip(buf);
+ console.log(zip.file("content.txt").asText());
+ });
+});
+
+req.on("error", function(err){
+ // handle error
+});
+```
+
+##### With request :
+
+```js
+"use strict";
+
+var request = require('request');
+var JSZip = require("jszip");
+
+request({
+ method : "GET",
+ url : "http://localhost/.../file.zip",
+ encoding: null // <- this one is important !
+}, function (error, response, body) {
+ if(error || response.statusCode !== 200) {
+ // handle error
+ return;
+ }
+ var zip = new JSZip(body);
+ console.log(zip.file("content.txt").asText());
+});
+```
diff --git a/afb-client/bower_components/jszip/documentation/howto/write_zip.md b/afb-client/bower_components/jszip/documentation/howto/write_zip.md
new file mode 100644
index 0000000..e524491
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/howto/write_zip.md
@@ -0,0 +1,106 @@
+---
+title: "How to write a file / give it to the user"
+layout: default
+section: example
+---
+
+### In the browser
+
+With only javascript, this part won't work in old browsers, including IE < 10.
+For those browsers, you can use a flash polyfill, see below.
+
+You can also see this
+[example]({{site.baseurl}}/documentation/examples/download-zip-file.html).
+
+#### Blob URL / FileSaver
+
+With recent browsers, the easiest way is to use `saveAs` or a polyfill, see
+[FileSaver.js](https://github.com/eligrey/FileSaver.js) :
+
+```js
+var blob = zip.generate({type:"blob"});
+saveAs(blob, "hello.zip");
+```
+
+Under the hood, the polyfill uses the native `saveAs` from the
+[FileSaver](http://www.w3.org/TR/file-writer-api/#the-filesaver-interface) API
+(on Chrome and IE10+) or use a [Blob URL](http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download)
+(on Firefox).
+
+
+#### Data URI
+
+For older browsers that support [data URI](http://caniuse.com/datauri), you can also
+do the following :
+
+```js
+location.href="data:application/zip;base64," + zip.generate({type:"base64"});
+```
+
+The biggest issue here is that the filenames are very awkward, Firefox
+generates filenames such as `a5sZQRsx.zip.part` (see bugs
+[367231](https://bugzilla.mozilla.org/show_bug.cgi?id=367231) and
+[532230](https://bugzilla.mozilla.org/show_bug.cgi?id=532230), and Safari
+isn't much better with just `Unknown`.
+
+Browser support and resulting filename :
+
+Opera | Firefox | Safari | Chrome | Internet Explorer
+-------|---------|--------|--------|------------------
+"default.zip" | random alphanumeric with ".part" extension | "Unknown" (no extension) | "download.zip" on OSX and Linux, just "download" on Windows | No
+
+#### Downloadify
+
+[Downloadify](https://github.com/dcneiner/downloadify) uses a small Flash SWF
+to download files to a user's computer with a filename that you can choose.
+Doug Neiner has added the `dataType` option to allow you to pass a zip for
+downloading. Follow the [Downloadify demo](http://pixelgraphics.us/downloadify/test.html)
+with the following changes:
+
+```js
+zip = new JSZip();
+zip.file("Hello.", "hello.txt");
+Downloadify.create('downloadify',{
+...
+ data: function(){
+ return zip.generate({type:"base64"});
+ },
+...
+ dataType: 'base64'
+});
+```
+
+<!--
+TODO : send data as GET / POST ?
+-->
+
+#### Deprecated google gears
+
+[Franz Buchinger](http://www.picurl.org/blog/author/franz/) has written a
+brilliant tutorial on [using JSZip with Google Gears](http://www.picurl.org/blog/2009/11/22/creating-zip-archives-with-gears)
+([part 2](http://www.picurl.org/blog/2009/11/29/gearszipper-part2-adding-support-for-real-files-and-canvas-elements/)).
+If you want to let your Gears users download several files at once I really
+recommend having a look at some of his [examples](http://picurl.org/gears/zipper/).
+
+
+
+### In nodejs
+
+JSZip can generate Buffers so you can do the following :
+
+```js
+var fs = require("fs");
+var JSZip = require("jszip");
+
+var zip = new JSZip();
+// zip.file("file", content);
+// ... and other manipulations
+
+var buffer = zip.generate({type:"nodebuffer"});
+
+fs.writeFile("test.zip", buffer, function(err) {
+ if (err) throw err;
+});
+```
+
+
diff --git a/afb-client/bower_components/jszip/documentation/limitations.md b/afb-client/bower_components/jszip/documentation/limitations.md
new file mode 100644
index 0000000..62db22e
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/limitations.md
@@ -0,0 +1,73 @@
+---
+title: "Limitations of JSZip"
+layout: default
+section: limitations
+fullpage: true
+---
+
+### Not supported features
+
+All the features of zip files are not supported. Classic zip files will work
+but encrypted zip, multi-volume, etc are not supported and the load() method
+will throw an `Error`.
+
+
+### ZIP64 and 32bit integers
+
+ZIP64 files can be loaded, but only if the zip file is not "too big". ZIP64 uses 64bits integers
+but Javascript represents all numbers as
+[64-bit double precision IEEE 754 floating point numbers](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
+(see section 8.5). So, we have 53bits for integers and
+[bitwise operations treat everything as 32bits](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators).
+So if all the 64bits integers can fit into 32 bits integers, everything will be
+fine. If it's not the case, you will have other problems anyway (see next
+limitation).
+
+### Performance issues
+
+An other limitation comes from the browser (and the machine running the
+browser). A compressed zip file of 10MB is "easily" opened by firefox / chrome
+/ opera / IE10+ but will crash older IE. Also keep in mind that strings in
+javascript are encoded in UTF-16 : a 10MB ascii text file will take 20MB of
+memory.
+
+If you're having performance issues, please consider the following :
+
+* Don't use IE &lt;= 9. Everything is better with typed arrays.
+* Use typed arrays (Uint8Array, ArrayBuffer, etc) if possible :
+ * If you generate a zip file, you should use `type:"uint8array"`
+ (or blob, arraybuffer, nodebuffer).
+ * If you load the file from an ajax call, ask your XHR an ArrayBuffer.
+ Loading a string is asking for troubles.
+* Don't use compression (see below).
+* If you want to get the content of an ASCII file as a string, consider using
+ `asBinary()` instead of `asText()`. The transformation
+ "binary string" -&gt; "unicode string" is a consuming process.
+
+Note about compression :
+When reading a file, JSZip will store the content without decompressing it.
+When generating a compressed file, JSZip will reuse if possible compressed
+content :
+
+* If you read a zip file compressed with DEFLATE and call `generate` with the
+ DEFLATE compression, JSZip won't call the compression algorithms (same with
+ STORE everywhere.)
+* If you read a zip file compressed with DEFLATE and call `generate` with the
+ STORE compression, JSZip will have to decompress everything.
+
+On IE &lt;=9, typed arrays are not supported and the compression algorithm
+will fallback on arrays. In that case, JSZip needs to convert the binary string
+into an array, DEFLATE it and convert the result into a binary string.
+You don't want that to happen.
+
+### The output zip will differ from the input zip
+
+Reading and generating a zip file won't give you back the same file.
+Some data are discarded (file metadata) and other are added (subfolders).
+
+### Encodings support
+
+JSZip only supports utf8 : if the names of the files inside the zip are not in
+utf8 (or ASCII), they won't be interpreted correctly. If the content is a text
+not encoded with utf8 (or ASCII), the `asText()` method won't decode it
+correctly.
diff --git a/afb-client/bower_components/jszip/documentation/upgrade_guide.md b/afb-client/bower_components/jszip/documentation/upgrade_guide.md
new file mode 100644
index 0000000..1dfac9c
--- /dev/null
+++ b/afb-client/bower_components/jszip/documentation/upgrade_guide.md
@@ -0,0 +1,57 @@
+---
+title: Upgrade Guide
+layout: default
+section: main
+---
+
+### From 2.2.2 to 2.3.0
+
+* On `ZipObject#options`, the attributes `date` and `dir` have been
+ deprecated and are now on `ZipObject`.
+* On `ZipObject#options`, the attributes `base64` and `binary` have been
+ deprecated.
+* `JSZip.base64`, `JSZip.prototype.crc32`, `JSZip.prototype.utf8decode`,
+ `JSZip.prototype.utf8encode` and `JSZip.utils` have been deprecated.
+
+```js
+// deprecated
+zip.file("test.txt").options.date
+zip.file("test.txt").options.dir
+// new API
+zip.file("test.txt").date
+zip.file("test.txt").dir
+```
+
+
+### From 2.0.0 to 2.1.0
+
+* The packaging changed : instead of loading jszip.js, jszip-load.js,
+ jszip-inflate.js, jszip-deflate.js, just include dist/jszip.js or
+ dist/jszip.min.js.
+ For AMD loader users : JSZip now registers itself. You just have to put the
+ file at the right place or configure your loader.
+
+
+### From 1.x to 2.x
+
+* `JSZipBase64` has been renamed to `JSZip.base64`.
+* The `data` attribute doesn't exist anymore :
+ use the getters `asText()`, `asBinary()`, etc
+* The compression/decompression methods now give their input type with the
+ `compressInputType` and `uncompressInputType` attributes.
+
+Example for the data attribute :
+
+```js
+// before
+zip.file("test.txt").data;
+zip.files["test.txt"].data;
+zip.file("image.png").data;
+zip.files["image.png"].data;
+
+// after
+zip.file("test.txt").asText();
+zip.files["test.txt"].asText();
+zip.file("image.png").asBinary();
+zip.files["image.png"].asBinary();
+```
diff --git a/afb-client/bower_components/jszip/index.html b/afb-client/bower_components/jszip/index.html
new file mode 100644
index 0000000..0939ee9
--- /dev/null
+++ b/afb-client/bower_components/jszip/index.html
@@ -0,0 +1,169 @@
+---
+title: JSZip
+layout: default
+section: main
+---
+
+<div class="row">
+<div class="col-md-5">
+
+JSZip is a javascript library for creating, reading and editing .zip files, with a
+lovely and simple API.
+
+</div>
+<div class="col-md-7">
+<p>
+ <strong>Current version</strong> : v2.5.0
+</p>
+<p>
+ <strong>License</strong> : JSZip is dual-licensed. You may use it under the
+ MIT license <em>or</em> the GPLv3 license. See
+ <a href="https://github.com/Stuk/jszip/blob/master/LICENSE.markdown">LICENSE.markdown</a>.
+</p>
+</div>
+
+<div class="row">
+<div class="col-md-5">
+
+<h3>Example</h3>
+
+<script type="text/javascript">
+imgData = "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=";
+
+jQuery(function($) {
+ if(!JSZip.support.blob) {
+ $("#demo-not-supported").removeClass("hidden");
+ $("#demo").hide();
+ return;
+ }
+ $("#demo").click(function () {
+ try {
+ eval($("#demo-code").val());
+ $("#status")
+ .removeClass()
+ .addClass("text-success")
+ .text("Done!");
+ }
+ catch (e) {
+ $("#status")
+ .removeClass()
+ .addClass("text-danger")
+ .text(e);
+ }
+ });
+});
+
+</script>
+<textarea class="form-control" id="demo-code" rows="7" spellcheck="false">
+var zip = new JSZip();
+zip.file("Hello.txt", "Hello World\n");
+var img = zip.folder("images");
+img.file("smile.gif", imgData, {base64: true});
+var content = zip.generate({type:"blob"});
+// see FileSaver.js
+saveAs(content, "example.zip");</textarea>
+<button id="demo" class="btn btn-primary">Run!</button>
+<span id="status"></span>
+<div id="demo-not-supported" class="alert alert-danger hidden">
+ This browser doesn't support blobs, this demo won't work :(
+ See <a href="{{site.baseurl}}/documentation/howto/write_zip.html" class="alert-link">here for more info</a>.
+</div>
+</div>
+<div class="col-md-7">
+
+<h3>Installation</h3>
+
+<p>
+ <strong>With npm</strong> : <code>npm install jszip</code>
+</p>
+<p>
+ <strong>With bower</strong> : <code>bower install Stuk/jszip</code>
+</p>
+<p>
+ <strong>With component</strong> : <code>component install Stuk/jszip</code>
+</p>
+<p>
+ <strong>Manually</strong> : <a href="http://github.com/Stuk/jszip/zipball/master">download JSZip</a>
+ and include the file <code>dist/jszip.js</code> or <code>dist/jszip.min.js</code>
+</p>
+<br>
+<p>
+ Installed ? Great ! You can now check our
+ <a href="{{site.baseurl}}/documentation/examples.html">guides and examples !</a>
+</p>
+</div>
+</div>
+
+<h3>Support</h3>
+
+<table class="browser_support">
+ <tr>
+ <th class="support_op">Opera</th>
+ <th class="support_ff">Firefox</th>
+ <th class="support_sf">Safari</th>
+ <th class="support_cr">Chrome</th>
+ <th class="support_ie">Internet Explorer</th>
+ <th class="support_nd">Node.js</th>
+ </tr>
+ <tr>
+ <td>Yes</td>
+ <td>Yes</td>
+ <td>Yes</td>
+ <td>Yes</td>
+ <td>Yes</td>
+ <td>Yes</td>
+ </tr>
+ <tr>
+ <td>Tested with the latest version</td>
+ <td>Tested with 3.0 / 3.6 / latest version</td>
+ <td>Tested with the latest version</td>
+ <td>Tested with the latest version</td>
+ <td>Tested with IE 6 / 7 / 8 / 9 / 10</td>
+ <td>Tested with node.js 0.8 and 0.10</td>
+ </tr>
+</table>
+
+<h3>Getting help</h3>
+
+<p>
+Having trouble ? We'd like to help !
+</p>
+<ul>
+ <li>
+ Try the <a href="{{site.baseurl}}/documentation/faq.html">FAQ</a>, it has
+ answers to common questions.
+ </li>
+ <li>
+ If you're looking for informations about a specific method, try the
+ <a href="{{site.baseurl}}/documentation/api_jszip.html">documentation</a>.
+ </li>
+ <li>
+ Check the
+ <a href="{{site.baseurl}}/documentation/examples.html">examples</a>.
+ </li>
+ <li>
+ Report bugs in our
+ <a href="https://github.com/Stuk/jszip/issues">Bug tracker</a>.
+ </li>
+</ul>
+
+<h3>Test status</h3>
+
+<dl class="dl-horizontal">
+ <dt>Travis build :</dt>
+ <dd>
+ <a href="http://travis-ci.org/Stuk/jszip">
+ <img src="https://api.travis-ci.org/Stuk/jszip.svg?branch=master" alt="" />
+ </a>
+ </dd>
+ <dt>Saucelabs build :</dt>
+ <dd>
+ <a href="https://saucelabs.com/u/jszip">
+ <img src="https://saucelabs.com/browser-matrix/jszip.svg" alt="" />
+ </a>
+ </dd>
+ <dt>Live tests :</dt>
+ <dd>
+ <a href="{{site.baseurl}}/test/">See for yourself !</a>
+ </dd>
+</dl>
diff --git a/afb-client/bower_components/jszip/lib/base64.js b/afb-client/bower_components/jszip/lib/base64.js
new file mode 100644
index 0000000..13b4863
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/base64.js
@@ -0,0 +1,70 @@
+'use strict';
+// private property
+var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+
+// public method for encoding
+exports.encode = function(input, utf8) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ }
+ else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
+
+ }
+
+ return output;
+};
+
+// public method for decoding
+exports.decode = function(input, utf8) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = _keyStr.indexOf(input.charAt(i++));
+ enc2 = _keyStr.indexOf(input.charAt(i++));
+ enc3 = _keyStr.indexOf(input.charAt(i++));
+ enc4 = _keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ return output;
+
+};
diff --git a/afb-client/bower_components/jszip/lib/compressedObject.js b/afb-client/bower_components/jszip/lib/compressedObject.js
new file mode 100644
index 0000000..d6de504
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/compressedObject.js
@@ -0,0 +1,28 @@
+'use strict';
+function CompressedObject() {
+ this.compressedSize = 0;
+ this.uncompressedSize = 0;
+ this.crc32 = 0;
+ this.compressionMethod = null;
+ this.compressedContent = null;
+}
+
+CompressedObject.prototype = {
+ /**
+ * Return the decompressed content in an unspecified format.
+ * The format will depend on the decompressor.
+ * @return {Object} the decompressed content.
+ */
+ getContent: function() {
+ return null; // see implementation
+ },
+ /**
+ * Return the compressed content in an unspecified format.
+ * The format will depend on the compressed conten source.
+ * @return {Object} the compressed content.
+ */
+ getCompressedContent: function() {
+ return null; // see implementation
+ }
+};
+module.exports = CompressedObject;
diff --git a/afb-client/bower_components/jszip/lib/compressions.js b/afb-client/bower_components/jszip/lib/compressions.js
new file mode 100644
index 0000000..a2c13ff
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/compressions.js
@@ -0,0 +1,13 @@
+'use strict';
+exports.STORE = {
+ magic: "\x00\x00",
+ compress: function(content, compressionOptions) {
+ return content; // no compression
+ },
+ uncompress: function(content) {
+ return content; // no compression
+ },
+ compressInputType: null,
+ uncompressInputType: null
+};
+exports.DEFLATE = require('./flate');
diff --git a/afb-client/bower_components/jszip/lib/crc32.js b/afb-client/bower_components/jszip/lib/crc32.js
new file mode 100644
index 0000000..48d4a4a
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/crc32.js
@@ -0,0 +1,102 @@
+'use strict';
+
+var utils = require('./utils');
+
+var table = [
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+];
+
+/**
+ *
+ * Javascript crc32
+ * http://www.webtoolkit.info/
+ *
+ */
+module.exports = function crc32(input, crc) {
+ if (typeof input === "undefined" || !input.length) {
+ return 0;
+ }
+
+ var isArray = utils.getTypeOf(input) !== "string";
+
+ if (typeof(crc) == "undefined") {
+ crc = 0;
+ }
+ var x = 0;
+ var y = 0;
+ var b = 0;
+
+ crc = crc ^ (-1);
+ for (var i = 0, iTop = input.length; i < iTop; i++) {
+ b = isArray ? input[i] : input.charCodeAt(i);
+ y = (crc ^ b) & 0xFF;
+ x = table[y];
+ crc = (crc >>> 8) ^ x;
+ }
+
+ return crc ^ (-1);
+};
+// vim: set shiftwidth=4 softtabstop=4:
diff --git a/afb-client/bower_components/jszip/lib/dataReader.js b/afb-client/bower_components/jszip/lib/dataReader.js
new file mode 100644
index 0000000..22e8cb3
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/dataReader.js
@@ -0,0 +1,107 @@
+'use strict';
+var utils = require('./utils');
+
+function DataReader(data) {
+ this.data = null; // type : see implementation
+ this.length = 0;
+ this.index = 0;
+}
+DataReader.prototype = {
+ /**
+ * Check that the offset will not go too far.
+ * @param {string} offset the additional offset to check.
+ * @throws {Error} an Error if the offset is out of bounds.
+ */
+ checkOffset: function(offset) {
+ this.checkIndex(this.index + offset);
+ },
+ /**
+ * Check that the specifed index will not be too far.
+ * @param {string} newIndex the index to check.
+ * @throws {Error} an Error if the index is out of bounds.
+ */
+ checkIndex: function(newIndex) {
+ if (this.length < newIndex || newIndex < 0) {
+ throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?");
+ }
+ },
+ /**
+ * Change the index.
+ * @param {number} newIndex The new index.
+ * @throws {Error} if the new index is out of the data.
+ */
+ setIndex: function(newIndex) {
+ this.checkIndex(newIndex);
+ this.index = newIndex;
+ },
+ /**
+ * Skip the next n bytes.
+ * @param {number} n the number of bytes to skip.
+ * @throws {Error} if the new index is out of the data.
+ */
+ skip: function(n) {
+ this.setIndex(this.index + n);
+ },
+ /**
+ * Get the byte at the specified index.
+ * @param {number} i the index to use.
+ * @return {number} a byte.
+ */
+ byteAt: function(i) {
+ // see implementations
+ },
+ /**
+ * Get the next number with a given byte size.
+ * @param {number} size the number of bytes to read.
+ * @return {number} the corresponding number.
+ */
+ readInt: function(size) {
+ var result = 0,
+ i;
+ this.checkOffset(size);
+ for (i = this.index + size - 1; i >= this.index; i--) {
+ result = (result << 8) + this.byteAt(i);
+ }
+ this.index += size;
+ return result;
+ },
+ /**
+ * Get the next string with a given byte size.
+ * @param {number} size the number of bytes to read.
+ * @return {string} the corresponding string.
+ */
+ readString: function(size) {
+ return utils.transformTo("string", this.readData(size));
+ },
+ /**
+ * Get raw data without conversion, <size> bytes.
+ * @param {number} size the number of bytes to read.
+ * @return {Object} the raw data, implementation specific.
+ */
+ readData: function(size) {
+ // see implementations
+ },
+ /**
+ * Find the last occurence of a zip signature (4 bytes).
+ * @param {string} sig the signature to find.
+ * @return {number} the index of the last occurence, -1 if not found.
+ */
+ lastIndexOfSignature: function(sig) {
+ // see implementations
+ },
+ /**
+ * Get the next date.
+ * @return {Date} the date.
+ */
+ readDate: function() {
+ var dostime = this.readInt(4);
+ return new Date(
+ ((dostime >> 25) & 0x7f) + 1980, // year
+ ((dostime >> 21) & 0x0f) - 1, // month
+ (dostime >> 16) & 0x1f, // day
+ (dostime >> 11) & 0x1f, // hour
+ (dostime >> 5) & 0x3f, // minute
+ (dostime & 0x1f) << 1); // second
+ }
+};
+module.exports = DataReader;
diff --git a/afb-client/bower_components/jszip/lib/defaults.js b/afb-client/bower_components/jszip/lib/defaults.js
new file mode 100644
index 0000000..720c4da
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/defaults.js
@@ -0,0 +1,11 @@
+'use strict';
+exports.base64 = false;
+exports.binary = false;
+exports.dir = false;
+exports.createFolders = false;
+exports.date = null;
+exports.compression = null;
+exports.compressionOptions = null;
+exports.comment = null;
+exports.unixPermissions = null;
+exports.dosPermissions = null;
diff --git a/afb-client/bower_components/jszip/lib/deprecatedPublicUtils.js b/afb-client/bower_components/jszip/lib/deprecatedPublicUtils.js
new file mode 100644
index 0000000..0c6b9b8
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/deprecatedPublicUtils.js
@@ -0,0 +1,105 @@
+'use strict';
+var utils = require('./utils');
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2binary = function(str) {
+ return utils.string2binary(str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2Uint8Array = function(str) {
+ return utils.transformTo("uint8array", str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.uint8Array2String = function(array) {
+ return utils.transformTo("string", array);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.string2Blob = function(str) {
+ var buffer = utils.transformTo("arraybuffer", str);
+ return utils.arrayBuffer2Blob(buffer);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.arrayBuffer2Blob = function(buffer) {
+ return utils.arrayBuffer2Blob(buffer);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.transformTo = function(outputType, input) {
+ return utils.transformTo(outputType, input);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.getTypeOf = function(input) {
+ return utils.getTypeOf(input);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.checkSupport = function(type) {
+ return utils.checkSupport(type);
+};
+
+/**
+ * @deprecated
+ * This value will be removed in a future version without replacement.
+ */
+exports.MAX_VALUE_16BITS = utils.MAX_VALUE_16BITS;
+
+/**
+ * @deprecated
+ * This value will be removed in a future version without replacement.
+ */
+exports.MAX_VALUE_32BITS = utils.MAX_VALUE_32BITS;
+
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.pretty = function(str) {
+ return utils.pretty(str);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.findCompression = function(compressionMethod) {
+ return utils.findCompression(compressionMethod);
+};
+
+/**
+ * @deprecated
+ * This function will be removed in a future version without replacement.
+ */
+exports.isRegExp = function (object) {
+ return utils.isRegExp(object);
+};
+
diff --git a/afb-client/bower_components/jszip/lib/flate.js b/afb-client/bower_components/jszip/lib/flate.js
new file mode 100644
index 0000000..d138177
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/flate.js
@@ -0,0 +1,16 @@
+'use strict';
+var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined');
+
+var pako = require("pako");
+exports.uncompressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
+exports.compressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
+
+exports.magic = "\x08\x00";
+exports.compress = function(input, compressionOptions) {
+ return pako.deflateRaw(input, {
+ level : compressionOptions.level || -1 // default compression
+ });
+};
+exports.uncompress = function(input) {
+ return pako.inflateRaw(input);
+};
diff --git a/afb-client/bower_components/jszip/lib/index.js b/afb-client/bower_components/jszip/lib/index.js
new file mode 100644
index 0000000..96c3389
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/index.js
@@ -0,0 +1,79 @@
+'use strict';
+
+var base64 = require('./base64');
+
+/**
+Usage:
+ zip = new JSZip();
+ zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing");
+ zip.folder("images").file("smile.gif", base64Data, {base64: true});
+ zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
+ zip.remove("tempfile");
+
+ base64zip = zip.generate();
+
+**/
+
+/**
+ * Representation a of zip file in js
+ * @constructor
+ * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional).
+ * @param {Object=} options the options for creating this objects (optional).
+ */
+function JSZip(data, options) {
+ // if this constructor is used without `new`, it adds `new` before itself:
+ if(!(this instanceof JSZip)) return new JSZip(data, options);
+
+ // object containing the files :
+ // {
+ // "folder/" : {...},
+ // "folder/data.txt" : {...}
+ // }
+ this.files = {};
+
+ this.comment = null;
+
+ // Where we are in the hierarchy
+ this.root = "";
+ if (data) {
+ this.load(data, options);
+ }
+ this.clone = function() {
+ var newObj = new JSZip();
+ for (var i in this) {
+ if (typeof this[i] !== "function") {
+ newObj[i] = this[i];
+ }
+ }
+ return newObj;
+ };
+}
+JSZip.prototype = require('./object');
+JSZip.prototype.load = require('./load');
+JSZip.support = require('./support');
+JSZip.defaults = require('./defaults');
+
+/**
+ * @deprecated
+ * This namespace will be removed in a future version without replacement.
+ */
+JSZip.utils = require('./deprecatedPublicUtils');
+
+JSZip.base64 = {
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ encode : function(input) {
+ return base64.encode(input);
+ },
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ decode : function(input) {
+ return base64.decode(input);
+ }
+};
+JSZip.compressions = require('./compressions');
+module.exports = JSZip;
diff --git a/afb-client/bower_components/jszip/lib/license_header.js b/afb-client/bower_components/jszip/lib/license_header.js
new file mode 100644
index 0000000..b156bc7
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/license_header.js
@@ -0,0 +1,11 @@
+/*!
+
+JSZip - A Javascript class for generating and reading zip files
+<http://stuartk.com/jszip>
+
+(c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
+Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
+
+JSZip uses the library pako released under the MIT license :
+https://github.com/nodeca/pako/blob/master/LICENSE
+*/
diff --git a/afb-client/bower_components/jszip/lib/load.js b/afb-client/bower_components/jszip/lib/load.js
new file mode 100644
index 0000000..e003110
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/load.js
@@ -0,0 +1,31 @@
+'use strict';
+var base64 = require('./base64');
+var ZipEntries = require('./zipEntries');
+module.exports = function(data, options) {
+ var files, zipEntries, i, input;
+ options = options || {};
+ if (options.base64) {
+ data = base64.decode(data);
+ }
+
+ zipEntries = new ZipEntries(data, options);
+ files = zipEntries.files;
+ for (i = 0; i < files.length; i++) {
+ input = files[i];
+ this.file(input.fileName, input.decompressed, {
+ binary: true,
+ optimizedBinaryString: true,
+ date: input.date,
+ dir: input.dir,
+ comment : input.fileComment.length ? input.fileComment : null,
+ unixPermissions : input.unixPermissions,
+ dosPermissions : input.dosPermissions,
+ createFolders: options.createFolders
+ });
+ }
+ if (zipEntries.zipComment.length) {
+ this.comment = zipEntries.zipComment;
+ }
+
+ return this;
+};
diff --git a/afb-client/bower_components/jszip/lib/nodeBuffer.js b/afb-client/bower_components/jszip/lib/nodeBuffer.js
new file mode 100644
index 0000000..84694f6
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/nodeBuffer.js
@@ -0,0 +1,7 @@
+'use strict';
+module.exports = function(data, encoding){
+ return new Buffer(data, encoding);
+};
+module.exports.test = function(b){
+ return Buffer.isBuffer(b);
+};
diff --git a/afb-client/bower_components/jszip/lib/nodeBufferReader.js b/afb-client/bower_components/jszip/lib/nodeBufferReader.js
new file mode 100644
index 0000000..223bd0b
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/nodeBufferReader.js
@@ -0,0 +1,20 @@
+'use strict';
+var Uint8ArrayReader = require('./uint8ArrayReader');
+
+function NodeBufferReader(data) {
+ this.data = data;
+ this.length = this.data.length;
+ this.index = 0;
+}
+NodeBufferReader.prototype = new Uint8ArrayReader();
+
+/**
+ * @see DataReader.readData
+ */
+NodeBufferReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ var result = this.data.slice(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = NodeBufferReader;
diff --git a/afb-client/bower_components/jszip/lib/object.js b/afb-client/bower_components/jszip/lib/object.js
new file mode 100644
index 0000000..3b5e5b8
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/object.js
@@ -0,0 +1,883 @@
+'use strict';
+var support = require('./support');
+var utils = require('./utils');
+var crc32 = require('./crc32');
+var signature = require('./signature');
+var defaults = require('./defaults');
+var base64 = require('./base64');
+var compressions = require('./compressions');
+var CompressedObject = require('./compressedObject');
+var nodeBuffer = require('./nodeBuffer');
+var utf8 = require('./utf8');
+var StringWriter = require('./stringWriter');
+var Uint8ArrayWriter = require('./uint8ArrayWriter');
+
+/**
+ * Returns the raw data of a ZipObject, decompress the content if necessary.
+ * @param {ZipObject} file the file to use.
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
+ */
+var getRawData = function(file) {
+ if (file._data instanceof CompressedObject) {
+ file._data = file._data.getContent();
+ file.options.binary = true;
+ file.options.base64 = false;
+
+ if (utils.getTypeOf(file._data) === "uint8array") {
+ var copy = file._data;
+ // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
+ // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
+ file._data = new Uint8Array(copy.length);
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
+ if (copy.length !== 0) {
+ file._data.set(copy, 0);
+ }
+ }
+ }
+ return file._data;
+};
+
+/**
+ * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.
+ * @param {ZipObject} file the file to use.
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
+ */
+var getBinaryData = function(file) {
+ var result = getRawData(file),
+ type = utils.getTypeOf(result);
+ if (type === "string") {
+ if (!file.options.binary) {
+ // unicode text !
+ // unicode string => binary string is a painful process, check if we can avoid it.
+ if (support.nodebuffer) {
+ return nodeBuffer(result, "utf-8");
+ }
+ }
+ return file.asBinary();
+ }
+ return result;
+};
+
+/**
+ * Transform this._data into a string.
+ * @param {function} filter a function String -> String, applied if not null on the result.
+ * @return {String} the string representing this._data.
+ */
+var dataToString = function(asUTF8) {
+ var result = getRawData(this);
+ if (result === null || typeof result === "undefined") {
+ return "";
+ }
+ // if the data is a base64 string, we decode it before checking the encoding !
+ if (this.options.base64) {
+ result = base64.decode(result);
+ }
+ if (asUTF8 && this.options.binary) {
+ // JSZip.prototype.utf8decode supports arrays as input
+ // skip to array => string step, utf8decode will do it.
+ result = out.utf8decode(result);
+ }
+ else {
+ // no utf8 transformation, do the array => string step.
+ result = utils.transformTo("string", result);
+ }
+
+ if (!asUTF8 && !this.options.binary) {
+ result = utils.transformTo("string", out.utf8encode(result));
+ }
+ return result;
+};
+/**
+ * A simple object representing a file in the zip file.
+ * @constructor
+ * @param {string} name the name of the file
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data
+ * @param {Object} options the options of the file
+ */
+var ZipObject = function(name, data, options) {
+ this.name = name;
+ this.dir = options.dir;
+ this.date = options.date;
+ this.comment = options.comment;
+ this.unixPermissions = options.unixPermissions;
+ this.dosPermissions = options.dosPermissions;
+
+ this._data = data;
+ this.options = options;
+
+ /*
+ * This object contains initial values for dir and date.
+ * With them, we can check if the user changed the deprecated metadata in
+ * `ZipObject#options` or not.
+ */
+ this._initialMetadata = {
+ dir : options.dir,
+ date : options.date
+ };
+};
+
+ZipObject.prototype = {
+ /**
+ * Return the content as UTF8 string.
+ * @return {string} the UTF8 string.
+ */
+ asText: function() {
+ return dataToString.call(this, true);
+ },
+ /**
+ * Returns the binary content.
+ * @return {string} the content as binary.
+ */
+ asBinary: function() {
+ return dataToString.call(this, false);
+ },
+ /**
+ * Returns the content as a nodejs Buffer.
+ * @return {Buffer} the content as a Buffer.
+ */
+ asNodeBuffer: function() {
+ var result = getBinaryData(this);
+ return utils.transformTo("nodebuffer", result);
+ },
+ /**
+ * Returns the content as an Uint8Array.
+ * @return {Uint8Array} the content as an Uint8Array.
+ */
+ asUint8Array: function() {
+ var result = getBinaryData(this);
+ return utils.transformTo("uint8array", result);
+ },
+ /**
+ * Returns the content as an ArrayBuffer.
+ * @return {ArrayBuffer} the content as an ArrayBufer.
+ */
+ asArrayBuffer: function() {
+ return this.asUint8Array().buffer;
+ }
+};
+
+/**
+ * Transform an integer into a string in hexadecimal.
+ * @private
+ * @param {number} dec the number to convert.
+ * @param {number} bytes the number of bytes to generate.
+ * @returns {string} the result.
+ */
+var decToHex = function(dec, bytes) {
+ var hex = "",
+ i;
+ for (i = 0; i < bytes; i++) {
+ hex += String.fromCharCode(dec & 0xff);
+ dec = dec >>> 8;
+ }
+ return hex;
+};
+
+/**
+ * Merge the objects passed as parameters into a new one.
+ * @private
+ * @param {...Object} var_args All objects to merge.
+ * @return {Object} a new object with the data of the others.
+ */
+var extend = function() {
+ var result = {}, i, attr;
+ for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
+ for (attr in arguments[i]) {
+ if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
+ result[attr] = arguments[i][attr];
+ }
+ }
+ }
+ return result;
+};
+
+/**
+ * Transforms the (incomplete) options from the user into the complete
+ * set of options to create a file.
+ * @private
+ * @param {Object} o the options from the user.
+ * @return {Object} the complete set of options.
+ */
+var prepareFileAttrs = function(o) {
+ o = o || {};
+ if (o.base64 === true && (o.binary === null || o.binary === undefined)) {
+ o.binary = true;
+ }
+ o = extend(o, defaults);
+ o.date = o.date || new Date();
+ if (o.compression !== null) o.compression = o.compression.toUpperCase();
+
+ return o;
+};
+
+/**
+ * Add a file in the current folder.
+ * @private
+ * @param {string} name the name of the file
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file
+ * @param {Object} o the options of the file
+ * @return {Object} the new file.
+ */
+var fileAdd = function(name, data, o) {
+ // be sure sub folders exist
+ var dataType = utils.getTypeOf(data),
+ parent;
+
+ o = prepareFileAttrs(o);
+
+ if (typeof o.unixPermissions === "string") {
+ o.unixPermissions = parseInt(o.unixPermissions, 8);
+ }
+
+ // UNX_IFDIR 0040000 see zipinfo.c
+ if (o.unixPermissions && (o.unixPermissions & 0x4000)) {
+ o.dir = true;
+ }
+ // Bit 4 Directory
+ if (o.dosPermissions && (o.dosPermissions & 0x0010)) {
+ o.dir = true;
+ }
+
+ if (o.dir) {
+ name = forceTrailingSlash(name);
+ }
+
+ if (o.createFolders && (parent = parentFolder(name))) {
+ folderAdd.call(this, parent, true);
+ }
+
+ if (o.dir || data === null || typeof data === "undefined") {
+ o.base64 = false;
+ o.binary = false;
+ data = null;
+ dataType = null;
+ }
+ else if (dataType === "string") {
+ if (o.binary && !o.base64) {
+ // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask
+ if (o.optimizedBinaryString !== true) {
+ // this is a string, not in a base64 format.
+ // Be sure that this is a correct "binary string"
+ data = utils.string2binary(data);
+ }
+ }
+ }
+ else { // arraybuffer, uint8array, ...
+ o.base64 = false;
+ o.binary = true;
+
+ if (!dataType && !(data instanceof CompressedObject)) {
+ throw new Error("The data of '" + name + "' is in an unsupported format !");
+ }
+
+ // special case : it's way easier to work with Uint8Array than with ArrayBuffer
+ if (dataType === "arraybuffer") {
+ data = utils.transformTo("uint8array", data);
+ }
+ }
+
+ var object = new ZipObject(name, data, o);
+ this.files[name] = object;
+ return object;
+};
+
+/**
+ * Find the parent folder of the path.
+ * @private
+ * @param {string} path the path to use
+ * @return {string} the parent folder, or ""
+ */
+var parentFolder = function (path) {
+ if (path.slice(-1) == '/') {
+ path = path.substring(0, path.length - 1);
+ }
+ var lastSlash = path.lastIndexOf('/');
+ return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
+};
+
+
+/**
+ * Returns the path with a slash at the end.
+ * @private
+ * @param {String} path the path to check.
+ * @return {String} the path with a trailing slash.
+ */
+var forceTrailingSlash = function(path) {
+ // Check the name ends with a /
+ if (path.slice(-1) != "/") {
+ path += "/"; // IE doesn't like substr(-1)
+ }
+ return path;
+};
+/**
+ * Add a (sub) folder in the current folder.
+ * @private
+ * @param {string} name the folder's name
+ * @param {boolean=} [createFolders] If true, automatically create sub
+ * folders. Defaults to false.
+ * @return {Object} the new folder.
+ */
+var folderAdd = function(name, createFolders) {
+ createFolders = (typeof createFolders !== 'undefined') ? createFolders : false;
+
+ name = forceTrailingSlash(name);
+
+ // Does this folder already exist?
+ if (!this.files[name]) {
+ fileAdd.call(this, name, null, {
+ dir: true,
+ createFolders: createFolders
+ });
+ }
+ return this.files[name];
+};
+
+/**
+ * Generate a JSZip.CompressedObject for a given zipOject.
+ * @param {ZipObject} file the object to read.
+ * @param {JSZip.compression} compression the compression to use.
+ * @param {Object} compressionOptions the options to use when compressing.
+ * @return {JSZip.CompressedObject} the compressed result.
+ */
+var generateCompressedObjectFrom = function(file, compression, compressionOptions) {
+ var result = new CompressedObject(),
+ content;
+
+ // the data has not been decompressed, we might reuse things !
+ if (file._data instanceof CompressedObject) {
+ result.uncompressedSize = file._data.uncompressedSize;
+ result.crc32 = file._data.crc32;
+
+ if (result.uncompressedSize === 0 || file.dir) {
+ compression = compressions['STORE'];
+ result.compressedContent = "";
+ result.crc32 = 0;
+ }
+ else if (file._data.compressionMethod === compression.magic) {
+ result.compressedContent = file._data.getCompressedContent();
+ }
+ else {
+ content = file._data.getContent();
+ // need to decompress / recompress
+ result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions);
+ }
+ }
+ else {
+ // have uncompressed data
+ content = getBinaryData(file);
+ if (!content || content.length === 0 || file.dir) {
+ compression = compressions['STORE'];
+ content = "";
+ }
+ result.uncompressedSize = content.length;
+ result.crc32 = crc32(content);
+ result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions);
+ }
+
+ result.compressedSize = result.compressedContent.length;
+ result.compressionMethod = compression.magic;
+
+ return result;
+};
+
+
+
+
+/**
+ * Generate the UNIX part of the external file attributes.
+ * @param {Object} unixPermissions the unix permissions or null.
+ * @param {Boolean} isDir true if the entry is a directory, false otherwise.
+ * @return {Number} a 32 bit integer.
+ *
+ * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute :
+ *
+ * TTTTsstrwxrwxrwx0000000000ADVSHR
+ * ^^^^____________________________ file type, see zipinfo.c (UNX_*)
+ * ^^^_________________________ setuid, setgid, sticky
+ * ^^^^^^^^^________________ permissions
+ * ^^^^^^^^^^______ not used ?
+ * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only
+ */
+var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
+
+ var result = unixPermissions;
+ if (!unixPermissions) {
+ // I can't use octal values in strict mode, hence the hexa.
+ // 040775 => 0x41fd
+ // 0100664 => 0x81b4
+ result = isDir ? 0x41fd : 0x81b4;
+ }
+
+ return (result & 0xFFFF) << 16;
+};
+
+/**
+ * Generate the DOS part of the external file attributes.
+ * @param {Object} dosPermissions the dos permissions or null.
+ * @param {Boolean} isDir true if the entry is a directory, false otherwise.
+ * @return {Number} a 32 bit integer.
+ *
+ * Bit 0 Read-Only
+ * Bit 1 Hidden
+ * Bit 2 System
+ * Bit 3 Volume Label
+ * Bit 4 Directory
+ * Bit 5 Archive
+ */
+var generateDosExternalFileAttr = function (dosPermissions, isDir) {
+
+ // the dir flag is already set for compatibility
+
+ return (dosPermissions || 0) & 0x3F;
+};
+
+/**
+ * Generate the various parts used in the construction of the final zip file.
+ * @param {string} name the file name.
+ * @param {ZipObject} file the file content.
+ * @param {JSZip.CompressedObject} compressedObject the compressed object.
+ * @param {number} offset the current offset from the start of the zip file.
+ * @param {String} platform let's pretend we are this platform (change platform dependents fields)
+ * @return {object} the zip parts.
+ */
+var generateZipParts = function(name, file, compressedObject, offset, platform) {
+ var data = compressedObject.compressedContent,
+ utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)),
+ comment = file.comment || "",
+ utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)),
+ useUTF8ForFileName = utfEncodedFileName.length !== file.name.length,
+ useUTF8ForComment = utfEncodedComment.length !== comment.length,
+ o = file.options,
+ dosTime,
+ dosDate,
+ extraFields = "",
+ unicodePathExtraField = "",
+ unicodeCommentExtraField = "",
+ dir, date;
+
+
+ // handle the deprecated options.dir
+ if (file._initialMetadata.dir !== file.dir) {
+ dir = file.dir;
+ } else {
+ dir = o.dir;
+ }
+
+ // handle the deprecated options.date
+ if(file._initialMetadata.date !== file.date) {
+ date = file.date;
+ } else {
+ date = o.date;
+ }
+
+ var extFileAttr = 0;
+ var versionMadeBy = 0;
+ if (dir) {
+ // dos or unix, we set the dos dir flag
+ extFileAttr |= 0x00010;
+ }
+ if(platform === "UNIX") {
+ versionMadeBy = 0x031E; // UNIX, version 3.0
+ extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir);
+ } else { // DOS or other, fallback to DOS
+ versionMadeBy = 0x0014; // DOS, version 2.0
+ extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir);
+ }
+
+ // date
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
+
+ dosTime = date.getHours();
+ dosTime = dosTime << 6;
+ dosTime = dosTime | date.getMinutes();
+ dosTime = dosTime << 5;
+ dosTime = dosTime | date.getSeconds() / 2;
+
+ dosDate = date.getFullYear() - 1980;
+ dosDate = dosDate << 4;
+ dosDate = dosDate | (date.getMonth() + 1);
+ dosDate = dosDate << 5;
+ dosDate = dosDate | date.getDate();
+
+ if (useUTF8ForFileName) {
+ // set the unicode path extra field. unzip needs at least one extra
+ // field to correctly handle unicode path, so using the path is as good
+ // as any other information. This could improve the situation with
+ // other archive managers too.
+ // This field is usually used without the utf8 flag, with a non
+ // unicode path in the header (winrar, winzip). This helps (a bit)
+ // with the messy Windows' default compressed folders feature but
+ // breaks on p7zip which doesn't seek the unicode path extra field.
+ // So for now, UTF-8 everywhere !
+ unicodePathExtraField =
+ // Version
+ decToHex(1, 1) +
+ // NameCRC32
+ decToHex(crc32(utfEncodedFileName), 4) +
+ // UnicodeName
+ utfEncodedFileName;
+
+ extraFields +=
+ // Info-ZIP Unicode Path Extra Field
+ "\x75\x70" +
+ // size
+ decToHex(unicodePathExtraField.length, 2) +
+ // content
+ unicodePathExtraField;
+ }
+
+ if(useUTF8ForComment) {
+
+ unicodeCommentExtraField =
+ // Version
+ decToHex(1, 1) +
+ // CommentCRC32
+ decToHex(this.crc32(utfEncodedComment), 4) +
+ // UnicodeName
+ utfEncodedComment;
+
+ extraFields +=
+ // Info-ZIP Unicode Path Extra Field
+ "\x75\x63" +
+ // size
+ decToHex(unicodeCommentExtraField.length, 2) +
+ // content
+ unicodeCommentExtraField;
+ }
+
+ var header = "";
+
+ // version needed to extract
+ header += "\x0A\x00";
+ // general purpose bit flag
+ // set bit 11 if utf8
+ header += (useUTF8ForFileName || useUTF8ForComment) ? "\x00\x08" : "\x00\x00";
+ // compression method
+ header += compressedObject.compressionMethod;
+ // last mod file time
+ header += decToHex(dosTime, 2);
+ // last mod file date
+ header += decToHex(dosDate, 2);
+ // crc-32
+ header += decToHex(compressedObject.crc32, 4);
+ // compressed size
+ header += decToHex(compressedObject.compressedSize, 4);
+ // uncompressed size
+ header += decToHex(compressedObject.uncompressedSize, 4);
+ // file name length
+ header += decToHex(utfEncodedFileName.length, 2);
+ // extra field length
+ header += decToHex(extraFields.length, 2);
+
+
+ var fileRecord = signature.LOCAL_FILE_HEADER + header + utfEncodedFileName + extraFields;
+
+ var dirRecord = signature.CENTRAL_FILE_HEADER +
+ // version made by (00: DOS)
+ decToHex(versionMadeBy, 2) +
+ // file header (common to file and central directory)
+ header +
+ // file comment length
+ decToHex(utfEncodedComment.length, 2) +
+ // disk number start
+ "\x00\x00" +
+ // internal file attributes TODO
+ "\x00\x00" +
+ // external file attributes
+ decToHex(extFileAttr, 4) +
+ // relative offset of local header
+ decToHex(offset, 4) +
+ // file name
+ utfEncodedFileName +
+ // extra field
+ extraFields +
+ // file comment
+ utfEncodedComment;
+
+ return {
+ fileRecord: fileRecord,
+ dirRecord: dirRecord,
+ compressedObject: compressedObject
+ };
+};
+
+
+// return the actual prototype of JSZip
+var out = {
+ /**
+ * Read an existing zip and merge the data in the current JSZip object.
+ * The implementation is in jszip-load.js, don't forget to include it.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load
+ * @param {Object} options Options for loading the stream.
+ * options.base64 : is the stream in base64 ? default : false
+ * @return {JSZip} the current JSZip object
+ */
+ load: function(stream, options) {
+ throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
+ },
+
+ /**
+ * Filter nested files/folders with the specified function.
+ * @param {Function} search the predicate to use :
+ * function (relativePath, file) {...}
+ * It takes 2 arguments : the relative path and the file.
+ * @return {Array} An array of matching elements.
+ */
+ filter: function(search) {
+ var result = [],
+ filename, relativePath, file, fileClone;
+ for (filename in this.files) {
+ if (!this.files.hasOwnProperty(filename)) {
+ continue;
+ }
+ file = this.files[filename];
+ // return a new object, don't let the user mess with our internal objects :)
+ fileClone = new ZipObject(file.name, file._data, extend(file.options));
+ relativePath = filename.slice(this.root.length, filename.length);
+ if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
+ search(relativePath, fileClone)) { // and the file matches the function
+ result.push(fileClone);
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Add a file to the zip file, or search a file.
+ * @param {string|RegExp} name The name of the file to add (if data is defined),
+ * the name of the file to find (if no data) or a regex to match files.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
+ * @param {Object} o File options
+ * @return {JSZip|Object|Array} this JSZip object (when adding a file),
+ * a file (when searching by string) or an array of files (when searching by regex).
+ */
+ file: function(name, data, o) {
+ if (arguments.length === 1) {
+ if (utils.isRegExp(name)) {
+ var regexp = name;
+ return this.filter(function(relativePath, file) {
+ return !file.dir && regexp.test(relativePath);
+ });
+ }
+ else { // text
+ return this.filter(function(relativePath, file) {
+ return !file.dir && relativePath === name;
+ })[0] || null;
+ }
+ }
+ else { // more than one argument : we have data !
+ name = this.root + name;
+ fileAdd.call(this, name, data, o);
+ }
+ return this;
+ },
+
+ /**
+ * Add a directory to the zip file, or search.
+ * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
+ * @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
+ */
+ folder: function(arg) {
+ if (!arg) {
+ return this;
+ }
+
+ if (utils.isRegExp(arg)) {
+ return this.filter(function(relativePath, file) {
+ return file.dir && arg.test(relativePath);
+ });
+ }
+
+ // else, name is a new folder
+ var name = this.root + arg;
+ var newFolder = folderAdd.call(this, name);
+
+ // Allow chaining by returning a new object with this folder as the root
+ var ret = this.clone();
+ ret.root = newFolder.name;
+ return ret;
+ },
+
+ /**
+ * Delete a file, or a directory and all sub-files, from the zip
+ * @param {string} name the name of the file to delete
+ * @return {JSZip} this JSZip object
+ */
+ remove: function(name) {
+ name = this.root + name;
+ var file = this.files[name];
+ if (!file) {
+ // Look for any folders
+ if (name.slice(-1) != "/") {
+ name += "/";
+ }
+ file = this.files[name];
+ }
+
+ if (file && !file.dir) {
+ // file
+ delete this.files[name];
+ } else {
+ // maybe a folder, delete recursively
+ var kids = this.filter(function(relativePath, file) {
+ return file.name.slice(0, name.length) === name;
+ });
+ for (var i = 0; i < kids.length; i++) {
+ delete this.files[kids[i].name];
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * Generate the complete zip file
+ * @param {Object} options the options to generate the zip file :
+ * - base64, (deprecated, use type instead) true to generate base64.
+ * - compression, "STORE" by default.
+ * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
+ * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
+ */
+ generate: function(options) {
+ options = extend(options || {}, {
+ base64: true,
+ compression: "STORE",
+ compressionOptions : null,
+ type: "base64",
+ platform: "DOS",
+ comment: null,
+ mimeType: 'application/zip'
+ });
+
+ utils.checkSupport(options.type);
+
+ // accept nodejs `process.platform`
+ if(
+ options.platform === 'darwin' ||
+ options.platform === 'freebsd' ||
+ options.platform === 'linux' ||
+ options.platform === 'sunos'
+ ) {
+ options.platform = "UNIX";
+ }
+ if (options.platform === 'win32') {
+ options.platform = "DOS";
+ }
+
+ var zipData = [],
+ localDirLength = 0,
+ centralDirLength = 0,
+ writer, i,
+ utfEncodedComment = utils.transformTo("string", this.utf8encode(options.comment || this.comment || ""));
+
+ // first, generate all the zip parts.
+ for (var name in this.files) {
+ if (!this.files.hasOwnProperty(name)) {
+ continue;
+ }
+ var file = this.files[name];
+
+ var compressionName = file.options.compression || options.compression.toUpperCase();
+ var compression = compressions[compressionName];
+ if (!compression) {
+ throw new Error(compressionName + " is not a valid compression method !");
+ }
+ var compressionOptions = file.options.compressionOptions || options.compressionOptions || {};
+
+ var compressedObject = generateCompressedObjectFrom.call(this, file, compression, compressionOptions);
+
+ var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength, options.platform);
+ localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;
+ centralDirLength += zipPart.dirRecord.length;
+ zipData.push(zipPart);
+ }
+
+ var dirEnd = "";
+
+ // end of central dir signature
+ dirEnd = signature.CENTRAL_DIRECTORY_END +
+ // number of this disk
+ "\x00\x00" +
+ // number of the disk with the start of the central directory
+ "\x00\x00" +
+ // total number of entries in the central directory on this disk
+ decToHex(zipData.length, 2) +
+ // total number of entries in the central directory
+ decToHex(zipData.length, 2) +
+ // size of the central directory 4 bytes
+ decToHex(centralDirLength, 4) +
+ // offset of start of central directory with respect to the starting disk number
+ decToHex(localDirLength, 4) +
+ // .ZIP file comment length
+ decToHex(utfEncodedComment.length, 2) +
+ // .ZIP file comment
+ utfEncodedComment;
+
+
+ // we have all the parts (and the total length)
+ // time to create a writer !
+ var typeName = options.type.toLowerCase();
+ if(typeName==="uint8array"||typeName==="arraybuffer"||typeName==="blob"||typeName==="nodebuffer") {
+ writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);
+ }else{
+ writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);
+ }
+
+ for (i = 0; i < zipData.length; i++) {
+ writer.append(zipData[i].fileRecord);
+ writer.append(zipData[i].compressedObject.compressedContent);
+ }
+ for (i = 0; i < zipData.length; i++) {
+ writer.append(zipData[i].dirRecord);
+ }
+
+ writer.append(dirEnd);
+
+ var zip = writer.finalize();
+
+
+
+ switch(options.type.toLowerCase()) {
+ // case "zip is an Uint8Array"
+ case "uint8array" :
+ case "arraybuffer" :
+ case "nodebuffer" :
+ return utils.transformTo(options.type.toLowerCase(), zip);
+ case "blob" :
+ return utils.arrayBuffer2Blob(utils.transformTo("arraybuffer", zip), options.mimeType);
+ // case "zip is a string"
+ case "base64" :
+ return (options.base64) ? base64.encode(zip) : zip;
+ default : // case "string" :
+ return zip;
+ }
+
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ crc32: function (input, crc) {
+ return crc32(input, crc);
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ utf8encode: function (string) {
+ return utils.transformTo("string", utf8.utf8encode(string));
+ },
+
+ /**
+ * @deprecated
+ * This method will be removed in a future version without replacement.
+ */
+ utf8decode: function (input) {
+ return utf8.utf8decode(input);
+ }
+};
+module.exports = out;
diff --git a/afb-client/bower_components/jszip/lib/signature.js b/afb-client/bower_components/jszip/lib/signature.js
new file mode 100644
index 0000000..4ee817b
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/signature.js
@@ -0,0 +1,7 @@
+'use strict';
+exports.LOCAL_FILE_HEADER = "PK\x03\x04";
+exports.CENTRAL_FILE_HEADER = "PK\x01\x02";
+exports.CENTRAL_DIRECTORY_END = "PK\x05\x06";
+exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07";
+exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06";
+exports.DATA_DESCRIPTOR = "PK\x07\x08";
diff --git a/afb-client/bower_components/jszip/lib/stringReader.js b/afb-client/bower_components/jszip/lib/stringReader.js
new file mode 100644
index 0000000..895331e
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/stringReader.js
@@ -0,0 +1,36 @@
+'use strict';
+var DataReader = require('./dataReader');
+var utils = require('./utils');
+
+function StringReader(data, optimizedBinaryString) {
+ this.data = data;
+ if (!optimizedBinaryString) {
+ this.data = utils.string2binary(this.data);
+ }
+ this.length = this.data.length;
+ this.index = 0;
+}
+StringReader.prototype = new DataReader();
+/**
+ * @see DataReader.byteAt
+ */
+StringReader.prototype.byteAt = function(i) {
+ return this.data.charCodeAt(i);
+};
+/**
+ * @see DataReader.lastIndexOfSignature
+ */
+StringReader.prototype.lastIndexOfSignature = function(sig) {
+ return this.data.lastIndexOf(sig);
+};
+/**
+ * @see DataReader.readData
+ */
+StringReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ // this will work because the constructor applied the "& 0xff" mask.
+ var result = this.data.slice(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = StringReader;
diff --git a/afb-client/bower_components/jszip/lib/stringWriter.js b/afb-client/bower_components/jszip/lib/stringWriter.js
new file mode 100644
index 0000000..45db548
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/stringWriter.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var utils = require('./utils');
+
+/**
+ * An object to write any content to a string.
+ * @constructor
+ */
+var StringWriter = function() {
+ this.data = [];
+};
+StringWriter.prototype = {
+ /**
+ * Append any content to the current string.
+ * @param {Object} input the content to add.
+ */
+ append: function(input) {
+ input = utils.transformTo("string", input);
+ this.data.push(input);
+ },
+ /**
+ * Finalize the construction an return the result.
+ * @return {string} the generated string.
+ */
+ finalize: function() {
+ return this.data.join("");
+ }
+};
+
+module.exports = StringWriter;
diff --git a/afb-client/bower_components/jszip/lib/support.js b/afb-client/bower_components/jszip/lib/support.js
new file mode 100644
index 0000000..b9bbb1f
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/support.js
@@ -0,0 +1,34 @@
+'use strict';
+exports.base64 = true;
+exports.array = true;
+exports.string = true;
+exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
+// contains true if JSZip can read/generate nodejs Buffer, false otherwise.
+// Browserify will provide a Buffer implementation for browsers, which is
+// an augmented Uint8Array (i.e., can be used as either Buffer or U8).
+exports.nodebuffer = typeof Buffer !== "undefined";
+// contains true if JSZip can read/generate Uint8Array, false otherwise.
+exports.uint8array = typeof Uint8Array !== "undefined";
+
+if (typeof ArrayBuffer === "undefined") {
+ exports.blob = false;
+}
+else {
+ var buffer = new ArrayBuffer(0);
+ try {
+ exports.blob = new Blob([buffer], {
+ type: "application/zip"
+ }).size === 0;
+ }
+ catch (e) {
+ try {
+ var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ var builder = new Builder();
+ builder.append(buffer);
+ exports.blob = builder.getBlob('application/zip').size === 0;
+ }
+ catch (e) {
+ exports.blob = false;
+ }
+ }
+}
diff --git a/afb-client/bower_components/jszip/lib/uint8ArrayReader.js b/afb-client/bower_components/jszip/lib/uint8ArrayReader.js
new file mode 100644
index 0000000..ce8d1a8
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/uint8ArrayReader.js
@@ -0,0 +1,47 @@
+'use strict';
+var DataReader = require('./dataReader');
+
+function Uint8ArrayReader(data) {
+ if (data) {
+ this.data = data;
+ this.length = this.data.length;
+ this.index = 0;
+ }
+}
+Uint8ArrayReader.prototype = new DataReader();
+/**
+ * @see DataReader.byteAt
+ */
+Uint8ArrayReader.prototype.byteAt = function(i) {
+ return this.data[i];
+};
+/**
+ * @see DataReader.lastIndexOfSignature
+ */
+Uint8ArrayReader.prototype.lastIndexOfSignature = function(sig) {
+ var sig0 = sig.charCodeAt(0),
+ sig1 = sig.charCodeAt(1),
+ sig2 = sig.charCodeAt(2),
+ sig3 = sig.charCodeAt(3);
+ for (var i = this.length - 4; i >= 0; --i) {
+ if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) {
+ return i;
+ }
+ }
+
+ return -1;
+};
+/**
+ * @see DataReader.readData
+ */
+Uint8ArrayReader.prototype.readData = function(size) {
+ this.checkOffset(size);
+ if(size === 0) {
+ // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of [].
+ return new Uint8Array(0);
+ }
+ var result = this.data.subarray(this.index, this.index + size);
+ this.index += size;
+ return result;
+};
+module.exports = Uint8ArrayReader;
diff --git a/afb-client/bower_components/jszip/lib/uint8ArrayWriter.js b/afb-client/bower_components/jszip/lib/uint8ArrayWriter.js
new file mode 100644
index 0000000..405397f
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/uint8ArrayWriter.js
@@ -0,0 +1,36 @@
+'use strict';
+
+var utils = require('./utils');
+
+/**
+ * An object to write any content to an Uint8Array.
+ * @constructor
+ * @param {number} length The length of the array.
+ */
+var Uint8ArrayWriter = function(length) {
+ this.data = new Uint8Array(length);
+ this.index = 0;
+};
+Uint8ArrayWriter.prototype = {
+ /**
+ * Append any content to the current array.
+ * @param {Object} input the content to add.
+ */
+ append: function(input) {
+ if (input.length !== 0) {
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
+ input = utils.transformTo("uint8array", input);
+ this.data.set(input, this.index);
+ this.index += input.length;
+ }
+ },
+ /**
+ * Finalize the construction an return the result.
+ * @return {Uint8Array} the generated array.
+ */
+ finalize: function() {
+ return this.data;
+ }
+};
+
+module.exports = Uint8ArrayWriter;
diff --git a/afb-client/bower_components/jszip/lib/utf8.js b/afb-client/bower_components/jszip/lib/utf8.js
new file mode 100644
index 0000000..8cc16b4
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/utf8.js
@@ -0,0 +1,207 @@
+'use strict';
+
+var utils = require('./utils');
+var support = require('./support');
+var nodeBuffer = require('./nodeBuffer');
+
+/**
+ * The following functions come from pako, from pako/lib/utils/strings
+ * released under the MIT license, see pako https://github.com/nodeca/pako/
+ */
+
+// Table with utf8 lengths (calculated by first byte of sequence)
+// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
+// because max possible codepoint is 0x10ffff
+var _utf8len = new Array(256);
+for (var i=0; i<256; i++) {
+ _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
+}
+_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
+
+// convert string to array (typed, when possible)
+var string2buf = function (str) {
+ var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
+
+ // count binary size
+ for (m_pos = 0; m_pos < str_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
+ }
+
+ // allocate buffer
+ if (support.uint8array) {
+ buf = new Uint8Array(buf_len);
+ } else {
+ buf = new Array(buf_len);
+ }
+
+ // convert
+ for (i=0, m_pos = 0; i < buf_len; m_pos++) {
+ c = str.charCodeAt(m_pos);
+ if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
+ c2 = str.charCodeAt(m_pos+1);
+ if ((c2 & 0xfc00) === 0xdc00) {
+ c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+ m_pos++;
+ }
+ }
+ if (c < 0x80) {
+ /* one byte */
+ buf[i++] = c;
+ } else if (c < 0x800) {
+ /* two bytes */
+ buf[i++] = 0xC0 | (c >>> 6);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else if (c < 0x10000) {
+ /* three bytes */
+ buf[i++] = 0xE0 | (c >>> 12);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ } else {
+ /* four bytes */
+ buf[i++] = 0xf0 | (c >>> 18);
+ buf[i++] = 0x80 | (c >>> 12 & 0x3f);
+ buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+ buf[i++] = 0x80 | (c & 0x3f);
+ }
+ }
+
+ return buf;
+};
+
+// Calculate max possible position in utf8 buffer,
+// that will not break sequence. If that's not possible
+// - (very small limits) return max size as is.
+//
+// buf[] - utf8 bytes array
+// max - length limit (mandatory);
+var utf8border = function(buf, max) {
+ var pos;
+
+ max = max || buf.length;
+ if (max > buf.length) { max = buf.length; }
+
+ // go back from last position, until start of sequence found
+ pos = max-1;
+ while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
+
+ // Fuckup - very small and broken sequence,
+ // return max, because we should return something anyway.
+ if (pos < 0) { return max; }
+
+ // If we came to start of buffer - that means vuffer is too small,
+ // return max too.
+ if (pos === 0) { return max; }
+
+ return (pos + _utf8len[buf[pos]] > max) ? pos : max;
+};
+
+// convert array to string
+var buf2string = function (buf) {
+ var str, i, out, c, c_len;
+ var len = buf.length;
+
+ // Reserve max possible length (2 words per char)
+ // NB: by unknown reasons, Array is significantly faster for
+ // String.fromCharCode.apply than Uint16Array.
+ var utf16buf = new Array(len*2);
+
+ for (out=0, i=0; i<len;) {
+ c = buf[i++];
+ // quick process ascii
+ if (c < 0x80) { utf16buf[out++] = c; continue; }
+
+ c_len = _utf8len[c];
+ // skip 5 & 6 byte codes
+ if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
+
+ // apply mask on first byte
+ c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
+ // join the rest
+ while (c_len > 1 && i < len) {
+ c = (c << 6) | (buf[i++] & 0x3f);
+ c_len--;
+ }
+
+ // terminated by end of string?
+ if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
+
+ if (c < 0x10000) {
+ utf16buf[out++] = c;
+ } else {
+ c -= 0x10000;
+ utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
+ utf16buf[out++] = 0xdc00 | (c & 0x3ff);
+ }
+ }
+
+ // shrinkBuf(utf16buf, out)
+ if (utf16buf.length !== out) {
+ if(utf16buf.subarray) {
+ utf16buf = utf16buf.subarray(0, out);
+ } else {
+ utf16buf.length = out;
+ }
+ }
+
+ // return String.fromCharCode.apply(null, utf16buf);
+ return utils.applyFromCharCode(utf16buf);
+};
+
+
+// That's all for the pako functions.
+
+
+/**
+ * Transform a javascript string into an array (typed if possible) of bytes,
+ * UTF-8 encoded.
+ * @param {String} str the string to encode
+ * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string.
+ */
+exports.utf8encode = function utf8encode(str) {
+ if (support.nodebuffer) {
+ return nodeBuffer(str, "utf-8");
+ }
+
+ return string2buf(str);
+};
+
+
+/**
+ * Transform a bytes array (or a representation) representing an UTF-8 encoded
+ * string into a javascript string.
+ * @param {Array|Uint8Array|Buffer} buf the data de decode
+ * @return {String} the decoded string.
+ */
+exports.utf8decode = function utf8decode(buf) {
+ if (support.nodebuffer) {
+ return utils.transformTo("nodebuffer", buf).toString("utf-8");
+ }
+
+ buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf);
+
+ // return buf2string(buf);
+ // Chrome prefers to work with "small" chunks of data
+ // for the method buf2string.
+ // Firefox and Chrome has their own shortcut, IE doesn't seem to really care.
+ var result = [], k = 0, len = buf.length, chunk = 65536;
+ while (k < len) {
+ var nextBoundary = utf8border(buf, Math.min(k + chunk, len));
+ if (support.uint8array) {
+ result.push(buf2string(buf.subarray(k, nextBoundary)));
+ } else {
+ result.push(buf2string(buf.slice(k, nextBoundary)));
+ }
+ k = nextBoundary;
+ }
+ return result.join("");
+
+};
+// vim: set shiftwidth=4 softtabstop=4:
diff --git a/afb-client/bower_components/jszip/lib/utils.js b/afb-client/bower_components/jszip/lib/utils.js
new file mode 100644
index 0000000..da54747
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/utils.js
@@ -0,0 +1,326 @@
+'use strict';
+var support = require('./support');
+var compressions = require('./compressions');
+var nodeBuffer = require('./nodeBuffer');
+/**
+ * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
+ * @param {string} str the string to transform.
+ * @return {String} the binary string.
+ */
+exports.string2binary = function(str) {
+ var result = "";
+ for (var i = 0; i < str.length; i++) {
+ result += String.fromCharCode(str.charCodeAt(i) & 0xff);
+ }
+ return result;
+};
+exports.arrayBuffer2Blob = function(buffer, mimeType) {
+ exports.checkSupport("blob");
+ mimeType = mimeType || 'application/zip';
+
+ try {
+ // Blob constructor
+ return new Blob([buffer], {
+ type: mimeType
+ });
+ }
+ catch (e) {
+
+ try {
+ // deprecated, browser only, old way
+ var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
+ var builder = new Builder();
+ builder.append(buffer);
+ return builder.getBlob(mimeType);
+ }
+ catch (e) {
+
+ // well, fuck ?!
+ throw new Error("Bug : can't construct the Blob.");
+ }
+ }
+
+
+};
+/**
+ * The identity function.
+ * @param {Object} input the input.
+ * @return {Object} the same input.
+ */
+function identity(input) {
+ return input;
+}
+
+/**
+ * Fill in an array with a string.
+ * @param {String} str the string to use.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
+ */
+function stringToArrayLike(str, array) {
+ for (var i = 0; i < str.length; ++i) {
+ array[i] = str.charCodeAt(i) & 0xFF;
+ }
+ return array;
+}
+
+/**
+ * Transform an array-like object to a string.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
+ * @return {String} the result.
+ */
+function arrayLikeToString(array) {
+ // Performances notes :
+ // --------------------
+ // String.fromCharCode.apply(null, array) is the fastest, see
+ // see http://jsperf.com/converting-a-uint8array-to-a-string/2
+ // but the stack is limited (and we can get huge arrays !).
+ //
+ // result += String.fromCharCode(array[i]); generate too many strings !
+ //
+ // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
+ var chunk = 65536;
+ var result = [],
+ len = array.length,
+ type = exports.getTypeOf(array),
+ k = 0,
+ canUseApply = true;
+ try {
+ switch(type) {
+ case "uint8array":
+ String.fromCharCode.apply(null, new Uint8Array(0));
+ break;
+ case "nodebuffer":
+ String.fromCharCode.apply(null, nodeBuffer(0));
+ break;
+ }
+ } catch(e) {
+ canUseApply = false;
+ }
+
+ // no apply : slow and painful algorithm
+ // default browser on android 4.*
+ if (!canUseApply) {
+ var resultStr = "";
+ for(var i = 0; i < array.length;i++) {
+ resultStr += String.fromCharCode(array[i]);
+ }
+ return resultStr;
+ }
+ while (k < len && chunk > 1) {
+ try {
+ if (type === "array" || type === "nodebuffer") {
+ result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));
+ }
+ else {
+ result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));
+ }
+ k += chunk;
+ }
+ catch (e) {
+ chunk = Math.floor(chunk / 2);
+ }
+ }
+ return result.join("");
+}
+
+exports.applyFromCharCode = arrayLikeToString;
+
+
+/**
+ * Copy the data from an array-like to an other array-like.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
+ */
+function arrayLikeToArrayLike(arrayFrom, arrayTo) {
+ for (var i = 0; i < arrayFrom.length; i++) {
+ arrayTo[i] = arrayFrom[i];
+ }
+ return arrayTo;
+}
+
+// a matrix containing functions to transform everything into everything.
+var transform = {};
+
+// string to ?
+transform["string"] = {
+ "string": identity,
+ "array": function(input) {
+ return stringToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return transform["string"]["uint8array"](input).buffer;
+ },
+ "uint8array": function(input) {
+ return stringToArrayLike(input, new Uint8Array(input.length));
+ },
+ "nodebuffer": function(input) {
+ return stringToArrayLike(input, nodeBuffer(input.length));
+ }
+};
+
+// array to ?
+transform["array"] = {
+ "string": arrayLikeToString,
+ "array": identity,
+ "arraybuffer": function(input) {
+ return (new Uint8Array(input)).buffer;
+ },
+ "uint8array": function(input) {
+ return new Uint8Array(input);
+ },
+ "nodebuffer": function(input) {
+ return nodeBuffer(input);
+ }
+};
+
+// arraybuffer to ?
+transform["arraybuffer"] = {
+ "string": function(input) {
+ return arrayLikeToString(new Uint8Array(input));
+ },
+ "array": function(input) {
+ return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
+ },
+ "arraybuffer": identity,
+ "uint8array": function(input) {
+ return new Uint8Array(input);
+ },
+ "nodebuffer": function(input) {
+ return nodeBuffer(new Uint8Array(input));
+ }
+};
+
+// uint8array to ?
+transform["uint8array"] = {
+ "string": arrayLikeToString,
+ "array": function(input) {
+ return arrayLikeToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return input.buffer;
+ },
+ "uint8array": identity,
+ "nodebuffer": function(input) {
+ return nodeBuffer(input);
+ }
+};
+
+// nodebuffer to ?
+transform["nodebuffer"] = {
+ "string": arrayLikeToString,
+ "array": function(input) {
+ return arrayLikeToArrayLike(input, new Array(input.length));
+ },
+ "arraybuffer": function(input) {
+ return transform["nodebuffer"]["uint8array"](input).buffer;
+ },
+ "uint8array": function(input) {
+ return arrayLikeToArrayLike(input, new Uint8Array(input.length));
+ },
+ "nodebuffer": identity
+};
+
+/**
+ * Transform an input into any type.
+ * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
+ * If no output type is specified, the unmodified input will be returned.
+ * @param {String} outputType the output type.
+ * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
+ * @throws {Error} an Error if the browser doesn't support the requested output type.
+ */
+exports.transformTo = function(outputType, input) {
+ if (!input) {
+ // undefined, null, etc
+ // an empty string won't harm.
+ input = "";
+ }
+ if (!outputType) {
+ return input;
+ }
+ exports.checkSupport(outputType);
+ var inputType = exports.getTypeOf(input);
+ var result = transform[inputType][outputType](input);
+ return result;
+};
+
+/**
+ * Return the type of the input.
+ * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
+ * @param {Object} input the input to identify.
+ * @return {String} the (lowercase) type of the input.
+ */
+exports.getTypeOf = function(input) {
+ if (typeof input === "string") {
+ return "string";
+ }
+ if (Object.prototype.toString.call(input) === "[object Array]") {
+ return "array";
+ }
+ if (support.nodebuffer && nodeBuffer.test(input)) {
+ return "nodebuffer";
+ }
+ if (support.uint8array && input instanceof Uint8Array) {
+ return "uint8array";
+ }
+ if (support.arraybuffer && input instanceof ArrayBuffer) {
+ return "arraybuffer";
+ }
+};
+
+/**
+ * Throw an exception if the type is not supported.
+ * @param {String} type the type to check.
+ * @throws {Error} an Error if the browser doesn't support the requested type.
+ */
+exports.checkSupport = function(type) {
+ var supported = support[type.toLowerCase()];
+ if (!supported) {
+ throw new Error(type + " is not supported by this browser");
+ }
+};
+exports.MAX_VALUE_16BITS = 65535;
+exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1
+
+/**
+ * Prettify a string read as binary.
+ * @param {string} str the string to prettify.
+ * @return {string} a pretty string.
+ */
+exports.pretty = function(str) {
+ var res = '',
+ code, i;
+ for (i = 0; i < (str || "").length; i++) {
+ code = str.charCodeAt(i);
+ res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
+ }
+ return res;
+};
+
+/**
+ * Find a compression registered in JSZip.
+ * @param {string} compressionMethod the method magic to find.
+ * @return {Object|null} the JSZip compression object, null if none found.
+ */
+exports.findCompression = function(compressionMethod) {
+ for (var method in compressions) {
+ if (!compressions.hasOwnProperty(method)) {
+ continue;
+ }
+ if (compressions[method].magic === compressionMethod) {
+ return compressions[method];
+ }
+ }
+ return null;
+};
+/**
+* Cross-window, cross-Node-context regular expression detection
+* @param {Object} object Anything
+* @return {Boolean} true if the object is a regular expression,
+* false otherwise
+*/
+exports.isRegExp = function (object) {
+ return Object.prototype.toString.call(object) === "[object RegExp]";
+};
+
diff --git a/afb-client/bower_components/jszip/lib/zipEntries.js b/afb-client/bower_components/jszip/lib/zipEntries.js
new file mode 100644
index 0000000..4b82561
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/zipEntries.js
@@ -0,0 +1,221 @@
+'use strict';
+var StringReader = require('./stringReader');
+var NodeBufferReader = require('./nodeBufferReader');
+var Uint8ArrayReader = require('./uint8ArrayReader');
+var utils = require('./utils');
+var sig = require('./signature');
+var ZipEntry = require('./zipEntry');
+var support = require('./support');
+var jszipProto = require('./object');
+// class ZipEntries {{{
+/**
+ * All the entries in the zip file.
+ * @constructor
+ * @param {String|ArrayBuffer|Uint8Array} data the binary stream to load.
+ * @param {Object} loadOptions Options for loading the stream.
+ */
+function ZipEntries(data, loadOptions) {
+ this.files = [];
+ this.loadOptions = loadOptions;
+ if (data) {
+ this.load(data);
+ }
+}
+ZipEntries.prototype = {
+ /**
+ * Check that the reader is on the speficied signature.
+ * @param {string} expectedSignature the expected signature.
+ * @throws {Error} if it is an other signature.
+ */
+ checkSignature: function(expectedSignature) {
+ var signature = this.reader.readString(4);
+ if (signature !== expectedSignature) {
+ throw new Error("Corrupted zip or bug : unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")");
+ }
+ },
+ /**
+ * Read the end of the central directory.
+ */
+ readBlockEndOfCentral: function() {
+ this.diskNumber = this.reader.readInt(2);
+ this.diskWithCentralDirStart = this.reader.readInt(2);
+ this.centralDirRecordsOnThisDisk = this.reader.readInt(2);
+ this.centralDirRecords = this.reader.readInt(2);
+ this.centralDirSize = this.reader.readInt(4);
+ this.centralDirOffset = this.reader.readInt(4);
+
+ this.zipCommentLength = this.reader.readInt(2);
+ // warning : the encoding depends of the system locale
+ // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded.
+ // On a windows machine, this field is encoded with the localized windows code page.
+ this.zipComment = this.reader.readString(this.zipCommentLength);
+ // To get consistent behavior with the generation part, we will assume that
+ // this is utf8 encoded.
+ this.zipComment = jszipProto.utf8decode(this.zipComment);
+ },
+ /**
+ * Read the end of the Zip 64 central directory.
+ * Not merged with the method readEndOfCentral :
+ * The end of central can coexist with its Zip64 brother,
+ * I don't want to read the wrong number of bytes !
+ */
+ readBlockZip64EndOfCentral: function() {
+ this.zip64EndOfCentralSize = this.reader.readInt(8);
+ this.versionMadeBy = this.reader.readString(2);
+ this.versionNeeded = this.reader.readInt(2);
+ this.diskNumber = this.reader.readInt(4);
+ this.diskWithCentralDirStart = this.reader.readInt(4);
+ this.centralDirRecordsOnThisDisk = this.reader.readInt(8);
+ this.centralDirRecords = this.reader.readInt(8);
+ this.centralDirSize = this.reader.readInt(8);
+ this.centralDirOffset = this.reader.readInt(8);
+
+ this.zip64ExtensibleData = {};
+ var extraDataSize = this.zip64EndOfCentralSize - 44,
+ index = 0,
+ extraFieldId,
+ extraFieldLength,
+ extraFieldValue;
+ while (index < extraDataSize) {
+ extraFieldId = this.reader.readInt(2);
+ extraFieldLength = this.reader.readInt(4);
+ extraFieldValue = this.reader.readString(extraFieldLength);
+ this.zip64ExtensibleData[extraFieldId] = {
+ id: extraFieldId,
+ length: extraFieldLength,
+ value: extraFieldValue
+ };
+ }
+ },
+ /**
+ * Read the end of the Zip 64 central directory locator.
+ */
+ readBlockZip64EndOfCentralLocator: function() {
+ this.diskWithZip64CentralDirStart = this.reader.readInt(4);
+ this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);
+ this.disksCount = this.reader.readInt(4);
+ if (this.disksCount > 1) {
+ throw new Error("Multi-volumes zip are not supported");
+ }
+ },
+ /**
+ * Read the local files, based on the offset read in the central part.
+ */
+ readLocalFiles: function() {
+ var i, file;
+ for (i = 0; i < this.files.length; i++) {
+ file = this.files[i];
+ this.reader.setIndex(file.localHeaderOffset);
+ this.checkSignature(sig.LOCAL_FILE_HEADER);
+ file.readLocalPart(this.reader);
+ file.handleUTF8();
+ file.processAttributes();
+ }
+ },
+ /**
+ * Read the central directory.
+ */
+ readCentralDir: function() {
+ var file;
+
+ this.reader.setIndex(this.centralDirOffset);
+ while (this.reader.readString(4) === sig.CENTRAL_FILE_HEADER) {
+ file = new ZipEntry({
+ zip64: this.zip64
+ }, this.loadOptions);
+ file.readCentralPart(this.reader);
+ this.files.push(file);
+ }
+ },
+ /**
+ * Read the end of central directory.
+ */
+ readEndOfCentral: function() {
+ var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END);
+ if (offset === -1) {
+ // Check if the content is a truncated zip or complete garbage.
+ // A "LOCAL_FILE_HEADER" is not required at the beginning (auto
+ // extractible zip for example) but it can give a good hint.
+ // If an ajax request was used without responseType, we will also
+ // get unreadable data.
+ var isGarbage = true;
+ try {
+ this.reader.setIndex(0);
+ this.checkSignature(sig.LOCAL_FILE_HEADER);
+ isGarbage = false;
+ } catch (e) {}
+
+ if (isGarbage) {
+ throw new Error("Can't find end of central directory : is this a zip file ? " +
+ "If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html");
+ } else {
+ throw new Error("Corrupted zip : can't find end of central directory");
+ }
+ }
+ this.reader.setIndex(offset);
+ this.checkSignature(sig.CENTRAL_DIRECTORY_END);
+ this.readBlockEndOfCentral();
+
+
+ /* extract from the zip spec :
+ 4) If one of the fields in the end of central directory
+ record is too small to hold required data, the field
+ should be set to -1 (0xFFFF or 0xFFFFFFFF) and the
+ ZIP64 format record should be created.
+ 5) The end of central directory record and the
+ Zip64 end of central directory locator record must
+ reside on the same disk when splitting or spanning
+ an archive.
+ */
+ if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) {
+ this.zip64 = true;
+
+ /*
+ Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from
+ the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents
+ all numbers as 64-bit double precision IEEE 754 floating point numbers.
+ So, we have 53bits for integers and bitwise operations treat everything as 32bits.
+ see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
+ and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5
+ */
+
+ // should look for a zip64 EOCD locator
+ offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
+ if (offset === -1) {
+ throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");
+ }
+ this.reader.setIndex(offset);
+ this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
+ this.readBlockZip64EndOfCentralLocator();
+
+ // now the zip64 EOCD record
+ this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);
+ this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END);
+ this.readBlockZip64EndOfCentral();
+ }
+ },
+ prepareReader: function(data) {
+ var type = utils.getTypeOf(data);
+ if (type === "string" && !support.uint8array) {
+ this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString);
+ }
+ else if (type === "nodebuffer") {
+ this.reader = new NodeBufferReader(data);
+ }
+ else {
+ this.reader = new Uint8ArrayReader(utils.transformTo("uint8array", data));
+ }
+ },
+ /**
+ * Read a zip file and create ZipEntries.
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.
+ */
+ load: function(data) {
+ this.prepareReader(data);
+ this.readEndOfCentral();
+ this.readCentralDir();
+ this.readLocalFiles();
+ }
+};
+// }}} end of ZipEntries
+module.exports = ZipEntries;
diff --git a/afb-client/bower_components/jszip/lib/zipEntry.js b/afb-client/bower_components/jszip/lib/zipEntry.js
new file mode 100644
index 0000000..70a3ac0
--- /dev/null
+++ b/afb-client/bower_components/jszip/lib/zipEntry.js
@@ -0,0 +1,310 @@
+'use strict';
+var StringReader = require('./stringReader');
+var utils = require('./utils');
+var CompressedObject = require('./compressedObject');
+var jszipProto = require('./object');
+
+var MADE_BY_DOS = 0x00;
+var MADE_BY_UNIX = 0x03;
+
+// class ZipEntry {{{
+/**
+ * An entry in the zip file.
+ * @constructor
+ * @param {Object} options Options of the current file.
+ * @param {Object} loadOptions Options for loading the stream.
+ */
+function ZipEntry(options, loadOptions) {
+ this.options = options;
+ this.loadOptions = loadOptions;
+}
+ZipEntry.prototype = {
+ /**
+ * say if the file is encrypted.
+ * @return {boolean} true if the file is encrypted, false otherwise.
+ */
+ isEncrypted: function() {
+ // bit 1 is set
+ return (this.bitFlag & 0x0001) === 0x0001;
+ },
+ /**
+ * say if the file has utf-8 filename/comment.
+ * @return {boolean} true if the filename/comment is in utf-8, false otherwise.
+ */
+ useUTF8: function() {
+ // bit 11 is set
+ return (this.bitFlag & 0x0800) === 0x0800;
+ },
+ /**
+ * Prepare the function used to generate the compressed content from this ZipFile.
+ * @param {DataReader} reader the reader to use.
+ * @param {number} from the offset from where we should read the data.
+ * @param {number} length the length of the data to read.
+ * @return {Function} the callback to get the compressed content (the type depends of the DataReader class).
+ */
+ prepareCompressedContent: function(reader, from, length) {
+ return function() {
+ var previousIndex = reader.index;
+ reader.setIndex(from);
+ var compressedFileData = reader.readData(length);
+ reader.setIndex(previousIndex);
+
+ return compressedFileData;
+ };
+ },
+ /**
+ * Prepare the function used to generate the uncompressed content from this ZipFile.
+ * @param {DataReader} reader the reader to use.
+ * @param {number} from the offset from where we should read the data.
+ * @param {number} length the length of the data to read.
+ * @param {JSZip.compression} compression the compression used on this file.
+ * @param {number} uncompressedSize the uncompressed size to expect.
+ * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class).
+ */
+ prepareContent: function(reader, from, length, compression, uncompressedSize) {
+ return function() {
+
+ var compressedFileData = utils.transformTo(compression.uncompressInputType, this.getCompressedContent());
+ var uncompressedFileData = compression.uncompress(compressedFileData);
+
+ if (uncompressedFileData.length !== uncompressedSize) {
+ throw new Error("Bug : uncompressed data size mismatch");
+ }
+
+ return uncompressedFileData;
+ };
+ },
+ /**
+ * Read the local part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readLocalPart: function(reader) {
+ var compression, localExtraFieldsLength;
+
+ // we already know everything from the central dir !
+ // If the central dir data are false, we are doomed.
+ // On the bright side, the local part is scary : zip64, data descriptors, both, etc.
+ // The less data we get here, the more reliable this should be.
+ // Let's skip the whole header and dash to the data !
+ reader.skip(22);
+ // in some zip created on windows, the filename stored in the central dir contains \ instead of /.
+ // Strangely, the filename here is OK.
+ // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes
+ // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators...
+ // Search "unzip mismatching "local" filename continuing with "central" filename version" on
+ // the internet.
+ //
+ // I think I see the logic here : the central directory is used to display
+ // content and the local directory is used to extract the files. Mixing / and \
+ // may be used to display \ to windows users and use / when extracting the files.
+ // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394
+ this.fileNameLength = reader.readInt(2);
+ localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir
+ this.fileName = reader.readString(this.fileNameLength);
+ reader.skip(localExtraFieldsLength);
+
+ if (this.compressedSize == -1 || this.uncompressedSize == -1) {
+ throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize == -1 || uncompressedSize == -1)");
+ }
+
+ compression = utils.findCompression(this.compressionMethod);
+ if (compression === null) { // no compression found
+ throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")");
+ }
+ this.decompressed = new CompressedObject();
+ this.decompressed.compressedSize = this.compressedSize;
+ this.decompressed.uncompressedSize = this.uncompressedSize;
+ this.decompressed.crc32 = this.crc32;
+ this.decompressed.compressionMethod = this.compressionMethod;
+ this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression);
+ this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize);
+
+ // we need to compute the crc32...
+ if (this.loadOptions.checkCRC32) {
+ this.decompressed = utils.transformTo("string", this.decompressed.getContent());
+ if (jszipProto.crc32(this.decompressed) !== this.crc32) {
+ throw new Error("Corrupted zip : CRC32 mismatch");
+ }
+ }
+ },
+
+ /**
+ * Read the central part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readCentralPart: function(reader) {
+ this.versionMadeBy = reader.readInt(2);
+ this.versionNeeded = reader.readInt(2);
+ this.bitFlag = reader.readInt(2);
+ this.compressionMethod = reader.readString(2);
+ this.date = reader.readDate();
+ this.crc32 = reader.readInt(4);
+ this.compressedSize = reader.readInt(4);
+ this.uncompressedSize = reader.readInt(4);
+ this.fileNameLength = reader.readInt(2);
+ this.extraFieldsLength = reader.readInt(2);
+ this.fileCommentLength = reader.readInt(2);
+ this.diskNumberStart = reader.readInt(2);
+ this.internalFileAttributes = reader.readInt(2);
+ this.externalFileAttributes = reader.readInt(4);
+ this.localHeaderOffset = reader.readInt(4);
+
+ if (this.isEncrypted()) {
+ throw new Error("Encrypted zip are not supported");
+ }
+
+ this.fileName = reader.readString(this.fileNameLength);
+ this.readExtraFields(reader);
+ this.parseZIP64ExtraField(reader);
+ this.fileComment = reader.readString(this.fileCommentLength);
+ },
+
+ /**
+ * Parse the external file attributes and get the unix/dos permissions.
+ */
+ processAttributes: function () {
+ this.unixPermissions = null;
+ this.dosPermissions = null;
+ var madeBy = this.versionMadeBy >> 8;
+
+ // Check if we have the DOS directory flag set.
+ // We look for it in the DOS and UNIX permissions
+ // but some unknown platform could set it as a compatibility flag.
+ this.dir = this.externalFileAttributes & 0x0010 ? true : false;
+
+ if(madeBy === MADE_BY_DOS) {
+ // first 6 bits (0 to 5)
+ this.dosPermissions = this.externalFileAttributes & 0x3F;
+ }
+
+ if(madeBy === MADE_BY_UNIX) {
+ this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;
+ // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);
+ }
+
+ // fail safe : if the name ends with a / it probably means a folder
+ if (!this.dir && this.fileName.slice(-1) === '/') {
+ this.dir = true;
+ }
+ },
+
+ /**
+ * Parse the ZIP64 extra field and merge the info in the current ZipEntry.
+ * @param {DataReader} reader the reader to use.
+ */
+ parseZIP64ExtraField: function(reader) {
+
+ if (!this.extraFields[0x0001]) {
+ return;
+ }
+
+ // should be something, preparing the extra reader
+ var extraReader = new StringReader(this.extraFields[0x0001].value);
+
+ // I really hope that these 64bits integer can fit in 32 bits integer, because js
+ // won't let us have more.
+ if (this.uncompressedSize === utils.MAX_VALUE_32BITS) {
+ this.uncompressedSize = extraReader.readInt(8);
+ }
+ if (this.compressedSize === utils.MAX_VALUE_32BITS) {
+ this.compressedSize = extraReader.readInt(8);
+ }
+ if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) {
+ this.localHeaderOffset = extraReader.readInt(8);
+ }
+ if (this.diskNumberStart === utils.MAX_VALUE_32BITS) {
+ this.diskNumberStart = extraReader.readInt(4);
+ }
+ },
+ /**
+ * Read the central part of a zip file and add the info in this object.
+ * @param {DataReader} reader the reader to use.
+ */
+ readExtraFields: function(reader) {
+ var start = reader.index,
+ extraFieldId,
+ extraFieldLength,
+ extraFieldValue;
+
+ this.extraFields = this.extraFields || {};
+
+ while (reader.index < start + this.extraFieldsLength) {
+ extraFieldId = reader.readInt(2);
+ extraFieldLength = reader.readInt(2);
+ extraFieldValue = reader.readString(extraFieldLength);
+
+ this.extraFields[extraFieldId] = {
+ id: extraFieldId,
+ length: extraFieldLength,
+ value: extraFieldValue
+ };
+ }
+ },
+ /**
+ * Apply an UTF8 transformation if needed.
+ */
+ handleUTF8: function() {
+ if (this.useUTF8()) {
+ this.fileName = jszipProto.utf8decode(this.fileName);
+ this.fileComment = jszipProto.utf8decode(this.fileComment);
+ } else {
+ var upath = this.findExtraFieldUnicodePath();
+ if (upath !== null) {
+ this.fileName = upath;
+ }
+ var ucomment = this.findExtraFieldUnicodeComment();
+ if (ucomment !== null) {
+ this.fileComment = ucomment;
+ }
+ }
+ },
+
+ /**
+ * Find the unicode path declared in the extra field, if any.
+ * @return {String} the unicode path, null otherwise.
+ */
+ findExtraFieldUnicodePath: function() {
+ var upathField = this.extraFields[0x7075];
+ if (upathField) {
+ var extraReader = new StringReader(upathField.value);
+
+ // wrong version
+ if (extraReader.readInt(1) !== 1) {
+ return null;
+ }
+
+ // the crc of the filename changed, this field is out of date.
+ if (jszipProto.crc32(this.fileName) !== extraReader.readInt(4)) {
+ return null;
+ }
+
+ return jszipProto.utf8decode(extraReader.readString(upathField.length - 5));
+ }
+ return null;
+ },
+
+ /**
+ * Find the unicode comment declared in the extra field, if any.
+ * @return {String} the unicode comment, null otherwise.
+ */
+ findExtraFieldUnicodeComment: function() {
+ var ucommentField = this.extraFields[0x6375];
+ if (ucommentField) {
+ var extraReader = new StringReader(ucommentField.value);
+
+ // wrong version
+ if (extraReader.readInt(1) !== 1) {
+ return null;
+ }
+
+ // the crc of the comment changed, this field is out of date.
+ if (jszipProto.crc32(this.fileComment) !== extraReader.readInt(4)) {
+ return null;
+ }
+
+ return jszipProto.utf8decode(extraReader.readString(ucommentField.length - 5));
+ }
+ return null;
+ }
+};
+module.exports = ZipEntry;
diff --git a/afb-client/bower_components/jszip/package.json b/afb-client/bower_components/jszip/package.json
new file mode 100644
index 0000000..a1a74c9
--- /dev/null
+++ b/afb-client/bower_components/jszip/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "jszip",
+ "version": "2.5.0",
+ "author": "Stuart Knightley <stuart@stuartk.com>",
+ "description": "Create, read and edit .zip files with Javascript http://stuartk.com/jszip",
+ "scripts": {
+ "test": "npm run test-node && npm run test-browser",
+ "test-node": "cd test && qunit -c node.js -t test.js",
+ "test-browser": "grunt build && grunt test",
+ "lint": "grunt jshint"
+ },
+ "contributors": [
+ {
+ "name": "Franz Buchinger"
+ },
+ {
+ "name": "António Afonso"
+ },
+ {
+ "name": "David Duponchel"
+ },
+ {
+ "name": "yiminghe"
+ }
+ ],
+ "main": "./lib/index",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Stuk/jszip.git"
+ },
+ "keywords": [
+ "zip",
+ "deflate",
+ "inflate"
+ ],
+ "devDependencies": {
+ "qunit": "~0.6.3",
+ "grunt": "~0.4.1",
+ "grunt-cli": "~0.1.9",
+ "grunt-saucelabs": "~7.0.0",
+ "grunt-contrib-connect": "~0.7.1",
+ "jshint": "~2.5.1",
+ "browserify": "~4.1.4",
+ "grunt-browserify": "~2.1.0",
+ "grunt-contrib-jshint": "~0.10.0",
+ "grunt-contrib-uglify": "~0.4.0",
+ "jszip-utils": "~0.0.2"
+ },
+ "dependencies":{
+ "pako": "~0.2.5"
+ },
+ "license": "MIT or GPLv3"
+}
diff --git a/afb-client/bower_components/jszip/vendor/FileSaver.js b/afb-client/bower_components/jszip/vendor/FileSaver.js
new file mode 100644
index 0000000..112efb0
--- /dev/null
+++ b/afb-client/bower_components/jszip/vendor/FileSaver.js
@@ -0,0 +1,247 @@
+/*! FileSaver.js
+ * A saveAs() FileSaver implementation.
+ * 2014-01-24
+ *
+ * By Eli Grey, http://eligrey.com
+ * License: X11/MIT
+ * See LICENSE.md
+ */
+
+/*global self */
+/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
+
+/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
+
+var saveAs = saveAs
+ // IE 10+ (native saveAs)
+ || (typeof navigator !== "undefined" &&
+ navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
+ // Everyone else
+ || (function(view) {
+ "use strict";
+ // IE <10 is explicitly unsupported
+ if (typeof navigator !== "undefined" &&
+ /MSIE [1-9]\./.test(navigator.userAgent)) {
+ return;
+ }
+ var
+ doc = view.document
+ // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
+ , get_URL = function() {
+ return view.URL || view.webkitURL || view;
+ }
+ , URL = view.URL || view.webkitURL || view
+ , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
+ , can_use_save_link = !view.externalHost && "download" in save_link
+ , click = function(node) {
+ var event = doc.createEvent("MouseEvents");
+ event.initMouseEvent(
+ "click", true, false, view, 0, 0, 0, 0, 0
+ , false, false, false, false, 0, null
+ );
+ node.dispatchEvent(event);
+ }
+ , webkit_req_fs = view.webkitRequestFileSystem
+ , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
+ , throw_outside = function(ex) {
+ (view.setImmediate || view.setTimeout)(function() {
+ throw ex;
+ }, 0);
+ }
+ , force_saveable_type = "application/octet-stream"
+ , fs_min_size = 0
+ , deletion_queue = []
+ , process_deletion_queue = function() {
+ var i = deletion_queue.length;
+ while (i--) {
+ var file = deletion_queue[i];
+ if (typeof file === "string") { // file is an object URL
+ URL.revokeObjectURL(file);
+ } else { // file is a File
+ file.remove();
+ }
+ }
+ deletion_queue.length = 0; // clear queue
+ }
+ , dispatch = function(filesaver, event_types, event) {
+ event_types = [].concat(event_types);
+ var i = event_types.length;
+ while (i--) {
+ var listener = filesaver["on" + event_types[i]];
+ if (typeof listener === "function") {
+ try {
+ listener.call(filesaver, event || filesaver);
+ } catch (ex) {
+ throw_outside(ex);
+ }
+ }
+ }
+ }
+ , FileSaver = function(blob, name) {
+ // First try a.download, then web filesystem, then object URLs
+ var
+ filesaver = this
+ , type = blob.type
+ , blob_changed = false
+ , object_url
+ , target_view
+ , get_object_url = function() {
+ var object_url = get_URL().createObjectURL(blob);
+ deletion_queue.push(object_url);
+ return object_url;
+ }
+ , dispatch_all = function() {
+ dispatch(filesaver, "writestart progress write writeend".split(" "));
+ }
+ // on any filesys errors revert to saving with object URLs
+ , fs_error = function() {
+ // don't create more object URLs than needed
+ if (blob_changed || !object_url) {
+ object_url = get_object_url(blob);
+ }
+ if (target_view) {
+ target_view.location.href = object_url;
+ } else {
+ window.open(object_url, "_blank");
+ }
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ }
+ , abortable = function(func) {
+ return function() {
+ if (filesaver.readyState !== filesaver.DONE) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+ , create_if_not_found = {create: true, exclusive: false}
+ , slice
+ ;
+ filesaver.readyState = filesaver.INIT;
+ if (!name) {
+ name = "download";
+ }
+ if (can_use_save_link) {
+ object_url = get_object_url(blob);
+ // FF for Android has a nasty garbage collection mechanism
+ // that turns all objects that are not pure javascript into 'deadObject'
+ // this means `doc` and `save_link` are unusable and need to be recreated
+ // `view` is usable though:
+ doc = view.document;
+ save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
+ save_link.href = object_url;
+ save_link.download = name;
+ var event = doc.createEvent("MouseEvents");
+ event.initMouseEvent(
+ "click", true, false, view, 0, 0, 0, 0, 0
+ , false, false, false, false, 0, null
+ );
+ save_link.dispatchEvent(event);
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ return;
+ }
+ // Object and web filesystem URLs have a problem saving in Google Chrome when
+ // viewed in a tab, so I force save with application/octet-stream
+ // http://code.google.com/p/chromium/issues/detail?id=91158
+ if (view.chrome && type && type !== force_saveable_type) {
+ slice = blob.slice || blob.webkitSlice;
+ blob = slice.call(blob, 0, blob.size, force_saveable_type);
+ blob_changed = true;
+ }
+ // Since I can't be sure that the guessed media type will trigger a download
+ // in WebKit, I append .download to the filename.
+ // https://bugs.webkit.org/show_bug.cgi?id=65440
+ if (webkit_req_fs && name !== "download") {
+ name += ".download";
+ }
+ if (type === force_saveable_type || webkit_req_fs) {
+ target_view = view;
+ }
+ if (!req_fs) {
+ fs_error();
+ return;
+ }
+ fs_min_size += blob.size;
+ req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
+ fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
+ var save = function() {
+ dir.getFile(name, create_if_not_found, abortable(function(file) {
+ file.createWriter(abortable(function(writer) {
+ writer.onwriteend = function(event) {
+ target_view.location.href = file.toURL();
+ deletion_queue.push(file);
+ filesaver.readyState = filesaver.DONE;
+ dispatch(filesaver, "writeend", event);
+ };
+ writer.onerror = function() {
+ var error = writer.error;
+ if (error.code !== error.ABORT_ERR) {
+ fs_error();
+ }
+ };
+ "writestart progress write abort".split(" ").forEach(function(event) {
+ writer["on" + event] = filesaver["on" + event];
+ });
+ writer.write(blob);
+ filesaver.abort = function() {
+ writer.abort();
+ filesaver.readyState = filesaver.DONE;
+ };
+ filesaver.readyState = filesaver.WRITING;
+ }), fs_error);
+ }), fs_error);
+ };
+ dir.getFile(name, {create: false}, abortable(function(file) {
+ // delete file if it already exists
+ file.remove();
+ save();
+ }), abortable(function(ex) {
+ if (ex.code === ex.NOT_FOUND_ERR) {
+ save();
+ } else {
+ fs_error();
+ }
+ }));
+ }), fs_error);
+ }), fs_error);
+ }
+ , FS_proto = FileSaver.prototype
+ , saveAs = function(blob, name) {
+ return new FileSaver(blob, name);
+ }
+ ;
+ FS_proto.abort = function() {
+ var filesaver = this;
+ filesaver.readyState = filesaver.DONE;
+ dispatch(filesaver, "abort");
+ };
+ FS_proto.readyState = FS_proto.INIT = 0;
+ FS_proto.WRITING = 1;
+ FS_proto.DONE = 2;
+
+ FS_proto.error =
+ FS_proto.onwritestart =
+ FS_proto.onprogress =
+ FS_proto.onwrite =
+ FS_proto.onabort =
+ FS_proto.onerror =
+ FS_proto.onwriteend =
+ null;
+
+ view.addEventListener("unload", process_deletion_queue, false);
+ saveAs.unload = function() {
+ process_deletion_queue();
+ view.removeEventListener("unload", process_deletion_queue, false);
+ };
+ return saveAs;
+}(
+ typeof self !== "undefined" && self
+ || typeof window !== "undefined" && window
+ || this.content
+));
+// `self` is undefined in Firefox for Android content script context
+// while `this` is nsIContentFrameMessageManager
+// with an attribute `content` that corresponds to the window
+
+if (typeof module !== "undefined") module.exports = saveAs;
diff --git a/afb-client/bower_components/tether/.bower.json b/afb-client/bower_components/tether/.bower.json
new file mode 100644
index 0000000..9186152
--- /dev/null
+++ b/afb-client/bower_components/tether/.bower.json
@@ -0,0 +1,31 @@
+{
+ "name": "tether",
+ "version": "0.6.5",
+ "main": "tether.js",
+ "homepage": "https://github.hubspot.com/tether",
+ "authors": [
+ "Zack Bloom <zackbloom@gmail.com>",
+ "Adam Schwartz <adam.flynn.schwartz@gmail.com>"
+ ],
+ "description": "Tether elements together",
+ "keywords": [
+ "javascript"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ],
+ "_release": "0.6.5",
+ "_resolution": {
+ "type": "version",
+ "tag": "v0.6.5",
+ "commit": "783528dac760cb0023e5bd02d63c79ec54b9fc25"
+ },
+ "_source": "git://github.com/HubSpot/tether.git",
+ "_target": "~0.6.5",
+ "_originalSource": "tether"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/tether/LICENSE b/afb-client/bower_components/tether/LICENSE
new file mode 100644
index 0000000..2b88ccf
--- /dev/null
+++ b/afb-client/bower_components/tether/LICENSE
@@ -0,0 +1,8 @@
+Copyright (c) 2014 HubSpot, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/afb-client/bower_components/tether/README.md b/afb-client/bower_components/tether/README.md
new file mode 100644
index 0000000..3a92b87
--- /dev/null
+++ b/afb-client/bower_components/tether/README.md
@@ -0,0 +1,11 @@
+## Tether
+
+Tether is a JavaScript library for efficiently making an absolutely positioned element stay next to another element on the page.
+
+It aims to be the canonical implementation of this type of positioning, such that you can build products, not positioning libraries.
+
+Take a look at the documentation for a more detailed explanation of why you should star it now to remember it for your next project.
+
+[![Tether Docs](http://i.imgur.com/YCx8cLr.png)](http://github.hubspot.com/tether/#usage)
+
+### [Demo & Documentation](http://github.hubspot.com/tether/)
diff --git a/afb-client/bower_components/tether/bower.json b/afb-client/bower_components/tether/bower.json
new file mode 100644
index 0000000..49765fa
--- /dev/null
+++ b/afb-client/bower_components/tether/bower.json
@@ -0,0 +1,22 @@
+{
+ "name": "tether",
+ "version": "0.6.5",
+ "main": "tether.js",
+ "homepage": "https://github.hubspot.com/tether",
+ "authors": [
+ "Zack Bloom <zackbloom@gmail.com>",
+ "Adam Schwartz <adam.flynn.schwartz@gmail.com>"
+ ],
+ "description": "Tether elements together",
+ "keywords": [
+ "javascript"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ]
+}
diff --git a/afb-client/bower_components/tether/coffee/abutment.coffee b/afb-client/bower_components/tether/coffee/abutment.coffee
new file mode 100644
index 0000000..5f331e4
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/abutment.coffee
@@ -0,0 +1,40 @@
+{getBounds, updateClasses, defer} = @Tether.Utils
+
+@Tether.modules.push
+ position: ({top, left}) ->
+ {height, width} = @cache 'element-bounds', => getBounds @element
+
+ targetPos = @getTargetBounds()
+
+ bottom = top + height
+ right = left + width
+
+ abutted = []
+ if top <= targetPos.bottom and bottom >= targetPos.top
+ for side in ['left', 'right']
+ if targetPos[side] in [left, right]
+ abutted.push side
+
+ if left <= targetPos.right and right >= targetPos.left
+ for side in ['top', 'bottom']
+ if targetPos[side] in [top, bottom]
+ abutted.push side
+
+ allClasses = []
+ addClasses = []
+
+ sides = ['left', 'top', 'right', 'bottom']
+ allClasses.push @getClass('abutted')
+ for side in sides
+ allClasses.push "#{ @getClass('abutted') }-#{ side }"
+
+ if abutted.length
+ addClasses.push @getClass('abutted')
+ for side in abutted
+ addClasses.push "#{ @getClass('abutted') }-#{ side }"
+
+ defer =>
+ updateClasses @target, addClasses, allClasses
+ updateClasses @element, addClasses, allClasses
+
+ true
diff --git a/afb-client/bower_components/tether/coffee/constraint.coffee b/afb-client/bower_components/tether/coffee/constraint.coffee
new file mode 100644
index 0000000..d27c1c9
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/constraint.coffee
@@ -0,0 +1,260 @@
+{getOuterSize, getBounds, getSize, extend, updateClasses, defer} = @Tether.Utils
+
+MIRROR_ATTACH =
+ left: 'right'
+ right: 'left'
+ top: 'bottom'
+ bottom: 'top'
+ middle: 'middle'
+
+BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom']
+
+getBoundingRect = (tether, to) ->
+ if to is 'scrollParent'
+ to = tether.scrollParent
+ else if to is 'window'
+ to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset]
+
+ if to is document
+ to = to.documentElement
+
+ if to.nodeType?
+ pos = size = getBounds to
+ style = getComputedStyle to
+
+ to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top]
+
+ for side, i in BOUNDS_FORMAT
+ side = side[0].toUpperCase() + side.substr(1)
+ if side in ['Top', 'Left']
+ to[i] += parseFloat style["border#{ side }Width"]
+ else
+ to[i] -= parseFloat style["border#{ side }Width"]
+
+ to
+
+@Tether.modules.push
+ position: ({top, left, targetAttachment}) ->
+ return true unless @options.constraints
+
+ removeClass = (prefix) =>
+ @removeClass prefix
+ for side in BOUNDS_FORMAT
+ @removeClass "#{ prefix }-#{ side }"
+
+ {height, width} = @cache 'element-bounds', => getBounds @element
+
+ if width is 0 and height is 0 and @lastSize?
+ # Handle the item getting hidden as a result of our positioning without glitching
+ # the classes in and out
+ {width, height} = @lastSize
+
+ targetSize = @cache 'target-bounds', => @getTargetBounds()
+ targetHeight = targetSize.height
+ targetWidth = targetSize.width
+
+ tAttachment = {}
+ eAttachment = {}
+
+ allClasses = [@getClass('pinned'), @getClass('out-of-bounds')]
+ for constraint in @options.constraints
+ allClasses.push(constraint.outOfBoundsClass) if constraint.outOfBoundsClass
+ allClasses.push(constraint.pinnedClass) if constraint.pinnedClass
+
+ for cls in allClasses
+ for side in ['left', 'top', 'right', 'bottom']
+ allClasses.push "#{ cls }-#{ side }"
+
+ addClasses = []
+
+ tAttachment = extend {}, targetAttachment
+ eAttachment = extend {}, @attachment
+
+ for constraint in @options.constraints
+ {to, attachment, pin} = constraint
+
+ attachment ?= ''
+
+ if ' ' in attachment
+ [changeAttachY, changeAttachX] = attachment.split(' ')
+ else
+ changeAttachX = changeAttachY = attachment
+
+ bounds = getBoundingRect @, to
+
+ if changeAttachY in ['target', 'both']
+ if (top < bounds[1] and tAttachment.top is 'top')
+ top += targetHeight
+ tAttachment.top = 'bottom'
+
+ if (top + height > bounds[3] and tAttachment.top is 'bottom')
+ top -= targetHeight
+ tAttachment.top = 'top'
+
+ if changeAttachY is 'together'
+ if top < bounds[1] and tAttachment.top is 'top'
+ if eAttachment.top is 'bottom'
+ top += targetHeight
+ tAttachment.top = 'bottom'
+
+ top += height
+ eAttachment.top = 'top'
+ else if eAttachment.top is 'top'
+ top += targetHeight
+ tAttachment.top = 'bottom'
+
+ top -= height
+ eAttachment.top = 'bottom'
+
+ if top + height > bounds[3] and tAttachment.top is 'bottom'
+ if eAttachment.top is 'top'
+ top -= targetHeight
+ tAttachment.top = 'top'
+
+ top -= height
+ eAttachment.top = 'bottom'
+ else if eAttachment.top is 'bottom'
+ top -= targetHeight
+ tAttachment.top = 'top'
+
+ top += height
+ eAttachment.top = 'top'
+
+ if tAttachment.top is 'middle'
+ if top + height > bounds[3] and eAttachment.top is 'top'
+ top -= height
+ eAttachment.top = 'bottom'
+
+ else if top < bounds[1] and eAttachment.top is 'bottom'
+ top += height
+ eAttachment.top = 'top'
+
+ if changeAttachX in ['target', 'both']
+ if (left < bounds[0] and tAttachment.left is 'left')
+ left += targetWidth
+ tAttachment.left = 'right'
+
+ if (left + width > bounds[2] and tAttachment.left is 'right')
+ left -= targetWidth
+ tAttachment.left = 'left'
+
+ if changeAttachX is 'together'
+ if left < bounds[0] and tAttachment.left is 'left'
+ if eAttachment.left is 'right'
+ left += targetWidth
+ tAttachment.left = 'right'
+
+ left += width
+ eAttachment.left = 'left'
+
+ else if eAttachment.left is 'left'
+ left += targetWidth
+ tAttachment.left = 'right'
+
+ left -= width
+ eAttachment.left = 'right'
+
+ else if left + width > bounds[2] and tAttachment.left is 'right'
+ if eAttachment.left is 'left'
+ left -= targetWidth
+ tAttachment.left = 'left'
+
+ left -= width
+ eAttachment.left = 'right'
+
+ else if eAttachment.left is 'right'
+ left -= targetWidth
+ tAttachment.left = 'left'
+
+ left += width
+ eAttachment.left = 'left'
+
+ else if tAttachment.left is 'center'
+ if left + width > bounds[2] and eAttachment.left is 'left'
+ left -= width
+ eAttachment.left = 'right'
+
+ else if left < bounds[0] and eAttachment.left is 'right'
+ left += width
+ eAttachment.left = 'left'
+
+ if changeAttachY in ['element', 'both']
+ if (top < bounds[1] and eAttachment.top is 'bottom')
+ top += height
+ eAttachment.top = 'top'
+
+ if (top + height > bounds[3] and eAttachment.top is 'top')
+ top -= height
+ eAttachment.top = 'bottom'
+
+ if changeAttachX in ['element', 'both']
+ if (left < bounds[0] and eAttachment.left is 'right')
+ left += width
+ eAttachment.left = 'left'
+
+ if (left + width > bounds[2] and eAttachment.left is 'left')
+ left -= width
+ eAttachment.left = 'right'
+
+ if typeof pin is 'string'
+ pin = (p.trim() for p in pin.split ',')
+ else if pin is true
+ pin = ['top', 'left', 'right', 'bottom']
+
+ pin or= []
+
+ pinned = []
+ oob = []
+ if top < bounds[1]
+ if 'top' in pin
+ top = bounds[1]
+ pinned.push 'top'
+ else
+ oob.push 'top'
+
+ if top + height > bounds[3]
+ if 'bottom' in pin
+ top = bounds[3] - height
+ pinned.push 'bottom'
+ else
+ oob.push 'bottom'
+
+ if left < bounds[0]
+ if 'left' in pin
+ left = bounds[0]
+ pinned.push 'left'
+ else
+ oob.push 'left'
+
+ if left + width > bounds[2]
+ if 'right' in pin
+ left = bounds[2] - width
+ pinned.push 'right'
+ else
+ oob.push 'right'
+
+ if pinned.length
+ pinnedClass = @options.pinnedClass ? @getClass('pinned')
+ addClasses.push pinnedClass
+ for side in pinned
+ addClasses.push "#{ pinnedClass }-#{ side }"
+
+ if oob.length
+ oobClass = @options.outOfBoundsClass ? @getClass('out-of-bounds')
+ addClasses.push oobClass
+ for side in oob
+ addClasses.push "#{ oobClass }-#{ side }"
+
+ if 'left' in pinned or 'right' in pinned
+ eAttachment.left = tAttachment.left = false
+ if 'top' in pinned or 'bottom' in pinned
+ eAttachment.top = tAttachment.top = false
+
+ if tAttachment.top isnt targetAttachment.top or tAttachment.left isnt targetAttachment.left or eAttachment.top isnt @attachment.top or eAttachment.left isnt @attachment.left
+ @updateAttachClasses eAttachment, tAttachment
+
+ defer =>
+ updateClasses @target, addClasses, allClasses
+ updateClasses @element, addClasses, allClasses
+
+ {top, left}
diff --git a/afb-client/bower_components/tether/coffee/markAttachment.coffee b/afb-client/bower_components/tether/coffee/markAttachment.coffee
new file mode 100644
index 0000000..b29c9ef
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/markAttachment.coffee
@@ -0,0 +1,30 @@
+@Tether.modules.push
+ initialize: ->
+ @markers = {}
+
+ for type in ['target', 'element']
+ el = document.createElement 'div'
+ el.className = @getClass("#{ type }-marker")
+
+ dot = document.createElement 'div'
+ dot.className = @getClass('marker-dot')
+ el.appendChild dot
+
+ @[type].appendChild el
+
+ @markers[type] = {dot, el}
+
+ position: ({manualOffset, manualTargetOffset}) ->
+ offsets =
+ element: manualOffset
+ target: manualTargetOffset
+
+ for type, offset of offsets
+ for side, val of offset
+ if typeof val isnt 'string' or (val.indexOf('%') is -1 and val.indexOf('px') is -1)
+ val += 'px'
+
+ if @markers[type].dot.style[side] isnt val
+ @markers[type].dot.style[side] = val
+
+ true
diff --git a/afb-client/bower_components/tether/coffee/shift.coffee b/afb-client/bower_components/tether/coffee/shift.coffee
new file mode 100644
index 0000000..4dede41
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/shift.coffee
@@ -0,0 +1,27 @@
+@Tether.modules.push
+ position: ({top, left}) ->
+ return unless @options.shift
+
+ result = (val) ->
+ if typeof val is 'function'
+ val.call @, {top, left}
+ else
+ val
+
+ shift = result @options.shift
+
+ if typeof shift is 'string'
+ shift = shift.split(' ')
+ shift[1] or= shift[0]
+
+ [shiftTop, shiftLeft] = shift
+
+ shiftTop = parseFloat shiftTop, 10
+ shiftLeft = parseFloat shiftLeft, 10
+ else
+ [shiftTop, shiftLeft] = [shift.top, shift.left]
+
+ top += shiftTop
+ left += shiftLeft
+
+ {top, left}
diff --git a/afb-client/bower_components/tether/coffee/tether.coffee b/afb-client/bower_components/tether/coffee/tether.coffee
new file mode 100644
index 0000000..3df246f
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/tether.coffee
@@ -0,0 +1,573 @@
+if not @Tether?
+ throw new Error "You must include the utils.js file before tether.js"
+
+Tether = @Tether
+
+{getScrollParent, getSize, getOuterSize, getBounds, getOffsetParent, extend, addClass, removeClass, updateClasses, defer, flush, getScrollBarSize} = Tether.Utils
+
+within = (a, b, diff=1) ->
+ a + diff >= b >= a - diff
+
+transformKey = do ->
+ el = document.createElement 'div'
+
+ for key in ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']
+ if el.style[key] isnt undefined
+ return key
+
+tethers = []
+
+position = ->
+ for tether in tethers
+ tether.position(false)
+
+ flush()
+
+now = ->
+ performance?.now?() ? +new Date
+
+do ->
+ lastCall = null
+ lastDuration = null
+ pendingTimeout = null
+
+ tick = ->
+ if lastDuration? and lastDuration > 16
+ # We voluntarily throttle ourselves if we can't manage 60fps
+ lastDuration = Math.min(lastDuration - 16, 250)
+
+ # Just in case this is the last event, remember to position just once more
+ pendingTimeout = setTimeout tick, 250
+ return
+
+ if lastCall? and (now() - lastCall) < 10
+ # Some browsers call events a little too frequently, refuse to run more than is reasonable
+ return
+
+ if pendingTimeout?
+ clearTimeout pendingTimeout
+ pendingTimeout = null
+
+ lastCall = now()
+
+ position()
+
+ lastDuration = now() - lastCall
+
+ for event in ['resize', 'scroll', 'touchmove']
+ window.addEventListener event, tick
+
+MIRROR_LR =
+ center: 'center'
+ left: 'right'
+ right: 'left'
+
+MIRROR_TB =
+ middle: 'middle'
+ top: 'bottom'
+ bottom: 'top'
+
+OFFSET_MAP =
+ top: 0
+ left: 0
+ middle: '50%'
+ center: '50%'
+ bottom: '100%'
+ right: '100%'
+
+autoToFixedAttachment = (attachment, relativeToAttachment) ->
+ {left, top} = attachment
+
+ if left is 'auto'
+ left = MIRROR_LR[relativeToAttachment.left]
+
+ if top is 'auto'
+ top = MIRROR_TB[relativeToAttachment.top]
+
+ {left, top}
+
+attachmentToOffset = (attachment) ->
+ return {
+ left: OFFSET_MAP[attachment.left] ? attachment.left
+ top: OFFSET_MAP[attachment.top] ? attachment.top
+ }
+
+addOffset = (offsets...) ->
+ out = {top: 0, left: 0}
+
+ for {top, left} in offsets
+ if typeof top is 'string'
+ top = parseFloat(top, 10)
+ if typeof left is 'string'
+ left = parseFloat(left, 10)
+
+ out.top += top
+ out.left += left
+
+ out
+
+offsetToPx = (offset, size) ->
+ if typeof offset.left is 'string' and offset.left.indexOf('%') isnt -1
+ offset.left = parseFloat(offset.left, 10) / 100 * size.width
+ if typeof offset.top is 'string' and offset.top.indexOf('%') isnt -1
+ offset.top = parseFloat(offset.top, 10) / 100 * size.height
+
+ offset
+
+parseAttachment = parseOffset = (value) ->
+ [top, left] = value.split(' ')
+
+ {top, left}
+
+class _Tether
+ @modules: []
+
+ constructor: (options) ->
+ tethers.push @
+
+ @history = []
+
+ @setOptions options, false
+
+ for module in Tether.modules
+ module.initialize?.call(@)
+
+ @position()
+
+ getClass: (key) ->
+ if @options.classes?[key]
+ @options.classes[key]
+ else if @options.classes?[key] isnt false
+ if @options.classPrefix
+ "#{ @options.classPrefix }-#{ key }"
+ else
+ key
+ else
+ ''
+
+ setOptions: (@options, position=true) ->
+ defaults =
+ offset: '0 0'
+ targetOffset: '0 0'
+ targetAttachment: 'auto auto'
+ classPrefix: 'tether'
+
+ @options = extend defaults, @options
+
+ {@element, @target, @targetModifier} = @options
+
+ if @target is 'viewport'
+ @target = document.body
+ @targetModifier = 'visible'
+ else if @target is 'scroll-handle'
+ @target = document.body
+ @targetModifier = 'scroll-handle'
+
+ for key in ['element', 'target']
+ if not @[key]?
+ throw new Error "Tether Error: Both element and target must be defined"
+
+ if @[key].jquery?
+ @[key] = @[key][0]
+ else if typeof @[key] is 'string'
+ @[key] = document.querySelector @[key]
+
+ addClass @element, @getClass 'element'
+ addClass @target, @getClass 'target'
+
+ if not @options.attachment
+ throw new Error "Tether Error: You must provide an attachment"
+
+ @targetAttachment = parseAttachment @options.targetAttachment
+ @attachment = parseAttachment @options.attachment
+ @offset = parseOffset @options.offset
+ @targetOffset = parseOffset @options.targetOffset
+
+ if @scrollParent?
+ @disable()
+
+ if @targetModifier is 'scroll-handle'
+ @scrollParent = @target
+ else
+ @scrollParent = getScrollParent @target
+
+ unless @options.enabled is false
+ @enable(position)
+
+ getTargetBounds: ->
+ if @targetModifier?
+ switch @targetModifier
+ when 'visible'
+ if @target is document.body
+ {top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth}
+ else
+ bounds = getBounds @target
+
+ out =
+ height: bounds.height
+ width: bounds.width
+ top: bounds.top
+ left: bounds.left
+
+ out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top))
+ out.height = Math.min(out.height, bounds.height - ((bounds.top + bounds.height) - (pageYOffset + innerHeight)))
+ out.height = Math.min(innerHeight, out.height)
+ out.height -= 2
+
+ out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left))
+ out.width = Math.min(out.width, bounds.width - ((bounds.left + bounds.width) - (pageXOffset + innerWidth)))
+ out.width = Math.min(innerWidth, out.width)
+ out.width -= 2
+
+ if out.top < pageYOffset
+ out.top = pageYOffset
+ if out.left < pageXOffset
+ out.left = pageXOffset
+
+ out
+
+ when 'scroll-handle'
+ target = @target
+ if target is document.body
+ target = document.documentElement
+
+ bounds =
+ left: pageXOffset
+ top: pageYOffset
+ height: innerHeight
+ width: innerWidth
+ else
+ bounds = getBounds target
+
+ style = getComputedStyle target
+
+ hasBottomScroll = target.scrollWidth > target.clientWidth or 'scroll' is [style.overflow, style.overflowX] or @target isnt document.body
+
+ scrollBottom = 0
+ if hasBottomScroll
+ scrollBottom = 15
+
+ height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom
+
+ out =
+ width: 15
+ height: height * 0.975 * (height / target.scrollHeight)
+ left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
+
+ fitAdj = 0
+ if height < 408 and @target is document.body
+ fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58
+
+ if @target isnt document.body
+ out.height = Math.max out.height, 24
+
+ scrollPercentage = @target.scrollTop / (target.scrollHeight - height)
+ out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth)
+
+ if @target is document.body
+ out.height = Math.max out.height, 24
+
+ out
+ else
+ getBounds @target
+
+ clearCache: ->
+ @_cache = {}
+
+ cache: (k, getter) ->
+ # More than one module will often need the same DOM info, so
+ # we keep a cache which is cleared on each position call
+ @_cache ?= {}
+
+ if not @_cache[k]?
+ @_cache[k] = getter.call(@)
+
+ @_cache[k]
+
+ enable: (position=true) ->
+ addClass @target, @getClass 'enabled'
+ addClass @element, @getClass 'enabled'
+ @enabled = true
+
+ if @scrollParent isnt document
+ @scrollParent.addEventListener 'scroll', @position
+
+ if position
+ @position()
+
+ disable: ->
+ removeClass @target, @getClass 'enabled'
+ removeClass @element, @getClass 'enabled'
+ @enabled = false
+
+ if @scrollParent?
+ @scrollParent.removeEventListener 'scroll', @position
+
+ destroy: ->
+ @disable()
+
+ for tether, i in tethers
+ if tether is @
+ tethers.splice i, 1
+ break
+
+ updateAttachClasses: (elementAttach=@attachment, targetAttach=@targetAttachment) ->
+ sides = ['left', 'top', 'bottom', 'right', 'middle', 'center']
+
+ if @_addAttachClasses?.length
+ # updateAttachClasses can be called more than once in a position call, so
+ # we need to clean up after ourselves such that when the last defer gets
+ # ran it doesn't add any extra classes from previous calls.
+ @_addAttachClasses.splice 0, @_addAttachClasses.length
+
+ add = @_addAttachClasses ?= []
+ add.push "#{ @getClass('element-attached') }-#{ elementAttach.top }" if elementAttach.top
+ add.push "#{ @getClass('element-attached') }-#{ elementAttach.left }" if elementAttach.left
+ add.push "#{ @getClass('target-attached') }-#{ targetAttach.top }" if targetAttach.top
+ add.push "#{ @getClass('target-attached') }-#{ targetAttach.left }" if targetAttach.left
+
+ all = []
+ all.push "#{ @getClass('element-attached') }-#{ side }" for side in sides
+ all.push "#{ @getClass('target-attached') }-#{ side }" for side in sides
+
+ defer =>
+ return unless @_addAttachClasses?
+
+ updateClasses @element, @_addAttachClasses, all
+ updateClasses @target, @_addAttachClasses, all
+
+ @_addAttachClasses = undefined
+
+ position: (flushChanges=true) =>
+ # flushChanges commits the changes immediately, leave true unless you are positioning multiple
+ # tethers (in which case call Tether.Utils.flush yourself when you're done)
+
+ return unless @enabled
+
+ @clearCache()
+
+ # Turn 'auto' attachments into the appropriate corner or edge
+ targetAttachment = autoToFixedAttachment(@targetAttachment, @attachment)
+
+ @updateAttachClasses @attachment, targetAttachment
+
+ elementPos = @cache 'element-bounds', => getBounds @element
+ {width, height} = elementPos
+
+ if width is 0 and height is 0 and @lastSize?
+ # We cache the height and width to make it possible to position elements that are
+ # getting hidden.
+ {width, height} = @lastSize
+ else
+ @lastSize = {width, height}
+
+ targetSize = targetPos = @cache 'target-bounds', => @getTargetBounds()
+
+ # Get an actual px offset from the attachment
+ offset = offsetToPx attachmentToOffset(@attachment), {width, height}
+ targetOffset = offsetToPx attachmentToOffset(targetAttachment), targetSize
+
+ manualOffset = offsetToPx(@offset, {width, height})
+ manualTargetOffset = offsetToPx(@targetOffset, targetSize)
+
+ # Add the manually provided offset
+ offset = addOffset offset, manualOffset
+ targetOffset = addOffset targetOffset, manualTargetOffset
+
+ # It's now our goal to make (element position + offset) == (target position + target offset)
+ left = targetPos.left + targetOffset.left - offset.left
+ top = targetPos.top + targetOffset.top - offset.top
+
+ for module in Tether.modules
+ ret = module.position.call(@, {left, top, targetAttachment, targetPos, @attachment, elementPos, offset, targetOffset, manualOffset, manualTargetOffset, scrollbarSize})
+
+ if not ret? or typeof ret isnt 'object'
+ continue
+ else if ret is false
+ return false
+ else
+ {top, left} = ret
+
+ # We describe the position three different ways to give the optimizer
+ # a chance to decide the best possible way to position the element
+ # with the fewest repaints.
+ next = {
+ # It's position relative to the page (absolute positioning when
+ # the element is a child of the body)
+ page:
+ top: top
+ left: left
+
+ # It's position relative to the viewport (fixed positioning)
+ viewport:
+ top: top - pageYOffset
+ bottom: pageYOffset - top - height + innerHeight
+ left: left - pageXOffset
+ right: pageXOffset - left - width + innerWidth
+ }
+
+ if document.body.scrollWidth > window.innerWidth
+ scrollbarSize = @cache 'scrollbar-size', getScrollBarSize
+ next.viewport.bottom -= scrollbarSize.height
+
+ if document.body.scrollHeight > window.innerHeight
+ scrollbarSize = @cache 'scrollbar-size', getScrollBarSize
+ next.viewport.right -= scrollbarSize.width
+
+ if document.body.style.position not in ['', 'static'] or document.body.parentElement.style.position not in ['', 'static']
+ # Absolute positioning in the body will be relative to the page, not the 'initial containing block'
+ next.page.bottom = document.body.scrollHeight - top - height
+ next.page.right = document.body.scrollWidth - left - width
+
+ if @options.optimizations?.moveElement isnt false and not @targetModifier?
+ offsetParent = @cache 'target-offsetparent', => getOffsetParent @target
+ offsetPosition = @cache 'target-offsetparent-bounds', -> getBounds offsetParent
+ offsetParentStyle = getComputedStyle offsetParent
+ elementStyle = getComputedStyle @element
+ offsetParentSize = offsetPosition
+
+ offsetBorder = {}
+ for side in ['Top', 'Left', 'Bottom', 'Right']
+ offsetBorder[side.toLowerCase()] = parseFloat offsetParentStyle["border#{ side }Width"]
+
+ offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right
+ offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom
+
+ if next.page.top >= (offsetPosition.top + offsetBorder.top) and next.page.bottom >= offsetPosition.bottom
+ if next.page.left >= (offsetPosition.left + offsetBorder.left) and next.page.right >= offsetPosition.right
+ # We're within the visible part of the target's scroll parent
+
+ scrollTop = offsetParent.scrollTop
+ scrollLeft = offsetParent.scrollLeft
+
+ # It's position relative to the target's offset parent (absolute positioning when
+ # the element is moved to be a child of the target's offset parent).
+ next.offset =
+ top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top
+ left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
+
+
+ # We could also travel up the DOM and try each containing context, rather than only
+ # looking at the body, but we're gonna get diminishing returns.
+
+ @move next
+
+ @history.unshift next
+
+ if @history.length > 3
+ @history.pop()
+
+ if flushChanges
+ flush()
+
+ true
+
+ move: (position) ->
+ return if not @element.parentNode?
+
+ same = {}
+
+ for type of position
+ same[type] = {}
+
+ for key of position[type]
+ found = false
+
+ for point in @history
+ unless within(point[type]?[key], position[type][key])
+ found = true
+ break
+
+ if not found
+ same[type][key] = true
+
+ css = {top: '', left: '', right: '', bottom: ''}
+
+ transcribe = (same, pos) =>
+ if @options.optimizations?.gpu isnt false
+ if same.top
+ css.top = 0
+ yPos = pos.top
+ else
+ css.bottom = 0
+ yPos = -pos.bottom
+
+ if same.left
+ css.left = 0
+ xPos = pos.left
+ else
+ css.right = 0
+ xPos = -pos.right
+
+
+ css[transformKey] = "translateX(#{ Math.round xPos }px) translateY(#{ Math.round yPos }px)"
+
+ if transformKey isnt 'msTransform'
+ # The Z transform will keep this in the GPU (faster, and prevents artifacts),
+ # but IE9 doesn't support 3d transforms and will choke.
+ css[transformKey] += " translateZ(0)"
+
+ else
+ if same.top
+ css.top = "#{ pos.top }px"
+ else
+ css.bottom = "#{ pos.bottom }px"
+
+ if same.left
+ css.left = "#{ pos.left }px"
+ else
+ css.right = "#{ pos.right }px"
+
+ moved = false
+ if (same.page.top or same.page.bottom) and (same.page.left or same.page.right)
+ css.position = 'absolute'
+ transcribe same.page, position.page
+
+ else if (same.viewport.top or same.viewport.bottom) and (same.viewport.left or same.viewport.right)
+ css.position = 'fixed'
+
+ transcribe same.viewport, position.viewport
+
+ else if same.offset? and same.offset.top and same.offset.left
+ css.position = 'absolute'
+
+ offsetParent = @cache 'target-offsetparent', => getOffsetParent @target
+
+ if getOffsetParent(@element) isnt offsetParent
+ defer =>
+ @element.parentNode.removeChild @element
+ offsetParent.appendChild @element
+
+ transcribe same.offset, position.offset
+
+ moved = true
+
+ else
+ css.position = 'absolute'
+ transcribe {top: true, left: true}, position.page
+
+ if not moved and @element.parentNode.tagName isnt 'BODY'
+ @element.parentNode.removeChild @element
+ document.body.appendChild @element
+
+ # Any css change will trigger a repaint, so let's avoid one if nothing changed
+ writeCSS = {}
+ write = false
+ for key, val of css
+ elVal = @element.style[key]
+
+ if elVal isnt '' and val isnt '' and key in ['top', 'left', 'bottom', 'right']
+ elVal = parseFloat elVal
+ val = parseFloat val
+
+ if elVal isnt val
+ write = true
+ writeCSS[key] = css[key]
+
+ if write
+ defer =>
+ extend @element.style, writeCSS
+
+Tether.position = position
+
+@Tether = extend _Tether, Tether
diff --git a/afb-client/bower_components/tether/coffee/utils.coffee b/afb-client/bower_components/tether/coffee/utils.coffee
new file mode 100644
index 0000000..ef1c0ed
--- /dev/null
+++ b/afb-client/bower_components/tether/coffee/utils.coffee
@@ -0,0 +1,211 @@
+@Tether ?= {modules: []}
+
+getScrollParent = (el) ->
+ position = getComputedStyle(el).position
+
+ if position is 'fixed'
+ return el
+
+ scrollParent = undefined
+
+ parent = el
+ while parent = parent.parentNode
+ try
+ style = getComputedStyle parent
+
+ return parent if not style?
+
+ if /(auto|scroll)/.test(style['overflow'] + style['overflow-y'] + style['overflow-x'])
+ if position isnt 'absolute' or style['position'] in ['relative', 'absolute', 'fixed']
+ return parent
+
+ return document.body
+
+uniqueId = do ->
+ id = 0
+ ->
+ id++
+
+zeroPosCache = {}
+getOrigin = (doc) ->
+ # getBoundingClientRect is unfortunately too accurate. It introduces a pixel or two of
+ # jitter as the user scrolls that messes with our ability to detect if two positions
+ # are equivilant or not. We place an element at the top left of the page that will
+ # get the same jitter, so we can cancel the two out.
+ node = doc._tetherZeroElement
+ if not node?
+ node = doc.createElement 'div'
+ node.setAttribute 'data-tether-id', uniqueId()
+ extend node.style,
+ top: 0
+ left: 0
+ position: 'absolute'
+
+ doc.body.appendChild node
+
+ doc._tetherZeroElement = node
+
+ id = node.getAttribute 'data-tether-id'
+ if not zeroPosCache[id]?
+ zeroPosCache[id] = {}
+ for k, v of node.getBoundingClientRect()
+ # Can't use extend, as on IE9, elements don't resolve to be hasOwnProperty
+ zeroPosCache[id][k] = v
+
+ # Clear the cache when this position call is done
+ defer ->
+ zeroPosCache[id] = undefined
+
+ return zeroPosCache[id]
+
+node = null
+getBounds = (el) ->
+ if el is document
+ doc = document
+ el = document.documentElement
+ else
+ doc = el.ownerDocument
+
+ docEl = doc.documentElement
+
+ box = {}
+ # The original object returned by getBoundingClientRect is immutable, so we clone it
+ # We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9
+ for k, v of el.getBoundingClientRect()
+ box[k] = v
+
+ origin = getOrigin doc
+
+ box.top -= origin.top
+ box.left -= origin.left
+
+ box.width ?= document.body.scrollWidth - box.left - box.right
+ box.height ?= document.body.scrollHeight - box.top - box.bottom
+
+ box.top = box.top - docEl.clientTop
+ box.left = box.left - docEl.clientLeft
+ box.right = doc.body.clientWidth - box.width - box.left
+ box.bottom = doc.body.clientHeight - box.height - box.top
+
+ box
+
+getOffsetParent = (el) ->
+ el.offsetParent or document.documentElement
+
+getScrollBarSize = ->
+ inner = document.createElement 'div'
+ inner.style.width = '100%'
+ inner.style.height = '200px'
+
+ outer = document.createElement 'div'
+ extend outer.style,
+ position: 'absolute'
+ top: 0
+ left: 0
+ pointerEvents: 'none'
+ visibility: 'hidden'
+ width: '200px'
+ height: '150px'
+ overflow: 'hidden'
+
+ outer.appendChild inner
+
+ document.body.appendChild outer
+
+ widthContained = inner.offsetWidth
+ outer.style.overflow = 'scroll'
+ widthScroll = inner.offsetWidth
+
+ if widthContained is widthScroll
+ widthScroll = outer.clientWidth
+
+ document.body.removeChild outer
+
+ width = widthContained - widthScroll
+
+ {width, height: width}
+
+extend = (out={}) ->
+ args = []
+ Array::push.apply(args, arguments)
+
+ for obj in args[1..] when obj
+ for own key, val of obj
+ out[key] = val
+
+ out
+
+removeClass = (el, name) ->
+ if el.classList?
+ el.classList.remove(cls) for cls in name.split(' ') when cls.trim()
+ else
+ el.className = el.className.replace new RegExp("(^| )#{ name.split(' ').join('|') }( |$)", 'gi'), ' '
+
+addClass = (el, name) ->
+ if el.classList?
+ el.classList.add(cls) for cls in name.split(' ') when cls.trim()
+ else
+ removeClass el, name
+ el.className += " #{ name }"
+
+hasClass = (el, name) ->
+ if el.classList?
+ el.classList.contains(name)
+ else
+ new RegExp("(^| )#{ name }( |$)", 'gi').test(el.className)
+
+updateClasses = (el, add, all) ->
+ # Of the set of 'all' classes, we need the 'add' classes, and only the
+ # 'add' classes to be set.
+ for cls in all when cls not in add
+ if hasClass(el, cls)
+ removeClass el, cls
+
+ for cls in add
+ if not hasClass(el, cls)
+ addClass el, cls
+
+deferred = []
+
+defer = (fn) ->
+ deferred.push fn
+
+flush = ->
+ fn() while fn = deferred.pop()
+
+class Evented
+ on: (event, handler, ctx, once=false) ->
+ @bindings ?= {}
+ @bindings[event] ?= []
+ @bindings[event].push {handler, ctx, once}
+
+ once: (event, handler, ctx) ->
+ @on(event, handler, ctx, true)
+
+ off: (event, handler) ->
+ return unless @bindings?[event]?
+
+ if not handler?
+ delete @bindings[event]
+ else
+ i = 0
+ while i < @bindings[event].length
+ if @bindings[event][i].handler is handler
+ @bindings[event].splice i, 1
+ else
+ i++
+
+ trigger: (event, args...) ->
+ if @bindings?[event]
+ i = 0
+ while i < @bindings[event].length
+ {handler, ctx, once} = @bindings[event][i]
+
+ handler.apply(ctx ? @, args)
+
+ if once
+ @bindings[event].splice i, 1
+ else
+ i++
+
+@Tether.Utils = {getScrollParent, getBounds, getOffsetParent, extend, addClass, removeClass, hasClass, updateClasses, defer, flush, uniqueId, Evented, getScrollBarSize}
diff --git a/afb-client/bower_components/tether/component.json b/afb-client/bower_components/tether/component.json
new file mode 100644
index 0000000..e593901
--- /dev/null
+++ b/afb-client/bower_components/tether/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "tether",
+ "repo": "HubSpot/tether",
+ "version": "0.6.5",
+ "description": "A client-side library to make absolutely positioned elements attach to elements in the page efficiently.",
+ "authors": [
+ "Zack Bloom <zackbloom@gmail.com>",
+ "Adam Schwartz <adam.flynn.schwartz@gmail.com>"
+ ],
+ "license": "MIT",
+ "demo": "http://github.hubspot.com/tether/docs/welcome/",
+ "main": "tether.js",
+ "styles": [
+ "css/tether.css"
+ ],
+ "scripts": [
+ "tether.js"
+ ]
+}
diff --git a/afb-client/bower_components/tether/css/tether-theme-arrows-dark.css b/afb-client/bower_components/tether/css/tether-theme-arrows-dark.css
new file mode 100644
index 0000000..2576f19
--- /dev/null
+++ b/afb-client/bower_components/tether/css/tether-theme-arrows-dark.css
@@ -0,0 +1,112 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+
+.tether-element {
+ position: absolute;
+ display: none; }
+ .tether-element.tether-open {
+ display: block; }
+
+.tether-element.tether-theme-arrows-dark {
+ max-width: 100%;
+ max-height: 100%; }
+ .tether-element.tether-theme-arrows-dark .tether-content {
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+ position: relative;
+ font-family: inherit;
+ background: black;
+ color: white;
+ padding: 1em;
+ font-size: 1.1em;
+ line-height: 1.5em; }
+ .tether-element.tether-theme-arrows-dark .tether-content:before {
+ content: "";
+ display: block;
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-width: 16px;
+ border-style: solid; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-center .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-center .tether-content:before {
+ top: 100%;
+ left: 50%;
+ margin-left: -16px;
+ border-top-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-center .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-center .tether-content:before {
+ bottom: 100%;
+ left: 50%;
+ margin-left: -16px;
+ border-bottom-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-right.tether-element-attached-middle .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-right.tether-element-attached-middle .tether-content:before {
+ left: 100%;
+ top: 50%;
+ margin-top: -16px;
+ border-left-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-left.tether-element-attached-middle .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-left.tether-element-attached-middle .tether-content:before {
+ right: 100%;
+ top: 50%;
+ margin-top: -16px;
+ border-right-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content:before {
+ bottom: 100%;
+ left: 16px;
+ border-bottom-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content:before {
+ bottom: 100%;
+ right: 16px;
+ border-bottom-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content:before {
+ top: 100%;
+ left: 16px;
+ border-top-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content:before {
+ top: 100%;
+ right: 16px;
+ border-top-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+ top: 16px;
+ left: 100%;
+ border-left-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+ top: 16px;
+ right: 100%;
+ border-right-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+ bottom: 16px;
+ left: 100%;
+ border-left-color: black; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+ bottom: 16px;
+ right: 100%;
+ border-right-color: black; }
diff --git a/afb-client/bower_components/tether/css/tether-theme-arrows.css b/afb-client/bower_components/tether/css/tether-theme-arrows.css
new file mode 100644
index 0000000..a3fb100
--- /dev/null
+++ b/afb-client/bower_components/tether/css/tether-theme-arrows.css
@@ -0,0 +1,120 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+
+.tether-element {
+ position: absolute;
+ display: none; }
+ .tether-element.tether-open {
+ display: block; }
+
+.tether-element.tether-theme-arrows {
+ max-width: 100%;
+ max-height: 100%; }
+ .tether-element.tether-theme-arrows .tether-content {
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+ position: relative;
+ font-family: inherit;
+ background: white;
+ color: inherit;
+ padding: 1em;
+ font-size: 1.1em;
+ line-height: 1.5em;
+ -webkit-transform: translateZ(0);
+ -moz-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ -o-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+ -moz-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+ filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); }
+ .tether-element.tether-theme-arrows .tether-content:before {
+ content: "";
+ display: block;
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-width: 16px;
+ border-style: solid; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-center .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-center .tether-content:before {
+ top: 100%;
+ left: 50%;
+ margin-left: -16px;
+ border-top-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-center .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-center .tether-content:before {
+ bottom: 100%;
+ left: 50%;
+ margin-left: -16px;
+ border-bottom-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-right.tether-element-attached-middle .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-right.tether-element-attached-middle .tether-content:before {
+ left: 100%;
+ top: 50%;
+ margin-top: -16px;
+ border-left-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-left.tether-element-attached-middle .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-left.tether-element-attached-middle .tether-content:before {
+ right: 100%;
+ top: 50%;
+ margin-top: -16px;
+ border-right-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content:before {
+ bottom: 100%;
+ left: 16px;
+ border-bottom-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content {
+ margin-top: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content:before {
+ bottom: 100%;
+ right: 16px;
+ border-bottom-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content:before {
+ top: 100%;
+ left: 16px;
+ border-top-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content {
+ margin-bottom: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content:before {
+ top: 100%;
+ right: 16px;
+ border-top-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+ top: 16px;
+ left: 100%;
+ border-left-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+ top: 16px;
+ right: 100%;
+ border-right-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content {
+ margin-right: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+ bottom: 16px;
+ left: 100%;
+ border-left-color: white; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content {
+ margin-left: 16px; }
+ .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+ bottom: 16px;
+ right: 100%;
+ border-right-color: white; }
diff --git a/afb-client/bower_components/tether/css/tether-theme-basic.css b/afb-client/bower_components/tether/css/tether-theme-basic.css
new file mode 100644
index 0000000..95bc689
--- /dev/null
+++ b/afb-client/bower_components/tether/css/tether-theme-basic.css
@@ -0,0 +1,29 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+
+.tether-element {
+ position: absolute;
+ display: none; }
+ .tether-element.tether-open {
+ display: block; }
+
+.tether-element.tether-theme-basic {
+ max-width: 100%;
+ max-height: 100%; }
+ .tether-element.tether-theme-basic .tether-content {
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+ -webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ font-family: inherit;
+ background: white;
+ color: inherit;
+ padding: 1em;
+ font-size: 1.1em;
+ line-height: 1.5em; }
diff --git a/afb-client/bower_components/tether/css/tether.css b/afb-client/bower_components/tether/css/tether.css
new file mode 100644
index 0000000..3372a2b
--- /dev/null
+++ b/afb-client/bower_components/tether/css/tether.css
@@ -0,0 +1,10 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+
+.tether-element {
+ position: absolute;
+ display: none; }
+ .tether-element.tether-open {
+ display: block; }
diff --git a/afb-client/bower_components/tether/docs/1-Overview/1-why_you_should_use_tether.md b/afb-client/bower_components/tether/docs/1-Overview/1-why_you_should_use_tether.md
new file mode 100644
index 0000000..6147d25
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/1-Overview/1-why_you_should_use_tether.md
@@ -0,0 +1,43 @@
+## Why You Should Use Tether
+
+Virtually every app includes some sort of overlay attached to an element on the page.
+Things like [tooltips](http://github.hubspot.com/tooltip/docs/welcome),
+[dropdowns](http://github.hubspot.com/select/docs/welcome), [hover-activated info boxes](http://github.hubspot.com/drop/docs/welcome), etc.
+
+Those elements need to be attached to something on the page. Actually placing them next to
+the element in the DOM causes problems though, if any parent element is anything
+but `overflow: visible`, the element gets cut off. So you need absolute positioning
+in the body.
+
+Some of the time absolute positioning is right, but what about if the thing we're
+attached to is fixed to the center of the screen? We'll have to move it every
+time the user scrolls. What about if the element is in a scrollable container,
+if the overlay is inside of it (so no clipping), it would be cool if the code
+were smart enough to move it inside when that area is scrolled. That way we
+need to reposition it even less.
+
+It would also be nice if the code could somehow figure out whether positioning it
+from the top, bottom, left, or right would result in the fewest repositionings
+as the user scrolls or resizes.
+
+Most of the time you're building these elements it would be nice for the element to
+flip to the other side of the element if it hits the edge of the screen, or a scrollable
+container it might be in. It would be nice if we could confine the element
+to within some area, or even hide it when it leaves.
+
+It would be nice for the element to be repositioned with CSS transforms
+rather than top and left when possible, to allow the positioning to be done entirely
+in the GPU.
+
+Now that the positioning is so fancy, you're going to use it for more and more
+elements. It would be cool if the library could optimize all of their repositioning
+into a single repaint.
+
+All of that is baked into Tether.
+
+### tl;dr
+
+- Optimized GPU-accelerated repositioning for 60fps scrolling
+- Reliable positioning on any possible corner, edge or point in between.
+- Support for repositioning or pinning the element when it would be offscreen
+- Designed to be embeddable in other libraries
diff --git a/afb-client/bower_components/tether/docs/1-Overview/2-repositioning.md b/afb-client/bower_components/tether/docs/1-Overview/2-repositioning.md
new file mode 100644
index 0000000..6c02483
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/1-Overview/2-repositioning.md
@@ -0,0 +1,46 @@
+Repositioning
+-----
+
+Tethers will be automatically repositioned when the page is resized, and when any element containing the Tether is scrolled.
+If the element moves for some other reason (e.g. with JavaScript), Tether won't know to reposition the element.
+
+#### Manually Repositioning
+
+The simplest way to reposition every Tether on the page is to call `Tether.position()`. It will efficiently reposition every
+Tether in a single repaint, making it more efficient than manually repositioning many Tethers individually.
+
+```javascript
+Tether.position()
+```
+
+#### Repositioning a Single Tether
+
+If you have many Tethers on screen, it may be more efficient to just reposition the tether that needs it. You can do this
+by calling the `.position` method on the Tether instance:
+
+```javascript
+tether = new Tether({ ... })
+
+// Later:
+tether.position()
+```
+
+#### Tethering Hidden Elements
+
+If you are creating a tether involving elements which are `display: none`, or not actually in the DOM,
+your Tether may not be able to position itself properly. One way around this is to
+ensure that a position call happens after all layouts have finished:
+
+```javascript
+myElement.style.display = 'block'
+
+tether = new Tether({ ... })
+
+setTimeout(function(){
+ tether.position();
+})
+```
+
+In general however, you shouldn't have any trouble if both the element and the target are visible and in the DOM when you
+create the Tether. If that is not the case, create the Tether disabled (option `enabled`: `false`), and enable it when
+the elements are ready.
diff --git a/afb-client/bower_components/tether/docs/1-Overview/3-why_we_dont_support_IE_8.md b/afb-client/bower_components/tether/docs/1-Overview/3-why_we_dont_support_IE_8.md
new file mode 100644
index 0000000..841de9e
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/1-Overview/3-why_we_dont_support_IE_8.md
@@ -0,0 +1,47 @@
+Why we don't support IE 8
+-------------------------
+
+We've been living in 2007 for a while now, pretending that new browser features don't
+exist because they aren't in IE8. You might not even know about some of these features,
+or think they are only enabled by jQuery or underscore, simply because it hasn't
+been an option to rely upon them.
+
+Here is the list of features you don't have if you choose to support IE 8:
+
+- HTML5 audio and video
+- SVG
+- Canvas
+- TrueType fonts
+- Media Queries
+- CSS Transforms
+- Multiple Backgrounds
+- CSS3 Units (vh, vw, rem)
+- Custom DOM events
+- Hardware accelerated graphics
+- The DOMContentLoaded event
+- addEventListener
+- Object.create, .seal, .freeze, .defineProperty
+- Array.isArray, .indexOf, .every, .some, .forEach, .map, .filter, .reduce
+- A modern JavaScript engine
+- A real developer tools
+- A consistent box model
+- jQuery 2
+- Google Apps
+- Tether
+
+It's true that IE 8 still holds a big chunk of the browsing population, but the reasons
+why they can't update are dwindling. There are two big reasons for continuing IE 8 support.
+
+#### Enterprises
+
+ Microsoft is dropping support for XP in April, organizations who want security updates will have to upgrade.
+
+#### China uses XP
+
+ Chrome, Firefox and Opera all support XP. Nothing prevents users from upgrading, except the inertia of
+ organizations who still support IE 8.
+
+#### The Future
+
+We are skating towards where the puck will be, and we hope that as you decide to drop IE 8 support,
+you choose to add Tether to the list of awesome things you can do.
diff --git a/afb-client/bower_components/tether/docs/2-Examples/1-list_of_examples.md b/afb-client/bower_components/tether/docs/2-Examples/1-list_of_examples.md
new file mode 100644
index 0000000..bbb7fd5
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/2-Examples/1-list_of_examples.md
@@ -0,0 +1,27 @@
+### Examples
+
+It's our goal to create a wide variety of example of how Tether
+can be used. Here's what we have so far, please send a PR with
+any examples you might create.
+
+#### Beginner
+
+- [simple](../../examples/simple): A simple example to get you started
+- [out-of-bounds](../../examples/out-of-bounds): How to hide the element when it would
+otherwise be offscreen
+- [pin](../../examples/pin): How to pin the element so it never goes offscreen
+- [enable-disable](../../examples/enable-disable): How to enable and disable the Tether
+in JavaScript
+
+#### Advanced
+
+- [content-visible](../../examples/content-visible): Demonstrates using the `'visible'`
+`targetModifier` to align an element with the visible portion of another.
+- [dolls](../../examples/dolls): A performance test to show several dozen elements,
+each tethered to the previous. Try dragging the top left tether.
+- [element-scroll](../../examples/element-scroll): Demonstrates using the `'scroll-handle'`
+`targetModifier` to align an element with the scrollbar of an element.
+- [scroll](../../examples/scroll): Demonstrates using the `'scroll-handle'` `targetModifier`
+to align an element with the body's scroll handle.
+- [viewport](../../examples/viewport): Demonstrates aligning an element with the
+viewport by using the `'visible'` `targetModifier` when tethered to the body.
diff --git a/afb-client/bower_components/tether/docs/2-Examples/2-projects_using_tether.md b/afb-client/bower_components/tether/docs/2-Examples/2-projects_using_tether.md
new file mode 100644
index 0000000..b668a03
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/2-Examples/2-projects_using_tether.md
@@ -0,0 +1,29 @@
+## Projects Using Tether
+
+Here at HubSpot we have built a bunch of libraries on top of Tether,
+both because we wanted Tether-performance, and because we saw opportunities
+to improve on what was available in the client-side ecosystem.
+
+### [Select](http://github.hubspot.com/select/docs/welcome)
+
+Select is a replacement for native browser select elements that is fully stylable.
+
+### [Shepherd](http://github.hubspot.com/shepherd/docs/welcome)
+
+Shepherd is a library for making tours of your app to help onboard users and show off
+new features.
+
+### [Tooltip](http://github.hubspot.com/tooltip/docs/welcome)
+
+A simple, easy-to-use implementation of tooltips that works well.
+
+### [Drop](http://github.hubspot.com/drop/docs/welcome)
+
+Where Tether does general-purpose positioning, Drop assumes that you are interested
+in making something which pops up next to something the user clicks or hovers on.
+
+If your building something that fits that pattern, Drop can make things a little easier.
+
+### Your Project Here
+
+If you have a cool open-source library built on Tether, PR this doc, or [get in touch](mailto:zbloom@hubspot.com).
diff --git a/afb-client/bower_components/tether/docs/3-Advanced/1-embedding_tether.md b/afb-client/bower_components/tether/docs/3-Advanced/1-embedding_tether.md
new file mode 100644
index 0000000..f47be16
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/3-Advanced/1-embedding_tether.md
@@ -0,0 +1,9 @@
+## Embedding Tether
+
+Tether is designed to be embeddable in other libraries.
+
+There is one thing you should think about doing to create an embedded Tether:
+
+- Set the `classPrefix` of the tethers you create. That prefix will replace `'tether'` in
+all of the classes. You can also disable classes you don't intend on using with the `classes`
+option.
diff --git a/afb-client/bower_components/tether/docs/3-Advanced/2-extending_tether.md b/afb-client/bower_components/tether/docs/3-Advanced/2-extending_tether.md
new file mode 100644
index 0000000..6a13e68
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/3-Advanced/2-extending_tether.md
@@ -0,0 +1,54 @@
+Extending Tether
+-----
+
+Tether has a module system which can be used to modify Tether's positioning, or just do something each time the Tether is moved.
+
+Tether has an array called `Tether.modules`, push onto it to add a module:
+
+```coffeescript
+Tether.modules.push
+ position: ({top, left}) ->
+ top += 10
+
+ {top, left}
+```
+
+#### Position
+
+Your position function can either return a new object with `top` and `left`, `null`/`undefined` to leave the coordinates unchanged, or
+`false` to cancel the positioning.
+
+The position function is passed an object with the following elements:
+
+```javascript
+{
+ left, // The element's new position, from the top left corner of the page
+ top,
+ targetAttachment, // The targetAttachment, with 'auto' resolved to an actual attachment
+ targetPos, // The coordinates of the target
+ attachment, // The attachment, as passed in the option
+ elementPos, // The coordinates of the element
+ offset, // The offset, after it's converted into pixels and the manual offset is added
+ targetOffset, // The attachment is converted into an offset and is included in these values
+ manualOffset, // The manual offset, in pixels
+ manualTargetOffset
+}
+```
+
+It is called with the Tether instance as its context (`this`).
+
+#### Initialize
+
+Modules can also have an `initialize` function which will be called when a new tether is created. The initialize function
+is also called with the Tether instance as its context.
+
+```coffeescript
+Tether.modules.push
+ initialize: ->
+ console.log "New Tether Created!", @
+```
+
+#### Examples
+
+[Constraints](https://github.com/HubSpot/tether/blob/master/coffee/constraint.coffee) and [shift](https://github.com/HubSpot/tether/blob/master/coffee/shift.coffee) are both implemented as modules.
+[Mark Attachment](https://github.com/HubSpot/tether/blob/master/coffee/markAttachment.coffee) is used by the docs.
diff --git a/afb-client/bower_components/tether/docs/coffee/intro.coffee b/afb-client/bower_components/tether/docs/coffee/intro.coffee
new file mode 100644
index 0000000..52a305d
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/coffee/intro.coffee
@@ -0,0 +1,113 @@
+{uniqueId} = Tether.Utils
+
+SETUP_JS = """
+yellowBox = $('.yellow-box', $output);
+greenBox = $('.green-box', $output);
+scrollBox = $('.scroll-box', $output);
+"""
+
+OUTPUT_HTML = (key) -> """
+<div class="scroll-box">
+ <div class="scroll-content">
+ <div class="yellow-box" data-example="#{ key }"></div>
+ <div class="green-box" data-example="#{ key }"></div>
+ </div>
+</div>
+"""
+
+tethers = {}
+
+getOutput = ($block) ->
+ key = $block.data('example')
+ if key and typeof key is 'string'
+ return $("output[data-example='#{ key }']")
+ else
+ return $block.parents('pre').nextAll('output').first()
+
+run = (key) ->
+ if typeof key is 'string'
+ $block = $("code[data-example='#{ key }']")
+ else
+ $block = key
+
+ key = $block.attr('data-example')
+
+ $output = getOutput $block
+
+ code = $block.text()
+ code = SETUP_JS + code
+
+ window.$output = $output
+ tethers[key] = eval code
+
+setupBlock = ($block) ->
+ key = $block.data('example')
+
+ $output = getOutput $block
+
+ if not key
+ key = uniqueId()
+ $block.attr('data-example', key)
+ $output.attr('data-example', key)
+ $output.find('.tether-element').attr('data-example', key)
+
+ $output.html OUTPUT_HTML(key)
+
+ $scrollBox = $output.find('.scroll-box')
+ $scrollContent = $scrollBox.find('.scroll-content')
+ $scrollBox.scrollTop(parseInt($scrollContent.css('height')) / 2 - $scrollBox.height() / 2)
+ $scrollBox.scrollLeft(parseInt($scrollContent.css('width')) / 2 - $scrollBox.width() / 2)
+ setTimeout ->
+ $scrollBox.on 'scroll', ->
+ $output.addClass 'scrolled'
+
+ $scrollBox.css 'height', "#{ $block.parent().outerHeight() }px"
+
+ if not $output.attr('deactivated')?
+ run $block
+
+$(document.body).on 'click', (e) ->
+ if $(e.target).is('output[deactivated]')
+ activate $(e.target)
+ false
+ else if $(e.target).is('output[activated]')
+ deactivate $(e.target)
+ false
+
+activate = ($output) ->
+ $block = $output.prev().find('code')
+
+ run $block
+
+ $output.find('.tether-element').show()
+
+ key = $output.data('example')
+ $(tethers[key].element).show()
+ tethers[key].enable()
+
+ $output.removeAttr('deactivated')
+ $output.attr('activated', true)
+
+deactivate = ($output) ->
+ $block = $output.prev().find('code')
+ key = $output.data('example')
+
+ tethers[key].disable()
+
+ $el = $(tethers[key].element)
+ $el.detach()
+ $output.find('.scroll-content').append $el
+ $el.hide()
+
+ $output.removeAttr('activated')
+ $output.attr('deactivated', true)
+
+init = ->
+ $blocks = $('code[data-example]')
+
+ setupBlock($ block) for block in $blocks
+
+window.EXECUTR_OPTIONS =
+ codeSelector: 'code[executable]'
+
+$ init
diff --git a/afb-client/bower_components/tether/docs/css/intro.css b/afb-client/bower_components/tether/docs/css/intro.css
new file mode 100644
index 0000000..46a9ce9
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/css/intro.css
@@ -0,0 +1,219 @@
+@charset "UTF-8";
+*, *:after, *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+
+body {
+ position: relative; }
+
+.yellow-box {
+ width: 100px;
+ height: 100px;
+ background-color: #ffee88;
+ pointer-events: none; }
+
+.green-box {
+ margin-top: 65px;
+ margin-left: 100px;
+ width: 200px;
+ height: 50px;
+ background-color: #44ee99; }
+ .no-green .green-box {
+ display: none; }
+
+.scroll-box {
+ height: 150px;
+ border: 10px solid #eeeeee;
+ background: #fbfbfb;
+ overflow: auto;
+ position: relative; }
+
+.scroll-content {
+ height: 2000px;
+ width: 2000px;
+ padding: 910px 809px; }
+
+pre.pre-with-output {
+ margin: 0;
+ width: 50%;
+ float: left; }
+ pre.pre-with-output code mark {
+ background: #b8daff;
+ color: black; }
+
+p, h2, h3 {
+ clear: both; }
+
+output {
+ display: block;
+ position: relative;
+ width: 50%;
+ float: right;
+ margin-bottom: 15px; }
+ output.scroll-page .scroll-box {
+ overflow: hidden; }
+ output.scroll-page:after {
+ content: "↕ scroll the page ↕"; }
+ output:after {
+ content: "↕ scroll this area ↕";
+ position: absolute;
+ bottom: 25px;
+ width: 100%;
+ text-align: center;
+ font-size: 16px;
+ font-variant: small-caps;
+ color: #777777;
+ opacity: 1;
+ transition: opacity 0.2s; }
+ output.scrolled:after {
+ opacity: 0; }
+ output[deactivated], output[activated] {
+ cursor: pointer; }
+ output[deactivated] .scroll-box, output[activated] .scroll-box {
+ pointer-events: none; }
+ output[deactivated]:after, output[activated]:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ opacity: 1;
+ content: "Click To Show";
+ background-color: #aaaaaa;
+ border-left: 10px solid #eeeeee;
+ color: white;
+ font-size: 24px;
+ font-variant: normal;
+ padding-top: 80px; }
+ output[activated]:after {
+ content: "Click To Hide"; }
+ output[activated].visible-enabled:after {
+ height: 35px;
+ padding-top: 5px; }
+
+.attachment-mark, .tether-marker-dot {
+ position: relative; }
+ .attachment-mark:after, .tether-marker-dot:after {
+ content: "A";
+ width: 10px;
+ height: 10px;
+ background-color: red;
+ display: inline-block;
+ line-height: 10px;
+ font-size: 9px;
+ color: white;
+ text-align: center;
+ position: absolute; }
+
+span.attachment-mark:after, span.tether-marker-dot:after {
+ position: relative;
+ top: -1px;
+ margin-right: 1px; }
+
+.tether-marker-dot {
+ position: absolute; }
+ .tether-marker-dot:after {
+ top: -5px;
+ left: -5px; }
+
+.tether-target-marker {
+ position: absolute; }
+ div.tether-target-attached-left .tether-target-marker {
+ left: 0; }
+ div.tether-target-attached-top .tether-target-marker {
+ top: 0; }
+ div.tether-target-attached-bottom .tether-target-marker {
+ bottom: 0; }
+ div.tether-target-attached-right .tether-target-marker {
+ right: 0; }
+ div.tether-target-attached-center .tether-target-marker {
+ left: 50%; }
+
+.tether-element-marker {
+ position: absolute; }
+ div.tether-element-attached-left .tether-element-marker {
+ left: 0; }
+ div.tether-element-attached-top .tether-element-marker {
+ top: 0; }
+ div.tether-element-attached-bottom .tether-element-marker {
+ bottom: 0; }
+ div.tether-element-attached-right .tether-element-marker {
+ right: 0; }
+ div.tether-element-attached-center .tether-element-marker {
+ left: 50%; }
+
+.tether-element-attached-middle .tether-element-marker {
+ top: 50px; }
+
+.tether-target-attached-middle .tether-target-marker {
+ top: 25px; }
+
+.tether-element {
+ position: relative; }
+ .tether-element.tether-pinned-left {
+ box-shadow: inset 2px 0 0 0 red; }
+ .tether-element.tether-pinned-right {
+ box-shadow: inset -2px 0 0 0 red; }
+ .tether-element.tether-pinned-top {
+ box-shadow: inset 0 2px 0 0 red; }
+ .tether-element.tether-pinned-bottom {
+ box-shadow: inset 0 -2px 0 0 red; }
+
+.tether-target {
+ position: relative; }
+
+.tether-element.tether-out-of-bounds[data-example="hide"] {
+ display: none; }
+
+[data-example^="optimizer"].lang-javascript {
+ /* This should just be a `code` selector, but sass doesn't allow that with & */
+ min-height: 220px; }
+[data-example^="optimizer"].tether-element:before {
+ margin-top: 26px;
+ display: block;
+ text-align: center;
+ content: "I'm in the body";
+ line-height: 1.2;
+ font-size: 15px;
+ padding: 4px;
+ color: #666666; }
+[data-example^="optimizer"] .scroll-box .tether-element:before {
+ content: "I'm in my scroll parent!"; }
+
+.tether-element[data-example="scroll-visible"] {
+ height: 30px; }
+ .tether-element[data-example="scroll-visible"] .tether-marker-dot {
+ display: none; }
+
+.hs-doc-content h2.projects-header {
+ text-align: center;
+ font-weight: 300; }
+
+.projects-paragraph {
+ text-align: center; }
+ .projects-paragraph a {
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ text-align: center;
+ margin-right: 30px;
+ color: inherit; }
+ .projects-paragraph a span {
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ margin-bottom: 20px;
+ font-size: 20px;
+ color: inherit;
+ font-weight: 300; }
+ .projects-paragraph a img {
+ display: block;
+ max-width: 100%;
+ width: 100px; }
diff --git a/afb-client/bower_components/tether/docs/intro.md b/afb-client/bower_components/tether/docs/intro.md
new file mode 100644
index 0000000..3681d29
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/intro.md
@@ -0,0 +1,600 @@
+<script src="tether.js"></script>
+<script src="js/markAttachment.js"></script>
+<script src="docs/js/intro.js"></script>
+<link rel="stylesheet" href="docs/css/intro.css"></link>
+
+Tether
+======
+
+Tether is a JavaScript library for efficiently making an absolutely positioned
+element stay next to another element on the page. For example, you might
+want a tooltip or dialog to open, and remain, next to the relevant item
+on the page.
+
+Tether includes the ability to constrain the element within the viewport, its
+scroll parent, any other element on the page, or a fixed bounding box. When it
+exceeds those constraints it can be pinned to the edge, flip to the other
+side of its target, or hide itself.
+
+Tether optimizes its location placement to result in the minimum amount of
+'jankyness' as the page is scrolled and resized. The page can maintain 60fps
+scrolling even with dozens or hundreds of tethers on screen (pop open the
+devtools timeline as you scroll this page).
+
+Tether is 5kb minified and gzipped, and supports IE9+, and all modern
+browsers.
+
+<h2 class="projects-header">Projects Built With Tether</h2>
+<p class="projects-paragraph">
+<a href="http://github.hubspot.com/select/docs/welcome"><span>Select</span><img src="http://github.hubspot.com/os-icons/select-icon.png" /></a>
+<a href="http://github.hubspot.com/drop/docs/welcome"><span>Drop</span><img src="http://github.hubspot.com/os-icons/drop-icon.png" /></a>
+<a href="http://github.hubspot.com/tooltip/docs/welcome"><span>Tooltip</span><img src="http://github.hubspot.com/os-icons/tooltip-icon.png" /></a>
+<a href="http://github.hubspot.com/shepherd/docs/welcome"><span>Shepherd</span><img src="http://github.hubspot.com/os-icons/shepherd-icon.png" /></a>
+</p>
+
+Usage
+-----
+
+The element to be moved is called the 'element'.
+The element in the page it's to be attached to is called the 'target'.
+
+To use Tether, you define a point on the target and a point on the element.
+Tether moves the element to keep those two points on top of each other.
+
+That point is called the attachment (we've marked it in the examples with
+a red <span class="attachment-mark"></span>). For example, if you'd like
+the element to sit on the left of the target:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example='usage'>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top right',
+ targetAttachment: 'top left'
+});
+</code></pre><output data-example='usage'></output>
+
+Attachment
+----------
+
+You can move the attachment points of both the element and the target.
+
+For example, lets move the element's attachment:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: <mark>'bottom left'</mark>,
+ targetAttachment: 'top left'
+});
+</code></pre><output></output>
+
+We can also change the target's attachment point:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'bottom left',
+ targetAttachment: <mark>'bottom right'</mark>
+});
+</code></pre><output></output>
+
+There are two more attachment points we haven't seen yet, center and middle:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: <mark>'middle center'</mark>,
+ targetAttachment: <mark>'middle center'</mark>
+});
+</code></pre><output></output>
+
+All told, Tether provides six built in attachment positions:
+
+- left
+- center
+- right
+- top
+- middle
+- bottom
+
+The syntax of the attachment properties is: `"vertical-attachment horizontal-attachment"`
+
+You must always supply an `attachment`. If you don't supply a `target-attachment`, it is
+assumed to be the mirror image of `attachment`.
+
+### Offset
+
+The six attachment points we provide are not always enough to place the element
+exactly where you want it. To correct this, we provide two more properties,
+`offset` and `targetOffset`.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top right',
+ targetAttachment: 'top left',
+ <mark>offset: '0 10px'</mark>
+});
+</code></pre><output></output>
+
+As you can see, we've moved the attachment point of the element 10px to the right.
+We can also move the attachment point of the target:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top right',
+ targetAttachment: 'top left',
+ offset: '0 10px',
+ <mark>targetOffset: '20px 0'</mark>
+});
+</code></pre><output></output>
+
+The offset properties also accept percentages. Percentages in `offset` refer to
+the height and width of the element, `targetOffset` the height and width of
+the target.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top right',
+ targetAttachment: 'top left',
+ targetOffset: <mark>'0 75%'</mark>
+});
+</code></pre><output></output>
+
+The syntax of the offset properties is `"vertical-offset horizontal-offset"`
+
+Tether offers a couple of special attachments, using the `targetModifier`
+option:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: scrollBox,
+ attachment: 'middle right',
+ targetAttachment: 'middle left',
+ targetModifier: 'scroll-handle'
+});
+</code></pre><output></output>
+
+Set the target to `document.body` to have the element follow the page's scroll bar.
+
+The `targetModifier` `visible` can be used to attach an element to the visible part
+of an element:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: document.body,
+ attachment: 'middle center',
+ targetAttachment: 'middle center',
+ <mark>targetModifier: 'visible'</mark>
+});
+</code></pre><output deactivated></output>
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example="scroll-visible">new Tether({
+ element: yellowBox,
+ <mark>target: scrollBox</mark>,
+ attachment: 'middle center',
+ targetAttachment: 'middle center',
+ targetModifier: 'visible'
+});
+</code></pre><output class="no-green scroll-page" data-example="scroll-visible"></output>
+
+Constraints
+-----------
+
+If you have tried any of the previous examples, you'll notice that it's pretty
+easy to scroll the regions in such a way that the element is hanging out on
+its own, with no target in sight.
+
+Constraints allow you to control what happens when the tethered element would
+have to fall outside of a defined region to maintain the attachment.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'middle left',
+ targetAttachment: 'middle left',
+ <mark>constraints</mark>: [
+ {
+ to: 'scrollParent',
+ pin: true
+ }
+ ]
+});
+</code></pre><output></output>
+
+We've created a constraint which will keep the element within its scroll
+parent by 'pinning' it to the edges if it tries to escape. For the sake
+of the example, we're also highlighting the pinned edge in red.
+
+Specify an array of sides if you'd only like to pin those edges:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'middle left',
+ targetAttachment: 'middle left',
+ constraints: [
+ {
+ to: 'scrollParent',
+ pin: <mark>['top']</mark>
+ }
+ ]
+});
+</code></pre><output></output>
+
+You might want to allow the element to change its attachment, if doing so
+would keep more of it within its assigned region:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: 'scrollParent',
+ <mark>attachment: 'together'</mark>
+ }
+ ]
+});
+</code></pre><output></output>
+
+If you scroll the example a bit, you'll see it flip the attachment when necessary.
+You can combine `pin` and `attachment` as well:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: 'scrollParent',
+ attachment: 'together',
+ <mark>pin: true</mark>
+ }
+ ]
+});
+</code></pre><output></output>
+
+Attachment will accept any of these values:
+
+- `element`: Only change the element's attachment
+- `target`: Only change the target's attachment
+- `both`: Change either's attachment (or both), as needed
+- `together`: Change both the element's and target's attachment at the same time (to
+'flip' the element to the other side of the attachment)
+- `none`: Don't allow changes to attachment (the default)
+
+Together is the option you will use most commonly:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top right',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: 'scrollParent',
+ attachment: <mark>'together'</mark>
+ }
+ ]
+});
+</code></pre><output></output>
+
+You can also provide different settings for the horizontal
+and vertical attachments:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: 'scrollParent',
+ attachment: <mark>'together none'</mark>
+ }
+ ]
+});
+</code></pre><output></output>
+
+Whenever the element is out of the constrained area, we add the `tether-out-of-bounds`
+class to it. If you add some CSS to make items with that class `display: none`, the
+tether will hide.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example="hide">new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'middle center',
+ targetAttachment: 'middle center',
+ constraints: [
+ {
+ to: 'scrollParent'
+ }
+ ]
+});
+</code></pre><output data-example="hide"></output>
+
+You can also constrain the element to the viewport, you'll have to scroll the
+page to see this one.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example="window">new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: <mark>'window'</mark>,
+ attachment: 'together'
+ }
+ ]
+});
+</code></pre><output data-example="window" class="scroll-page"></output>
+
+You can, of course, use pin with the window as well to
+make it always visible no matter where the user scrolls:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: 'window',
+ attachment: 'together',
+ <mark>pin: true</mark>
+ }
+ ]
+});
+</code></pre><output deactivated class="scroll-page visible-enabled"></output>
+
+`to` can be any of:
+
+- `'scrollParent'`
+- `'window'`
+- any DOM element
+- an array of bound points relative to the body `[X1, Y1, X2, Y2]`
+
+You can also provide multiple constraints, keeping in mind that they are
+processed in the order supplied (the last one always has the final word).
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ constraints: [
+ {
+ to: <mark>'scrollParent'</mark>,
+ pin: true
+ },
+ {
+ to: <mark>'window'</mark>,
+ attachment: 'together'
+ }
+ ]
+});
+</code></pre><output></output>
+
+Optimization
+------------
+
+### Element Moving
+
+The goal of Tether's optimizer is to not have to change the positioning
+CSS as the page is scrolled or resized. To accomplish this it looks at the
+last few positions, finds commonalities, and uses them to decide whether to
+position the element absolutely or with fixed positioning.
+
+If the element is fully contained within its scroll parent, its DOM node
+can also be moved inside the scroll parent, to avoid repaints as the
+container is scrolled.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example="optimizer">new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left'
+});
+</code></pre><output data-example="optimizer"></output>
+
+We are moving where the DOM node is, so if you have CSS which styles elements
+within the offset parent, you may see some rendering changes. Also note
+that this optimization works best if the scroll parent is the offset parent.
+In other words, **the scroll parent should be made position relative, fixed or
+absolute to enable this optimization.**
+
+If you do see stylistic changes occur when the element is moved,
+you might want to disable this optimization. You can do that by
+setting `optimizations.moveElement` to false.
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example="optimizer2">new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ targetAttachment: 'bottom left',
+ optimizations: {
+ <mark>moveElement: false</mark>
+ }
+});
+</code></pre><output data-example="optimizer2"></output>
+
+### GPU
+
+By default tether positions elements using CSS transforms. These transforms allow the
+tethered element to be moved as its own layer to not force a repaint of the underlying
+page.
+
+This method of positioning can cause some issues however, including color shifts and artifacts.
+
+If you experience these issues, you can disable this optimization by setting `optimizations.gpu`
+to false:
+
+<pre class="pre-with-output"><code class="lang-javascript" data-example>new Tether({
+ element: yellowBox,
+ target: greenBox,
+ attachment: 'top left',
+ optimizations: {
+ <mark>gpu: false</mark>
+ }
+});
+</code></pre><output></output>
+
+Methods
+-------
+
+The `Tether` constructor we've been using in these examples returns us a
+`Tether` object.
+
+The `Tether` object has these methods:
+
+- `setOptions({ options })` - Update any of the options (such as attachment)
+- `disable()` - Disable the tethering
+- `enable()` - Enable the tethering
+- `destroy()` - Disable and remove all references
+- `position()` - Manually trigger a repositioning
+
+Options
+-------
+
+The full list of options which can be passed to the `Tether` constructor and
+`setOptions`:
+
+- `element`: The DOM element, jQuery element, or a selector string of an element which will be moved
+- `target`: The DOM element, jQuery element, or a selector string of an element which the `element` will be attached to
+- `attachment`: A string of the form `'vert-attachment horiz-attachment'`
+ - `vert-attachment` can be any of `'top'`, `'middle'`, `'bottom'`
+ - `horiz-attachment` can be any of `'left'`, `'center'`, `'right'`
+- `targetAttachment`: A string similar to `attachment`.
+ The one difference is that, if it's not provided, targetAttachment will assume the mirror
+ image of `attachment`.
+- `offset`: A string of the form `'vert-offset horiz-offset'`
+ - `vert-offset` and `horiz-offset` can be of the form `"20px"` or `"55%"`
+- `targetOffset`: A string similar to `offset`, but refering to the offset of the target
+- `targetModifier`: Can be set to `'visible'` or `'scroll-handle'`
+- `enabled`: Should the tether be enabled initially? Defaults to `true`.
+- `classes`: A hash of classes which should be changed or disabled
+- `classPrefix`: The prefix placed at the beginning of the default classes, defaults to `'tether'`
+- `optimizations`: A hash of optimizations, used to disable them
+- `constraints`: An array of constraint definition objects. Each definition is of the form:
+ - `to`: A DOM element, bounding box, the string `'window'`, or the string `'scrollParent'`
+ - `pin`: `true` or an array of strings representing the sides of the constraint
+ - `attachment`: A string of the form `"vert-modifier horiz-modifier"`, or a single value
+ representing both
+ - Each modifier should be one of `"none"`, `"together"`, `"element"`, `"target"`, or `"both"`.
+ - `outOfBoundsClass`: An alternative to `"tether-out-of-bounds"`, useful if the class
+ needs to be differentiated from that of another constraint.
+ - `pinnedClass`: An alternative to `"tether-pinned"`, similar to `outOfBoundsClass`.
+
+Classes
+-------
+
+Tether adds a variety of classes to the element and target to allow you to style
+them based on their tethering.
+
+You can change the prefix of the classes with the `classPrefix` option. It is `'tether'` by
+default, but you could, for example, change it to be `'bill'` if you were building the bill
+library and all the classes would be `'bill-*'`.
+
+```javascript
+new Tether({
+ classPrefix: 'bill'
+});
+```
+
+The sass/css is similarily configurable, see
+[tooltip](https://github.com/HubSpot/tooltip/blob/master/sass/tooltip-theme-arrows.sass#L14) for
+an example of how to make your own prefixed css file.
+
+All classes can be changed or disabled with the `classes` option. For example, to change the
+`tether-element` class to be `my-box`:
+
+```javascript
+new Tether({
+ classes: {
+ element: 'my-box'
+ }
+});
+```
+
+You can also disable classes you're not going to use:
+
+```javascript
+new Tether({
+ classes: {
+ out-of-bounds: false
+ }
+});
+```
+
+- `tether-element` is added to the element
+- `tether-target` is added to the target
+- `tether-enabled` is added to both elements when tether is not disabled
+- `tether-element-attached-[left,right,top,bottom,middle,center]` is added to both
+elements based on the elements attachment, if the element becomes detached (for
+example, if it's pinned), that class is removed. The class reflects how the
+element is actually attached, so if a constraint changes the attachment, that
+change will be reflected in the class.
+- `tether-target-attached-[left,right,top,bottom,middle,center]` is added to both
+elements based on the target's attachment. All of the characteristics are the
+same as for element-attached.
+
+### Constraint-related Classes
+
+- `tether-out-of-bounds`, `tether-out-of-bounds-[side]` are added to both the element and the target
+when the element is placed outside of its constraint.
+- `tether-pinned`, `tether-pinned-[side]` are added to both the element and target when a constraint
+has pinned the element to the [side] of the container.
+
+Browser Support
+---------------
+
+Tether supports IE9+, and all modern browsers.
+
+Google doesn't support IE8, Microsoft is dropping support in a few months, and not supporting it saves
+us a whole lot of trouble. If you are interested in adding support, get in touch, we're happy to accept
+a PR.
+
+Contributing
+------------
+
+Please contribute! Tether is developed in Coffeescript, but if that's problematic for you, feel free
+to submit pull requests which just change the JavaScript files, we can adapt them as needed.
+
+To build Tether, you need:
+
+- Node.js
+- Ruby (for compass)
+
+#### Instructions
+
+- Install compass (if you don't have it already)
+
+```bash
+gem update --system
+gem install compass
+```
+
+- Install the build tool
+
+```bash
+npm install -g gulp
+```
+
+- Install the project
+
+```bash
+# In the project directory
+npm install
+```
+
+- Build / Watch
+
+```bash
+gulp
+```
diff --git a/afb-client/bower_components/tether/docs/js/intro.js b/afb-client/bower_components/tether/docs/js/intro.js
new file mode 100644
index 0000000..47ed6e5
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/js/intro.js
@@ -0,0 +1,117 @@
+(function() {
+ var OUTPUT_HTML, SETUP_JS, activate, deactivate, getOutput, init, run, setupBlock, tethers, uniqueId;
+
+ uniqueId = Tether.Utils.uniqueId;
+
+ SETUP_JS = "yellowBox = $('.yellow-box', $output);\ngreenBox = $('.green-box', $output);\nscrollBox = $('.scroll-box', $output);";
+
+ OUTPUT_HTML = function(key) {
+ return "<div class=\"scroll-box\">\n <div class=\"scroll-content\">\n <div class=\"yellow-box\" data-example=\"" + key + "\"></div>\n <div class=\"green-box\" data-example=\"" + key + "\"></div>\n </div>\n</div>";
+ };
+
+ tethers = {};
+
+ getOutput = function($block) {
+ var key;
+ key = $block.data('example');
+ if (key && typeof key === 'string') {
+ return $("output[data-example='" + key + "']");
+ } else {
+ return $block.parents('pre').nextAll('output').first();
+ }
+ };
+
+ run = function(key) {
+ var $block, $output, code;
+ if (typeof key === 'string') {
+ $block = $("code[data-example='" + key + "']");
+ } else {
+ $block = key;
+ }
+ key = $block.attr('data-example');
+ $output = getOutput($block);
+ code = $block.text();
+ code = SETUP_JS + code;
+ window.$output = $output;
+ return tethers[key] = eval(code);
+ };
+
+ setupBlock = function($block) {
+ var $output, $scrollBox, $scrollContent, key;
+ key = $block.data('example');
+ $output = getOutput($block);
+ if (!key) {
+ key = uniqueId();
+ $block.attr('data-example', key);
+ $output.attr('data-example', key);
+ $output.find('.tether-element').attr('data-example', key);
+ }
+ $output.html(OUTPUT_HTML(key));
+ $scrollBox = $output.find('.scroll-box');
+ $scrollContent = $scrollBox.find('.scroll-content');
+ $scrollBox.scrollTop(parseInt($scrollContent.css('height')) / 2 - $scrollBox.height() / 2);
+ $scrollBox.scrollLeft(parseInt($scrollContent.css('width')) / 2 - $scrollBox.width() / 2);
+ setTimeout(function() {
+ return $scrollBox.on('scroll', function() {
+ return $output.addClass('scrolled');
+ });
+ });
+ $scrollBox.css('height', "" + ($block.parent().outerHeight()) + "px");
+ if ($output.attr('deactivated') == null) {
+ return run($block);
+ }
+ };
+
+ $(document.body).on('click', function(e) {
+ if ($(e.target).is('output[deactivated]')) {
+ activate($(e.target));
+ return false;
+ } else if ($(e.target).is('output[activated]')) {
+ deactivate($(e.target));
+ return false;
+ }
+ });
+
+ activate = function($output) {
+ var $block, key;
+ $block = $output.prev().find('code');
+ run($block);
+ $output.find('.tether-element').show();
+ key = $output.data('example');
+ $(tethers[key].element).show();
+ tethers[key].enable();
+ $output.removeAttr('deactivated');
+ return $output.attr('activated', true);
+ };
+
+ deactivate = function($output) {
+ var $block, $el, key;
+ $block = $output.prev().find('code');
+ key = $output.data('example');
+ tethers[key].disable();
+ $el = $(tethers[key].element);
+ $el.detach();
+ $output.find('.scroll-content').append($el);
+ $el.hide();
+ $output.removeAttr('activated');
+ return $output.attr('deactivated', true);
+ };
+
+ init = function() {
+ var $blocks, block, _i, _len, _results;
+ $blocks = $('code[data-example]');
+ _results = [];
+ for (_i = 0, _len = $blocks.length; _i < _len; _i++) {
+ block = $blocks[_i];
+ _results.push(setupBlock($(block)));
+ }
+ return _results;
+ };
+
+ window.EXECUTR_OPTIONS = {
+ codeSelector: 'code[executable]'
+ };
+
+ $(init);
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/docs/sass/intro.sass b/afb-client/bower_components/tether/docs/sass/intro.sass
new file mode 100644
index 0000000..6088a41
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/sass/intro.sass
@@ -0,0 +1,228 @@
+@import compass/css3
+
+$scrollableArea: 2000px
+$exampleWidth: 400px
+$exampleHeight: 180px
+
+*, *:after, *:before
+ +box-sizing(border-box)
+
+body
+ position: relative
+
+.yellow-box
+ width: 100px
+ height: 100px
+ background-color: #fe8
+ pointer-events: none
+
+.green-box
+ margin-top: ($exampleHeight - 50px) / 2
+ margin-left: ($exampleWidth - 200px) / 2
+ width: 200px
+ height: 50px
+ background-color: #4e9
+
+ .no-green &
+ display: none
+
+.scroll-box
+ height: 150px
+ border: 10px solid #eee
+ background: #fbfbfb
+ overflow: auto
+ position: relative
+
+.scroll-content
+ height: $scrollableArea
+ width: $scrollableArea
+ padding: ($scrollableArea - $exampleHeight)/2 ($scrollableArea - $exampleWidth)/2 + 9
+
+pre.pre-with-output
+ margin: 0
+ width: 50%
+ float: left
+
+ code mark
+ background: #b8daff
+ color: #000
+
+p, h2, h3
+ clear: both
+
+output
+ display: block
+ position: relative
+ width: 50%
+ float: right
+ margin-bottom: 15px
+
+ &.scroll-page
+ .scroll-box
+ overflow: hidden
+
+ &:after
+ content: "↕ scroll the page ↕"
+
+ &:after
+ content: "↕ scroll this area ↕"
+ position: absolute
+ bottom: 25px
+ width: 100%
+ text-align: center
+ font-size: 16px
+ font-variant: small-caps
+ color: #777
+ opacity: 1
+ transition: opacity 0.2s
+
+ &.scrolled:after
+ opacity: 0
+
+ &[deactivated], &[activated]
+ .scroll-box
+ pointer-events: none
+
+ cursor: pointer
+
+ &:after
+ position: absolute
+ top: 0
+ left: 0
+ right: 0
+ bottom: 0
+ opacity: 1
+ content: "Click To Show"
+ background-color: #AAA
+ border-left: 10px solid #EEE
+ color: white
+ font-size: 24px
+ font-variant: normal
+ padding-top: 80px
+
+ &[activated]
+ &:after
+ content: "Click To Hide"
+
+ &.visible-enabled
+ &:after
+ height: 35px
+ padding-top: 5px
+
+.attachment-mark
+ position: relative
+
+ &:after
+ content: "A"
+ width: 10px
+ height: 10px
+ background-color: red
+ display: inline-block
+
+ line-height: 10px
+ font-size: 9px
+ color: white
+ text-align: center
+
+ position: absolute
+
+span.attachment-mark
+ &:after
+ position: relative
+ top: -1px
+ margin-right: 1px
+
+.tether-marker-dot
+ @extend .attachment-mark
+
+ position: absolute
+
+ &:after
+ top: -5px
+ left: -5px
+
+@each $type in target, element
+ .tether-#{ $type }-marker
+ position: absolute
+
+ @each $side in left, top, bottom, right
+ div.tether-#{ $type }-attached-#{ $side } &
+ #{ $side }: 0
+
+ div.tether-#{ $type }-attached-center &
+ left: 50%
+
+.tether-element-attached-middle .tether-element-marker
+ top: 50px
+
+.tether-target-attached-middle .tether-target-marker
+ top: 25px
+
+.tether-element
+ position: relative
+
+ &.tether-pinned-left
+ box-shadow: inset 2px 0 0 0 red
+ &.tether-pinned-right
+ box-shadow: inset -2px 0 0 0 red
+ &.tether-pinned-top
+ box-shadow: inset 0 2px 0 0 red
+ &.tether-pinned-bottom
+ box-shadow: inset 0 -2px 0 0 red
+
+.tether-target
+ position: relative
+
+.tether-element.tether-out-of-bounds[data-example="hide"]
+ display: none
+
+[data-example^="optimizer"]
+ &.lang-javascript
+ /* This should just be a `code` selector, but sass doesn't allow that with & */
+ min-height: 220px
+
+ &.tether-element
+
+ &:before
+ margin-top: 26px
+ display: block
+ text-align: center
+ content: "I'm in the body"
+ line-height: 1.2
+ font-size: 15px
+ padding: 4px
+ color: #666
+
+ .scroll-box .tether-element:before
+ content: "I'm in my scroll parent!"
+
+.tether-element[data-example="scroll-visible"]
+ height: 30px
+
+ .tether-marker-dot
+ display: none
+
+.hs-doc-content h2.projects-header
+ text-align: center
+ font-weight: 300
+
+.projects-paragraph
+ text-align: center
+
+ a
+ +inline-block
+ text-align: center
+ margin-right: 30px
+ color: inherit
+
+ span
+ +inline-block
+ margin-bottom: 20px
+ font-size: 20px
+ color: inherit
+ font-weight: 300
+
+ img
+ display: block
+ max-width: 100%
+ width: 100px \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/browser-demo.html b/afb-client/bower_components/tether/docs/welcome/browser-demo.html
new file mode 100644
index 0000000..4915b77
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/browser-demo.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <title>Drop – Browser Demo</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="icon" href="http://static.hubspot.com/favicon.ico">
+
+ <script type="text/javascript" src="//use.typekit.net/ghy0wve.js"></script>
+ <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
+
+ <!-- Drop themes -->
+ <link rel="stylesheet" href="/tether/css/tether-theme-arrows-dark.css" />
+
+ <!-- Browser demo styles -->
+ <link rel="stylesheet" href="/tether/docs/welcome/css/browser-demo.css" />
+</head>
+<body>
+ <div class="browser-demo">
+ <div class="top"><div class="title"></div></div>
+ <div class="bottom">
+ <div class="left">
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item"></div>
+ </div>
+ <div class="right">
+ <div class="title"></div>
+ <p>
+ <div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div>
+ </p>
+ <p>
+ <div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div><div class="word"></div>
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <!-- Tether javascript -->
+ <script src="/tether/tether.min.js"></script>
+
+ <!-- Welcome docs javascript -->
+ <script src="/tether/docs/welcome/js/log.js"></script>
+ <script src="/tether/docs/welcome/js/jquery.js"></script>
+ <script src="/tether/docs/welcome/js/drop.js"></script>
+</body>
+</html>
diff --git a/afb-client/bower_components/tether/docs/welcome/coffee/welcome.coffee b/afb-client/bower_components/tether/docs/welcome/coffee/welcome.coffee
new file mode 100644
index 0000000..a431602
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/coffee/welcome.coffee
@@ -0,0 +1,212 @@
+_Drop = Drop.createContext classPrefix: 'tether'
+
+isMobile = $(window).width() < 567
+
+init = ->
+ setupHero()
+ setupBrowserDemo()
+
+setupHero = ->
+ $target = $('.tether-target-demo')
+
+ positions = [
+ 'top left'
+ 'left top'
+ 'left middle'
+ 'left bottom'
+ 'bottom left'
+ 'bottom center'
+ 'bottom right'
+ 'right bottom'
+ 'right middle'
+ 'right top'
+ 'top right'
+ 'top center'
+ ]
+
+ if isMobile
+ positions = [
+ 'top left'
+ 'bottom left'
+ 'bottom right'
+ 'top right'
+ ]
+
+ window.drops = {}
+
+ for position in positions
+ drops[position] = new _Drop
+ target: $target[0]
+ classes: 'tether-theme-arrows-dark'
+ position: position
+ constrainToWindow: false
+ openOn: ''
+ content: '<div style="height: 50px; width: 50px"></div>'
+
+ openIndex = 0
+ frames = 0
+ frameLengthMS = 10
+
+ openAllDrops = ->
+ for position, drop of drops
+ drop.open()
+
+ openNextDrop = ->
+ for position, drop of drops
+ drop.close()
+
+ drops[positions[openIndex]].open()
+ drops[positions[(openIndex + 6) % positions.length]].open()
+
+ openIndex = (openIndex + 1) % positions.length
+
+ if frames > 5
+ finalDropState()
+ return
+
+ frames += 1
+
+ setTimeout openNextDrop, frameLengthMS * frames
+
+ finalDropState = ->
+ $(drops['top left'].dropContent).html('Marrying DOM elements for life.')
+ $(drops['bottom right'].dropContent).html('<a class="button" href="http://github.com/HubSpot/tether">★ On Github</a>')
+ drops['top left'].open()
+ drops['bottom right'].open()
+
+ if true or isMobile
+ drops['top left'].open()
+ drops['top left'].tether.position()
+ drops['bottom right'].open()
+ drops['bottom right'].tether.position()
+ finalDropState()
+
+ else
+ openNextDrop()
+
+setupBrowserDemo = ->
+ $browserDemo = $('.browser-demo.showcase')
+
+ $startPoint = $('.browser-demo-start-point')
+ $stopPoint = $('.browser-demo-stop-point')
+
+ $iframe = $('.browser-window iframe')
+ $browserContents = $('.browser-content .browser-demo-inner')
+
+ $sections = $('.browser-demo-section')
+
+ $('body').append """
+ <style>
+ table.showcase.browser-demo.fixed-bottom {
+ top: #{ $sections.length }00%
+ }
+ </style>
+ """
+
+ $(window).scroll ->
+ scrollTop = $(window).scrollTop()
+
+ if $startPoint.position().top < scrollTop and scrollTop + window.innerHeight < $stopPoint.position().top
+ $browserDemo.removeClass('fixed-bottom')
+ $browserDemo.addClass('fixed')
+
+ $sections.each ->
+ $section = $ @
+
+ if $section.position().top < scrollTop < $section.position().top + $section.outerHeight()
+ setSection $section.data('section')
+
+ return true
+
+ else
+ $browserDemo.removeAttr('data-section')
+ $browserDemo.removeClass('fixed')
+
+ if scrollTop + window.innerHeight > $stopPoint.position().top
+ $browserDemo.addClass('fixed-bottom')
+ else
+ $browserDemo.removeClass('fixed-bottom')
+
+ $iframe.load ->
+ iframeWindow = $iframe[0].contentWindow
+
+ $items = $iframe.contents().find('.item')
+
+ $items.each (i) ->
+ $item = $(@)
+
+ _iframeWindowDrop = iframeWindow.Drop.createContext classPrefix: 'tether'
+
+ drop = new _iframeWindowDrop
+ target: $item[0]
+ classes: 'tether-theme-arrows-dark'
+ position: 'right top'
+ constrainToWindow: true
+ openOn: 'click'
+ content: '''
+ <ul>
+ <li>Action&nbsp;1</li>
+ <li>Action&nbsp;2</li>
+ <li>Action&nbsp;3</li>
+ </ul>
+ '''
+
+ $item.data('drop', drop)
+
+ scrollInterval = undefined
+ scrollTop = 0
+ scrollTopDirection = 1
+
+ setSection = (section) ->
+ $browserDemo.attr('data-section', section)
+
+ $('.section-copy').removeClass('active')
+ $(""".section-copy[data-section="#{ section }"]""").addClass('active')
+
+ openExampleItem = ->
+ if isMobile
+ $iframe.contents().find('.item:first').data().drop.open()
+ else
+ $iframe.contents().find('.item:eq(2)').data().drop.open()
+
+ closeAllItems = ->
+ $iframe.contents().find('.item').each -> $(@).data().drop.close() or true
+
+ scrollLeftSection = ->
+ scrollInterval = setInterval ->
+ $iframe.contents().find('.left').scrollTop scrollTop
+ scrollTop += scrollTopDirection
+ if scrollTop > 50
+ scrollTopDirection = -1
+ if scrollTop < 0
+ scrollTopDirection = 1
+ , 30
+
+ stopScrollingLeftSection = ->
+ clearInterval scrollInterval
+
+ switch section
+
+ when 'what'
+ closeAllItems()
+ openExampleItem()
+ stopScrollingLeftSection()
+
+ when 'how'
+ closeAllItems()
+ openExampleItem()
+ stopScrollingLeftSection()
+ scrollLeftSection()
+
+ when 'why'
+ closeAllItems()
+ openExampleItem()
+ stopScrollingLeftSection()
+ scrollLeftSection()
+
+ when 'outro'
+ closeAllItems()
+ openExampleItem()
+ stopScrollingLeftSection()
+
+init() \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/css/browser-demo.css b/afb-client/bower_components/tether/docs/welcome/css/browser-demo.css
new file mode 100644
index 0000000..c41b020
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/css/browser-demo.css
@@ -0,0 +1,91 @@
+html, body {
+ height: 100%;
+ overflow: hidden;
+ font-family: "proxima-nova", sans-serif; }
+
+.tether.tether-theme-arrows-dark .tether-content {
+ -webkit-filter: none;
+ -moz-filter: none;
+ filter: none;
+ background: black; }
+ .tether.tether-theme-arrows-dark .tether-content ul {
+ color: white;
+ list-style: none;
+ padding: 0;
+ margin: 0; }
+
+.tether.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+ border-right-color: black; }
+
+.browser-demo {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0; }
+ .browser-demo *, .browser-demo *:after, .browser-demo *:before {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box; }
+ .browser-demo .top {
+ position: absolute;
+ height: 60px;
+ padding: 20px;
+ line-height: 40px;
+ width: 100%;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
+ .browser-demo .bottom {
+ position: absolute;
+ top: 60px;
+ bottom: 0;
+ width: 100%; }
+ .browser-demo .bottom .left {
+ border-right: 1px solid rgba(0, 0, 0, 0.1);
+ position: absolute;
+ width: 30%;
+ height: 100%;
+ overflow: auto; }
+ .browser-demo .bottom .left .item {
+ height: 64px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ cursor: pointer; }
+ .browser-demo .bottom .left .item:hover, .browser-demo .bottom .left .item.tether-open {
+ background: rgba(0, 0, 0, 0.1);
+ border-bottom: 1px solid rgba(0, 0, 0, 0); }
+ .browser-demo .bottom .left .item:last-child {
+ border-bottom: 0; }
+ .browser-demo .bottom .right {
+ position: absolute;
+ width: 70%;
+ right: 0;
+ height: 100%;
+ padding: 20px; }
+ .browser-demo .title {
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ background: rgba(0, 0, 0, 0.1);
+ width: 150px;
+ height: 15px;
+ margin-bottom: 20px; }
+ .browser-demo .word {
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ background: rgba(0, 0, 0, 0.1);
+ width: 50px;
+ height: 8px;
+ margin-right: 5px;
+ margin-bottom: 5px; }
+ .browser-demo .word:nth-last-child(4n+1) {
+ width: 73px; }
+ .browser-demo .word:nth-last-child(10n+1) {
+ width: 14px; }
+ .browser-demo .word:nth-last-child(9n+1) {
+ width: 80px; }
diff --git a/afb-client/bower_components/tether/docs/welcome/css/prism.css b/afb-client/bower_components/tether/docs/welcome/css/prism.css
new file mode 100644
index 0000000..b86d1c2
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/css/prism.css
@@ -0,0 +1,2 @@
+/* Prism.js */
+code[class*="language-"], pre[class*="language-"] {color: black; font-family: Consolas, Monaco, 'Andale Mono', monospace; direction: ltr; text-align: left; white-space: pre; word-spacing: normal; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } /* Code blocks */ pre[class*="language-"] {padding: 1em; margin: .5em 0; overflow: auto; font-size: 14px; } :not(pre) > code[class*="language-"], pre[class*="language-"] {background: rgba(0, 0, 0, .05); } /* Inline code */ :not(pre) > code[class*="language-"] {padding: .1em; border-radius: .3em; } .token.comment, .token.prolog, .token.doctype, .token.cdata {color: slategray; } .token.punctuation {color: #999; } .namespace {opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol {color: #905; } .token.selector, .token.attr-name, .token.string, .token.builtin {color: #690; } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string, .token.variable {color: #a67f59; } .token.atrule, .token.attr-value, .token.keyword {color: #07a; } .token.regex, .token.important {color: #e90; } .token.important {font-weight: bold; } .token.entity {cursor: help; } \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/css/welcome.css b/afb-client/bower_components/tether/docs/welcome/css/welcome.css
new file mode 100644
index 0000000..7db9b3b
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/css/welcome.css
@@ -0,0 +1,272 @@
+html, body {
+ height: 100%; }
+
+body {
+ margin: 0;
+ font-family: "proxima-nova", "Helvetica Neue", sans-serif; }
+
+.button {
+ display: inline-block;
+ border: 2px solid #333333;
+ color: #333333;
+ padding: 1em 1.25em;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 3px;
+ text-decoration: none;
+ cursor: pointer;
+ width: 140px;
+ font-size: 0.8em;
+ line-height: 1.3em;
+ text-align: center; }
+
+.tether-element.tether-theme-arrows-dark .tether-content {
+ padding: 1em;
+ font-size: 1.1em; }
+ .tether-element.tether-theme-arrows-dark .tether-content .button {
+ border-color: white;
+ color: white;
+ width: 170px;
+ pointer-events: all; }
+
+.mobile-copy {
+ display: none; }
+ @media (max-width: 568px) {
+ .mobile-copy {
+ display: block; } }
+
+.button.dark {
+ background: #333333;
+ color: white; }
+
+.hero-wrap {
+ height: 100%;
+ overflow: hidden; }
+
+table.showcase {
+ height: 100%;
+ width: 100%;
+ position: relative; }
+ table.showcase:after {
+ content: "";
+ display: block;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 20px;
+ margin: auto;
+ height: 0;
+ width: 0;
+ border-width: 18px;
+ border-style: solid;
+ border-color: transparent;
+ border-top-color: rgba(0, 0, 0, 0.2); }
+ table.showcase.no-next-arrow:after {
+ display: none; }
+ table.showcase .showcase-inner {
+ margin: 40px auto 60px;
+ padding: 10px; }
+ table.showcase .showcase-inner h1 {
+ font-size: 50px;
+ text-align: center;
+ font-weight: 300; }
+ @media (max-width: 567px) {
+ table.showcase .showcase-inner h1 {
+ font-size: 40px; } }
+ table.showcase .showcase-inner h2 {
+ font-size: 24px;
+ text-align: center;
+ font-weight: 300;
+ margin: 1em 0 1em; }
+ @media (max-width: 567px) {
+ table.showcase .showcase-inner h2 {
+ font-size: 14px; } }
+ table.showcase .showcase-inner p {
+ text-align: center; }
+ table.showcase.hero {
+ text-align: center; }
+ table.showcase.hero .tether-target-demo {
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ border: 2px dotted black;
+ margin: 5rem auto;
+ padding: 5rem; }
+ @media (max-width: 567px) {
+ table.showcase.hero .tether-target-demo {
+ padding: 1rem; } }
+ table.showcase.share {
+ background: #f3f3f3; }
+ table.showcase.projects-showcase .showcase-inner .projects-list {
+ width: 80%;
+ max-width: 1200px;
+ margin: 0 auto; }
+ table.showcase.projects-showcase .showcase-inner .projects-list .project {
+ color: inherit;
+ text-decoration: none;
+ position: relative;
+ width: 50%;
+ float: left;
+ text-align: center;
+ margin-bottom: 2rem; }
+ table.showcase.projects-showcase .showcase-inner .projects-list .os-icon {
+ width: 8rem;
+ height: 8rem;
+ margin-bottom: 1rem;
+ background-size: 100%; }
+ table.showcase.projects-showcase .showcase-inner .projects-list h1 {
+ font-size: 2.5rem; }
+ table.showcase.projects-showcase .showcase-inner .projects-list p {
+ font-size: 1.3rem; }
+ table.showcase.browser-demo {
+ background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #723362), color-stop(100%, #9d223c));
+ background-image: -webkit-linear-gradient(top left, #723362 0%, #9d223c 100%);
+ background-image: -moz-linear-gradient(top left, #723362 0%, #9d223c 100%);
+ background-image: -o-linear-gradient(top left, #723362 0%, #9d223c 100%);
+ background-image: linear-gradient(top left, #723362 0%, #9d223c 100%);
+ background-color: #9d223c;
+ position: absolute;
+ top: 100%; }
+ table.showcase.browser-demo.fixed {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 1; }
+ table.showcase.browser-demo.fixed .browser-demo-inner {
+ -webkit-transition: width 2s ease-in-out, height 2s ease-in-out;
+ -moz-transition: width 2s ease-in-out, height 2s ease-in-out;
+ -o-transition: width 2s ease-in-out, height 2s ease-in-out;
+ transition: width 2s ease-in-out, height 2s ease-in-out; }
+ table.showcase.browser-demo.fixed[data-section="what"] {
+ box-shadow: 0 0 0 0; }
+ table.showcase.browser-demo.fixed[data-section="why"] .browser-demo-inner {
+ width: 70%; }
+ table.showcase.browser-demo.fixed[data-section="outro"] .showcase-inner {
+ pointer-events: all; }
+ table.showcase.browser-demo .showcase-inner {
+ pointer-events: none;
+ position: absolute;
+ left: 10%;
+ right: 40%;
+ top: 220px;
+ bottom: 120px;
+ margin: 0;
+ padding: 0; }
+ @media (max-width: 567px) {
+ table.showcase.browser-demo .showcase-inner {
+ bottom: 90px;
+ top: 180px; } }
+ table.showcase.browser-demo .browser-demo-inner {
+ height: 100%;
+ width: 100%; }
+ table.showcase.browser-demo .section-copy {
+ -webkit-transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
+ -moz-transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
+ -o-transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
+ transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ position: absolute;
+ height: 200px;
+ color: white;
+ text-align: center;
+ width: 100%; }
+ table.showcase.browser-demo .section-copy.active {
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+ opacity: 1;
+ top: -150px; }
+ @media (max-width: 567px) {
+ table.showcase.browser-demo .section-copy.active {
+ top: -130px; } }
+ table.showcase.browser-demo .section-copy h2 {
+ font-size: 40px;
+ font-weight: bold;
+ line-height: 1;
+ margin: 25px 0 15px; }
+ @media (max-width: 567px) {
+ table.showcase.browser-demo .section-copy h2 {
+ font-size: 30px; } }
+ table.showcase.browser-demo .browser-window {
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ -ms-border-radius: 4px;
+ -o-border-radius: 4px;
+ border-radius: 4px;
+ background: white;
+ position: relative;
+ height: 100%;
+ width: 100%;
+ max-width: 1200px;
+ margin: 0 auto; }
+ table.showcase.browser-demo .browser-window .browser-titlebar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-bottom: 1px solid #eeeeee;
+ height: 55px; }
+ table.showcase.browser-demo .browser-window .browser-titlebar .browser-dots {
+ padding: 16px; }
+ table.showcase.browser-demo .browser-window .browser-titlebar .browser-dots b {
+ -webkit-border-radius: 50%;
+ -moz-border-radius: 50%;
+ -ms-border-radius: 50%;
+ -o-border-radius: 50%;
+ border-radius: 50%;
+ display: -moz-inline-stack;
+ display: inline-block;
+ vertical-align: middle;
+ *vertical-align: auto;
+ zoom: 1;
+ *display: inline;
+ width: 10px;
+ height: 10px;
+ margin-right: 7px;
+ background: rgba(0, 0, 0, 0.1); }
+ table.showcase.browser-demo .browser-window .browser-frame {
+ position: absolute;
+ top: 55px;
+ left: 0;
+ right: 0;
+ bottom: 0; }
+ table.showcase.browser-demo .browser-window .browser-frame iframe {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ -ms-border-radius: 0 0 4px 4px;
+ -o-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+ border: 0;
+ width: 100%;
+ height: 100%; }
+ table.showcase.browser-demo-section .section-scroll-copy {
+ position: relative;
+ z-index: 10;
+ color: white;
+ width: 100%;
+ font-size: 22px; }
+ table.showcase.browser-demo-section .section-scroll-copy .section-scroll-copy-inner {
+ position: absolute;
+ z-index: 10;
+ color: white;
+ right: 10%;
+ width: 23%; }
+ table.showcase.browser-demo-section .section-scroll-copy .section-scroll-copy-inner a {
+ color: inherit; }
+ table.showcase.browser-demo-section .section-scroll-copy .section-scroll-copy-inner .example-paragraph {
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ -ms-border-radius: 4px;
+ -o-border-radius: 4px;
+ border-radius: 4px;
+ background: black;
+ padding: 1rem; }
+
+.browser-content {
+ display: none; }
diff --git a/afb-client/bower_components/tether/docs/welcome/index.html b/afb-client/bower_components/tether/docs/welcome/index.html
new file mode 100644
index 0000000..856d58e
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/index.html
@@ -0,0 +1,227 @@
+<!doctype html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <title>Tether – Marrying elements for life</title>
+ <meta name="description" content="Tether is a JavaScript and CSS library. It is free and open source and was developed by HubSpot developers Adam Schwartz (@adamfschwartz) and Zack Bloom (@zackbloom).">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="icon" href="http://static.hubspot.com/favicon.ico">
+
+ <script type="text/javascript" src="//use.typekit.net/ghy0wve.js"></script>
+ <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
+
+ <!-- Tether themes -->
+ <link rel="stylesheet" href="/tether/css/tether-theme-arrows-dark.css" />
+
+ <!-- Welcome docs styles -->
+ <link rel="stylesheet" href="/tether/docs/welcome/css/prism.css" />
+ <link rel="stylesheet" href="/tether/docs/welcome/css/welcome.css" />
+
+ <!-- OS icons -->
+ <link rel="stylesheet" href="http://github.hubspot.com/os-icons/os-icons.css" />
+</head>
+<body>
+ <div class="hero-wrap">
+ <table class="showcase hero"><tr><td>
+ <div class="showcase-inner">
+ <div class="tether-target-demo">
+ <h1>Tether</h1>
+ <div class="mobile-copy">
+ <h2>Marrying elements for life</h2>
+ <p>
+ <a class="button" href="http://github.com/HubSpot/tether">★ On Github</a>
+ </p>
+ </div>
+ </div>
+ </div>
+ </td></tr></table>
+ </div>
+
+ <div class="browser-demo-start-point"></div>
+
+ <table class="showcase browser-demo"><tr><td>
+ <div class="showcase-inner">
+ <div class="section-copy" data-section="what">
+ <h2>What is Tether?</h2>
+ </div>
+ <div class="section-copy" data-section="how">
+ <h2>How Tether works.</h2>
+ </div>
+ <div class="section-copy" data-section="why">
+ <h2>Tether is powerful.</h2>
+ </div>
+ <div class="section-copy" data-section="outro">
+ <h2>Play with Tether</h2>
+ </div>
+ <div class="browser-demo-inner">
+ <div class="browser-window">
+ <div class="browser-titlebar">
+ <div class="browser-dots"><b></b><b></b><b></b></div>
+ </div>
+ <div class="browser-frame">
+ <iframe src="browser-demo.html"></iframe>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase browser-demo-section no-next-arrow" data-section="what"><tr><td>
+ <div class="section-scroll-copy">
+ <div class="section-scroll-copy-inner">
+ <p>Tether is a low-level UI library that can be used to position any element on a page <i>next to any other element</i>.</p>
+ <p>It can be used for dropdown menus, tooltips, popovers, tours, help information, scroll guides, autocompletes, etc. The possibilities are endless.</p>
+ <p class="example-paragraph">In this example we're showing an action menu <em>tethered</em> to a list item.</p>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase browser-demo-section no-next-arrow" data-section="how"><tr><td>
+ <div class="section-scroll-copy">
+ <div class="section-scroll-copy-inner">
+ <p>Tether works by creating an absolutely positioned element and meticulously tracking the movements of a <i>target</i> which you specify.</p>
+ <p>The <i>target</i> and <i>element</i> can be tethered together in a variety of different ways.</p>
+ <p class="example-paragraph">Notice how the <i>tethered element</i> stays tethered to its <i>target</i> list item even as the left pane is scrolled up and down.</p>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase browser-demo-section no-next-arrow" data-section="why"><tr><td>
+ <div class="section-scroll-copy">
+ <div class="section-scroll-copy-inner">
+ <p>Tether can keep your element positioned properly even in some tough situations.</p>
+ <p>Tether handles all of the common pain points:</p>
+ <ul>
+ <li>Automatically detect collisions with the edge of the page or edge of the scrollParent</li>
+ <li>Automatically reposition on browser resize, scroll, and other events,</li>
+ <li>Constrain the position to any bounding box,</li>
+ </ul>
+ <p>...and a lot more.</p>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase browser-demo-section no-next-arrow" data-section="outro"><tr><td>
+ <div class="section-scroll-copy">
+ <div class="section-scroll-copy-inner">
+ <p class="example-paragraph">Interact with this demo.</p>
+ <p>&nbsp;</p>
+ <p>To learn more, check out our <a href="/tether">documentation</a>.</p>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase browser-demo-section no-next-arrow" data-section="__empty"><tr><td></td></tr></table>
+
+ <div class="browser-demo-stop-point"></div>
+
+ <table class="showcase projects-showcase no-next-arrow"><tr><td>
+ <div class="showcase-inner">
+ <h1>Tether Family</h1>
+ <h2>These projects are all powered by Tether's positioning engine.</h2>
+ <div class="projects-list">
+ <a href="/drop/docs/welcome" class="project">
+ <h1>Drop</h1>
+ <span class="os-icon drop-icon"></span>
+ <p>Create dropdowns, popovers, and more.</p>
+ </a>
+ <a href="/tooltip/docs/welcome" class="project">
+ <h1>Tooltip</h1>
+ <span class="os-icon tooltip-icon"></span>
+ <p>Stylable tooltips built on Tether.</p>
+ </a>
+ <a href="/select/docs/welcome" class="project">
+ <h1>Select</h1>
+ <span class="os-icon select-icon"></span>
+ <p>Stylable select elements built on Tether.</p>
+ </a>
+ <a href="/shepherd/docs/welcome" class="project">
+ <h1>Shepherd</h1>
+ <span class="os-icon shepherd-icon"></span>
+ <p>Guide your users through a tour of your app.</p>
+ </a>
+ </div>
+ </div>
+ </td></tr></table>
+
+ <table class="showcase last-showcase no-next-arrow share"><tr><td>
+ <div class="showcase-inner">
+ <h1>Share</h1>
+ <h2>Help us spread the word.</h2>
+ <!-- Share -->
+ <style>
+ .share-buttons {
+ margin: 4em auto;
+ text-align: center;
+ }
+ .share-button {
+ display: inline-block;
+ }
+ .retweet-button {
+ width: 100px;
+ margin-left: 20px;
+ }
+ .github-stars {
+ width: 100px;
+ }
+ </style>
+ <div class="share-buttons">
+ <div class="share-button retweet-button">
+ <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://github.hubspot.com/tether/docs/welcome" data-text="Tether.js - A positioning engine for JavaScript" data-count="horizontal" data-via="HubSpotDev">Tweet</a>
+ <script>
+ (function(){
+ var recommends, button;
+
+ if (Math.random() >= 0.5) {
+ recommends = ['hubspotdev', 'zackbloom', 'adamfschwartz'];
+ } else {
+ recommends = ['hubspotdev', 'adamfschwartz', 'zackbloom'];
+ }
+
+ button = document.querySelector('.twitter-share-button');
+
+ if (button) {
+ button.setAttribute('data-related', recommends.join(','));
+ }
+ })();
+ </script>
+ <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
+ </div>
+ <div class="share-button github-stars-button">
+ <iframe src="http://ghbtns.com/github-btn.html?user=HubSpot&amp;repo=tether&amp;type=watch&amp;count=true&amp;size=small" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
+ </div>
+ </p>
+ </div>
+ </td></tr></table>
+
+ <!-- Tether javascript -->
+ <script src="/tether/tether.min.js"></script>
+
+ <!-- Welcome docs javascript -->
+ <script src="/tether/docs/welcome/js/log.js"></script>
+ <script src="/tether/docs/welcome/js/jquery.js"></script>
+ <script src="/tether/docs/welcome/js/drop.js"></script>
+ <script src="/tether/docs/welcome/js/welcome.js"></script>
+
+ <!-- HubSpot analytics -->
+ <script type="text/javascript">
+ (function(d,s,i,r) {
+ if (d.getElementById(i)){return;}
+ var n=d.createElement(s),e=d.getElementsByTagName(s)[0];
+ n.id=i;n.src='//js.hubspot.com/analytics/'+(Math.ceil(new Date()/r)*r)+'/51294.js';
+ e.parentNode.insertBefore(n, e);
+ })(document,"script","hs-analytics",300000);
+ </script>
+
+ <!-- Google analytics -->
+ <script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-45159009-1', 'auto');
+ ga('send', 'pageview');
+ </script>
+</body>
+</html>
diff --git a/afb-client/bower_components/tether/docs/welcome/js/drop.js b/afb-client/bower_components/tether/docs/welcome/js/drop.js
new file mode 100644
index 0000000..0058819
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/js/drop.js
@@ -0,0 +1,239 @@
+(function() {
+ var Evented, MIRROR_ATTACH, addClass, allDrops, clickEvent, createContext, extend, hasClass, removeClass, sortAttach, touchDevice, _ref,
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ _ref = Tether.Utils, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, hasClass = _ref.hasClass, Evented = _ref.Evented;
+
+ touchDevice = 'ontouchstart' in document.documentElement;
+
+ clickEvent = touchDevice ? 'touchstart' : 'click';
+
+ sortAttach = function(str) {
+ var first, second, _ref1, _ref2;
+ _ref1 = str.split(' '), first = _ref1[0], second = _ref1[1];
+ if (first === 'left' || first === 'right') {
+ _ref2 = [second, first], first = _ref2[0], second = _ref2[1];
+ }
+ return [first, second].join(' ');
+ };
+
+ MIRROR_ATTACH = {
+ left: 'right',
+ right: 'left',
+ top: 'bottom',
+ bottom: 'top',
+ middle: 'middle',
+ center: 'center'
+ };
+
+ allDrops = {};
+
+ createContext = function(options) {
+ var DropInstance, defaultOptions, drop, _name;
+ if (options == null) {
+ options = {};
+ }
+ drop = function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(DropInstance, arguments, function(){});
+ };
+ extend(drop, {
+ createContext: createContext,
+ drops: [],
+ defaults: {}
+ });
+ defaultOptions = {
+ classPrefix: 'drop',
+ defaults: {
+ attach: 'bottom left',
+ openOn: 'click',
+ constrainToScrollParent: true,
+ constrainToWindow: true,
+ classes: '',
+ tetherOptions: {}
+ }
+ };
+ extend(drop, defaultOptions, options);
+ extend(drop.defaults, defaultOptions.defaults, options.defaults);
+ if (allDrops[_name = drop.classPrefix] == null) {
+ allDrops[_name] = [];
+ }
+ drop.updateBodyClasses = function() {
+ var anyOpen, _drop, _i, _len, _ref1;
+ anyOpen = false;
+ _ref1 = allDrops[drop.classPrefix];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ _drop = _ref1[_i];
+ if (!(_drop.isOpened())) {
+ continue;
+ }
+ anyOpen = true;
+ break;
+ }
+ if (anyOpen) {
+ return addClass(document.body, "" + drop.classPrefix + "-open");
+ } else {
+ return removeClass(document.body, "" + drop.classPrefix + "-open");
+ }
+ };
+ DropInstance = (function(_super) {
+ __extends(DropInstance, _super);
+
+ function DropInstance(options) {
+ this.options = options;
+ this.options = extend({}, drop.defaults, this.options);
+ this.target = this.options.target;
+ if (this.target == null) {
+ throw new Error('Drop Error: You must provide a target.');
+ }
+ drop.drops.push(this);
+ allDrops[drop.classPrefix].push(this);
+ this.setupElements();
+ this.setupEvents();
+ this.setupTether();
+ }
+
+ DropInstance.prototype.setupElements = function() {
+ this.drop = document.createElement('div');
+ addClass(this.drop, drop.classPrefix);
+ if (this.options.classes) {
+ addClass(this.drop, this.options.classes);
+ }
+ this.dropContent = document.createElement('div');
+ addClass(this.dropContent, "" + drop.classPrefix + "-content");
+ if (typeof this.options.content === 'object') {
+ this.dropContent.appendChild(this.options.content);
+ } else {
+ this.dropContent.innerHTML = this.options.content;
+ }
+ return this.drop.appendChild(this.dropContent);
+ };
+
+ DropInstance.prototype.setupTether = function() {
+ var constraints, dropAttach;
+ dropAttach = this.options.position.split(' ');
+ dropAttach[0] = MIRROR_ATTACH[dropAttach[0]];
+ dropAttach = dropAttach.join(' ');
+ constraints = [];
+ if (this.options.constrainToScrollParent) {
+ constraints.push({
+ to: 'scrollParent',
+ pin: 'top, bottom',
+ attachment: 'together none'
+ });
+ }
+ if (this.options.constrainToWindow !== false) {
+ constraints.push({
+ to: 'window',
+ pin: true,
+ attachment: 'together'
+ });
+ }
+ constraints.push({
+ to: 'scrollParent'
+ });
+ options = {
+ element: this.drop,
+ target: this.target,
+ attachment: sortAttach(dropAttach),
+ targetAttachment: sortAttach(this.options.position),
+ classPrefix: drop.classPrefix,
+ offset: '0 0',
+ targetOffset: '0 0',
+ enabled: false,
+ constraints: constraints
+ };
+ if (this.options.tether !== false) {
+ return this.tether = new Tether(extend({}, options, this.options.tether));
+ }
+ };
+
+ DropInstance.prototype.setupEvents = function() {
+ var events,
+ _this = this;
+ if (!this.options.openOn) {
+ return;
+ }
+ events = this.options.openOn.split(' ');
+ if (__indexOf.call(events, 'click') >= 0) {
+ this.target.addEventListener(clickEvent, function() {
+ return _this.toggle();
+ });
+ document.addEventListener(clickEvent, function(event) {
+ if (!_this.isOpened()) {
+ return;
+ }
+ if (event.target === _this.drop || _this.drop.contains(event.target)) {
+ return;
+ }
+ if (event.target === _this.target || _this.target.contains(event.target)) {
+ return;
+ }
+ return _this.close();
+ });
+ }
+ if (__indexOf.call(events, 'hover') >= 0) {
+ this.target.addEventListener('mouseover', function() {
+ return _this.open();
+ });
+ return this.target.addEventListener('mouseout', function() {
+ return _this.close();
+ });
+ }
+ };
+
+ DropInstance.prototype.isOpened = function() {
+ return hasClass(this.drop, "" + drop.classPrefix + "-open");
+ };
+
+ DropInstance.prototype.toggle = function() {
+ if (this.isOpened()) {
+ return this.close();
+ } else {
+ return this.open();
+ }
+ };
+
+ DropInstance.prototype.open = function() {
+ var _ref1;
+ if (!this.drop.parentNode) {
+ document.body.appendChild(this.drop);
+ }
+ addClass(this.target, "" + drop.classPrefix + "-open");
+ addClass(this.drop, "" + drop.classPrefix + "-open");
+ if ((_ref1 = this.tether) != null) {
+ _ref1.enable();
+ }
+ this.trigger('open');
+ return drop.updateBodyClasses();
+ };
+
+ DropInstance.prototype.close = function() {
+ var _ref1;
+ removeClass(this.target, "" + drop.classPrefix + "-open");
+ removeClass(this.drop, "" + drop.classPrefix + "-open");
+ this.trigger('close');
+ if ((_ref1 = this.tether) != null) {
+ _ref1.disable();
+ }
+ return drop.updateBodyClasses();
+ };
+
+ return DropInstance;
+
+ })(Evented);
+ return drop;
+ };
+
+ window.Drop = createContext();
+
+ document.addEventListener('DOMContentLoaded', function() {
+ return Drop.updateBodyClasses();
+ });
+
+}).call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/js/jquery.js b/afb-client/bower_components/tether/docs/welcome/js/jquery.js
new file mode 100644
index 0000000..3f70a60
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/js/jquery.js
@@ -0,0 +1,9597 @@
+/*!
+ * jQuery JavaScript Library v1.9.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-2-4
+ */
+(function( window, undefined ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//"use strict";
+var
+ // The deferred used on DOM ready
+ readyList,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // Support: IE<9
+ // For `typeof node.method` instead of `node.method !== undefined`
+ core_strundefined = typeof undefined,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+ location = window.location,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // [[Class]] -> type pairs
+ class2type = {},
+
+ // List of deleted data cache ids, so we can reuse them
+ core_deletedIds = [],
+
+ core_version = "1.9.1",
+
+ // Save a reference to some core methods
+ core_concat = core_deletedIds.concat,
+ core_push = core_deletedIds.push,
+ core_slice = core_deletedIds.slice,
+ core_indexOf = core_deletedIds.indexOf,
+ core_toString = class2type.toString,
+ core_hasOwn = class2type.hasOwnProperty,
+ core_trim = core_version.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
+
+ // Used for splitting on whitespace
+ core_rnotwhite = /\S+/g,
+
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ },
+
+ // The ready event handler
+ completed = function( event ) {
+
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+ },
+ // Clean-up method for dom ready events
+ detach = function() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: core_version,
+
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return String( obj );
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ core_toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !core_hasOwn.call(obj, "constructor") &&
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || core_hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+ if ( scripts ) {
+ jQuery( scripts ).remove();
+ }
+ return jQuery.merge( [], parsed.childNodes );
+ },
+
+ parseJSON: function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ if ( data === null ) {
+ return data;
+ }
+
+ if ( typeof data === "string" ) {
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ if ( data ) {
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+ }
+ }
+ }
+
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+ function( text ) {
+ return text == null ?
+ "" :
+ core_trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ core_push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( core_indexOf ) {
+ return core_indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return core_concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ }
+});
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || type !== "function" &&
+ ( length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( list && ( !fired || stack ) ) {
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+jQuery.support = (function() {
+
+ var support, all, a,
+ input, select, fragment,
+ opt, eventName, isSupported, i,
+ div = document.createElement("div");
+
+ // Setup
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+ // Support tests won't run in some limited or non-browser environments
+ all = div.getElementsByTagName("*");
+ a = div.getElementsByTagName("a")[ 0 ];
+ if ( !all || !a || !all.length ) {
+ return {};
+ }
+
+ // First batch of tests
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px;float:left;opacity:.5";
+ support = {
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.5/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ checkOn: !!input.value,
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Tests for enctype support on a form (#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+ boxModel: document.compatMode === "CSS1Compat",
+
+ // Will be defined later
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ boxSizingReliable: true,
+ pixelPosition: false
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<9
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ // Check if we can trust getAttribute("value")
+ input = document.createElement("input");
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "checked", "t" );
+ input.setAttribute( "name", "t" );
+
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( input );
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
+ for ( i in { submit: true, change: true, focusin: true }) {
+ div.setAttribute( eventName = "on" + i, "t" );
+
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
+ }
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, marginDiv, tds,
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName("td");
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Support: IE8
+ // Check if empty table cells still have offsetWidth/Height
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check box-sizing and margin behavior
+ div.innerHTML = "";
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+ support.boxSizing = ( div.offsetWidth === 4 );
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = div.appendChild( document.createElement("div") );
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ if ( typeof div.style.zoom !== core_strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.innerHTML = "";
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ div.style.display = "block";
+ div.innerHTML = "<div></div>";
+ div.firstChild.style.width = "5px";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+ if ( support.inlineBlockNeedsLayout ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+
+ // Null elements to avoid leaks in IE
+ container = div = tds = marginDiv = null;
+ });
+
+ // Null elements to avoid leaks in IE
+ all = select = fragment = opt = a = input = null;
+
+ return support;
+})();
+
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ){
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var i, l, thisCache,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ // Do not set data on non-element because it will not be cleared (#8335).
+ if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
+ return false;
+ }
+
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ // nodes accept data unless otherwise specified; rejection can be conditional
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var attrs, name,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attrs = elem.attributes;
+ for ( ; i < attrs.length; i++ ) {
+ name = attrs[i].name;
+
+ if ( !name.indexOf( "data-" ) ) {
+ name = jQuery.camelCase( name.slice(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ // Try to fetch any internally stored data first
+ return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
+ }
+
+ this.each(function() {
+ jQuery.data( this, key, value );
+ });
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ hooks.cur = fn;
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var nodeHook, boolHook,
+ rclass = /[\t\r\n]/g,
+ rreturn = /\r/g,
+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i,
+ rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ getSetInput = jQuery.support.input;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
+
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( cur ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.match( core_rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ // Toggle whole class name
+ } else if ( type === core_strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var ret, hooks, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val,
+ self = jQuery(this);
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attr: function( elem, name, value ) {
+ var hooks, notxml, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === core_strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ // In IE9+, Flash objects don't have .getAttribute (#12945)
+ // Support: IE9+
+ if ( typeof elem.getAttribute !== core_strundefined ) {
+ ret = elem.getAttribute( name );
+ }
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( core_rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( rboolean.test( name ) ) {
+ // Set corresponding property to false for boolean attributes
+ // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
+ if ( !getSetAttribute && ruseDefault.test( name ) ) {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ } else {
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ var
+ // Use .prop to determine if this attribute is understood as boolean
+ prop = jQuery.prop( elem, name ),
+
+ // Fetch it accordingly
+ attr = typeof prop === "boolean" && elem.getAttribute( name ),
+ detail = typeof prop === "boolean" ?
+
+ getSetInput && getSetAttribute ?
+ attr != null :
+ // oldIE fabricates an empty string for missing boolean attributes
+ // and conflates checked/selected into attroperties
+ ruseDefault.test( name ) ?
+ elem[ jQuery.camelCase( "default-" + name ) ] :
+ !!attr :
+
+ // fetch an attribute node for properties not recognized as boolean
+ elem.getAttributeNode( name );
+
+ return detail && detail.value !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+};
+
+// fix oldIE value attroperty
+if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return jQuery.nodeName( elem, "input" ) ?
+
+ // Ignore the value *property* by using defaultValue
+ elem.defaultValue :
+
+ ret && ret.specified ? ret.value : undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
+ ret.value :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ return name === "value" || value === elem.getAttribute( name ) ?
+ value :
+ undefined;
+ }
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+}
+
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret == null ? undefined : ret;
+ }
+ });
+ });
+
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ event.isTrigger = true;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = core_slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ }
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== document.activeElement && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === document.activeElement && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Even when returnValue equals to undefined Firefox will still show alert
+ if ( event.result !== undefined ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === core_strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function( window, undefined ) {
+
+var i,
+ cachedruns,
+ Expr,
+ getText,
+ isXML,
+ compile,
+ hasDuplicate,
+ outermostContext,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsXML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+ sortOrder,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ support = {},
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Array methods
+ arr = [],
+ pop = arr.pop,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments quoted,
+ // then not containing pseudos/brackets,
+ // then attribute selectors/non-parenthetical expressions,
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
+
+ rnative = /^[^{]+\{\s*\[native code/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rescape = /'|\\/g,
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
+ funescape = function( _, escaped ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ return high !== high ?
+ escaped :
+ // BMP codepoint
+ high < 0 ?
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Use a stripped-down slice if we can't use a native one
+try {
+ slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
+} catch ( e ) {
+ slice = function( i ) {
+ var elem,
+ results = [];
+ while ( (elem = this[i++]) ) {
+ results.push( elem );
+ }
+ return results;
+ };
+}
+
+/**
+ * For feature detection
+ * @param {Function} fn The function to test for native support
+ */
+function isNative( fn ) {
+ return rnative.test( fn + "" );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var cache,
+ keys = [];
+
+ return (cache = function( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key ] = value);
+ });
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // release memory in IE
+ div = null;
+ }
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !documentIsXML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
+ old = true;
+ nid = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results, slice.call( newContext.querySelectorAll(
+ newSelector
+ ), 0 ) );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Detect xml
+ * @param {Element|Object} elem An element or a document
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsXML = isXML( doc );
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.tagNameNoComments = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if attributes should be retrieved by attribute nodes
+ support.attributes = assert(function( div ) {
+ div.innerHTML = "<select></select>";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getByClassName = assert(function( div ) {
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+ return false;
+ }
+
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ });
+
+ // Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ support.getByName = assert(function( div ) {
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
+ docElem.insertBefore( div, docElem.firstChild );
+
+ // Test
+ var pass = doc.getElementsByName &&
+ // buggy browsers will return fewer than the correct 2
+ doc.getElementsByName( expando ).length === 2 +
+ // buggy browsers will return more than the correct 0
+ doc.getElementsByName( expando + 0 ).length;
+ support.getIdNotName = !doc.getElementById( expando );
+
+ // Cleanup
+ docElem.removeChild( div );
+
+ return pass;
+ });
+
+ // IE6/7 return modified attributes
+ Expr.attrHandle = assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+ div.firstChild.getAttribute("href") === "#";
+ }) ?
+ {} :
+ {
+ "href": function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ },
+ "type": function( elem ) {
+ return elem.getAttribute("type");
+ }
+ };
+
+ // ID find and filter
+ if ( support.getIdNotName ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+
+ return m ?
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.tagNameNoComments ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Name
+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
+ if ( typeof context.getElementsByName !== strundefined ) {
+ return context.getElementsByName( name );
+ }
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21),
+ // no need to also add to buggyMatches since matches checks buggyQSA
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [ ":focus" ];
+
+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select><option selected=''></option></select>";
+
+ // IE8 - Some boolean attributes are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Opera 10-12/IE8 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = "<input type='hidden' i=''/>";
+ if ( div.querySelectorAll("[i^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.webkitMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // Document order sorting
+ sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var compare;
+
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
+ if ( a === doc || contains( preferredDoc, a ) ) {
+ return -1;
+ }
+ if ( b === doc || contains( preferredDoc, b ) ) {
+ return 1;
+ }
+ return 0;
+ }
+ return compare & 4 ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition ? -1 : 1;
+ } :
+ function( a, b ) {
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Parentless nodes are either documents or disconnected
+ } else if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ // Always assume the presence of duplicates if sort doesn't
+ // pass them to our comparison function (as in Google Chrome).
+ hasDuplicate = false;
+ [0, 0].sort( sortOrder );
+ support.detectDuplicates = hasDuplicate;
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ // rbuggyQSA always contains :focus, so no need for an existence check
+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [elem] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ var val;
+
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ if ( !documentIsXML ) {
+ name = name.toLowerCase();
+ }
+ if ( (val = Expr.attrHandle[ name ]) ) {
+ return val( elem );
+ }
+ if ( documentIsXML || support.attributes ) {
+ return elem.getAttribute( name );
+ }
+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
+ name :
+ val && val.specified ? val.value : null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+// Document sorting and removing duplicates
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ i = 1,
+ j = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem === results[ i - 1 ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ return results;
+};
+
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+// Returns a function to use in pseudos for input types
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for buttons
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for positionals
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[5] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[4] ) {
+ match[2] = match[4];
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeName ) {
+ if ( nodeName === "*" ) {
+ return function() { return true; };
+ }
+
+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifider
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsXML ?
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
+ elem.lang) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ type: type,
+ matches: match
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+}
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var data, cache, outerCache,
+ dirkey = dirruns + " " + doneName;
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
+ if ( (data = cache[1]) === true || data === cachedruns ) {
+ return data === true;
+ }
+ } else {
+ cache = outerCache[ dir ] = [ dirkey ];
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
+ if ( cache[1] === true ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ // A counter to specify which element is currently being matched
+ var matcherCachedRuns = 0,
+ bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = matcherCachedRuns;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++matcherCachedRuns;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+};
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function select( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector );
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && !documentIsXML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
+ if ( !context ) {
+ return results;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, slice.call( seed, 0 ) );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ documentIsXML,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+}
+
+// Deprecated
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Easy API for creating new setFilters
+function setFilters() {}
+Expr.filters = setFilters.prototype = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+// Initialize with the default document
+setDocument();
+
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i, ret, self,
+ len = this.length;
+
+ if ( typeof selector !== "string" ) {
+ self = this;
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ ret = [];
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, this[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
+ return ret;
+ },
+
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false) );
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true) );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ rneedsContext.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ ret = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( jQuery.unique(all) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ area: [ 1, "<map>", "</map>" ],
+ param: [ 1, "<object>", "</object>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ var isFunc = jQuery.isFunction( value );
+
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( !isFunc && typeof value !== "string" ) {
+ value = jQuery( value ).not( this ).detach();
+ }
+
+ return this.domManip( [ value ], true, function( elem ) {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ if ( parent ) {
+ jQuery( this ).remove();
+ parent.insertBefore( elem, next );
+ }
+ });
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+
+ // Flatten any nested arrays
+ args = core_concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, table ? self.html() : undefined );
+ }
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call(
+ table && jQuery.nodeName( this[i], "table" ) ?
+ findOrAppend( this[i], "tbody" ) :
+ this[i],
+ node,
+ i
+ );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Hope ajax is available...
+ jQuery.ajax({
+ url: node.src,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+});
+
+function findOrAppend( elem, tag ) {
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ var attr = elem.getAttributeNode("type");
+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ core_push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !jQuery.support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = jQuery.support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ core_deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+var iframe, getStyles, curCSS,
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+ rposition = /^(top|right|bottom|left)$/,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
+ elemdisplay = { BODY: "block" },
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function isHidden( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+
+ if ( !values[ index ] ) {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ var len, styles,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ var bool = typeof state === "boolean";
+
+ return this.each(function() {
+ if ( bool ? state : isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+// NOTE: we've included the "window" in window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ return window.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var width, minWidth, maxWidth,
+ computed = _computed || getStyles( elem ),
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
+ style = elem.style;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+ };
+} else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var left, rs, rsLeft,
+ computed = _computed || getStyles( elem ),
+ ret = computed ? computed[ name ] : undefined,
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+ // Use the already-created iframe if possible
+ iframe = ( iframe ||
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
+ .css( "cssText", "display:block !important" )
+ ).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
+ doc.write("<!doctype html><html><body>");
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+// Called ONLY from within css_defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+ display = jQuery.css( elem[0], "display" );
+ elem.remove();
+ return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ };
+ });
+ }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.hover = function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+};
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+ ajax_nonce = jQuery.now(),
+
+ ajax_rquery = /\?/,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType[0] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 ) {
+ isSuccess = true;
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ isSuccess = true;
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ isSuccess = ajaxConvert( s, response );
+ statusText = isSuccess.state;
+ success = isSuccess.data;
+ error = isSuccess.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ }
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+ var conv2, current, conv, tmp,
+ converters = {},
+ i = 0,
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice(),
+ prev = dataTypes[ 0 ];
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ // Convert to each sequential dataType, tolerating list modification
+ for ( ; (current = dataTypes[++i]); ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current !== "*" ) {
+
+ // Convert response if prev dataType is non-auto and differs from current
+ if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split(" ");
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.splice( i--, 0, current );
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s["throws"] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+
+ // Update prev for next iteration
+ prev = current;
+ }
+ }
+
+ return { state: "success", data: response };
+}
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+var xhrCallbacks, xhrSupported,
+ xhrId = 0,
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
+ // Abort all pending requests
+ var key;
+ for ( key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ };
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+xhrSupported = jQuery.ajaxSettings.xhr();
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = jQuery.support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var handle, i,
+ xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( err ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, responseHeaders, statusText, responses;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occurred
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ if ( !s.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var end, unit,
+ tween = this.createTween( prop, value ),
+ parts = rfxnum.exec( value ),
+ target = tween.cur(),
+ start = +target || 0,
+ scale = 1,
+ maxIterations = 20;
+
+ if ( parts ) {
+ end = +parts[2];
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" && start ) {
+ // Iteratively approximate from a nonzero starting point
+ // Prefer the current property, because this process will be trivial if it uses the same units
+ // Fallback to end or a simple constant
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ tween.unit = unit;
+ tween.start = start;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+ }
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+function createTweens( animation, props ) {
+ jQuery.each( props, function( prop, value ) {
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( collection[ index ].call( animation, prop, value ) ) {
+
+ // we're done with this property
+ return;
+ }
+ }
+ });
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ createTweens( animation, props );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+ var value, name, index, easing, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+ /*jshint validthis:true */
+ var prop, index, length,
+ value, dataShow, toggle,
+ tween, hooks, oldfire,
+ anim = this,
+ style = elem.style,
+ orig = {},
+ handled = [],
+ hidden = elem.nodeType && isHidden( elem );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !jQuery.support.shrinkWrapBlocks ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+
+ // show/hide pass
+ for ( index in props ) {
+ value = props[ index ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ index ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+ continue;
+ }
+ handled.push( index );
+ }
+ }
+
+ length = handled.length;
+ if ( length ) {
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( index = 0 ; index < length ; index++ ) {
+ prop = handled[ index ];
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+ doAnimation.finish = function() {
+ anim.stop( true );
+ };
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.cur && hooks.cur.finish ) {
+ hooks.cur.finish.call( this );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+};
+
+jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.documentElement;
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || document.documentElement;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// })();
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+})( window ); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/js/log.js b/afb-client/bower_components/tether/docs/welcome/js/log.js
new file mode 100644
index 0000000..6acd4fd
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/js/log.js
@@ -0,0 +1,134 @@
+(function() {
+ var ffSupport, formats, getOrderedMatches, hasMatches, isFF, isIE, isOpera, isSafari, log, makeArray, operaSupport, safariSupport, stringToArgs, _log;
+ if (!(window.console && window.console.log)) {
+ return;
+ }
+ log = function() {
+ var args;
+ args = [];
+ makeArray(arguments).forEach(function(arg) {
+ if (typeof arg === 'string') {
+ return args = args.concat(stringToArgs(arg));
+ } else {
+ return args.push(arg);
+ }
+ });
+ return _log.apply(window, args);
+ };
+ _log = function() {
+ return console.log.apply(console, makeArray(arguments));
+ };
+ makeArray = function(arrayLikeThing) {
+ return Array.prototype.slice.call(arrayLikeThing);
+ };
+ formats = [
+ {
+ regex: /\*([^\*]+)\*/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['font-style: italic', ''];
+ }
+ }, {
+ regex: /\_([^\_]+)\_/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['font-weight: bold', ''];
+ }
+ }, {
+ regex: /\`([^\`]+)\`/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['background: rgb(255, 255, 219); padding: 1px 5px; border: 1px solid rgba(0, 0, 0, 0.1)', ''];
+ }
+ }, {
+ regex: /\[c\=(?:\"|\')?((?:(?!(?:\"|\')\]).)*)(?:\"|\')?\]((?:(?!\[c\]).)*)\[c\]/,
+ replacer: function(m, p1, p2) {
+ return "%c" + p2 + "%c";
+ },
+ styles: function(match) {
+ return [match[1], ''];
+ }
+ }
+ ];
+ hasMatches = function(str) {
+ var _hasMatches;
+ _hasMatches = false;
+ formats.forEach(function(format) {
+ if (format.regex.test(str)) {
+ return _hasMatches = true;
+ }
+ });
+ return _hasMatches;
+ };
+ getOrderedMatches = function(str) {
+ var matches;
+ matches = [];
+ formats.forEach(function(format) {
+ var match;
+ match = str.match(format.regex);
+ if (match) {
+ return matches.push({
+ format: format,
+ match: match
+ });
+ }
+ });
+ return matches.sort(function(a, b) {
+ return a.match.index - b.match.index;
+ });
+ };
+ stringToArgs = function(str) {
+ var firstMatch, matches, styles;
+ styles = [];
+ while (hasMatches(str)) {
+ matches = getOrderedMatches(str);
+ firstMatch = matches[0];
+ str = str.replace(firstMatch.format.regex, firstMatch.format.replacer);
+ styles = styles.concat(firstMatch.format.styles(firstMatch.match));
+ }
+ return [str].concat(styles);
+ };
+ isSafari = function() {
+ return /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
+ };
+ isOpera = function() {
+ return /OPR/.test(navigator.userAgent) && /Opera/.test(navigator.vendor);
+ };
+ isFF = function() {
+ return /Firefox/.test(navigator.userAgent);
+ };
+ isIE = function() {
+ return /MSIE/.test(navigator.userAgent);
+ };
+ safariSupport = function() {
+ var m;
+ m = navigator.userAgent.match(/AppleWebKit\/(\d+)\.(\d+)(\.|\+|\s)/);
+ if (!m) {
+ return false;
+ }
+ return 537.38 <= parseInt(m[1], 10) + (parseInt(m[2], 10) / 100);
+ };
+ operaSupport = function() {
+ var m;
+ m = navigator.userAgent.match(/OPR\/(\d+)\./);
+ if (!m) {
+ return false;
+ }
+ return 15 <= parseInt(m[1], 10);
+ };
+ ffSupport = function() {
+ return window.console.firebug || window.console.exception;
+ };
+ if (isIE() || (isFF() && !ffSupport()) || (isOpera() && !operaSupport()) || (isSafari() && !safariSupport())) {
+ window.log = _log;
+ } else {
+ window.log = log;
+ }
+ window.log.l = _log;
+}).call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/js/tether-v0.1.3.js b/afb-client/bower_components/tether/docs/welcome/js/tether-v0.1.3.js
new file mode 100644
index 0000000..98af16f
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/js/tether-v0.1.3.js
@@ -0,0 +1,2 @@
+/*! tether.js 0.1.3 */
+(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=[].slice,s=function(a,b){return function(){return a.apply(b,arguments)}};a=jQuery,l=/msie [\w.]+/.test(navigator.userAgent.toLowerCase()),k=function(b){var c,d;return c=b.css("position"),"fixed"===c?b:(d=void 0,d="absolute"===c||l&&("static"===c||"relative"===c)?b.parents().filter(function(){var b;return("relative"===(b=a.css(this,"position"))||"absolute"===b||"fixed"===b)&&/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).first():b.parents().filter(function(){return/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).first(),d.length?d:a("html"))},b=16,j=function(a,c){var d;return null==c&&(c=b),d=!1,function(){var b,e=this;if(!d)return b=arguments,d=!0,setTimeout(function(){return d=!1,a.apply(e,b)},c),!0}},q=[],p=function(){var a,b,c;for(b=0,c=q.length;c>b;b++)a=q[b],a.position();return!0},l&&(p=j(p)),a(window).on("resize scroll",p),c={center:"center",left:"right",right:"left"},d={middle:"middle",top:"bottom",bottom:"top"},e={top:"0",left:"0",middle:"50%",center:"50%",bottom:"100%",right:"100%"},i=function(a,b){var e,f;return e=a.left,f=a.top,"auto"===e&&(e=c[b.left]),"auto"===f&&(f=d[b.top]),{left:e,top:f}},h=function(a){var b,c;return{left:null!=(b=e[a.left])?b:a.left,top:null!=(c=e[a.top])?c:a.top}},g=function(){var a,b,c,d,e,f,g;for(b=1<=arguments.length?r.call(arguments,0):[],c={top:0,left:0},e=0,f=b.length;f>e;e++)g=b[e],d=g.top,a=g.left,"string"==typeof d&&(d=parseFloat(d,10)),"string"==typeof a&&(a=parseFloat(a,10)),c.top+=d,c.left+=a;return c},m=function(b,c){return"string"==typeof b.left&&-1!==b.left.indexOf("%")&&(b.left=parseFloat(b.left,10)/100*a(c).outerWidth()),"string"==typeof b.top&&-1!==b.top.indexOf("%")&&(b.top=parseFloat(b.top,10)/100*a(c).outerHeight()),b},n=o=function(a){var b,c,d;return d=a.split(" "),c=d[0],b=d[1],{top:c,left:b}},f=function(){function b(a){this.position=s(this.position,this);var c,d,e,f,g;for(q.push(this),this.history=[],this.setOptions(a,!1),f=b.modules,d=0,e=f.length;e>d;d++)c=f[d],null!=(g=c.initialize)&&g.call(this);this.position()}return b.modules=[],b.prototype.setOptions=function(b,c){var d,e;return this.options=b,null==c&&(c=!0),d={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto"},this.options=a.extend(d,this.options),e=this.options,this.element=e.element,this.target=e.target,this.element.jquery&&(this.$element=this.element,this.element=this.element[0]),this.target.jquery&&(this.$target=this.target,this.target=this.target[0]),null==this.$element&&(this.$element=a(this.element)),null==this.$target&&(this.$target=a(this.target)),this.$element.addClass("tether-element"),this.$target.addClass("tether-target"),this.targetAttachment=n(this.options.targetAttachment),this.attachment=n(this.options.attachment),this.offset=o(this.options.offset),this.targetOffset=o(this.options.targetOffset),null!=this.scrollParent&&this.disable(),this.scrollParent=k(a(this.target)),this.options.enabled!==!1?this.enable(c):void 0},b.prototype.enable=function(a){return null==a&&(a=!0),this.addClass("tether-enabled"),this.enabled=!0,this.scrollParent.on("scroll",this.position),a?this.position():void 0},b.prototype.disable=function(){return this.removeClass("tether-enabled"),this.enabled=!1,null!=this.scrollParent?this.scrollParent.off("scroll",this.position):void 0},b.prototype.destroy=function(){var a,b,c,d,e;for(this.disable(),e=[],a=c=0,d=q.length;d>c;a=++c){if(b=q[a],b===this){q.splice(a,1);break}e.push(void 0)}return e},b.prototype.updateAttachClasses=function(a,b){var c,d,e,f,g,h;for(null==a&&(a=this.attachment),null==b&&(b=this.targetAttachment),d=["left","top","bottom","right","middle","center"],e=0,g=d.length;g>e;e++)c=d[e],this.removeClass("tether-element-attached-"+c);for(a.top&&this.addClass("tether-element-attached-"+a.top),a.left&&this.addClass("tether-element-attached-"+a.left),f=0,h=d.length;h>f;f++)c=d[f],this.removeClass("tether-target-attached-"+c);return b.top&&this.addClass("tether-target-attached-"+b.top),b.left?this.addClass("tether-target-attached-"+b.left):void 0},b.prototype.addClass=function(a){return this.$element.addClass(a),this.$target.addClass(a)},b.prototype.removeClass=function(a){return this.$element.removeClass(a),this.$target.removeClass(a)},b.prototype.position=function(){var a,c,d,e,f,j,k,l,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F;if(this.enabled){for(u=i(this.targetAttachment,this.attachment),this.updateAttachClasses(this.attachment,u),n=m(h(this.attachment),this.element),v=m(h(u),this.target),f=m(this.offset,this.element),j=m(this.targetOffset,this.target),n=g(n,f),v=g(v,j),w=this.$target.offset(),c=this.$element.offset(),e=w.left+v.left-n.left,x=w.top+v.top-n.top,D=b.modules,z=0,B=D.length;B>z;z++)if(k=D[z],q=k.position.call(this,{left:e,top:x,targetAttachment:u,targetPos:w,elementPos:c,offset:n,targetOffset:v,manualOffset:f,manualTargetOffset:j}),null!=q&&"object"==typeof q){if(q===!1)return!1;x=q.top,e=q.left}if(y=this.$element.outerWidth(),d=this.$element.outerHeight(),l={page:{top:x,bottom:document.body.scrollHeight-x-d,left:e,right:document.body.scrollWidth-e-y},viewport:{top:x-pageYOffset,bottom:pageYOffset-x-d+innerHeight,left:e-pageXOffset,right:pageXOffset-e-y+innerWidth}},(null!=(E=this.options.optimizations)?E.moveElement:void 0)!==!1){for(a=this.$target.offsetParent(),p=a.offset(),o={},F=["top","left","bottom","right"],A=0,C=F.length;C>A;A++)t=F[A],o[t]=parseFloat(a.css("border-"+t+"-width"));p.left+=o.left,p.top+=o.top,p.right=document.body.scrollWidth-p.left-a.width(),p.bottom=document.body.scrollHeight-p.top-a.height(),l.page.top>=p.top&&l.page.bottom>=p.bottom&&l.page.left>=p.left&&l.page.right>=p.right&&(s=a.scrollTop(),r=a.scrollLeft(),l.offset={top:l.page.top-p.top+s+o.top,left:l.page.left-p.left+r+o.left,right:l.page.right-p.right-r+o.right,bottom:l.page.bottom-p.bottom-s+o.bottom})}return this.move(l),this.history.unshift(l),this.history.length>3&&this.history.pop(),!0}},b.prototype.move=function(b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v;j={};for(m in b){j[m]={};for(f in b[m]){for(e=!1,t=this.history,p=0,r=t.length;r>p;p++)if(i=t[p],(null!=(u=i[m])?u[f]:void 0)!==b[m][f]){e=!0;break}e||(j[m][f]=!0)}}if(d={top:"",left:"",right:"",bottom:""},l=function(a,b){return a.top?d.top=""+b.top+"px":d.bottom=""+b.bottom+"px",a.left?d.left=""+b.left+"px":d.right=""+b.right+"px"},g=!1,(j.page.top||j.page.bottom)&&(j.page.left||j.page.right))d.position="absolute",l(j.page,b.page);else if((j.viewport.top||j.viewport.bottom)&&(j.viewport.left||j.viewport.right))d.position="fixed",l(j.viewport,b.viewport);else if(null!=j.offset&&(j.offset.top||j.offset.bottom)&&(j.offset.left||j.offset.right)){for(d.position="absolute",c=this.$target.offsetParent(),this.$element.offsetParent()[0]!==c[0]&&(this.$element.detach(),c.append(this.$element)),h=a.extend({},b.offset),v=["top","left","bottom","right"],q=0,s=v.length;s>q;q++)k=v[q],h[k]-=parseFloat(c.css("border-"+k+"-width"),10);l(j.offset,h),g=!0}else d.position="absolute",d.top=""+b.page.top+"px",d.left=""+b.page.left+"px";g||this.$element.parent().is("body")||(this.$element.detach(),a(document.body).append(this.$element)),o=!1;for(f in d)if(n=d[f],this.$element.css(f)!==n){o=!0;break}return o?this.$element.css(d):void 0},b}(),window.Tether=f}).call(this),function(){var a,b,c,d,e=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};a=jQuery,c={left:"right",right:"left",top:"bottom",bottom:"top",middle:"middle"},b=["left","top","right","bottom"],d=function(c,d){var e,f,g,h,i,j;if("scrollParent"===d?d=c.scrollParent[0]:"window"===d&&(d=[pageXOffset,pageYOffset,innerWidth+pageXOffset,innerHeight+pageYOffset]),null!=d.nodeType)for(e=a(d),g=e.offset(),d=[g.left,g.top,e.width()+g.left,e.height()+g.top],f=i=0,j=b.length;j>i;f=++i)h=b[f],d[f]+=parseFloat(e.css("border-"+h+"-width"),10);return d},Tether.modules.push({position:function(c){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T=this;if(C=c.top,n=c.left,y=c.targetAttachment,this.options.constraints){for(u=function(a){var c,d,e,f;for(T.removeClass(a),f=[],d=0,e=b.length;e>d;d++)c=b[d],f.push(T.removeClass(""+a+"-"+c));return f},m=this.$element.outerHeight(),D=this.$element.outerWidth(),z=this.$target.outerHeight(),A=this.$target.outerWidth(),x={},l={},v=["tether-pinned","tether-out-of-bounds"],O=this.options.constraints,E=0,I=O.length;I>E;E++)k=O[E],k.outOfBoundsClass&&v.push(k.outOfBoundsClass),k.pinnedClass&&v.push(k.pinnedClass);for(F=0,J=v.length;J>F;F++)j=v[F],u(j);for(x=a.extend({},y),l=a.extend({},this.attachment),P=this.options.constraints,G=0,K=P.length;K>G;G++){if(k=P[G],B=k.to,f=k.attachment,r=k.pin,null==f&&(f=""),e.call(f," ")>=0?(Q=f.split(" "),i=Q[0],h=Q[1]):h=i=f,g=d(this,B),("target"===i||"both"===i)&&(C<g[1]&&"top"===x.top&&(C+=z,x.top="bottom"),C+m>g[3]&&"bottom"===x.top&&(C-=z,x.top="top")),"together"===i&&(C<g[1]&&"top"===x.top&&("bottom"===l.top?(C+=z,x.top="bottom",C+=m,l.top="top"):"top"===l.top&&(C+=z,x.top="bottom",C-=m,l.top="bottom")),C+m>g[3]&&"bottom"===x.top&&("top"===l.top?(C-=z,x.top="top",C-=m,l.top="bottom"):"bottom"===l.top&&(C-=z,x.top="top",C+=m,l.top="top"))),("target"===h||"both"===h)&&(n<g[0]&&"left"===x.left&&(n+=A,x.left="right"),n+D>g[2]&&"right"===x.left&&(n-=A,x.left="left")),"together"===h&&(n<g[0]&&"left"===x.left?"right"===l.left?(n+=A,x.left="right",n+=D,l.left="left"):"left"===l.left&&(n+=A,x.left="right",n-=D,l.left="right"):n+D>g[2]&&"right"===x.left&&("left"===l.left?(n-=A,x.left="left",n-=D,l.left="right"):"right"===l.left&&(n-=A,x.left="left",n+=D,l.left="left"))),("element"===i||"both"===i)&&(C<g[1]&&"bottom"===l.top&&(C+=m,l.top="top"),C+m>g[3]&&"top"===l.top&&(C-=m,l.top="bottom")),("element"===h||"both"===h)&&(n<g[0]&&"right"===l.left&&(n+=D,l.left="left"),n+D>g[2]&&"left"===l.left&&(n-=D,l.left="right")),"string"==typeof r?r=function(){var a,b,c,d;for(c=r.split(","),d=[],a=0,b=c.length;b>a;a++)q=c[a],d.push(q.trim());return d}():r===!0&&(r=["top","left","right","bottom"]),r||(r=[]),s=[],o=[],C<g[1]&&(e.call(r,"top")>=0?(C=g[1],s.push("top")):o.push("top")),C+m>g[3]&&(e.call(r,"bottom")>=0?(C=g[3]-m,s.push("bottom")):o.push("bottom")),n<g[0]&&(e.call(r,"left")>=0?(n=g[0],s.push("left")):o.push("left")),n+D>g[2]&&(e.call(r,"right")>=0?(n=g[2]-D,s.push("right")):o.push("right")),s.length)for(t=null!=(R=this.options.pinnedClass)?R:"tether-pinned",this.addClass(t),H=0,L=s.length;L>H;H++)w=s[H],this.addClass(""+t+"-"+w);if(o.length)for(p=null!=(S=this.options.outOfBoundsClass)?S:"tether-out-of-bounds",this.addClass(p),N=0,M=o.length;M>N;N++)w=o[N],this.addClass(""+p+"-"+w);(e.call(s,"left")>=0||e.call(s,"right")>=0)&&(l.left=x.left=!1),(e.call(s,"top")>=0||e.call(s,"bottom")>=0)&&(l.top=x.top=!1),(x.top!==y.top||x.left!==y.left||l.top!==this.attachment.top||l.left!==this.attachment.left)&&this.updateAttachClasses(l,x)}return{top:C,left:n}}}})}.call(this),function(){var a;a=jQuery,Tether.modules.push({position:function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y;if(l=a.top,e=a.left,d=this.$element.outerHeight(),m=this.$element.outerWidth(),i=this.$target.outerHeight(),k=this.$target.outerWidth(),j=this.$target.offset(),j.bottom=j.top+i,j.right=j.left+k,c=l+d,f=e+m,b=[],l<=j.bottom&&c>=j.top)for(v=["left","right"],n=0,r=v.length;r>n;n++)g=v[n],((w=j[g])===e||w===f)&&b.push(g);if(e<=j.right&&f>=j.left)for(x=["top","bottom"],o=0,s=x.length;s>o;o++)g=x[o],((y=j[g])===l||y===c)&&b.push(g);for(h=["left","top","right","bottom"],this.removeClass("tether-abutted"),p=0,t=h.length;t>p;p++)g=h[p],this.removeClass("tether-abutted-"+g);for(b.length&&this.addClass("tether-abutted"),q=0,u=b.length;u>q;q++)g=b[q],this.addClass("tether-abutted-"+g);return!0}})}.call(this),function(){Tether.modules.push({position:function(a){var b,c,d,e,f,g,h;return g=a.top,b=a.left,this.options.shift?(c=function(a){return"function"==typeof a?a.call(this,{top:g,left:b}):a},d=c(this.options.shift),"string"==typeof d?(d=d.split(" "),d[1]||(d[1]=d[0]),f=d[0],e=d[1],f=parseFloat(f,10),e=parseFloat(e,10)):(h=[d.top,d.left],f=h[0],e=h[1]),g+=f,b+=e,{top:g,left:b}):void 0}})}.call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/js/welcome.js b/afb-client/bower_components/tether/docs/welcome/js/welcome.js
new file mode 100644
index 0000000..6f587e6
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/js/welcome.js
@@ -0,0 +1,193 @@
+(function() {
+ var init, isMobile, setupBrowserDemo, setupHero, _Drop;
+
+ _Drop = Drop.createContext({
+ classPrefix: 'tether'
+ });
+
+ isMobile = $(window).width() < 567;
+
+ init = function() {
+ setupHero();
+ return setupBrowserDemo();
+ };
+
+ setupHero = function() {
+ var $target, finalDropState, frameLengthMS, frames, openAllDrops, openIndex, openNextDrop, position, positions, _i, _len;
+ $target = $('.tether-target-demo');
+ positions = ['top left', 'left top', 'left middle', 'left bottom', 'bottom left', 'bottom center', 'bottom right', 'right bottom', 'right middle', 'right top', 'top right', 'top center'];
+ if (isMobile) {
+ positions = ['top left', 'bottom left', 'bottom right', 'top right'];
+ }
+ window.drops = {};
+ for (_i = 0, _len = positions.length; _i < _len; _i++) {
+ position = positions[_i];
+ drops[position] = new _Drop({
+ target: $target[0],
+ classes: 'tether-theme-arrows-dark',
+ position: position,
+ constrainToWindow: false,
+ openOn: '',
+ content: '<div style="height: 50px; width: 50px"></div>'
+ });
+ }
+ openIndex = 0;
+ frames = 0;
+ frameLengthMS = 10;
+ openAllDrops = function() {
+ var drop, _results;
+ _results = [];
+ for (position in drops) {
+ drop = drops[position];
+ _results.push(drop.open());
+ }
+ return _results;
+ };
+ openNextDrop = function() {
+ var drop;
+ for (position in drops) {
+ drop = drops[position];
+ drop.close();
+ }
+ drops[positions[openIndex]].open();
+ drops[positions[(openIndex + 6) % positions.length]].open();
+ openIndex = (openIndex + 1) % positions.length;
+ if (frames > 5) {
+ finalDropState();
+ return;
+ }
+ frames += 1;
+ return setTimeout(openNextDrop, frameLengthMS * frames);
+ };
+ finalDropState = function() {
+ $(drops['top left'].dropContent).html('Marrying DOM elements for life.');
+ $(drops['bottom right'].dropContent).html('<a class="button" href="http://github.com/HubSpot/tether">★ On Github</a>');
+ drops['top left'].open();
+ return drops['bottom right'].open();
+ };
+ if (true || isMobile) {
+ drops['top left'].open();
+ drops['top left'].tether.position();
+ drops['bottom right'].open();
+ drops['bottom right'].tether.position();
+ return finalDropState();
+ } else {
+ return openNextDrop();
+ }
+ };
+
+ setupBrowserDemo = function() {
+ var $browserContents, $browserDemo, $iframe, $sections, $startPoint, $stopPoint, scrollInterval, scrollTop, scrollTopDirection, setSection;
+ $browserDemo = $('.browser-demo.showcase');
+ $startPoint = $('.browser-demo-start-point');
+ $stopPoint = $('.browser-demo-stop-point');
+ $iframe = $('.browser-window iframe');
+ $browserContents = $('.browser-content .browser-demo-inner');
+ $sections = $('.browser-demo-section');
+ $('body').append("<style>\n table.showcase.browser-demo.fixed-bottom {\n top: " + $sections.length + "00%\n }\n</style>");
+ $(window).scroll(function() {
+ var scrollTop;
+ scrollTop = $(window).scrollTop();
+ if ($startPoint.position().top < scrollTop && scrollTop + window.innerHeight < $stopPoint.position().top) {
+ $browserDemo.removeClass('fixed-bottom');
+ $browserDemo.addClass('fixed');
+ return $sections.each(function() {
+ var $section;
+ $section = $(this);
+ if (($section.position().top < scrollTop && scrollTop < $section.position().top + $section.outerHeight())) {
+ setSection($section.data('section'));
+ }
+ return true;
+ });
+ } else {
+ $browserDemo.removeAttr('data-section');
+ $browserDemo.removeClass('fixed');
+ if (scrollTop + window.innerHeight > $stopPoint.position().top) {
+ return $browserDemo.addClass('fixed-bottom');
+ } else {
+ return $browserDemo.removeClass('fixed-bottom');
+ }
+ }
+ });
+ $iframe.load(function() {
+ var $items, iframeWindow;
+ iframeWindow = $iframe[0].contentWindow;
+ $items = $iframe.contents().find('.item');
+ return $items.each(function(i) {
+ var $item, drop, _iframeWindowDrop;
+ $item = $(this);
+ _iframeWindowDrop = iframeWindow.Drop.createContext({
+ classPrefix: 'tether'
+ });
+ drop = new _iframeWindowDrop({
+ target: $item[0],
+ classes: 'tether-theme-arrows-dark',
+ position: 'right top',
+ constrainToWindow: true,
+ openOn: 'click',
+ content: '<ul>\n <li>Action&nbsp;1</li>\n <li>Action&nbsp;2</li>\n <li>Action&nbsp;3</li>\n</ul>'
+ });
+ return $item.data('drop', drop);
+ });
+ });
+ scrollInterval = void 0;
+ scrollTop = 0;
+ scrollTopDirection = 1;
+ return setSection = function(section) {
+ var closeAllItems, openExampleItem, scrollLeftSection, stopScrollingLeftSection;
+ $browserDemo.attr('data-section', section);
+ $('.section-copy').removeClass('active');
+ $(".section-copy[data-section=\"" + section + "\"]").addClass('active');
+ openExampleItem = function() {
+ if (isMobile) {
+ return $iframe.contents().find('.item:first').data().drop.open();
+ } else {
+ return $iframe.contents().find('.item:eq(2)').data().drop.open();
+ }
+ };
+ closeAllItems = function() {
+ return $iframe.contents().find('.item').each(function() {
+ return $(this).data().drop.close() || true;
+ });
+ };
+ scrollLeftSection = function() {
+ return scrollInterval = setInterval(function() {
+ $iframe.contents().find('.left').scrollTop(scrollTop);
+ scrollTop += scrollTopDirection;
+ if (scrollTop > 50) {
+ scrollTopDirection = -1;
+ }
+ if (scrollTop < 0) {
+ return scrollTopDirection = 1;
+ }
+ }, 30);
+ };
+ stopScrollingLeftSection = function() {
+ return clearInterval(scrollInterval);
+ };
+ switch (section) {
+ case 'what':
+ closeAllItems();
+ openExampleItem();
+ return stopScrollingLeftSection();
+ case 'how':
+ closeAllItems();
+ openExampleItem();
+ stopScrollingLeftSection();
+ return scrollLeftSection();
+ case 'why':
+ closeAllItems();
+ openExampleItem();
+ stopScrollingLeftSection();
+ return scrollLeftSection();
+ case 'outro':
+ closeAllItems();
+ openExampleItem();
+ return stopScrollingLeftSection();
+ }
+ };
+ };
+
+ init();
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/docs/welcome/sass/browser-demo.sass b/afb-client/bower_components/tether/docs/welcome/sass/browser-demo.sass
new file mode 100644
index 0000000..e0347f5
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/sass/browser-demo.sass
@@ -0,0 +1,93 @@
+@import compass/css3
+
+html, body
+ height: 100%
+ overflow: hidden
+ font-family: "proxima-nova", sans-serif
+
+.tether.tether-theme-arrows-dark .tether-content
+ +filter(none)
+ background: #000
+
+ ul
+ color: #fff
+ list-style: none
+ padding: 0
+ margin: 0
+
+.tether.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before
+ border-right-color: #000
+
+.browser-demo
+ position: absolute
+ top: 0
+ left: 0
+ bottom: 0
+ right: 0
+
+ *, *:after, *:before
+ +box-sizing(border-box)
+
+ .top
+ position: absolute
+ height: 60px
+ padding: 20px
+ line-height: 40px
+ width: 100%
+ border-bottom: 1px solid rgba(0, 0, 0, .1)
+
+ .bottom
+ position: absolute
+ top: 60px
+ bottom: 0
+ width: 100%
+
+ .left
+ border-right: 1px solid rgba(0, 0, 0, .1)
+ position: absolute
+ width: 30%
+ height: 100%
+ overflow: auto
+
+ .item
+ height: 64px
+ border-bottom: 1px solid rgba(0, 0, 0, .1)
+ cursor: pointer
+
+ &:hover, &.tether-open
+ background: rgba(0, 0, 0, .1)
+ border-bottom: 1px solid rgba(0, 0, 0, 0)
+
+ &:last-child
+ border-bottom: 0
+
+ .right
+ position: absolute
+ width: 70%
+ right: 0
+ height: 100%
+ padding: 20px
+
+ .title
+ +inline-block
+ background: rgba(0, 0, 0, .1)
+ width: 150px
+ height: 15px
+ margin-bottom: 20px
+
+ .word
+ +inline-block
+ background: rgba(0, 0, 0, .1)
+ width: 50px
+ height: 8px
+ margin-right: 5px
+ margin-bottom: 5px
+
+ &:nth-last-child(4n+1)
+ width: 73px
+
+ &:nth-last-child(10n+1)
+ width: 14px
+
+ &:nth-last-child(9n+1)
+ width: 80px \ No newline at end of file
diff --git a/afb-client/bower_components/tether/docs/welcome/sass/welcome.sass b/afb-client/bower_components/tether/docs/welcome/sass/welcome.sass
new file mode 100644
index 0000000..7a75238
--- /dev/null
+++ b/afb-client/bower_components/tether/docs/welcome/sass/welcome.sass
@@ -0,0 +1,282 @@
+@import compass/css3
+
+html, body
+ height: 100%
+
+body
+ margin: 0
+ font-family: "proxima-nova", "Helvetica Neue", sans-serif
+
+.button
+ display: inline-block
+ border: 2px solid #333
+ color: #333
+ padding: 1em 1.25em
+ font-weight: 500
+ text-transform: uppercase
+ letter-spacing: 3px
+ text-decoration: none
+ cursor: pointer
+ width: 140px
+ font-size: .8em
+ line-height: 1.3em
+ text-align: center
+
+.tether-element.tether-theme-arrows-dark .tether-content
+ padding: 1em
+ font-size: 1.1em
+
+ .button
+ border-color: #fff
+ color: #fff
+ width: 170px
+ pointer-events: all
+
+.mobile-copy
+ display: none
+
+ @media (max-width: 568px)
+ display: block
+
+.button.dark
+ background: #333
+ color: #fff
+
+.hero-wrap
+ height: 100%
+ overflow: hidden
+
+table.showcase
+ height: 100%
+ width: 100%
+ position: relative
+
+ &:after
+ content: ""
+ display: block
+ position: absolute
+ left: 0
+ right: 0
+ bottom: 20px
+ margin: auto
+ height: 0
+ width: 0
+ border-width: 18px
+ border-style: solid
+ border-color: transparent
+ border-top-color: rgba(0, 0, 0, 0.2)
+
+ &.no-next-arrow:after
+ display: none
+
+ .showcase-inner
+ margin: 40px auto 60px
+ padding: 10px
+
+ h1
+ font-size: 50px
+ text-align: center
+ font-weight: 300
+
+ @media (max-width: 567px)
+ font-size: 40px
+
+ h2
+ font-size: 24px
+ text-align: center
+ font-weight: 300
+ margin: 1em 0 1em
+
+ @media (max-width: 567px)
+ font-size: 14px
+
+ p
+ text-align: center
+
+ &.hero
+ text-align: center
+
+ .tether-target-demo
+ +inline-block
+ border: 2px dotted #000
+ margin: 5rem auto
+ padding: 5rem
+
+ @media (max-width: 567px)
+ padding: 1rem
+
+ &.share
+ background: #f3f3f3
+
+ &.projects-showcase .showcase-inner
+
+ .projects-list
+ width: 80%
+ max-width: 1200px
+ margin: 0 auto
+
+ .project
+ color: inherit
+ text-decoration: none
+ position: relative
+ width: 50%
+ float: left
+ text-align: center
+ margin-bottom: 2rem
+
+ .os-icon
+ width: 8rem
+ height: 8rem
+ margin-bottom: 1rem
+ background-size: 100%
+
+ h1
+ font-size: 2.5rem
+
+ p
+ font-size: 1.3rem
+
+ &.browser-demo
+ +background-image(linear-gradient(top left, #723362 0%, #9d223c 100%))
+ background-color: #9d223c
+ position: absolute
+ top: 100%
+
+ &.fixed
+ position: fixed
+ top: 0
+ bottom: 0
+ left: 0
+ right: 0
+ z-index: 1
+
+ .browser-demo-inner
+ +transition(width 2s ease-in-out, height 2s ease-in-out)
+
+ // Sections
+
+ &[data-section="what"]
+ box-shadow: 0 0 0 0
+
+ &[data-section="why"]
+
+ .browser-demo-inner
+ width: 70%
+
+ &[data-section="outro"]
+
+ .showcase-inner
+ pointer-events: all
+
+ .showcase-inner
+ pointer-events: none
+ position: absolute
+ left: 10%
+ right: 40%
+ top: 220px
+ bottom: 120px
+ margin: 0
+ padding: 0
+
+ @media (max-width: 567px)
+ bottom: 90px
+ top: 180px
+
+ .browser-demo-inner
+ height: 100%
+ width: 100%
+
+ .section-copy
+ +transition(opacity .5s ease-in-out, top .5s ease-in-out)
+ +opacity(0)
+ position: absolute
+ top: 0
+ position: absolute
+ height: 200px
+ color: #fff
+ text-align: center
+ width: 100%
+
+ &.active
+ +opacity(1)
+ top: -150px
+
+ @media (max-width: 567px)
+ top: -130px
+
+ h2
+ font-size: 40px
+ font-weight: bold
+ line-height: 1
+ margin: 25px 0 15px
+
+ @media (max-width: 567px)
+ font-size: 30px
+
+ .browser-window
+ +border-radius(4px)
+ background: #fff
+ position: relative
+ height: 100%
+ width: 100%
+ max-width: 1200px
+ margin: 0 auto
+
+ .browser-titlebar
+ position: absolute
+ top: 0
+ left: 0
+ right: 0
+ border-bottom: 1px solid #eee
+ height: 55px
+
+ .browser-dots
+ padding: 16px
+
+ b
+ +border-radius(50%)
+ +inline-block
+ width: 10px
+ height: 10px
+ margin-right: 7px
+ background: rgba(0, 0, 0, .1)
+
+ .browser-frame
+ position: absolute
+ top: 55px
+ left: 0
+ right: 0
+ bottom: 0
+
+ iframe
+ +border-radius(0 0 4px 4px)
+ border: 0
+ width: 100%
+ height: 100%
+
+ &.browser-demo-section
+
+ .section-scroll-copy
+ position: relative
+ z-index: 10
+ color: #fff
+ width: 100%
+ font-size: 22px
+
+ .section-scroll-copy-inner
+ position: absolute
+ z-index: 10
+ color: #fff
+ right: 10%
+ width: 23%
+
+ a
+ color: inherit
+
+ .example-paragraph
+ +border-radius(4px)
+ background: #000
+ padding: 1rem
+
+.browser-content
+ display: none
diff --git a/afb-client/bower_components/tether/examples/chosen/chosen-sprite.png b/afb-client/bower_components/tether/examples/chosen/chosen-sprite.png
new file mode 100644
index 0000000..3611ae4
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/chosen/chosen-sprite.png
Binary files differ
diff --git a/afb-client/bower_components/tether/examples/chosen/chosen.css b/afb-client/bower_components/tether/examples/chosen/chosen.css
new file mode 100644
index 0000000..828fe1f
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/chosen/chosen.css
@@ -0,0 +1,430 @@
+/* @group Base */
+.chosen-container {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ font-size: 13px;
+ zoom: 1;
+ *display: inline;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+}
+.chosen-container .chosen-drop {
+ position: absolute;
+ top: 100%;
+ left: -9999px;
+ z-index: 1010;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ border: 1px solid #aaa;
+ border-top: 0;
+ background: #fff;
+ box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
+}
+.chosen-container.chosen-with-drop .chosen-drop {
+ left: 0;
+}
+.chosen-container a {
+ cursor: pointer;
+}
+
+/* @end */
+/* @group Single Chosen */
+.chosen-container-single .chosen-single {
+ position: relative;
+ display: block;
+ overflow: hidden;
+ padding: 0 0 0 8px;
+ height: 23px;
+ border: 1px solid #aaa;
+ border-radius: 5px;
+ background-color: #fff;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
+ background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background-clip: padding-box;
+ box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
+ color: #444;
+ text-decoration: none;
+ white-space: nowrap;
+ line-height: 24px;
+}
+.chosen-container-single .chosen-default {
+ color: #999;
+}
+.chosen-container-single .chosen-single span {
+ display: block;
+ overflow: hidden;
+ margin-right: 26px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.chosen-container-single .chosen-single-with-deselect span {
+ margin-right: 38px;
+}
+.chosen-container-single .chosen-single abbr {
+ position: absolute;
+ top: 6px;
+ right: 26px;
+ display: block;
+ width: 12px;
+ height: 12px;
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
+ font-size: 1px;
+}
+.chosen-container-single .chosen-single abbr:hover {
+ background-position: -42px -10px;
+}
+.chosen-container-single.chosen-disabled .chosen-single abbr:hover {
+ background-position: -42px -10px;
+}
+.chosen-container-single .chosen-single div {
+ position: absolute;
+ top: 0;
+ right: 0;
+ display: block;
+ width: 18px;
+ height: 100%;
+}
+.chosen-container-single .chosen-single div b {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background: url('chosen-sprite.png') no-repeat 0px 2px;
+}
+.chosen-container-single .chosen-search {
+ position: relative;
+ z-index: 1010;
+ margin: 0;
+ padding: 3px 4px;
+ white-space: nowrap;
+}
+.chosen-container-single .chosen-search input[type="text"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin: 1px 0;
+ padding: 4px 20px 4px 5px;
+ width: 100%;
+ height: auto;
+ outline: 0;
+ border: 1px solid #aaa;
+ background: white url('chosen-sprite.png') no-repeat 100% -20px;
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+ font-size: 1em;
+ font-family: sans-serif;
+ line-height: normal;
+ border-radius: 0;
+}
+.chosen-container-single .chosen-drop {
+ margin-top: -1px;
+ border-radius: 0 0 4px 4px;
+ background-clip: padding-box;
+}
+.chosen-container-single.chosen-container-single-nosearch .chosen-search {
+ position: absolute;
+ left: -9999px;
+}
+
+/* @end */
+/* @group Results */
+.chosen-container .chosen-results {
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: auto;
+ margin: 0 4px 4px 0;
+ padding: 0 0 0 4px;
+ max-height: 240px;
+ -webkit-overflow-scrolling: touch;
+}
+.chosen-container .chosen-results li {
+ display: none;
+ margin: 0;
+ padding: 5px 6px;
+ list-style: none;
+ line-height: 15px;
+}
+.chosen-container .chosen-results li.active-result {
+ display: list-item;
+ cursor: pointer;
+}
+.chosen-container .chosen-results li.disabled-result {
+ display: list-item;
+ color: #ccc;
+ cursor: default;
+}
+.chosen-container .chosen-results li.highlighted {
+ background-color: #3875d7;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
+ background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
+ background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
+ background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
+ color: #fff;
+}
+.chosen-container .chosen-results li.no-results {
+ display: list-item;
+ background: #f4f4f4;
+}
+.chosen-container .chosen-results li.group-result {
+ display: list-item;
+ font-weight: bold;
+ cursor: default;
+}
+.chosen-container .chosen-results li.group-option {
+ padding-left: 15px;
+}
+.chosen-container .chosen-results li em {
+ font-style: normal;
+ text-decoration: underline;
+}
+
+/* @end */
+/* @group Multi Chosen */
+.chosen-container-multi .chosen-choices {
+ position: relative;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: auto !important;
+ height: 1%;
+ border: 1px solid #aaa;
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
+ cursor: text;
+}
+.chosen-container-multi .chosen-choices li {
+ float: left;
+ list-style: none;
+}
+.chosen-container-multi .chosen-choices li.search-field {
+ margin: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.chosen-container-multi .chosen-choices li.search-field input[type="text"] {
+ margin: 1px 0;
+ padding: 5px;
+ height: 15px;
+ outline: 0;
+ border: 0 !important;
+ background: transparent !important;
+ box-shadow: none;
+ color: #666;
+ font-size: 100%;
+ font-family: sans-serif;
+ line-height: normal;
+ border-radius: 0;
+}
+.chosen-container-multi .chosen-choices li.search-field .default {
+ color: #999;
+}
+.chosen-container-multi .chosen-choices li.search-choice {
+ position: relative;
+ margin: 3px 0 3px 5px;
+ padding: 3px 20px 3px 5px;
+ border: 1px solid #aaa;
+ border-radius: 3px;
+ background-color: #e4e4e4;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+ background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-clip: padding-box;
+ box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
+ color: #333;
+ line-height: 13px;
+ cursor: default;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
+ position: absolute;
+ top: 4px;
+ right: 3px;
+ display: block;
+ width: 12px;
+ height: 12px;
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
+ font-size: 1px;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
+ background-position: -42px -10px;
+}
+.chosen-container-multi .chosen-choices li.search-choice-disabled {
+ padding-right: 5px;
+ border: 1px solid #ccc;
+ background-color: #e4e4e4;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ color: #666;
+}
+.chosen-container-multi .chosen-choices li.search-choice-focus {
+ background: #d4d4d4;
+}
+.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
+ background-position: -42px -10px;
+}
+.chosen-container-multi .chosen-results {
+ margin: 0;
+ padding: 0;
+}
+.chosen-container-multi .chosen-drop .result-selected {
+ display: list-item;
+ color: #ccc;
+ cursor: default;
+}
+
+/* @end */
+/* @group Active */
+.chosen-container-active .chosen-single {
+ border: 1px solid #5897fb;
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
+}
+.chosen-container-active.chosen-with-drop .chosen-single {
+ border: 1px solid #aaa;
+ -moz-border-radius-bottomright: 0;
+ border-bottom-right-radius: 0;
+ -moz-border-radius-bottomleft: 0;
+ border-bottom-left-radius: 0;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
+ background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
+ background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
+ background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
+ box-shadow: 0 1px 0 #fff inset;
+}
+.chosen-container-active.chosen-with-drop .chosen-single div {
+ border-left: none;
+ background: transparent;
+}
+.chosen-container-active.chosen-with-drop .chosen-single div b {
+ background-position: -18px 2px;
+}
+.chosen-container-active .chosen-choices {
+ border: 1px solid #5897fb;
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
+}
+.chosen-container-active .chosen-choices li.search-field input[type="text"] {
+ color: #111 !important;
+}
+
+/* @end */
+/* @group Disabled Support */
+.chosen-disabled {
+ opacity: 0.5 !important;
+ cursor: default;
+}
+.chosen-disabled .chosen-single {
+ cursor: default;
+}
+.chosen-disabled .chosen-choices .search-choice .search-choice-close {
+ cursor: default;
+}
+
+/* @end */
+/* @group Right to Left */
+.chosen-rtl {
+ text-align: right;
+}
+.chosen-rtl .chosen-single {
+ overflow: visible;
+ padding: 0 8px 0 0;
+}
+.chosen-rtl .chosen-single span {
+ margin-right: 0;
+ margin-left: 26px;
+ direction: rtl;
+}
+.chosen-rtl .chosen-single-with-deselect span {
+ margin-left: 38px;
+}
+.chosen-rtl .chosen-single div {
+ right: auto;
+ left: 3px;
+}
+.chosen-rtl .chosen-single abbr {
+ right: auto;
+ left: 26px;
+}
+.chosen-rtl .chosen-choices li {
+ float: right;
+}
+.chosen-rtl .chosen-choices li.search-field input[type="text"] {
+ direction: rtl;
+}
+.chosen-rtl .chosen-choices li.search-choice {
+ margin: 3px 5px 3px 0;
+ padding: 3px 5px 3px 19px;
+}
+.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
+ right: auto;
+ left: 4px;
+}
+.chosen-rtl.chosen-container-single-nosearch .chosen-search,
+.chosen-rtl .chosen-drop {
+ left: 9999px;
+}
+.chosen-rtl.chosen-container-single .chosen-results {
+ margin: 0 0 4px 4px;
+ padding: 0 4px 0 0;
+}
+.chosen-rtl .chosen-results li.group-option {
+ padding-right: 15px;
+ padding-left: 0;
+}
+.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
+ border-right: none;
+}
+.chosen-rtl .chosen-search input[type="text"] {
+ padding: 4px 5px 4px 20px;
+ background: white url('chosen-sprite.png') no-repeat -30px -20px;
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+ direction: rtl;
+}
+.chosen-rtl.chosen-container-single .chosen-single div b {
+ background-position: 6px 2px;
+}
+.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
+ background-position: -12px 2px;
+}
+
+/* @end */
+/* @group Retina compatibility */
+@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
+ .chosen-rtl .chosen-search input[type="text"],
+ .chosen-container-single .chosen-single abbr,
+ .chosen-container-single .chosen-single div b,
+ .chosen-container-single .chosen-search input[type="text"],
+ .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
+ .chosen-container .chosen-results-scroll-down span,
+ .chosen-container .chosen-results-scroll-up span {
+ background-image: url('chosen-sprite@2x.png') !important;
+ background-size: 52px 37px !important;
+ background-repeat: no-repeat !important;
+ }
+}
+/* @end */ \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/chosen/chosen.js b/afb-client/bower_components/tether/examples/chosen/chosen.js
new file mode 100644
index 0000000..521556b
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/chosen/chosen.js
@@ -0,0 +1,1166 @@
+// Chosen, a Select Box Enhancer for jQuery and Prototype
+// by Patrick Filler for Harvest, http://getharvest.com
+//
+// Version 1.0.0
+// Full source at https://github.com/harvesthq/chosen
+// Copyright (c) 2011 Harvest http://getharvest.com
+
+// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
+// This file is generated by `grunt build`, do not edit it by hand.
+(function() {
+ var $, AbstractChosen, Chosen, SelectParser, _ref,
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ SelectParser = (function() {
+ function SelectParser() {
+ this.options_index = 0;
+ this.parsed = [];
+ }
+
+ SelectParser.prototype.add_node = function(child) {
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
+ return this.add_group(child);
+ } else {
+ return this.add_option(child);
+ }
+ };
+
+ SelectParser.prototype.add_group = function(group) {
+ var group_position, option, _i, _len, _ref, _results;
+
+ group_position = this.parsed.length;
+ this.parsed.push({
+ array_index: group_position,
+ group: true,
+ label: this.escapeExpression(group.label),
+ children: 0,
+ disabled: group.disabled
+ });
+ _ref = group.childNodes;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ option = _ref[_i];
+ _results.push(this.add_option(option, group_position, group.disabled));
+ }
+ return _results;
+ };
+
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
+ if (option.nodeName.toUpperCase() === "OPTION") {
+ if (option.text !== "") {
+ if (group_position != null) {
+ this.parsed[group_position].children += 1;
+ }
+ this.parsed.push({
+ array_index: this.parsed.length,
+ options_index: this.options_index,
+ value: option.value,
+ text: option.text,
+ html: option.innerHTML,
+ selected: option.selected,
+ disabled: group_disabled === true ? group_disabled : option.disabled,
+ group_array_index: group_position,
+ classes: option.className,
+ style: option.style.cssText
+ });
+ } else {
+ this.parsed.push({
+ array_index: this.parsed.length,
+ options_index: this.options_index,
+ empty: true
+ });
+ }
+ return this.options_index += 1;
+ }
+ };
+
+ SelectParser.prototype.escapeExpression = function(text) {
+ var map, unsafe_chars;
+
+ if ((text == null) || text === false) {
+ return "";
+ }
+ if (!/[\&\<\>\"\'\`]/.test(text)) {
+ return text;
+ }
+ map = {
+ "<": "&lt;",
+ ">": "&gt;",
+ '"': "&quot;",
+ "'": "&#x27;",
+ "`": "&#x60;"
+ };
+ unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
+ return text.replace(unsafe_chars, function(chr) {
+ return map[chr] || "&amp;";
+ });
+ };
+
+ return SelectParser;
+
+ })();
+
+ SelectParser.select_to_array = function(select) {
+ var child, parser, _i, _len, _ref;
+
+ parser = new SelectParser();
+ _ref = select.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ parser.add_node(child);
+ }
+ return parser.parsed;
+ };
+
+ AbstractChosen = (function() {
+ function AbstractChosen(form_field, options) {
+ this.form_field = form_field;
+ this.options = options != null ? options : {};
+ if (!AbstractChosen.browser_is_supported()) {
+ return;
+ }
+ this.is_multiple = this.form_field.multiple;
+ this.set_default_text();
+ this.set_default_values();
+ this.setup();
+ this.set_up_html();
+ this.register_observers();
+ }
+
+ AbstractChosen.prototype.set_default_values = function() {
+ var _this = this;
+
+ this.click_test_action = function(evt) {
+ return _this.test_active_click(evt);
+ };
+ this.activate_action = function(evt) {
+ return _this.activate_field(evt);
+ };
+ this.active_field = false;
+ this.mouse_on_container = false;
+ this.results_showing = false;
+ this.result_highlighted = null;
+ this.result_single_selected = null;
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
+ this.disable_search = this.options.disable_search || false;
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
+ this.search_contains = this.options.search_contains || false;
+ this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
+ this.max_selected_options = this.options.max_selected_options || Infinity;
+ this.inherit_select_classes = this.options.inherit_select_classes || false;
+ this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
+ return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
+ };
+
+ AbstractChosen.prototype.set_default_text = function() {
+ if (this.form_field.getAttribute("data-placeholder")) {
+ this.default_text = this.form_field.getAttribute("data-placeholder");
+ } else if (this.is_multiple) {
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
+ } else {
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
+ }
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
+ };
+
+ AbstractChosen.prototype.mouse_enter = function() {
+ return this.mouse_on_container = true;
+ };
+
+ AbstractChosen.prototype.mouse_leave = function() {
+ return this.mouse_on_container = false;
+ };
+
+ AbstractChosen.prototype.input_focus = function(evt) {
+ var _this = this;
+
+ if (this.is_multiple) {
+ if (!this.active_field) {
+ return setTimeout((function() {
+ return _this.container_mousedown();
+ }), 50);
+ }
+ } else {
+ if (!this.active_field) {
+ return this.activate_field();
+ }
+ }
+ };
+
+ AbstractChosen.prototype.input_blur = function(evt) {
+ var _this = this;
+
+ if (!this.mouse_on_container) {
+ this.active_field = false;
+ return setTimeout((function() {
+ return _this.blur_test();
+ }), 100);
+ }
+ };
+
+ AbstractChosen.prototype.results_option_build = function(options) {
+ var content, data, _i, _len, _ref;
+
+ content = '';
+ _ref = this.results_data;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ data = _ref[_i];
+ if (data.group) {
+ content += this.result_add_group(data);
+ } else {
+ content += this.result_add_option(data);
+ }
+ if (options != null ? options.first : void 0) {
+ if (data.selected && this.is_multiple) {
+ this.choice_build(data);
+ } else if (data.selected && !this.is_multiple) {
+ this.single_set_selected_text(data.text);
+ }
+ }
+ }
+ return content;
+ };
+
+ AbstractChosen.prototype.result_add_option = function(option) {
+ var classes, style;
+
+ if (!option.search_match) {
+ return '';
+ }
+ if (!this.include_option_in_results(option)) {
+ return '';
+ }
+ classes = [];
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
+ classes.push("active-result");
+ }
+ if (option.disabled && !(option.selected && this.is_multiple)) {
+ classes.push("disabled-result");
+ }
+ if (option.selected) {
+ classes.push("result-selected");
+ }
+ if (option.group_array_index != null) {
+ classes.push("group-option");
+ }
+ if (option.classes !== "") {
+ classes.push(option.classes);
+ }
+ style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
+ return "<li class=\"" + (classes.join(' ')) + "\"" + style + " data-option-array-index=\"" + option.array_index + "\">" + option.search_text + "</li>";
+ };
+
+ AbstractChosen.prototype.result_add_group = function(group) {
+ if (!(group.search_match || group.group_match)) {
+ return '';
+ }
+ if (!(group.active_options > 0)) {
+ return '';
+ }
+ return "<li class=\"group-result\">" + group.search_text + "</li>";
+ };
+
+ AbstractChosen.prototype.results_update_field = function() {
+ this.set_default_text();
+ if (!this.is_multiple) {
+ this.results_reset_cleanup();
+ }
+ this.result_clear_highlight();
+ this.result_single_selected = null;
+ this.results_build();
+ if (this.results_showing) {
+ return this.winnow_results();
+ }
+ };
+
+ AbstractChosen.prototype.results_toggle = function() {
+ if (this.results_showing) {
+ return this.results_hide();
+ } else {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.results_search = function(evt) {
+ if (this.results_showing) {
+ return this.winnow_results();
+ } else {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.winnow_results = function() {
+ var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
+
+ this.no_results_clear();
+ results = 0;
+ searchText = this.get_search_text();
+ escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ regexAnchor = this.search_contains ? "" : "^";
+ regex = new RegExp(regexAnchor + escapedSearchText, 'i');
+ zregex = new RegExp(escapedSearchText, 'i');
+ _ref = this.results_data;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ option = _ref[_i];
+ option.search_match = false;
+ results_group = null;
+ if (this.include_option_in_results(option)) {
+ if (option.group) {
+ option.group_match = false;
+ option.active_options = 0;
+ }
+ if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
+ results_group = this.results_data[option.group_array_index];
+ if (results_group.active_options === 0 && results_group.search_match) {
+ results += 1;
+ }
+ results_group.active_options += 1;
+ }
+ if (!(option.group && !this.group_search)) {
+ option.search_text = option.group ? option.label : option.html;
+ option.search_match = this.search_string_match(option.search_text, regex);
+ if (option.search_match && !option.group) {
+ results += 1;
+ }
+ if (option.search_match) {
+ if (searchText.length) {
+ startpos = option.search_text.search(zregex);
+ text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
+ option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
+ }
+ if (results_group != null) {
+ results_group.group_match = true;
+ }
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
+ option.search_match = true;
+ }
+ }
+ }
+ }
+ this.result_clear_highlight();
+ if (results < 1 && searchText.length) {
+ this.update_results_content("");
+ return this.no_results(searchText);
+ } else {
+ this.update_results_content(this.results_option_build());
+ return this.winnow_results_set_highlight();
+ }
+ };
+
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
+ var part, parts, _i, _len;
+
+ if (regex.test(search_string)) {
+ return true;
+ } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
+ parts = search_string.replace(/\[|\]/g, "").split(" ");
+ if (parts.length) {
+ for (_i = 0, _len = parts.length; _i < _len; _i++) {
+ part = parts[_i];
+ if (regex.test(part)) {
+ return true;
+ }
+ }
+ }
+ }
+ };
+
+ AbstractChosen.prototype.choices_count = function() {
+ var option, _i, _len, _ref;
+
+ if (this.selected_option_count != null) {
+ return this.selected_option_count;
+ }
+ this.selected_option_count = 0;
+ _ref = this.form_field.options;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ option = _ref[_i];
+ if (option.selected) {
+ this.selected_option_count += 1;
+ }
+ }
+ return this.selected_option_count;
+ };
+
+ AbstractChosen.prototype.choices_click = function(evt) {
+ evt.preventDefault();
+ if (!(this.results_showing || this.is_disabled)) {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.keyup_checker = function(evt) {
+ var stroke, _ref;
+
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
+ this.search_field_scale();
+ switch (stroke) {
+ case 8:
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
+ return this.keydown_backstroke();
+ } else if (!this.pending_backstroke) {
+ this.result_clear_highlight();
+ return this.results_search();
+ }
+ break;
+ case 13:
+ evt.preventDefault();
+ if (this.results_showing) {
+ return this.result_select(evt);
+ }
+ break;
+ case 27:
+ if (this.results_showing) {
+ this.results_hide();
+ }
+ return true;
+ case 9:
+ case 38:
+ case 40:
+ case 16:
+ case 91:
+ case 17:
+ break;
+ default:
+ return this.results_search();
+ }
+ };
+
+ AbstractChosen.prototype.container_width = function() {
+ if (this.options.width != null) {
+ return this.options.width;
+ } else {
+ return "" + this.form_field.offsetWidth + "px";
+ }
+ };
+
+ AbstractChosen.prototype.include_option_in_results = function(option) {
+ if (this.is_multiple && (!this.display_selected_options && option.selected)) {
+ return false;
+ }
+ if (!this.display_disabled_options && option.disabled) {
+ return false;
+ }
+ if (option.empty) {
+ return false;
+ }
+ return true;
+ };
+
+ AbstractChosen.browser_is_supported = function() {
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
+ return document.documentMode >= 8;
+ }
+ if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
+ return false;
+ }
+ if (/Android/i.test(window.navigator.userAgent)) {
+ if (/Mobile/i.test(window.navigator.userAgent)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ AbstractChosen.default_multiple_text = "Select Some Options";
+
+ AbstractChosen.default_single_text = "Select an Option";
+
+ AbstractChosen.default_no_result_text = "No results match";
+
+ return AbstractChosen;
+
+ })();
+
+ $ = jQuery;
+
+ $.fn.extend({
+ chosen: function(options) {
+ if (!AbstractChosen.browser_is_supported()) {
+ return this;
+ }
+ return this.each(function(input_field) {
+ var $this, chosen;
+
+ $this = $(this);
+ chosen = $this.data('chosen');
+ if (options === 'destroy' && chosen) {
+ chosen.destroy();
+ } else if (!chosen) {
+ $this.data('chosen', new Chosen(this, options));
+ }
+ });
+ }
+ });
+
+ Chosen = (function(_super) {
+ __extends(Chosen, _super);
+
+ function Chosen() {
+ _ref = Chosen.__super__.constructor.apply(this, arguments);
+ return _ref;
+ }
+
+ Chosen.prototype.setup = function() {
+ this.form_field_jq = $(this.form_field);
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
+ };
+
+ Chosen.prototype.set_up_html = function() {
+ var container_classes, container_props;
+
+ container_classes = ["chosen-container"];
+ container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
+ if (this.inherit_select_classes && this.form_field.className) {
+ container_classes.push(this.form_field.className);
+ }
+ if (this.is_rtl) {
+ container_classes.push("chosen-rtl");
+ }
+ container_props = {
+ 'class': container_classes.join(' '),
+ 'style': "width: " + (this.container_width()) + ";",
+ 'title': this.form_field.title
+ };
+ if (this.form_field.id.length) {
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
+ }
+ this.container = $("<div />", container_props);
+ if (this.is_multiple) {
+ this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
+ } else {
+ this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
+ }
+ this.form_field_jq.hide().after(this.container);
+ this.dropdown = this.container.find('div.chosen-drop').first();
+ this.search_field = this.container.find('input').first();
+ this.search_results = this.container.find('ul.chosen-results').first();
+ this.search_field_scale();
+ this.search_no_results = this.container.find('li.no-results').first();
+ if (this.is_multiple) {
+ this.search_choices = this.container.find('ul.chosen-choices').first();
+ this.search_container = this.container.find('li.search-field').first();
+ } else {
+ this.search_container = this.container.find('div.chosen-search').first();
+ this.selected_item = this.container.find('.chosen-single').first();
+ }
+ this.results_build();
+ this.set_tab_index();
+ this.set_label_behavior();
+ return this.form_field_jq.trigger("chosen:ready", {
+ chosen: this
+ });
+ };
+
+ Chosen.prototype.register_observers = function() {
+ var _this = this;
+
+ this.container.bind('mousedown.chosen', function(evt) {
+ _this.container_mousedown(evt);
+ });
+ this.container.bind('mouseup.chosen', function(evt) {
+ _this.container_mouseup(evt);
+ });
+ this.container.bind('mouseenter.chosen', function(evt) {
+ _this.mouse_enter(evt);
+ });
+ this.container.bind('mouseleave.chosen', function(evt) {
+ _this.mouse_leave(evt);
+ });
+ this.search_results.bind('mouseup.chosen', function(evt) {
+ _this.search_results_mouseup(evt);
+ });
+ this.search_results.bind('mouseover.chosen', function(evt) {
+ _this.search_results_mouseover(evt);
+ });
+ this.search_results.bind('mouseout.chosen', function(evt) {
+ _this.search_results_mouseout(evt);
+ });
+ this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
+ _this.search_results_mousewheel(evt);
+ });
+ this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
+ _this.results_update_field(evt);
+ });
+ this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
+ _this.activate_field(evt);
+ });
+ this.form_field_jq.bind("chosen:open.chosen", function(evt) {
+ _this.container_mousedown(evt);
+ });
+ this.search_field.bind('blur.chosen', function(evt) {
+ _this.input_blur(evt);
+ });
+ this.search_field.bind('keyup.chosen', function(evt) {
+ _this.keyup_checker(evt);
+ });
+ this.search_field.bind('keydown.chosen', function(evt) {
+ _this.keydown_checker(evt);
+ });
+ this.search_field.bind('focus.chosen', function(evt) {
+ _this.input_focus(evt);
+ });
+ if (this.is_multiple) {
+ return this.search_choices.bind('click.chosen', function(evt) {
+ _this.choices_click(evt);
+ });
+ } else {
+ return this.container.bind('click.chosen', function(evt) {
+ evt.preventDefault();
+ });
+ }
+ };
+
+ Chosen.prototype.destroy = function() {
+ $(document).unbind("click.chosen", this.click_test_action);
+ if (this.search_field[0].tabIndex) {
+ this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
+ }
+ this.container.remove();
+ this.form_field_jq.removeData('chosen');
+ return this.form_field_jq.show();
+ };
+
+ Chosen.prototype.search_field_disabled = function() {
+ this.is_disabled = this.form_field_jq[0].disabled;
+ if (this.is_disabled) {
+ this.container.addClass('chosen-disabled');
+ this.search_field[0].disabled = true;
+ if (!this.is_multiple) {
+ this.selected_item.unbind("focus.chosen", this.activate_action);
+ }
+ return this.close_field();
+ } else {
+ this.container.removeClass('chosen-disabled');
+ this.search_field[0].disabled = false;
+ if (!this.is_multiple) {
+ return this.selected_item.bind("focus.chosen", this.activate_action);
+ }
+ }
+ };
+
+ Chosen.prototype.container_mousedown = function(evt) {
+ if (!this.is_disabled) {
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
+ evt.preventDefault();
+ }
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
+ if (!this.active_field) {
+ if (this.is_multiple) {
+ this.search_field.val("");
+ }
+ $(document).bind('click.chosen', this.click_test_action);
+ this.results_show();
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
+ evt.preventDefault();
+ this.results_toggle();
+ }
+ return this.activate_field();
+ }
+ }
+ };
+
+ Chosen.prototype.container_mouseup = function(evt) {
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
+ return this.results_reset(evt);
+ }
+ };
+
+ Chosen.prototype.search_results_mousewheel = function(evt) {
+ var delta, _ref1, _ref2;
+
+ delta = -((_ref1 = evt.originalEvent) != null ? _ref1.wheelDelta : void 0) || ((_ref2 = evt.originialEvent) != null ? _ref2.detail : void 0);
+ if (delta != null) {
+ evt.preventDefault();
+ if (evt.type === 'DOMMouseScroll') {
+ delta = delta * 40;
+ }
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
+ }
+ };
+
+ Chosen.prototype.blur_test = function(evt) {
+ if (!this.active_field && this.container.hasClass("chosen-container-active")) {
+ return this.close_field();
+ }
+ };
+
+ Chosen.prototype.close_field = function() {
+ $(document).unbind("click.chosen", this.click_test_action);
+ this.active_field = false;
+ this.results_hide();
+ this.container.removeClass("chosen-container-active");
+ this.clear_backstroke();
+ this.show_search_field_default();
+ return this.search_field_scale();
+ };
+
+ Chosen.prototype.activate_field = function() {
+ this.container.addClass("chosen-container-active");
+ this.active_field = true;
+ this.search_field.val(this.search_field.val());
+ return this.search_field.focus();
+ };
+
+ Chosen.prototype.test_active_click = function(evt) {
+ if (this.container.is($(evt.target).closest('.chosen-container'))) {
+ return this.active_field = true;
+ } else {
+ return this.close_field();
+ }
+ };
+
+ Chosen.prototype.results_build = function() {
+ this.parsing = true;
+ this.selected_option_count = null;
+ this.results_data = SelectParser.select_to_array(this.form_field);
+ if (this.is_multiple) {
+ this.search_choices.find("li.search-choice").remove();
+ } else if (!this.is_multiple) {
+ this.single_set_selected_text();
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
+ this.search_field[0].readOnly = true;
+ this.container.addClass("chosen-container-single-nosearch");
+ } else {
+ this.search_field[0].readOnly = false;
+ this.container.removeClass("chosen-container-single-nosearch");
+ }
+ }
+ this.update_results_content(this.results_option_build({
+ first: true
+ }));
+ this.search_field_disabled();
+ this.show_search_field_default();
+ this.search_field_scale();
+ return this.parsing = false;
+ };
+
+ Chosen.prototype.result_do_highlight = function(el) {
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
+
+ if (el.length) {
+ this.result_clear_highlight();
+ this.result_highlight = el;
+ this.result_highlight.addClass("highlighted");
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
+ visible_top = this.search_results.scrollTop();
+ visible_bottom = maxHeight + visible_top;
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
+ high_bottom = high_top + this.result_highlight.outerHeight();
+ if (high_bottom >= visible_bottom) {
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
+ } else if (high_top < visible_top) {
+ return this.search_results.scrollTop(high_top);
+ }
+ }
+ };
+
+ Chosen.prototype.result_clear_highlight = function() {
+ if (this.result_highlight) {
+ this.result_highlight.removeClass("highlighted");
+ }
+ return this.result_highlight = null;
+ };
+
+ Chosen.prototype.results_show = function() {
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
+ this.form_field_jq.trigger("chosen:maxselected", {
+ chosen: this
+ });
+ return false;
+ }
+ this.container.addClass("chosen-with-drop");
+ this.form_field_jq.trigger("chosen:showing_dropdown", {
+ chosen: this
+ });
+ this.results_showing = true;
+ this.search_field.focus();
+ this.search_field.val(this.search_field.val());
+ return this.winnow_results();
+ };
+
+ Chosen.prototype.update_results_content = function(content) {
+ return this.search_results.html(content);
+ };
+
+ Chosen.prototype.results_hide = function() {
+ if (this.results_showing) {
+ this.result_clear_highlight();
+ this.container.removeClass("chosen-with-drop");
+ this.form_field_jq.trigger("chosen:hiding_dropdown", {
+ chosen: this
+ });
+ }
+ return this.results_showing = false;
+ };
+
+ Chosen.prototype.set_tab_index = function(el) {
+ var ti;
+
+ if (this.form_field.tabIndex) {
+ ti = this.form_field.tabIndex;
+ this.form_field.tabIndex = -1;
+ return this.search_field[0].tabIndex = ti;
+ }
+ };
+
+ Chosen.prototype.set_label_behavior = function() {
+ var _this = this;
+
+ this.form_field_label = this.form_field_jq.parents("label");
+ if (!this.form_field_label.length && this.form_field.id.length) {
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
+ }
+ if (this.form_field_label.length > 0) {
+ return this.form_field_label.bind('click.chosen', function(evt) {
+ if (_this.is_multiple) {
+ return _this.container_mousedown(evt);
+ } else {
+ return _this.activate_field();
+ }
+ });
+ }
+ };
+
+ Chosen.prototype.show_search_field_default = function() {
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
+ this.search_field.val(this.default_text);
+ return this.search_field.addClass("default");
+ } else {
+ this.search_field.val("");
+ return this.search_field.removeClass("default");
+ }
+ };
+
+ Chosen.prototype.search_results_mouseup = function(evt) {
+ var target;
+
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+ if (target.length) {
+ this.result_highlight = target;
+ this.result_select(evt);
+ return this.search_field.focus();
+ }
+ };
+
+ Chosen.prototype.search_results_mouseover = function(evt) {
+ var target;
+
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+ if (target) {
+ return this.result_do_highlight(target);
+ }
+ };
+
+ Chosen.prototype.search_results_mouseout = function(evt) {
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
+ return this.result_clear_highlight();
+ }
+ };
+
+ Chosen.prototype.choice_build = function(item) {
+ var choice, close_link,
+ _this = this;
+
+ choice = $('<li />', {
+ "class": "search-choice"
+ }).html("<span>" + item.html + "</span>");
+ if (item.disabled) {
+ choice.addClass('search-choice-disabled');
+ } else {
+ close_link = $('<a />', {
+ "class": 'search-choice-close',
+ 'data-option-array-index': item.array_index
+ });
+ close_link.bind('click.chosen', function(evt) {
+ return _this.choice_destroy_link_click(evt);
+ });
+ choice.append(close_link);
+ }
+ return this.search_container.before(choice);
+ };
+
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (!this.is_disabled) {
+ return this.choice_destroy($(evt.target));
+ }
+ };
+
+ Chosen.prototype.choice_destroy = function(link) {
+ if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
+ this.show_search_field_default();
+ if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
+ this.results_hide();
+ }
+ link.parents('li').first().remove();
+ return this.search_field_scale();
+ }
+ };
+
+ Chosen.prototype.results_reset = function() {
+ this.form_field.options[0].selected = true;
+ this.selected_option_count = null;
+ this.single_set_selected_text();
+ this.show_search_field_default();
+ this.results_reset_cleanup();
+ this.form_field_jq.trigger("change");
+ if (this.active_field) {
+ return this.results_hide();
+ }
+ };
+
+ Chosen.prototype.results_reset_cleanup = function() {
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.selected_item.find("abbr").remove();
+ };
+
+ Chosen.prototype.result_select = function(evt) {
+ var high, item, selected_index;
+
+ if (this.result_highlight) {
+ high = this.result_highlight;
+ this.result_clear_highlight();
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
+ this.form_field_jq.trigger("chosen:maxselected", {
+ chosen: this
+ });
+ return false;
+ }
+ if (this.is_multiple) {
+ high.removeClass("active-result");
+ } else {
+ if (this.result_single_selected) {
+ this.result_single_selected.removeClass("result-selected");
+ selected_index = this.result_single_selected[0].getAttribute('data-option-array-index');
+ this.results_data[selected_index].selected = false;
+ }
+ this.result_single_selected = high;
+ }
+ high.addClass("result-selected");
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
+ item.selected = true;
+ this.form_field.options[item.options_index].selected = true;
+ this.selected_option_count = null;
+ if (this.is_multiple) {
+ this.choice_build(item);
+ } else {
+ this.single_set_selected_text(item.text);
+ }
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
+ this.results_hide();
+ }
+ this.search_field.val("");
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
+ this.form_field_jq.trigger("change", {
+ 'selected': this.form_field.options[item.options_index].value
+ });
+ }
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.search_field_scale();
+ }
+ };
+
+ Chosen.prototype.single_set_selected_text = function(text) {
+ if (text == null) {
+ text = this.default_text;
+ }
+ if (text === this.default_text) {
+ this.selected_item.addClass("chosen-default");
+ } else {
+ this.single_deselect_control_build();
+ this.selected_item.removeClass("chosen-default");
+ }
+ return this.selected_item.find("span").text(text);
+ };
+
+ Chosen.prototype.result_deselect = function(pos) {
+ var result_data;
+
+ result_data = this.results_data[pos];
+ if (!this.form_field.options[result_data.options_index].disabled) {
+ result_data.selected = false;
+ this.form_field.options[result_data.options_index].selected = false;
+ this.selected_option_count = null;
+ this.result_clear_highlight();
+ if (this.results_showing) {
+ this.winnow_results();
+ }
+ this.form_field_jq.trigger("change", {
+ deselected: this.form_field.options[result_data.options_index].value
+ });
+ this.search_field_scale();
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ Chosen.prototype.single_deselect_control_build = function() {
+ if (!this.allow_single_deselect) {
+ return;
+ }
+ if (!this.selected_item.find("abbr").length) {
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
+ }
+ return this.selected_item.addClass("chosen-single-with-deselect");
+ };
+
+ Chosen.prototype.get_search_text = function() {
+ if (this.search_field.val() === this.default_text) {
+ return "";
+ } else {
+ return $('<div/>').text($.trim(this.search_field.val())).html();
+ }
+ };
+
+ Chosen.prototype.winnow_results_set_highlight = function() {
+ var do_high, selected_results;
+
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
+ if (do_high != null) {
+ return this.result_do_highlight(do_high);
+ }
+ };
+
+ Chosen.prototype.no_results = function(terms) {
+ var no_results_html;
+
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
+ no_results_html.find("span").first().html(terms);
+ return this.search_results.append(no_results_html);
+ };
+
+ Chosen.prototype.no_results_clear = function() {
+ return this.search_results.find(".no-results").remove();
+ };
+
+ Chosen.prototype.keydown_arrow = function() {
+ var next_sib;
+
+ if (this.results_showing && this.result_highlight) {
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
+ if (next_sib) {
+ return this.result_do_highlight(next_sib);
+ }
+ } else {
+ return this.results_show();
+ }
+ };
+
+ Chosen.prototype.keyup_arrow = function() {
+ var prev_sibs;
+
+ if (!this.results_showing && !this.is_multiple) {
+ return this.results_show();
+ } else if (this.result_highlight) {
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
+ if (prev_sibs.length) {
+ return this.result_do_highlight(prev_sibs.first());
+ } else {
+ if (this.choices_count() > 0) {
+ this.results_hide();
+ }
+ return this.result_clear_highlight();
+ }
+ }
+ };
+
+ Chosen.prototype.keydown_backstroke = function() {
+ var next_available_destroy;
+
+ if (this.pending_backstroke) {
+ this.choice_destroy(this.pending_backstroke.find("a").first());
+ return this.clear_backstroke();
+ } else {
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
+ this.pending_backstroke = next_available_destroy;
+ if (this.single_backstroke_delete) {
+ return this.keydown_backstroke();
+ } else {
+ return this.pending_backstroke.addClass("search-choice-focus");
+ }
+ }
+ }
+ };
+
+ Chosen.prototype.clear_backstroke = function() {
+ if (this.pending_backstroke) {
+ this.pending_backstroke.removeClass("search-choice-focus");
+ }
+ return this.pending_backstroke = null;
+ };
+
+ Chosen.prototype.keydown_checker = function(evt) {
+ var stroke, _ref1;
+
+ stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
+ this.search_field_scale();
+ if (stroke !== 8 && this.pending_backstroke) {
+ this.clear_backstroke();
+ }
+ switch (stroke) {
+ case 8:
+ this.backstroke_length = this.search_field.val().length;
+ break;
+ case 9:
+ if (this.results_showing && !this.is_multiple) {
+ this.result_select(evt);
+ }
+ this.mouse_on_container = false;
+ break;
+ case 13:
+ evt.preventDefault();
+ break;
+ case 38:
+ evt.preventDefault();
+ this.keyup_arrow();
+ break;
+ case 40:
+ evt.preventDefault();
+ this.keydown_arrow();
+ break;
+ }
+ };
+
+ Chosen.prototype.search_field_scale = function() {
+ var div, f_width, h, style, style_block, styles, w, _i, _len;
+
+ if (this.is_multiple) {
+ h = 0;
+ w = 0;
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
+ style = styles[_i];
+ style_block += style + ":" + this.search_field.css(style) + ";";
+ }
+ div = $('<div />', {
+ 'style': style_block
+ });
+ div.text(this.search_field.val());
+ $('body').append(div);
+ w = div.width() + 25;
+ div.remove();
+ f_width = this.container.outerWidth();
+ if (w > f_width - 10) {
+ w = f_width - 10;
+ }
+ return this.search_field.css({
+ 'width': w + 'px'
+ });
+ }
+ };
+
+ return Chosen;
+
+ })(AbstractChosen);
+
+}).call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/chosen/index.html b/afb-client/bower_components/tether/examples/chosen/index.html
new file mode 100644
index 0000000..cf5b490
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/chosen/index.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../../css/drop.css" />
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="chosen.css" />
+ </head>
+ <body>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ <br/>
+ Favorite pizza style: <br/>
+ <div class="drop-chosen-target chosen-container chosen-container-single chosen-with-drop" style="width: 350px">
+ <a class="chosen-single chosen-default" tabindex="-1"><span>Choose a style...</span><div><b></b></div></a>
+ </div>
+ <br/>
+ <br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ text<br/>
+ <script src="../resources/js/log.js"></script>
+ <script src="../resources/js/jquery.js"></script>
+ <script src="chosen.js"></script>
+ <script src="../../drop.js"></script>
+ <script>
+ $(function(){
+ var $target, $drop;
+
+ $target = $('.drop-chosen-target').drop({
+ className: 'drop-chosen',
+ attach: 'bottom-left',
+ content: ''
+ });
+
+ $drop = $target.data().drop.$drop;
+
+ $drop.append('<select><option>Plain</option><option>Pepperoni</option><option>Supreme</option></select>');
+
+ $drop.on('openDrop', function(event){
+ $target.addClass('chosen-container-active');
+ }).on('closeDrop', function(event){
+ $target.removeClass('chosen-container-active');
+ });
+
+ $drop.on('openDrop', function(event) {
+ var $select = $drop.find('select');
+
+ if (!$drop.find('.chosen-container').length) {
+ $select
+ .css('width', $target.outerWidth())
+ .chosen({
+ allow_single_deselect: true,
+ disable_search_threshold: 0
+ })
+ ;
+ }
+
+ setTimeout(function(){
+ $drop.find('.chosen-search input').click().focus().keyup();
+ $target.drop('positionDrop');
+ }, 0);
+ });
+ });
+ </script>
+ <style>
+ .drop-chosen-target > a {
+ outline: none;
+ }
+
+ .drop.drop-chosen {
+ background: transparent;
+ }
+
+ .drop.drop-chosen .chosen-container > .chosen-single {
+ display: none;
+ }
+
+ .drop.drop-chosen .chosen-container .chosen-drop {
+ position: static;
+ }
+ </style>
+ </body>
+</html> \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/common/css/style.css b/afb-client/bower_components/tether/examples/common/css/style.css
new file mode 100644
index 0000000..2d82380
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/common/css/style.css
@@ -0,0 +1,48 @@
+body {
+ min-height: 3000px;
+}
+.element {
+ width: 200px;
+ height: 200px;
+ background-color: #fe8;
+ position: absolute;
+ z-index: 6;
+}
+
+.target {
+ width: 300px;
+ height: 50px;
+ margin: 0 35%;
+ background-color: #4e9;
+}
+
+.container {
+ height: 600px;
+ overflow: scroll;
+ width: 600px;
+ border: 20px solid #CCC;
+ margin-top: 100px;
+}
+
+body {
+ padding: 15px;
+}
+
+body > .container {
+ margin: 0 auto;
+}
+
+.pad {
+ height: 400px;
+ width: 100px;
+}
+
+.instructions {
+ width: 100%;
+ text-align: center;
+ font-size: 24px;
+ padding: 15px;
+ background-color: rgba(210, 180, 140, 0.4);
+ margin: -15px -15px 0 -15px;
+}
+
diff --git a/afb-client/bower_components/tether/examples/content-visible/index.html b/afb-client/bower_components/tether/examples/content-visible/index.html
new file mode 100644
index 0000000..94e2176
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/content-visible/index.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ </head>
+ <body>
+
+ <div class="instructions">Scroll the page</div>
+
+ <style>
+ .instructions {
+ width: 100%;
+ text-align: center;
+ font-size: 24px;
+ padding: 15px;
+ background-color: rgba(210, 180, 140, 0.4);
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+ body {
+ min-height: 1200vh;
+ height: 100%;
+ }
+
+ .content-box {
+ width: 600px;
+ border: 10px solid #999;
+ height: 600vh;
+ background-color: #439CCC;
+ margin: 200vh auto;
+ }
+ .element {
+ border: 10px solid #999;
+ background-color: #FFDC00;
+ width: 300px;
+ height: 200px;
+ padding: 0 15px;
+ font-size: 20px;
+ font-weight: bold;
+ }
+ </style>
+
+ <div class="content-box">
+ <div class="element">
+ <p>This is some sort of crazy dialog.</p>
+
+ <p>It's setup to align with the center of the visible part of the blue area.</p>
+ </div>
+ </div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: '.content-box',
+ attachment: 'middle center',
+ targetAttachment: 'middle center',
+ targetModifier: 'visible'
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/dolls/dolls.css b/afb-client/bower_components/tether/examples/dolls/dolls.css
new file mode 100644
index 0000000..931c0de
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/dolls/dolls.css
@@ -0,0 +1,18 @@
+.tether-element, .tether-target {
+ width: 200px;
+ height: 50px;
+ background-color: #4cc;
+ position: absolute;
+}
+body {
+ width: 100%;
+ height: 100%;
+ overflow: scroll;
+}
+.scroll {
+ width: 400%;
+ height: 400%;
+}
+.tether-target:not(.tether-element) {
+ cursor: move;
+}
diff --git a/afb-client/bower_components/tether/examples/dolls/dolls.js b/afb-client/bower_components/tether/examples/dolls/dolls.js
new file mode 100644
index 0000000..5d0b06b
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/dolls/dolls.js
@@ -0,0 +1,83 @@
+var tethers = [];
+
+document.addEventListener('DOMContentLoaded', function(){
+ dragging = null;
+
+ document.body.addEventListener('mouseup', function(){
+ dragging = null;
+ });
+
+ document.body.addEventListener('mousemove', function(e){
+ if (dragging){
+ dragging.style.top = e.clientY + 'px';
+ dragging.style.left = e.clientX + 'px';
+
+ Tether.position()
+ }
+ });
+
+ document.body.addEventListener('mousedown', function(e){
+ if (e.target.getAttribute('data-index'))
+ dragging = e.target;
+ })
+
+ var count = 60;
+ var parent = null;
+ var dir = 'left';
+ var first = null;
+
+ while (count--){
+ var el = document.createElement('div');
+ el.setAttribute('data-index', count);
+ document.querySelector('.scroll').appendChild(el);
+
+ if (!first)
+ first = el;
+
+ if (count % 10 === 0)
+ dir = dir == 'right' ? 'left' : 'right';
+
+ if (parent){
+ tethers.push(new Tether({
+ element: el,
+ target: parent,
+ attachment: 'middle ' + dir,
+ targetOffset: (dir == 'left' ? '10px 10px' : '10px -10px')
+ }));
+
+ }
+
+ parent = el;
+ }
+
+ initAnim(first);
+});
+
+function initAnim(el){
+ var start = performance.now()
+ var last = 0;
+ var lastTop = 0;
+ var tick = function(){
+ var diff = performance.now() - last;
+
+ if (!last || diff > 50){
+ last = performance.now();
+
+ var nextTop = 50 * Math.sin((last - start) / 1000);
+
+ var curTop = parseFloat(el.style.top || 0);
+ var topChange = nextTop - lastTop;
+ lastTop = nextTop;
+
+ var top = curTop + topChange;
+
+ el.style.top = top + 'px';
+
+ Tether.position();
+ }
+
+ requestAnimationFrame(tick);
+ };
+
+ tick();
+}
diff --git a/afb-client/bower_components/tether/examples/dolls/index.html b/afb-client/bower_components/tether/examples/dolls/index.html
new file mode 100644
index 0000000..610fb34
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/dolls/index.html
@@ -0,0 +1,7 @@
+<link rel="stylesheet" href="./dolls.css" />
+<script src="../../tether.js"></script>
+<script src="./dolls.js"></script>
+<body>
+ <div class="scroll">
+ </div>
+</body>
diff --git a/afb-client/bower_components/tether/examples/element-scroll/index.html b/afb-client/bower_components/tether/examples/element-scroll/index.html
new file mode 100644
index 0000000..1eb6f1e
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/element-scroll/index.html
@@ -0,0 +1,499 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ </head>
+ <body>
+
+ <div class="scroll">
+ <p>For a long time after the course of the steamer <em>Sofala</em> had been
+ altered for the land, the low swampy coast had retained its appearance
+ of a mere smudge of darkness beyond a belt of glitter. The sunrays
+ seemed to fall violently upon the calm sea--seemed to shatter themselves
+ upon an adamantine surface into sparkling dust, into a dazzling vapor
+ of light that blinded the eye and wearied the brain with its unsteady
+ brightness.</p>
+
+ <p>Captain Whalley did not look at it. When his Serang, approaching the
+ roomy cane arm-chair which he filled capably, had informed him in a low
+ voice that the course was to be altered, he had risen at once and had
+ remained on his feet, face forward, while the head of his ship swung
+ through a quarter of a circle. He had not uttered a single word, not
+ even the word to steady the helm. It was the Serang, an elderly, alert,
+ little Malay, with a very dark skin, who murmured the order to the
+ helmsman. And then slowly Captain Whalley sat down again in the
+ arm-chair on the bridge and fixed his eyes on the deck between his feet.</p>
+
+ <p>He could not hope to see anything new upon this lane of the sea. He had
+ been on these coasts for the last three years. From Low Cape to Malantan
+ the distance was fifty miles, six hours' steaming for the old ship with
+ the tide, or seven against. Then you steered straight for the land, and
+ by-and-by three palms would appear on the sky, tall and slim, and with
+ their disheveled heads in a bunch, as if in confidential criticism of
+ the dark mangroves. The Sofala would be headed towards the somber
+ strip of the coast, which at a given moment, as the ship closed with
+ it obliquely, would show several clean shining fractures--the brimful
+ estuary of a river. Then on through a brown liquid, three parts water
+ and one part black earth, on and on between the low shores, three parts
+ black earth and one part brackish water, the Sofala would plow her way
+ up-stream, as she had done once every month for these seven years or
+ more, long before he was aware of her existence, long before he had ever
+ thought of having anything to do with her and her invariable voyages.
+ The old ship ought to have known the road better than her men, who had
+ not been kept so long at it without a change; better than the faithful
+ Serang, whom he had brought over from his last ship to keep the
+ captain's watch; better than he himself, who had been her captain for
+ the last three years only. She could always be depended upon to make her
+ courses. Her compasses were never out. She was no trouble at all to
+ take about, as if her great age had given her knowledge, wisdom, and
+ steadiness. She made her landfalls to a degree of the bearing, and
+ almost to a minute of her allowed time. At any moment, as he sat on
+ the bridge without looking up, or lay sleepless in his bed, simply by
+ reckoning the days and the hours he could tell where he was--the precise
+ spot of the beat. He knew it well too, this monotonous huckster's
+ round, up and down the Straits; he knew its order and its sights and its
+ people. Malacca to begin with, in at daylight and out at dusk, to cross
+ over with a rigid phosphorescent wake this highway of the Far East.
+ Darkness and gleams on the water, clear stars on a black sky, perhaps
+ the lights of a home steamer keeping her unswerving course in the
+ middle, or maybe the elusive shadow of a native craft with her mat sails
+ flitting by silently--and the low land on the other side in sight
+ at daylight. At noon the three palms of the next place of call, up a
+ sluggish river. The only white man residing there was a retired young
+ sailor, with whom he had become friendly in the course of many voyages.
+ Sixty miles farther on there was another place of call, a deep bay with
+ only a couple of houses on the beach. And so on, in and out, picking
+ up coastwise cargo here and there, and finishing with a hundred miles'
+ steady steaming through the maze of an archipelago of small islands up
+ to a large native town at the end of the beat. There was a three days'
+ rest for the old ship before he started her again in inverse order,
+ seeing the same shores from another bearing, hearing the same voices
+ in the same places, back again to the Sofala's port of registry on
+ the great highway to the East, where he would take up a berth nearly
+ opposite the big stone pile of the harbor office till it was time to
+ start again on the old round of 1600 miles and thirty days. Not a very
+ enterprising life, this, for Captain Whalley, Henry Whalley, otherwise
+ Dare-devil Harry--Whalley of the Condor, a famous clipper in her day.
+ No. Not a very enterprising life for a man who had served famous firms,
+ who had sailed famous ships (more than one or two of them his own); who
+ had made famous passages, had been the pioneer of new routes and new
+ trades; who had steered across the unsurveyed tracts of the South Seas,
+ and had seen the sun rise on uncharted islands. Fifty years at sea, and
+ forty out in the East ("a pretty thorough apprenticeship," he used
+ to remark smilingly), had made him honorably known to a generation of
+ shipowners and merchants in all the ports from Bombay clear over to
+ where the East merges into the West upon the coast of the two Americas.
+ His fame remained writ, not very large but plain enough, on the
+ Admiralty charts. Was there not somewhere between Australia and China a
+ Whalley Island and a Condor Reef? On that dangerous coral formation the
+ celebrated clipper had hung stranded for three days, her captain and
+ crew throwing her cargo overboard with one hand and with the other, as
+ it were, keeping off her a flotilla of savage war-canoes. At that time
+ neither the island nor the reef had any official existence. Later the
+ officers of her Majesty's steam vessel Fusilier, dispatched to make a
+ survey of the route, recognized in the adoption of these two names the
+ enterprise of the man and the solidity of the ship. Besides, as anyone
+ who cares may see, the "General Directory," vol. ii. p. 410, begins the
+ description of the "Malotu or Whalley Passage" with the words: "This
+ advantageous route, first discovered in 1850 by Captain Whalley in the
+ ship Condor," &amp;c., and ends by recommending it warmly to sailing vessels
+ leaving the China ports for the south in the months from December to
+ April inclusive.</p>
+
+ <p>This was the clearest gain he had out of life. Nothing could rob him
+ of this kind of fame. The piercing of the Isthmus of Suez, like the
+ breaking of a dam, had let in upon the East a flood of new ships, new
+ men, new methods of trade. It had changed the face of the Eastern seas
+ and the very spirit of their life; so that his early experiences meant
+ nothing whatever to the new generation of seamen.</p>
+
+ <p>In those bygone days he had handled many thousands of pounds of his
+ employers' money and of his own; he had attended faithfully, as by law
+ a shipmaster is expected to do, to the conflicting interests of owners,
+ charterers, and underwriters. He had never lost a ship or consented to
+ a shady transaction; and he had lasted well, outlasting in the end the
+ conditions that had gone to the making of his name. He had buried his
+ wife (in the Gulf of Petchili), had married off his daughter to the man
+ of her unlucky choice, and had lost more than an ample competence in the
+ crash of the notorious Travancore and Deccan Banking Corporation, whose
+ downfall had shaken the East like an earthquake. And he was sixty-five
+ years old.</p>
+
+ <p>His age sat lightly enough on him; and of his ruin he was not ashamed.
+ He had not been alone to believe in the stability of the Banking
+ Corporation. Men whose judgment in matters of finance was as expert as
+ his seamanship had commended the prudence of his investments, and had
+ themselves lost much money in the great failure. The only difference
+ between him and them was that he had lost his all. And yet not his all.
+ There had remained to him from his lost fortune a very pretty little
+ bark, Fair Maid, which he had bought to occupy his leisure of a retired
+ sailor--"to play with," as he expressed it himself.</p>
+
+ <p>He had formally declared himself tired of the sea the year preceding his
+ daughter's marriage. But after the young couple had gone to settle in
+ Melbourne he found out that he could not make himself happy on shore. He
+ was too much of a merchant sea-captain for mere yachting to satisfy him.
+ He wanted the illusion of affairs; and his acquisition of the Fair
+ Maid preserved the continuity of his life. He introduced her to his
+ acquaintances in various ports as "my last command." When he grew too
+ old to be trusted with a ship, he would lay her up and go ashore to be
+ buried, leaving directions in his will to have the bark towed out and
+ scuttled decently in deep water on the day of the funeral. His daughter
+ would not grudge him the satisfaction of knowing that no stranger would
+ handle his last command after him. With the fortune he was able to leave
+ her, the value of a 500-ton bark was neither here nor there. All this
+ would be said with a jocular twinkle in his eye: the vigorous old man
+ had too much vitality for the sentimentalism of regret; and a little
+ wistfully withal, because he was at home in life, taking a genuine
+ pleasure in its feelings and its possessions; in the dignity of his
+ reputation and his wealth, in his love for his daughter, and in his
+ satisfaction with the ship--the plaything of his lonely leisure.</p>
+
+ <p>He had the cabin arranged in accordance with his simple ideal of comfort
+ at sea. A big bookcase (he was a great reader) occupied one side of his
+ stateroom; the portrait of his late wife, a flat bituminous oil-painting
+ representing the profile and one long black ringlet of a young woman,
+ faced his bed-place. Three chronometers ticked him to sleep and greeted
+ him on waking with the tiny competition of their beats. He rose at five
+ every day. The officer of the morning watch, drinking his early cup
+ of coffee aft by the wheel, would hear through the wide orifice of the
+ copper ventilators all the splashings, blowings, and splutterings of
+ his captain's toilet. These noises would be followed by a sustained
+ deep murmur of the Lord's Prayer recited in a loud earnest voice. Five
+ minutes afterwards the head and shoulders of Captain Whalley emerged
+ out of the companion-hatchway. Invariably he paused for a while on the
+ stairs, looking all round at the horizon; upwards at the trim of the
+ sails; inhaling deep draughts of the fresh air. Only then he would step
+ out on the poop, acknowledging the hand raised to the peak of the cap
+ with a majestic and benign "Good morning to you." He walked the deck
+ till eight scrupulously. Sometimes, not above twice a year, he had to
+ use a thick cudgel-like stick on account of a stiffness in the hip--a
+ slight touch of rheumatism, he supposed. Otherwise he knew nothing of
+ the ills of the flesh. At the ringing of the breakfast bell he went
+ below to feed his canaries, wind up the chronometers, and take the
+ head of the table. From there he had before his eyes the big carbon
+ photographs of his daughter, her husband, and two fat-legged babies
+ --his grandchildren--set in black frames into the maplewood bulkheads
+ of the cuddy. After breakfast he dusted the glass over these portraits
+ himself with a cloth, and brushed the oil painting of his wife with a
+ plumate kept suspended from a small brass hook by the side of the heavy
+ gold frame. Then with the door of his stateroom shut, he would sit down
+ on the couch under the portrait to read a chapter out of a thick pocket
+ Bible--her Bible. But on some days he only sat there for half an hour
+ with his finger between the leaves and the closed book resting on his
+ knees. Perhaps he had remembered suddenly how fond of boat-sailing she
+ used to be.</p>
+
+ <p>She had been a real shipmate and a true woman too. It was like an
+ article of faith with him that there never had been, and never could be,
+ a brighter, cheerier home anywhere afloat or ashore than his home under
+ the poop-deck of the Condor, with the big main cabin all white and gold,
+ garlanded as if for a perpetual festival with an unfading wreath. She
+ had decorated the center of every panel with a cluster of home flowers.
+ It took her a twelvemonth to go round the cuddy with this labor of love.
+ To him it had remained a marvel of painting, the highest achievement of
+ taste and skill; and as to old Swinburne, his mate, every time he
+ came down to his meals he stood transfixed with admiration before the
+ progress of the work. You could almost smell these roses, he declared,
+ sniffing the faint flavor of turpentine which at that time pervaded the
+ saloon, and (as he confessed afterwards) made him somewhat less hearty
+ than usual in tackling his food. But there was nothing of the sort to
+ interfere with his enjoyment of her singing. "Mrs. Whalley is a regular
+ out-and-out nightingale, sir," he would pronounce with a judicial air
+ after listening profoundly over the skylight to the very end of the
+ piece. In fine weather, in the second dog-watch, the two men could hear
+ her trills and roulades going on to the accompaniment of the piano in
+ the cabin. On the very day they got engaged he had written to London
+ for the instrument; but they had been married for over a year before it
+ reached them, coming out round the Cape. The big case made part of the
+ first direct general cargo landed in Hong-kong harbor--an event that to
+ the men who walked the busy quays of to-day seemed as hazily remote as
+ the dark ages of history. But Captain Whalley could in a half hour of
+ solitude live again all his life, with its romance, its idyl, and its
+ sorrow. He had to close her eyes himself. She went away from under the
+ ensign like a sailor's wife, a sailor herself at heart. He had read
+ the service over her, out of her own prayer-book, without a break in his
+ voice. When he raised his eyes he could see old Swinburne facing him
+ with his cap pressed to his breast, and his rugged, weather-beaten,
+ impassive face streaming with drops of water like a lump of chipped red
+ granite in a shower. It was all very well for that old sea-dog to cry.
+ He had to read on to the end; but after the splash he did not remember
+ much of what happened for the next few days. An elderly sailor of the
+ crew, deft at needlework, put together a mourning frock for the child
+ out of one of her black skirts.</p>
+
+ <p>He was not likely to forget; but you cannot dam up life like a sluggish
+ stream. It will break out and flow over a man's troubles, it will close
+ upon a sorrow like the sea upon a dead body, no matter how much love has
+ gone to the bottom. And the world is not bad. People had been very
+ kind to him; especially Mrs. Gardner, the wife of the senior partner
+ in Gardner, Patteson, &amp; Co., the owners of the Condor. It was she who
+ volunteered to look after the little one, and in due course took her to
+ England (something of a journey in those days, even by the overland
+ mail route) with her own girls to finish her education. It was ten years
+ before he saw her again.</p>
+
+ <p>As a little child she had never been frightened of bad weather; she
+ would beg to be taken up on deck in the bosom of his oilskin coat to
+ watch the big seas hurling themselves upon the Condor. The swirl and
+ crash of the waves seemed to fill her small soul with a breathless
+ delight. "A good boy spoiled," he used to say of her in joke. He had
+ named her Ivy because of the sound of the word, and obscurely fascinated
+ by a vague association of ideas. She had twined herself tightly round
+ his heart, and he intended her to cling close to her father as to a
+ tower of strength; forgetting, while she was little, that in the nature
+ of things she would probably elect to cling to someone else. But
+ he loved life well enough for even that event to give him a certain
+ satisfaction, apart from his more intimate feeling of loss.</p>
+
+ <p>After he had purchased the Fair Maid to occupy his loneliness, he
+ hastened to accept a rather unprofitable freight to Australia simply for
+ the opportunity of seeing his daughter in her own home. What made him
+ dissatisfied there was not to see that she clung now to somebody else,
+ but that the prop she had selected seemed on closer examination "a
+ rather poor stick"--even in the matter of health. He disliked his
+ son-in-law's studied civility perhaps more than his method of
+ handling the sum of money he had given Ivy at her marriage. But of his
+ apprehensions he said nothing. Only on the day of his departure, with
+ the hall-door open already, holding her hands and looking steadily into
+ her eyes, he had said, "You know, my dear, all I have is for you and the
+ chicks. Mind you write to me openly." She had answered him by an almost
+ imperceptible movement of her head. She resembled her mother in
+ the color of her eyes, and in character--and also in this, that she
+ understood him without many words.</p>
+
+ <p>Sure enough she had to write; and some of these letters made Captain
+ Whalley lift his white eye-brows. For the rest he considered he was
+ reaping the true reward of his life by being thus able to produce on
+ demand whatever was needed. He had not enjoyed himself so much in a
+ way since his wife had died. Characteristically enough his son-in-law's
+ punctuality in failure caused him at a distance to feel a sort of
+ kindness towards the man. The fellow was so perpetually being jammed on
+ a lee shore that to charge it all to his reckless navigation would be
+ manifestly unfair. No, no! He knew well what that meant. It was bad
+ luck. His own had been simply marvelous, but he had seen in his life too
+ many good men--seamen and others--go under with the sheer weight of bad
+ luck not to recognize the fatal signs. For all that, he was cogitating
+ on the best way of tying up very strictly every penny he had to leave,
+ when, with a preliminary rumble of rumors (whose first sound reached
+ him in Shanghai as it happened), the shock of the big failure came;
+ and, after passing through the phases of stupor, of incredulity, of
+ indignation, he had to accept the fact that he had nothing to speak of
+ to leave.</p>
+
+ <p>Upon that, as if he had only waited for this catastrophe, the unlucky
+ man, away there in Melbourne, gave up his unprofitable game, and sat
+ down--in an invalid's bath-chair at that too. "He will never walk
+ again," wrote the wife. For the first time in his life Captain Whalley
+ was a bit staggered.</p>
+
+ <p>The Fair Maid had to go to work in bitter earnest now. It was no longer
+ a matter of preserving alive the memory of Dare-devil Harry Whalley in
+ the Eastern Seas, or of keeping an old man in pocket-money and clothes,
+ with, perhaps, a bill for a few hundred first-class cigars thrown in at
+ the end of the year. He would have to buckle-to, and keep her going hard
+ on a scant allowance of gilt for the ginger-bread scrolls at her stem
+ and stern.</p>
+
+ <p>This necessity opened his eyes to the fundamental changes of the world.
+ Of his past only the familiar names remained, here and there, but
+ the things and the men, as he had known them, were gone. The name of
+ Gardner, Patteson, &amp; Co. was still displayed on the walls of warehouses
+ by the waterside, on the brass plates and window-panes in the business
+ quarters of more than one Eastern port, but there was no longer a
+ Gardner or a Patteson in the firm. There was no longer for Captain
+ Whalley an arm-chair and a welcome in the private office, with a bit of
+ business ready to be put in the way of an old friend, for the sake of
+ bygone services. The husbands of the Gardner girls sat behind the desks
+ in that room where, long after he had left the employ, he had kept his
+ right of entrance in the old man's time. Their ships now had yellow
+ funnels with black tops, and a time-table of appointed routes like a
+ confounded service of tramways. The winds of December and June were all
+ one to them; their captains (excellent young men he doubted not) were,
+ to be sure, familiar with Whalley Island, because of late years the
+ Government had established a white fixed light on the north end (with
+ a red danger sector over the Condor Reef), but most of them would have
+ been extremely surprised to hear that a flesh-and-blood Whalley still
+ existed--an old man going about the world trying to pick up a cargo here
+ and there for his little bark.</p>
+
+ <p>And everywhere it was the same. Departed the men who would have nodded
+ appreciatively at the mention of his name, and would have thought
+ themselves bound in honor to do something for Dare-devil Harry Whalley.
+ Departed the opportunities which he would have known how to seize; and
+ gone with them the white-winged flock of clippers that lived in the
+ boisterous uncertain life of the winds, skimming big fortunes out of
+ the foam of the sea. In a world that pared down the profits to an
+ irreducible minimum, in a world that was able to count its disengaged
+ tonnage twice over every day, and in which lean charters were snapped up
+ by cable three months in advance, there were no chances of fortune for
+ an individual wandering haphazard with a little bark--hardly indeed any
+ room to exist.</p>
+
+ <p>He found it more difficult from year to year. He suffered greatly from
+ the smallness of remittances he was able to send his daughter. Meantime
+ he had given up good cigars, and even in the matter of inferior cheroots
+ limited himself to six a day. He never told her of his difficulties, and
+ she never enlarged upon her struggle to live. Their confidence in each
+ other needed no explanations, and their perfect understanding endured
+ without protestations of gratitude or regret. He would have been shocked
+ if she had taken it into her head to thank him in so many words, but
+ he found it perfectly natural that she should tell him she needed two
+ hundred pounds.</p>
+
+ <p>He had come in with the Fair Maid in ballast to look for a freight in
+ the Sofala's port of registry, and her letter met him there. Its tenor
+ was that it was no use mincing matters. Her only resource was in opening
+ a boarding-house, for which the prospects, she judged, were good. Good
+ enough, at any rate, to make her tell him frankly that with two hundred
+ pounds she could make a start. He had torn the envelope open, hastily,
+ on deck, where it was handed to him by the ship-chandler's runner, who
+ had brought his mail at the moment of anchoring. For the second time
+ in his life he was appalled, and remained stock-still at the cabin door
+ with the paper trembling between his fingers. Open a boarding-house! Two
+ hundred pounds for a start! The only resource! And he did not know where
+ to lay his hands on two hundred pence.</p>
+
+ <p>All that night Captain Whalley walked the poop of his anchored ship, as
+ though he had been about to close with the land in thick weather, and
+ uncertain of his position after a run of many gray days without a sight
+ of sun, moon, or stars. The black night twinkled with the guiding lights
+ of seamen and the steady straight lines of lights on shore; and all
+ around the Fair Maid the riding lights of ships cast trembling trails
+ upon the water of the roadstead. Captain Whalley saw not a gleam
+ anywhere till the dawn broke and he found out that his clothing was
+ soaked through with the heavy dew.</p>
+
+ <p>His ship was awake. He stopped short, stroked his wet beard, and
+ descended the poop ladder backwards, with tired feet. At the sight
+ of him the chief officer, lounging about sleepily on the quarterdeck,
+ remained open-mouthed in the middle of a great early-morning yawn.</p>
+
+ <p>"Good morning to you," pronounced Captain Whalley solemnly, passing into
+ the cabin. But he checked himself in the doorway, and without looking
+ back, "By the bye," he said, "there should be an empty wooden case put
+ away in the lazarette. It has not been broken up--has it?"</p>
+
+ <p>The mate shut his mouth, and then asked as if dazed, "What empty case,
+ sir?"</p>
+
+ <p>"A big flat packing-case belonging to that painting in my room. Let it
+ be taken up on deck and tell the carpenter to look it over. I may want
+ to use it before long."</p>
+
+ <p>The chief officer did not stir a limb till he had heard the door of the
+ captain's state-room slam within the cuddy. Then he beckoned aft the
+ second mate with his forefinger to tell him that there was something "in
+ the wind."</p>
+
+ <p>When the bell rang Captain Whalley's authoritative voice boomed out
+ through a closed door, "Sit down and don't wait for me." And his
+ impressed officers took their places, exchanging looks and whispers
+ across the table. What! No breakfast? And after apparently knocking
+ about all night on deck, too! Clearly, there was something in the wind.
+ In the skylight above their heads, bowed earnestly over the plates,
+ three wire cages rocked and rattled to the restless jumping of the
+ hungry canaries; and they could detect the sounds of their "old
+ man's" deliberate movements within his state-room. Captain Whalley was
+ methodically winding up the chronometers, dusting the portrait of
+ his late wife, getting a clean white shirt out of the drawers, making
+ himself ready in his punctilious unhurried manner to go ashore. He could
+ not have swallowed a single mouthful of food that morning. He had made
+ up his mind to sell the Fair Maid.</p>
+ </div>
+
+ <div class="pointer"></div>
+
+ <style>
+ body {
+ cursor: pointer;
+ }
+ .scroll {
+ height: 80vh;
+ width: 80vw;
+ max-height: 600px;
+ position: fixed;
+ top: 5em;
+ left: 10vw;
+
+ overflow-y: scroll;
+ padding: 4em;
+ box-sizing: border-box;
+ line-height: 1.2;
+ }
+ .scroll::-webkit-scrollbar, .scroll::-webkit-scrollbar-track, .scroll::-webkit-scrollbar-thumb {
+ display: none;
+ }
+
+ .pointer {
+ height: 3.6em;
+ width: 77vw;
+ border: 5px solid #CCC;
+ border-radius: 15px;
+ background-color: rgba(0, 0, 0, 0.05);
+ pointer-events: none;
+ }
+ .highlight {
+ background-color: rgba(255, 255, 0, 0.3);
+ }
+ .hover {
+ background-color: rgba(0, 255, 255, 0.2);
+ }
+ </style>
+
+ <script src="../../tether.js"></script>
+ <script>
+ var pointer = document.querySelector('.pointer');
+ var scroll = document.querySelector('.scroll');
+
+ // This creates the pointer tether and links it up
+ // with the scroll handle
+ new Tether({
+ element: pointer,
+ target: scroll,
+ attachment: 'middle right',
+ targetAttachment: 'middle left',
+ targetModifier: 'scroll-handle'
+ });
+
+ // Everything after this is for the highlighting effect
+ var paras = document.querySelectorAll('p');
+ for(var i=paras.length; i--;){
+ var sents = paras[i].innerHTML.split('.');
+ for (var j=sents.length; j--;){
+ if (sents[j].trim().length)
+ sents[j] = '<span>' + sents[j] + '.</span>';
+ }
+ paras[i].innerHTML = sents.join('');
+ }
+
+ var spans = document.querySelectorAll('p span');
+
+ function highlight(){
+ if (!spans) return;
+
+ var bar = pointer.getBoundingClientRect();
+
+ for (var i=spans.length; i--;){
+ var coord = spans[i].getBoundingClientRect();
+
+ if (bar.top < coord.top && bar.bottom > coord.top){
+ spans[i].classList.add('hover');
+ } else if (spans[i].classList.contains('hover')) {
+ spans[i].classList.remove('hover');
+ }
+ }
+
+ requestAnimationFrame(highlight);
+ }
+
+ highlight();
+
+ document.body.addEventListener('click', function(){
+ var els = document.querySelectorAll('.hover');
+ for (var i=els.length; i--;)
+ els[i].classList.toggle('highlight');
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/enable-disable/index.html b/afb-client/bower_components/tether/examples/enable-disable/index.html
new file mode 100644
index 0000000..c962adf
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/enable-disable/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ </head>
+ <body>
+ <div class="instructions">Click the green target to enable/disable the tethering.</div>
+
+ <div class="element"></div>
+ <div class="container">
+ <div class="pad"></div>
+ <div class="target"></div>
+ <div class="pad"></div>
+ </div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ var tether = new Tether({
+ element: '.element',
+ target: '.target',
+ attachment: 'top left',
+ targetAttachment: 'top right'
+ });
+
+ document.querySelector('.target').addEventListener('click', function(){
+ if (tether.enabled)
+ tether.disable();
+ else
+ tether.enable();
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/facebook/facebook.css b/afb-client/bower_components/tether/examples/facebook/facebook.css
new file mode 100644
index 0000000..eae1508
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/facebook/facebook.css
@@ -0,0 +1,86 @@
+.drop-target.drop-open {
+ outline: 2px solid;
+}
+
+.body {
+ position: relative;
+ margin-right: 300px;
+}
+
+.page {
+ max-width: 100%;
+ width: 1080px;
+ padding: 0 10px;
+ box-sizing: border-box;
+ margin: 0 auto;
+}
+
+.navigation {
+ background: blue;
+ color: #fff;
+ margin-right: 300px;
+ margin-bottom: 30px;
+}
+
+.navigation .item a {
+ padding: 30px 20px;
+ display: inline-block;
+}
+
+.navigation .item a {
+ color: inherit;
+}
+
+.navigation .drop-target.drop-open {
+ background: #fff;
+ color: blue;
+ outline: none;
+}
+
+.right-sidebar {
+ position: fixed;
+ height: 50%;
+ width: 300px;
+ background: #eee;
+ overflow: auto;
+ right: 0;
+}
+
+.right-sidebar .drop-target.drop-open {
+ background: blue;
+ color: #fff;
+ outline: none;
+}
+
+.right-sidebar .item a {
+ display: block;
+ padding: 20px;
+ margin-bottom: 10px;
+ background: rgba(0, 0, 0, .1);
+}
+
+.right-sidebar-top {
+ top: 0;
+}
+
+.right-sidebar-bottom {
+ top: 50%;
+ background: #ccc;
+}
+
+.scroll-container {
+ position: relative;
+ overflow: auto;
+ background: #eee;
+ padding: 20px;
+ margin-bottom: 20px;
+ margin-right: 20px;
+ height: 200px;
+ width: 200px;
+}
+
+.absolute-container {
+ position: absolute;
+ top: 20px;
+ right: 300px;
+}
diff --git a/afb-client/bower_components/tether/examples/facebook/index.html b/afb-client/bower_components/tether/examples/facebook/index.html
new file mode 100644
index 0000000..d4bcf8e
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/facebook/index.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../../css/drop.css" />
+ <link rel="stylesheet" href="../../css/drop-theme-default.css" />
+ <link rel="stylesheet" href="../../css/drop-theme-arrows.css" />
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="facebook.css" />
+ </head>
+ <body>
+ <div class="navigation">
+ <div class="page">
+ <span class="item">DROPBOOK</span>
+ <span class="item">
+ <a class="drop-target" data-constrain="false" data-attach="bottom left">DROP</a>
+ </span>
+ <span class="item">
+ <a class="drop-target" data-constrain="false" data-attach="bottom left">DROP</a>
+ </span>
+ <span class="item">
+ <a class="drop-target" data-constrain="false" data-attach="bottom left">DROP</a>
+ </span>
+ </div>
+ </div>
+ <div class="right-sidebar right-sidebar-top">
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="true" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left top">DROP</a>
+ </div>
+ </div>
+ <div class="right-sidebar right-sidebar-bottom">
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="true" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ <div class="item">
+ <a class="drop-target" data-constrain="false" data-class="drop-theme-arrows" data-attach="left bottom">DROP</a>
+ </div>
+ </div>
+ <div class="body">
+ <div class="page">
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor<br/>
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud<br/>
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/><br/>
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor<br/>
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud<br/>
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/><br/>
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor<br/>
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud<br/>
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/><br/>
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor<br/>
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud<br/>
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/><br/>
+
+ <a class="drop-target" data-constrain="true" data-attach="bottom left">DROP</a><br/><br/>
+ <div class="scroll-container">
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ <br/><br/><a class="drop-target" data-constrain="true" data-attach="bottom left">DROP</a><br/><br/> sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/>
+ </div>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/><br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/><br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/><br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/><br/>
+ <div class="scroll-container">
+ <br/>
+ <a class="drop-target" data-constrain="true" data-attach="bottom left">DROP</a><br/>
+ <br/>
+ <div style="width: 150%; background: #ccc; height: 1px"></div>
+ </div>
+ <div class="scroll-container">
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ <br/><br/>
+ <div style="width: 150%; background: #ccc; height: 1px">
+ <div style="margin-left: 100%">
+ <a class="drop-target" data-constrain="true" data-attach="bottom left">DROP</a>
+ </div>
+ </div>
+ <br/><br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/>
+ </div>
+ <div class="scroll-container absolute-container">
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, <br/><br/><a class="drop-target" data-constrain="false" data-attach="left top">DROP</a><br/><br/> sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br/>
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br/>
+ </div>
+ </div>
+ </div>
+
+ <script src="../resources/js/log.js"></script>
+ <script src="../resources/js/jquery.js"></script>
+ <script src="../../utils.js"></script>
+ <script src="../../tether.js"></script>
+ <script src="../../drop.js"></script>
+ <script src="../../constraint.js"></script>
+ <style>
+ .drop .drop-content {
+ min-height: 100px;
+ min-width: 100px;
+ }
+ </style>
+ <script>
+ $('.drop-target').each(function(){
+ new Drop({
+ target: this,
+ className: $(this).data().class || 'drop-theme-default',
+ attach: $(this).data().attach,
+ constrainToScrollParent: $(this).data().constrain,
+ openOn: 'click'
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/out-of-bounds/index.html b/afb-client/bower_components/tether/examples/out-of-bounds/index.html
new file mode 100644
index 0000000..f8aa6ab
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/out-of-bounds/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ <style>
+ .tether-element.tether-out-of-bounds {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions">Resize the screen to see the tethered element disappear when it can't fit.</div>
+
+ <div class="element"></div>
+ <div class="target"></div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: '.target',
+ attachment: 'top left',
+ targetAttachment: 'top right',
+ constraints: [{
+ to: 'window',
+ attachment: 'together'
+ }]
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/pin/index.html b/afb-client/bower_components/tether/examples/pin/index.html
new file mode 100644
index 0000000..9ed4a88
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/pin/index.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ </head>
+ <body>
+ <div class="instructions">Resize the screen to see the tethered element stick to the edges of the screen when it's resized.</div>
+
+ <div class="element"></div>
+ <div class="target"></div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: '.target',
+ attachment: 'top left',
+ targetAttachment: 'top right',
+ constraints: [{
+ to: 'window',
+ pin: true
+ }]
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/resources/css/base.css b/afb-client/bower_components/tether/examples/resources/css/base.css
new file mode 100644
index 0000000..8006e9d
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/resources/css/base.css
@@ -0,0 +1,10 @@
+body {
+ font-family: "Helvetica Neue", sans-serif;
+ color: #444;
+ margin: 0px;
+}
+
+a {
+ cursor: pointer;
+ color: blue;
+} \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/resources/js/jquery.js b/afb-client/bower_components/tether/examples/resources/js/jquery.js
new file mode 100644
index 0000000..11be4b4
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/resources/js/jquery.js
@@ -0,0 +1,9597 @@
+/*!
+ * jQuery JavaScript Library v1.9.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-2-4
+ */
+(function( window, undefined ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//"use strict";
+var
+ // The deferred used on DOM ready
+ readyList,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // Support: IE<9
+ // For `typeof node.method` instead of `node.method !== undefined`
+ core_strundefined = typeof undefined,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+ location = window.location,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // [[Class]] -> type pairs
+ class2type = {},
+
+ // List of deleted data cache ids, so we can reuse them
+ core_deletedIds = [],
+
+ core_version = "1.9.1",
+
+ // Save a reference to some core methods
+ core_concat = core_deletedIds.concat,
+ core_push = core_deletedIds.push,
+ core_slice = core_deletedIds.slice,
+ core_indexOf = core_deletedIds.indexOf,
+ core_toString = class2type.toString,
+ core_hasOwn = class2type.hasOwnProperty,
+ core_trim = core_version.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
+
+ // Used for splitting on whitespace
+ core_rnotwhite = /\S+/g,
+
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ },
+
+ // The ready event handler
+ completed = function( event ) {
+
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+ },
+ // Clean-up method for dom ready events
+ detach = function() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: core_version,
+
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return String( obj );
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ core_toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !core_hasOwn.call(obj, "constructor") &&
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || core_hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+ if ( scripts ) {
+ jQuery( scripts ).remove();
+ }
+ return jQuery.merge( [], parsed.childNodes );
+ },
+
+ parseJSON: function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ if ( data === null ) {
+ return data;
+ }
+
+ if ( typeof data === "string" ) {
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ if ( data ) {
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+ }
+ }
+ }
+
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+ function( text ) {
+ return text == null ?
+ "" :
+ core_trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ core_push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( core_indexOf ) {
+ return core_indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return core_concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ }
+});
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || type !== "function" &&
+ ( length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( list && ( !fired || stack ) ) {
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+jQuery.support = (function() {
+
+ var support, all, a,
+ input, select, fragment,
+ opt, eventName, isSupported, i,
+ div = document.createElement("div");
+
+ // Setup
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+ // Support tests won't run in some limited or non-browser environments
+ all = div.getElementsByTagName("*");
+ a = div.getElementsByTagName("a")[ 0 ];
+ if ( !all || !a || !all.length ) {
+ return {};
+ }
+
+ // First batch of tests
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px;float:left;opacity:.5";
+ support = {
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.5/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ checkOn: !!input.value,
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Tests for enctype support on a form (#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+ boxModel: document.compatMode === "CSS1Compat",
+
+ // Will be defined later
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ boxSizingReliable: true,
+ pixelPosition: false
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<9
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ // Check if we can trust getAttribute("value")
+ input = document.createElement("input");
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "checked", "t" );
+ input.setAttribute( "name", "t" );
+
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( input );
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
+ for ( i in { submit: true, change: true, focusin: true }) {
+ div.setAttribute( eventName = "on" + i, "t" );
+
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
+ }
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, marginDiv, tds,
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName("td");
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Support: IE8
+ // Check if empty table cells still have offsetWidth/Height
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check box-sizing and margin behavior
+ div.innerHTML = "";
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+ support.boxSizing = ( div.offsetWidth === 4 );
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = div.appendChild( document.createElement("div") );
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ if ( typeof div.style.zoom !== core_strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.innerHTML = "";
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ div.style.display = "block";
+ div.innerHTML = "<div></div>";
+ div.firstChild.style.width = "5px";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+ if ( support.inlineBlockNeedsLayout ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+
+ // Null elements to avoid leaks in IE
+ container = div = tds = marginDiv = null;
+ });
+
+ // Null elements to avoid leaks in IE
+ all = select = fragment = opt = a = input = null;
+
+ return support;
+})();
+
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ){
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var i, l, thisCache,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ // Do not set data on non-element because it will not be cleared (#8335).
+ if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
+ return false;
+ }
+
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ // nodes accept data unless otherwise specified; rejection can be conditional
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var attrs, name,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attrs = elem.attributes;
+ for ( ; i < attrs.length; i++ ) {
+ name = attrs[i].name;
+
+ if ( !name.indexOf( "data-" ) ) {
+ name = jQuery.camelCase( name.slice(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ // Try to fetch any internally stored data first
+ return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
+ }
+
+ this.each(function() {
+ jQuery.data( this, key, value );
+ });
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ hooks.cur = fn;
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var nodeHook, boolHook,
+ rclass = /[\t\r\n]/g,
+ rreturn = /\r/g,
+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i,
+ rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ getSetInput = jQuery.support.input;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
+
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( cur ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.match( core_rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ // Toggle whole class name
+ } else if ( type === core_strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var ret, hooks, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val,
+ self = jQuery(this);
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attr: function( elem, name, value ) {
+ var hooks, notxml, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === core_strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ // In IE9+, Flash objects don't have .getAttribute (#12945)
+ // Support: IE9+
+ if ( typeof elem.getAttribute !== core_strundefined ) {
+ ret = elem.getAttribute( name );
+ }
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( core_rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( rboolean.test( name ) ) {
+ // Set corresponding property to false for boolean attributes
+ // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
+ if ( !getSetAttribute && ruseDefault.test( name ) ) {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ } else {
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ var
+ // Use .prop to determine if this attribute is understood as boolean
+ prop = jQuery.prop( elem, name ),
+
+ // Fetch it accordingly
+ attr = typeof prop === "boolean" && elem.getAttribute( name ),
+ detail = typeof prop === "boolean" ?
+
+ getSetInput && getSetAttribute ?
+ attr != null :
+ // oldIE fabricates an empty string for missing boolean attributes
+ // and conflates checked/selected into attroperties
+ ruseDefault.test( name ) ?
+ elem[ jQuery.camelCase( "default-" + name ) ] :
+ !!attr :
+
+ // fetch an attribute node for properties not recognized as boolean
+ elem.getAttributeNode( name );
+
+ return detail && detail.value !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+};
+
+// fix oldIE value attroperty
+if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return jQuery.nodeName( elem, "input" ) ?
+
+ // Ignore the value *property* by using defaultValue
+ elem.defaultValue :
+
+ ret && ret.specified ? ret.value : undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
+ ret.value :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ return name === "value" || value === elem.getAttribute( name ) ?
+ value :
+ undefined;
+ }
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+}
+
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret == null ? undefined : ret;
+ }
+ });
+ });
+
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ event.isTrigger = true;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = core_slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ }
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== document.activeElement && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === document.activeElement && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Even when returnValue equals to undefined Firefox will still show alert
+ if ( event.result !== undefined ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === core_strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function( window, undefined ) {
+
+var i,
+ cachedruns,
+ Expr,
+ getText,
+ isXML,
+ compile,
+ hasDuplicate,
+ outermostContext,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsXML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+ sortOrder,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ support = {},
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Array methods
+ arr = [],
+ pop = arr.pop,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments quoted,
+ // then not containing pseudos/brackets,
+ // then attribute selectors/non-parenthetical expressions,
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
+
+ rnative = /^[^{]+\{\s*\[native code/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rescape = /'|\\/g,
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
+ funescape = function( _, escaped ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ return high !== high ?
+ escaped :
+ // BMP codepoint
+ high < 0 ?
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Use a stripped-down slice if we can't use a native one
+try {
+ slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
+} catch ( e ) {
+ slice = function( i ) {
+ var elem,
+ results = [];
+ while ( (elem = this[i++]) ) {
+ results.push( elem );
+ }
+ return results;
+ };
+}
+
+/**
+ * For feature detection
+ * @param {Function} fn The function to test for native support
+ */
+function isNative( fn ) {
+ return rnative.test( fn + "" );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var cache,
+ keys = [];
+
+ return (cache = function( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key ] = value);
+ });
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // release memory in IE
+ div = null;
+ }
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !documentIsXML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
+ old = true;
+ nid = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results, slice.call( newContext.querySelectorAll(
+ newSelector
+ ), 0 ) );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Detect xml
+ * @param {Element|Object} elem An element or a document
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsXML = isXML( doc );
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.tagNameNoComments = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if attributes should be retrieved by attribute nodes
+ support.attributes = assert(function( div ) {
+ div.innerHTML = "<select></select>";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getByClassName = assert(function( div ) {
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+ return false;
+ }
+
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ });
+
+ // Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ support.getByName = assert(function( div ) {
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
+ docElem.insertBefore( div, docElem.firstChild );
+
+ // Test
+ var pass = doc.getElementsByName &&
+ // buggy browsers will return fewer than the correct 2
+ doc.getElementsByName( expando ).length === 2 +
+ // buggy browsers will return more than the correct 0
+ doc.getElementsByName( expando + 0 ).length;
+ support.getIdNotName = !doc.getElementById( expando );
+
+ // Cleanup
+ docElem.removeChild( div );
+
+ return pass;
+ });
+
+ // IE6/7 return modified attributes
+ Expr.attrHandle = assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+ div.firstChild.getAttribute("href") === "#";
+ }) ?
+ {} :
+ {
+ "href": function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ },
+ "type": function( elem ) {
+ return elem.getAttribute("type");
+ }
+ };
+
+ // ID find and filter
+ if ( support.getIdNotName ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+
+ return m ?
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.tagNameNoComments ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Name
+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
+ if ( typeof context.getElementsByName !== strundefined ) {
+ return context.getElementsByName( name );
+ }
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21),
+ // no need to also add to buggyMatches since matches checks buggyQSA
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [ ":focus" ];
+
+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select><option selected=''></option></select>";
+
+ // IE8 - Some boolean attributes are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Opera 10-12/IE8 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = "<input type='hidden' i=''/>";
+ if ( div.querySelectorAll("[i^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.webkitMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // Document order sorting
+ sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var compare;
+
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
+ if ( a === doc || contains( preferredDoc, a ) ) {
+ return -1;
+ }
+ if ( b === doc || contains( preferredDoc, b ) ) {
+ return 1;
+ }
+ return 0;
+ }
+ return compare & 4 ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition ? -1 : 1;
+ } :
+ function( a, b ) {
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Parentless nodes are either documents or disconnected
+ } else if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ // Always assume the presence of duplicates if sort doesn't
+ // pass them to our comparison function (as in Google Chrome).
+ hasDuplicate = false;
+ [0, 0].sort( sortOrder );
+ support.detectDuplicates = hasDuplicate;
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ // rbuggyQSA always contains :focus, so no need for an existence check
+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [elem] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ var val;
+
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ if ( !documentIsXML ) {
+ name = name.toLowerCase();
+ }
+ if ( (val = Expr.attrHandle[ name ]) ) {
+ return val( elem );
+ }
+ if ( documentIsXML || support.attributes ) {
+ return elem.getAttribute( name );
+ }
+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
+ name :
+ val && val.specified ? val.value : null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+// Document sorting and removing duplicates
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ i = 1,
+ j = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem === results[ i - 1 ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ return results;
+};
+
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+// Returns a function to use in pseudos for input types
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for buttons
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for positionals
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[5] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[4] ) {
+ match[2] = match[4];
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeName ) {
+ if ( nodeName === "*" ) {
+ return function() { return true; };
+ }
+
+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifider
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsXML ?
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
+ elem.lang) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ type: type,
+ matches: match
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+}
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var data, cache, outerCache,
+ dirkey = dirruns + " " + doneName;
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
+ if ( (data = cache[1]) === true || data === cachedruns ) {
+ return data === true;
+ }
+ } else {
+ cache = outerCache[ dir ] = [ dirkey ];
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
+ if ( cache[1] === true ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ // A counter to specify which element is currently being matched
+ var matcherCachedRuns = 0,
+ bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = matcherCachedRuns;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++matcherCachedRuns;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+};
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function select( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector );
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && !documentIsXML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
+ if ( !context ) {
+ return results;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, slice.call( seed, 0 ) );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ documentIsXML,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+}
+
+// Deprecated
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Easy API for creating new setFilters
+function setFilters() {}
+Expr.filters = setFilters.prototype = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+// Initialize with the default document
+setDocument();
+
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i, ret, self,
+ len = this.length;
+
+ if ( typeof selector !== "string" ) {
+ self = this;
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ ret = [];
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, this[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
+ return ret;
+ },
+
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false) );
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true) );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ rneedsContext.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ ret = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( jQuery.unique(all) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ area: [ 1, "<map>", "</map>" ],
+ param: [ 1, "<object>", "</object>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ var isFunc = jQuery.isFunction( value );
+
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( !isFunc && typeof value !== "string" ) {
+ value = jQuery( value ).not( this ).detach();
+ }
+
+ return this.domManip( [ value ], true, function( elem ) {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ if ( parent ) {
+ jQuery( this ).remove();
+ parent.insertBefore( elem, next );
+ }
+ });
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+
+ // Flatten any nested arrays
+ args = core_concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, table ? self.html() : undefined );
+ }
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call(
+ table && jQuery.nodeName( this[i], "table" ) ?
+ findOrAppend( this[i], "tbody" ) :
+ this[i],
+ node,
+ i
+ );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Hope ajax is available...
+ jQuery.ajax({
+ url: node.src,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+});
+
+function findOrAppend( elem, tag ) {
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ var attr = elem.getAttributeNode("type");
+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ core_push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !jQuery.support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = jQuery.support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ core_deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+var iframe, getStyles, curCSS,
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+ rposition = /^(top|right|bottom|left)$/,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
+ elemdisplay = { BODY: "block" },
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function isHidden( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+
+ if ( !values[ index ] ) {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ var len, styles,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ var bool = typeof state === "boolean";
+
+ return this.each(function() {
+ if ( bool ? state : isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+// NOTE: we've included the "window" in window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ return window.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var width, minWidth, maxWidth,
+ computed = _computed || getStyles( elem ),
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
+ style = elem.style;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+ };
+} else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var left, rs, rsLeft,
+ computed = _computed || getStyles( elem ),
+ ret = computed ? computed[ name ] : undefined,
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+ // Use the already-created iframe if possible
+ iframe = ( iframe ||
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
+ .css( "cssText", "display:block !important" )
+ ).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
+ doc.write("<!doctype html><html><body>");
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+// Called ONLY from within css_defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+ display = jQuery.css( elem[0], "display" );
+ elem.remove();
+ return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ };
+ });
+ }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.hover = function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+};
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+ ajax_nonce = jQuery.now(),
+
+ ajax_rquery = /\?/,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType[0] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 ) {
+ isSuccess = true;
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ isSuccess = true;
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ isSuccess = ajaxConvert( s, response );
+ statusText = isSuccess.state;
+ success = isSuccess.data;
+ error = isSuccess.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ }
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+ var conv2, current, conv, tmp,
+ converters = {},
+ i = 0,
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice(),
+ prev = dataTypes[ 0 ];
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ // Convert to each sequential dataType, tolerating list modification
+ for ( ; (current = dataTypes[++i]); ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current !== "*" ) {
+
+ // Convert response if prev dataType is non-auto and differs from current
+ if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split(" ");
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.splice( i--, 0, current );
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s["throws"] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+
+ // Update prev for next iteration
+ prev = current;
+ }
+ }
+
+ return { state: "success", data: response };
+}
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+var xhrCallbacks, xhrSupported,
+ xhrId = 0,
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
+ // Abort all pending requests
+ var key;
+ for ( key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ };
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+xhrSupported = jQuery.ajaxSettings.xhr();
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = jQuery.support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var handle, i,
+ xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( err ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, responseHeaders, statusText, responses;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occurred
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ if ( !s.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var end, unit,
+ tween = this.createTween( prop, value ),
+ parts = rfxnum.exec( value ),
+ target = tween.cur(),
+ start = +target || 0,
+ scale = 1,
+ maxIterations = 20;
+
+ if ( parts ) {
+ end = +parts[2];
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" && start ) {
+ // Iteratively approximate from a nonzero starting point
+ // Prefer the current property, because this process will be trivial if it uses the same units
+ // Fallback to end or a simple constant
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ tween.unit = unit;
+ tween.start = start;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+ }
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+function createTweens( animation, props ) {
+ jQuery.each( props, function( prop, value ) {
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( collection[ index ].call( animation, prop, value ) ) {
+
+ // we're done with this property
+ return;
+ }
+ }
+ });
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ createTweens( animation, props );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+ var value, name, index, easing, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+ /*jshint validthis:true */
+ var prop, index, length,
+ value, dataShow, toggle,
+ tween, hooks, oldfire,
+ anim = this,
+ style = elem.style,
+ orig = {},
+ handled = [],
+ hidden = elem.nodeType && isHidden( elem );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !jQuery.support.shrinkWrapBlocks ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+
+ // show/hide pass
+ for ( index in props ) {
+ value = props[ index ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ index ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+ continue;
+ }
+ handled.push( index );
+ }
+ }
+
+ length = handled.length;
+ if ( length ) {
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( index = 0 ; index < length ; index++ ) {
+ prop = handled[ index ];
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+ doAnimation.finish = function() {
+ anim.stop( true );
+ };
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.cur && hooks.cur.finish ) {
+ hooks.cur.finish.call( this );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+};
+
+jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.documentElement;
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || document.documentElement;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// })();
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+})( window ); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/resources/js/log.js b/afb-client/bower_components/tether/examples/resources/js/log.js
new file mode 100644
index 0000000..6acd4fd
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/resources/js/log.js
@@ -0,0 +1,134 @@
+(function() {
+ var ffSupport, formats, getOrderedMatches, hasMatches, isFF, isIE, isOpera, isSafari, log, makeArray, operaSupport, safariSupport, stringToArgs, _log;
+ if (!(window.console && window.console.log)) {
+ return;
+ }
+ log = function() {
+ var args;
+ args = [];
+ makeArray(arguments).forEach(function(arg) {
+ if (typeof arg === 'string') {
+ return args = args.concat(stringToArgs(arg));
+ } else {
+ return args.push(arg);
+ }
+ });
+ return _log.apply(window, args);
+ };
+ _log = function() {
+ return console.log.apply(console, makeArray(arguments));
+ };
+ makeArray = function(arrayLikeThing) {
+ return Array.prototype.slice.call(arrayLikeThing);
+ };
+ formats = [
+ {
+ regex: /\*([^\*]+)\*/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['font-style: italic', ''];
+ }
+ }, {
+ regex: /\_([^\_]+)\_/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['font-weight: bold', ''];
+ }
+ }, {
+ regex: /\`([^\`]+)\`/,
+ replacer: function(m, p1) {
+ return "%c" + p1 + "%c";
+ },
+ styles: function() {
+ return ['background: rgb(255, 255, 219); padding: 1px 5px; border: 1px solid rgba(0, 0, 0, 0.1)', ''];
+ }
+ }, {
+ regex: /\[c\=(?:\"|\')?((?:(?!(?:\"|\')\]).)*)(?:\"|\')?\]((?:(?!\[c\]).)*)\[c\]/,
+ replacer: function(m, p1, p2) {
+ return "%c" + p2 + "%c";
+ },
+ styles: function(match) {
+ return [match[1], ''];
+ }
+ }
+ ];
+ hasMatches = function(str) {
+ var _hasMatches;
+ _hasMatches = false;
+ formats.forEach(function(format) {
+ if (format.regex.test(str)) {
+ return _hasMatches = true;
+ }
+ });
+ return _hasMatches;
+ };
+ getOrderedMatches = function(str) {
+ var matches;
+ matches = [];
+ formats.forEach(function(format) {
+ var match;
+ match = str.match(format.regex);
+ if (match) {
+ return matches.push({
+ format: format,
+ match: match
+ });
+ }
+ });
+ return matches.sort(function(a, b) {
+ return a.match.index - b.match.index;
+ });
+ };
+ stringToArgs = function(str) {
+ var firstMatch, matches, styles;
+ styles = [];
+ while (hasMatches(str)) {
+ matches = getOrderedMatches(str);
+ firstMatch = matches[0];
+ str = str.replace(firstMatch.format.regex, firstMatch.format.replacer);
+ styles = styles.concat(firstMatch.format.styles(firstMatch.match));
+ }
+ return [str].concat(styles);
+ };
+ isSafari = function() {
+ return /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
+ };
+ isOpera = function() {
+ return /OPR/.test(navigator.userAgent) && /Opera/.test(navigator.vendor);
+ };
+ isFF = function() {
+ return /Firefox/.test(navigator.userAgent);
+ };
+ isIE = function() {
+ return /MSIE/.test(navigator.userAgent);
+ };
+ safariSupport = function() {
+ var m;
+ m = navigator.userAgent.match(/AppleWebKit\/(\d+)\.(\d+)(\.|\+|\s)/);
+ if (!m) {
+ return false;
+ }
+ return 537.38 <= parseInt(m[1], 10) + (parseInt(m[2], 10) / 100);
+ };
+ operaSupport = function() {
+ var m;
+ m = navigator.userAgent.match(/OPR\/(\d+)\./);
+ if (!m) {
+ return false;
+ }
+ return 15 <= parseInt(m[1], 10);
+ };
+ ffSupport = function() {
+ return window.console.firebug || window.console.exception;
+ };
+ if (isIE() || (isFF() && !ffSupport()) || (isOpera() && !operaSupport()) || (isSafari() && !safariSupport())) {
+ window.log = _log;
+ } else {
+ window.log = log;
+ }
+ window.log.l = _log;
+}).call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/examples/scroll/index.html b/afb-client/bower_components/tether/examples/scroll/index.html
new file mode 100644
index 0000000..40b0a61
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/scroll/index.html
@@ -0,0 +1,922 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ </head>
+ <body>
+
+ <div class="instructions">Scroll the page</div>
+
+ <h2>THE END OF THE TETHER</h2>
+
+ <p>By Joseph Conrad</p>
+
+ <h3>Chapter I</h3>
+
+ <p>For a long time after the course of the steamer <em>Sofala</em> had been
+ altered for the land, the low swampy coast had retained its appearance
+ of a mere smudge of darkness beyond a belt of glitter. The sunrays
+ seemed to fall violently upon the calm sea--seemed to shatter themselves
+ upon an adamantine surface into sparkling dust, into a dazzling vapor
+ of light that blinded the eye and wearied the brain with its unsteady
+ brightness.</p>
+
+ <p>Captain Whalley did not look at it. When his Serang, approaching the
+ roomy cane arm-chair which he filled capably, had informed him in a low
+ voice that the course was to be altered, he had risen at once and had
+ remained on his feet, face forward, while the head of his ship swung
+ through a quarter of a circle. He had not uttered a single word, not
+ even the word to steady the helm. It was the Serang, an elderly, alert,
+ little Malay, with a very dark skin, who murmured the order to the
+ helmsman. And then slowly Captain Whalley sat down again in the
+ arm-chair on the bridge and fixed his eyes on the deck between his feet.</p>
+
+ <p>He could not hope to see anything new upon this lane of the sea. He had
+ been on these coasts for the last three years. From Low Cape to Malantan
+ the distance was fifty miles, six hours' steaming for the old ship with
+ the tide, or seven against. Then you steered straight for the land, and
+ by-and-by three palms would appear on the sky, tall and slim, and with
+ their disheveled heads in a bunch, as if in confidential criticism of
+ the dark mangroves. The Sofala would be headed towards the somber
+ strip of the coast, which at a given moment, as the ship closed with
+ it obliquely, would show several clean shining fractures--the brimful
+ estuary of a river. Then on through a brown liquid, three parts water
+ and one part black earth, on and on between the low shores, three parts
+ black earth and one part brackish water, the Sofala would plow her way
+ up-stream, as she had done once every month for these seven years or
+ more, long before he was aware of her existence, long before he had ever
+ thought of having anything to do with her and her invariable voyages.
+ The old ship ought to have known the road better than her men, who had
+ not been kept so long at it without a change; better than the faithful
+ Serang, whom he had brought over from his last ship to keep the
+ captain's watch; better than he himself, who had been her captain for
+ the last three years only. She could always be depended upon to make her
+ courses. Her compasses were never out. She was no trouble at all to
+ take about, as if her great age had given her knowledge, wisdom, and
+ steadiness. She made her landfalls to a degree of the bearing, and
+ almost to a minute of her allowed time. At any moment, as he sat on
+ the bridge without looking up, or lay sleepless in his bed, simply by
+ reckoning the days and the hours he could tell where he was--the precise
+ spot of the beat. He knew it well too, this monotonous huckster's
+ round, up and down the Straits; he knew its order and its sights and its
+ people. Malacca to begin with, in at daylight and out at dusk, to cross
+ over with a rigid phosphorescent wake this highway of the Far East.
+ Darkness and gleams on the water, clear stars on a black sky, perhaps
+ the lights of a home steamer keeping her unswerving course in the
+ middle, or maybe the elusive shadow of a native craft with her mat sails
+ flitting by silently--and the low land on the other side in sight
+ at daylight. At noon the three palms of the next place of call, up a
+ sluggish river. The only white man residing there was a retired young
+ sailor, with whom he had become friendly in the course of many voyages.
+ Sixty miles farther on there was another place of call, a deep bay with
+ only a couple of houses on the beach. And so on, in and out, picking
+ up coastwise cargo here and there, and finishing with a hundred miles'
+ steady steaming through the maze of an archipelago of small islands up
+ to a large native town at the end of the beat. There was a three days'
+ rest for the old ship before he started her again in inverse order,
+ seeing the same shores from another bearing, hearing the same voices
+ in the same places, back again to the Sofala's port of registry on
+ the great highway to the East, where he would take up a berth nearly
+ opposite the big stone pile of the harbor office till it was time to
+ start again on the old round of 1600 miles and thirty days. Not a very
+ enterprising life, this, for Captain Whalley, Henry Whalley, otherwise
+ Dare-devil Harry--Whalley of the Condor, a famous clipper in her day.
+ No. Not a very enterprising life for a man who had served famous firms,
+ who had sailed famous ships (more than one or two of them his own); who
+ had made famous passages, had been the pioneer of new routes and new
+ trades; who had steered across the unsurveyed tracts of the South Seas,
+ and had seen the sun rise on uncharted islands. Fifty years at sea, and
+ forty out in the East ("a pretty thorough apprenticeship," he used
+ to remark smilingly), had made him honorably known to a generation of
+ shipowners and merchants in all the ports from Bombay clear over to
+ where the East merges into the West upon the coast of the two Americas.
+ His fame remained writ, not very large but plain enough, on the
+ Admiralty charts. Was there not somewhere between Australia and China a
+ Whalley Island and a Condor Reef? On that dangerous coral formation the
+ celebrated clipper had hung stranded for three days, her captain and
+ crew throwing her cargo overboard with one hand and with the other, as
+ it were, keeping off her a flotilla of savage war-canoes. At that time
+ neither the island nor the reef had any official existence. Later the
+ officers of her Majesty's steam vessel Fusilier, dispatched to make a
+ survey of the route, recognized in the adoption of these two names the
+ enterprise of the man and the solidity of the ship. Besides, as anyone
+ who cares may see, the "General Directory," vol. ii. p. 410, begins the
+ description of the "Malotu or Whalley Passage" with the words: "This
+ advantageous route, first discovered in 1850 by Captain Whalley in the
+ ship Condor," &amp;c., and ends by recommending it warmly to sailing vessels
+ leaving the China ports for the south in the months from December to
+ April inclusive.</p>
+
+ <p>This was the clearest gain he had out of life. Nothing could rob him
+ of this kind of fame. The piercing of the Isthmus of Suez, like the
+ breaking of a dam, had let in upon the East a flood of new ships, new
+ men, new methods of trade. It had changed the face of the Eastern seas
+ and the very spirit of their life; so that his early experiences meant
+ nothing whatever to the new generation of seamen.</p>
+
+ <p>In those bygone days he had handled many thousands of pounds of his
+ employers' money and of his own; he had attended faithfully, as by law
+ a shipmaster is expected to do, to the conflicting interests of owners,
+ charterers, and underwriters. He had never lost a ship or consented to
+ a shady transaction; and he had lasted well, outlasting in the end the
+ conditions that had gone to the making of his name. He had buried his
+ wife (in the Gulf of Petchili), had married off his daughter to the man
+ of her unlucky choice, and had lost more than an ample competence in the
+ crash of the notorious Travancore and Deccan Banking Corporation, whose
+ downfall had shaken the East like an earthquake. And he was sixty-five
+ years old.</p>
+
+ <h3>Chapter II</h3>
+
+ <p>His age sat lightly enough on him; and of his ruin he was not ashamed.
+ He had not been alone to believe in the stability of the Banking
+ Corporation. Men whose judgment in matters of finance was as expert as
+ his seamanship had commended the prudence of his investments, and had
+ themselves lost much money in the great failure. The only difference
+ between him and them was that he had lost his all. And yet not his all.
+ There had remained to him from his lost fortune a very pretty little
+ bark, Fair Maid, which he had bought to occupy his leisure of a retired
+ sailor--"to play with," as he expressed it himself.</p>
+
+ <p>He had formally declared himself tired of the sea the year preceding his
+ daughter's marriage. But after the young couple had gone to settle in
+ Melbourne he found out that he could not make himself happy on shore. He
+ was too much of a merchant sea-captain for mere yachting to satisfy him.
+ He wanted the illusion of affairs; and his acquisition of the Fair
+ Maid preserved the continuity of his life. He introduced her to his
+ acquaintances in various ports as "my last command." When he grew too
+ old to be trusted with a ship, he would lay her up and go ashore to be
+ buried, leaving directions in his will to have the bark towed out and
+ scuttled decently in deep water on the day of the funeral. His daughter
+ would not grudge him the satisfaction of knowing that no stranger would
+ handle his last command after him. With the fortune he was able to leave
+ her, the value of a 500-ton bark was neither here nor there. All this
+ would be said with a jocular twinkle in his eye: the vigorous old man
+ had too much vitality for the sentimentalism of regret; and a little
+ wistfully withal, because he was at home in life, taking a genuine
+ pleasure in its feelings and its possessions; in the dignity of his
+ reputation and his wealth, in his love for his daughter, and in his
+ satisfaction with the ship--the plaything of his lonely leisure.</p>
+
+ <p>He had the cabin arranged in accordance with his simple ideal of comfort
+ at sea. A big bookcase (he was a great reader) occupied one side of his
+ stateroom; the portrait of his late wife, a flat bituminous oil-painting
+ representing the profile and one long black ringlet of a young woman,
+ faced his bed-place. Three chronometers ticked him to sleep and greeted
+ him on waking with the tiny competition of their beats. He rose at five
+ every day. The officer of the morning watch, drinking his early cup
+ of coffee aft by the wheel, would hear through the wide orifice of the
+ copper ventilators all the splashings, blowings, and splutterings of
+ his captain's toilet. These noises would be followed by a sustained
+ deep murmur of the Lord's Prayer recited in a loud earnest voice. Five
+ minutes afterwards the head and shoulders of Captain Whalley emerged
+ out of the companion-hatchway. Invariably he paused for a while on the
+ stairs, looking all round at the horizon; upwards at the trim of the
+ sails; inhaling deep draughts of the fresh air. Only then he would step
+ out on the poop, acknowledging the hand raised to the peak of the cap
+ with a majestic and benign "Good morning to you." He walked the deck
+ till eight scrupulously. Sometimes, not above twice a year, he had to
+ use a thick cudgel-like stick on account of a stiffness in the hip--a
+ slight touch of rheumatism, he supposed. Otherwise he knew nothing of
+ the ills of the flesh. At the ringing of the breakfast bell he went
+ below to feed his canaries, wind up the chronometers, and take the
+ head of the table. From there he had before his eyes the big carbon
+ photographs of his daughter, her husband, and two fat-legged babies
+ --his grandchildren--set in black frames into the maplewood bulkheads
+ of the cuddy. After breakfast he dusted the glass over these portraits
+ himself with a cloth, and brushed the oil painting of his wife with a
+ plumate kept suspended from a small brass hook by the side of the heavy
+ gold frame. Then with the door of his stateroom shut, he would sit down
+ on the couch under the portrait to read a chapter out of a thick pocket
+ Bible--her Bible. But on some days he only sat there for half an hour
+ with his finger between the leaves and the closed book resting on his
+ knees. Perhaps he had remembered suddenly how fond of boat-sailing she
+ used to be.</p>
+
+ <p>She had been a real shipmate and a true woman too. It was like an
+ article of faith with him that there never had been, and never could be,
+ a brighter, cheerier home anywhere afloat or ashore than his home under
+ the poop-deck of the Condor, with the big main cabin all white and gold,
+ garlanded as if for a perpetual festival with an unfading wreath. She
+ had decorated the center of every panel with a cluster of home flowers.
+ It took her a twelvemonth to go round the cuddy with this labor of love.
+ To him it had remained a marvel of painting, the highest achievement of
+ taste and skill; and as to old Swinburne, his mate, every time he
+ came down to his meals he stood transfixed with admiration before the
+ progress of the work. You could almost smell these roses, he declared,
+ sniffing the faint flavor of turpentine which at that time pervaded the
+ saloon, and (as he confessed afterwards) made him somewhat less hearty
+ than usual in tackling his food. But there was nothing of the sort to
+ interfere with his enjoyment of her singing. "Mrs. Whalley is a regular
+ out-and-out nightingale, sir," he would pronounce with a judicial air
+ after listening profoundly over the skylight to the very end of the
+ piece. In fine weather, in the second dog-watch, the two men could hear
+ her trills and roulades going on to the accompaniment of the piano in
+ the cabin. On the very day they got engaged he had written to London
+ for the instrument; but they had been married for over a year before it
+ reached them, coming out round the Cape. The big case made part of the
+ first direct general cargo landed in Hong-kong harbor--an event that to
+ the men who walked the busy quays of to-day seemed as hazily remote as
+ the dark ages of history. But Captain Whalley could in a half hour of
+ solitude live again all his life, with its romance, its idyl, and its
+ sorrow. He had to close her eyes himself. She went away from under the
+ ensign like a sailor's wife, a sailor herself at heart. He had read
+ the service over her, out of her own prayer-book, without a break in his
+ voice. When he raised his eyes he could see old Swinburne facing him
+ with his cap pressed to his breast, and his rugged, weather-beaten,
+ impassive face streaming with drops of water like a lump of chipped red
+ granite in a shower. It was all very well for that old sea-dog to cry.
+ He had to read on to the end; but after the splash he did not remember
+ much of what happened for the next few days. An elderly sailor of the
+ crew, deft at needlework, put together a mourning frock for the child
+ out of one of her black skirts.</p>
+
+ <p>He was not likely to forget; but you cannot dam up life like a sluggish
+ stream. It will break out and flow over a man's troubles, it will close
+ upon a sorrow like the sea upon a dead body, no matter how much love has
+ gone to the bottom. And the world is not bad. People had been very
+ kind to him; especially Mrs. Gardner, the wife of the senior partner
+ in Gardner, Patteson, &amp; Co., the owners of the Condor. It was she who
+ volunteered to look after the little one, and in due course took her to
+ England (something of a journey in those days, even by the overland
+ mail route) with her own girls to finish her education. It was ten years
+ before he saw her again.</p>
+
+ <p>As a little child she had never been frightened of bad weather; she
+ would beg to be taken up on deck in the bosom of his oilskin coat to
+ watch the big seas hurling themselves upon the Condor. The swirl and
+ crash of the waves seemed to fill her small soul with a breathless
+ delight. "A good boy spoiled," he used to say of her in joke. He had
+ named her Ivy because of the sound of the word, and obscurely fascinated
+ by a vague association of ideas. She had twined herself tightly round
+ his heart, and he intended her to cling close to her father as to a
+ tower of strength; forgetting, while she was little, that in the nature
+ of things she would probably elect to cling to someone else. But
+ he loved life well enough for even that event to give him a certain
+ satisfaction, apart from his more intimate feeling of loss.</p>
+
+ <p>After he had purchased the Fair Maid to occupy his loneliness, he
+ hastened to accept a rather unprofitable freight to Australia simply for
+ the opportunity of seeing his daughter in her own home. What made him
+ dissatisfied there was not to see that she clung now to somebody else,
+ but that the prop she had selected seemed on closer examination "a
+ rather poor stick"--even in the matter of health. He disliked his
+ son-in-law's studied civility perhaps more than his method of
+ handling the sum of money he had given Ivy at her marriage. But of his
+ apprehensions he said nothing. Only on the day of his departure, with
+ the hall-door open already, holding her hands and looking steadily into
+ her eyes, he had said, "You know, my dear, all I have is for you and the
+ chicks. Mind you write to me openly." She had answered him by an almost
+ imperceptible movement of her head. She resembled her mother in
+ the color of her eyes, and in character--and also in this, that she
+ understood him without many words.</p>
+
+ <p>Sure enough she had to write; and some of these letters made Captain
+ Whalley lift his white eye-brows. For the rest he considered he was
+ reaping the true reward of his life by being thus able to produce on
+ demand whatever was needed. He had not enjoyed himself so much in a
+ way since his wife had died. Characteristically enough his son-in-law's
+ punctuality in failure caused him at a distance to feel a sort of
+ kindness towards the man. The fellow was so perpetually being jammed on
+ a lee shore that to charge it all to his reckless navigation would be
+ manifestly unfair. No, no! He knew well what that meant. It was bad
+ luck. His own had been simply marvelous, but he had seen in his life too
+ many good men--seamen and others--go under with the sheer weight of bad
+ luck not to recognize the fatal signs. For all that, he was cogitating
+ on the best way of tying up very strictly every penny he had to leave,
+ when, with a preliminary rumble of rumors (whose first sound reached
+ him in Shanghai as it happened), the shock of the big failure came;
+ and, after passing through the phases of stupor, of incredulity, of
+ indignation, he had to accept the fact that he had nothing to speak of
+ to leave.</p>
+
+ <p>Upon that, as if he had only waited for this catastrophe, the unlucky
+ man, away there in Melbourne, gave up his unprofitable game, and sat
+ down--in an invalid's bath-chair at that too. "He will never walk
+ again," wrote the wife. For the first time in his life Captain Whalley
+ was a bit staggered.</p>
+
+ <p>The Fair Maid had to go to work in bitter earnest now. It was no longer
+ a matter of preserving alive the memory of Dare-devil Harry Whalley in
+ the Eastern Seas, or of keeping an old man in pocket-money and clothes,
+ with, perhaps, a bill for a few hundred first-class cigars thrown in at
+ the end of the year. He would have to buckle-to, and keep her going hard
+ on a scant allowance of gilt for the ginger-bread scrolls at her stem
+ and stern.</p>
+
+ <p>This necessity opened his eyes to the fundamental changes of the world.
+ Of his past only the familiar names remained, here and there, but
+ the things and the men, as he had known them, were gone. The name of
+ Gardner, Patteson, &amp; Co. was still displayed on the walls of warehouses
+ by the waterside, on the brass plates and window-panes in the business
+ quarters of more than one Eastern port, but there was no longer a
+ Gardner or a Patteson in the firm. There was no longer for Captain
+ Whalley an arm-chair and a welcome in the private office, with a bit of
+ business ready to be put in the way of an old friend, for the sake of
+ bygone services. The husbands of the Gardner girls sat behind the desks
+ in that room where, long after he had left the employ, he had kept his
+ right of entrance in the old man's time. Their ships now had yellow
+ funnels with black tops, and a time-table of appointed routes like a
+ confounded service of tramways. The winds of December and June were all
+ one to them; their captains (excellent young men he doubted not) were,
+ to be sure, familiar with Whalley Island, because of late years the
+ Government had established a white fixed light on the north end (with
+ a red danger sector over the Condor Reef), but most of them would have
+ been extremely surprised to hear that a flesh-and-blood Whalley still
+ existed--an old man going about the world trying to pick up a cargo here
+ and there for his little bark.</p>
+
+ <p>And everywhere it was the same. Departed the men who would have nodded
+ appreciatively at the mention of his name, and would have thought
+ themselves bound in honor to do something for Dare-devil Harry Whalley.
+ Departed the opportunities which he would have known how to seize; and
+ gone with them the white-winged flock of clippers that lived in the
+ boisterous uncertain life of the winds, skimming big fortunes out of
+ the foam of the sea. In a world that pared down the profits to an
+ irreducible minimum, in a world that was able to count its disengaged
+ tonnage twice over every day, and in which lean charters were snapped up
+ by cable three months in advance, there were no chances of fortune for
+ an individual wandering haphazard with a little bark--hardly indeed any
+ room to exist.</p>
+
+ <p>He found it more difficult from year to year. He suffered greatly from
+ the smallness of remittances he was able to send his daughter. Meantime
+ he had given up good cigars, and even in the matter of inferior cheroots
+ limited himself to six a day. He never told her of his difficulties, and
+ she never enlarged upon her struggle to live. Their confidence in each
+ other needed no explanations, and their perfect understanding endured
+ without protestations of gratitude or regret. He would have been shocked
+ if she had taken it into her head to thank him in so many words, but
+ he found it perfectly natural that she should tell him she needed two
+ hundred pounds.</p>
+
+ <p>He had come in with the Fair Maid in ballast to look for a freight in
+ the Sofala's port of registry, and her letter met him there. Its tenor
+ was that it was no use mincing matters. Her only resource was in opening
+ a boarding-house, for which the prospects, she judged, were good. Good
+ enough, at any rate, to make her tell him frankly that with two hundred
+ pounds she could make a start. He had torn the envelope open, hastily,
+ on deck, where it was handed to him by the ship-chandler's runner, who
+ had brought his mail at the moment of anchoring. For the second time
+ in his life he was appalled, and remained stock-still at the cabin door
+ with the paper trembling between his fingers. Open a boarding-house! Two
+ hundred pounds for a start! The only resource! And he did not know where
+ to lay his hands on two hundred pence.</p>
+
+ <p>All that night Captain Whalley walked the poop of his anchored ship, as
+ though he had been about to close with the land in thick weather, and
+ uncertain of his position after a run of many gray days without a sight
+ of sun, moon, or stars. The black night twinkled with the guiding lights
+ of seamen and the steady straight lines of lights on shore; and all
+ around the Fair Maid the riding lights of ships cast trembling trails
+ upon the water of the roadstead. Captain Whalley saw not a gleam
+ anywhere till the dawn broke and he found out that his clothing was
+ soaked through with the heavy dew.</p>
+
+ <p>His ship was awake. He stopped short, stroked his wet beard, and
+ descended the poop ladder backwards, with tired feet. At the sight
+ of him the chief officer, lounging about sleepily on the quarterdeck,
+ remained open-mouthed in the middle of a great early-morning yawn.</p>
+
+ <p>"Good morning to you," pronounced Captain Whalley solemnly, passing into
+ the cabin. But he checked himself in the doorway, and without looking
+ back, "By the bye," he said, "there should be an empty wooden case put
+ away in the lazarette. It has not been broken up--has it?"</p>
+
+ <p>The mate shut his mouth, and then asked as if dazed, "What empty case,
+ sir?"</p>
+
+ <p>"A big flat packing-case belonging to that painting in my room. Let it
+ be taken up on deck and tell the carpenter to look it over. I may want
+ to use it before long."</p>
+
+ <p>The chief officer did not stir a limb till he had heard the door of the
+ captain's state-room slam within the cuddy. Then he beckoned aft the
+ second mate with his forefinger to tell him that there was something "in
+ the wind."</p>
+
+ <p>When the bell rang Captain Whalley's authoritative voice boomed out
+ through a closed door, "Sit down and don't wait for me." And his
+ impressed officers took their places, exchanging looks and whispers
+ across the table. What! No breakfast? And after apparently knocking
+ about all night on deck, too! Clearly, there was something in the wind.
+ In the skylight above their heads, bowed earnestly over the plates,
+ three wire cages rocked and rattled to the restless jumping of the
+ hungry canaries; and they could detect the sounds of their "old
+ man's" deliberate movements within his state-room. Captain Whalley was
+ methodically winding up the chronometers, dusting the portrait of
+ his late wife, getting a clean white shirt out of the drawers, making
+ himself ready in his punctilious unhurried manner to go ashore. He could
+ not have swallowed a single mouthful of food that morning. He had made
+ up his mind to sell the Fair Maid.</p>
+
+ <h3>Chapter III</h3>
+
+ <p>Just at that time the Japanese were casting far and wide for ships
+ of European build, and he had no difficulty in finding a purchaser, a
+ speculator who drove a hard bargain, but paid cash down for the Fair
+ Maid, with a view to a profitable resale. Thus it came about that
+ Captain Whalley found himself on a certain afternoon descending the
+ steps of one of the most important post-offices of the East with a slip
+ of bluish paper in his hand. This was the receipt of a registered letter
+ enclosing a draft for two hundred pounds, and addressed to Melbourne.
+ Captain Whalley pushed the paper into his waistcoat-pocket, took his
+ stick from under his arm, and walked down the street.</p>
+
+ <p>It was a recently opened and untidy thoroughfare with rudimentary
+ side-walks and a soft layer of dust cushioning the whole width of
+ the road. One end touched the slummy street of Chinese shops near the
+ harbor, the other drove straight on, without houses, for a couple of
+ miles, through patches of jungle-like vegetation, to the yard gates
+ of the new Consolidated Docks Company. The crude frontages of the new
+ Government buildings alternated with the blank fencing of vacant plots,
+ and the view of the sky seemed to give an added spaciousness to the
+ broad vista. It was empty and shunned by natives after business
+ hours, as though they had expected to see one of the tigers from the
+ neighborhood of the New Waterworks on the hill coming at a loping canter
+ down the middle to get a Chinese shopkeeper for supper. Captain Whalley
+ was not dwarfed by the solitude of the grandly planned street. He
+ had too fine a presence for that. He was only a lonely figure walking
+ purposefully, with a great white beard like a pilgrim, and with a thick
+ stick that resembled a weapon. On one side the new Courts of Justice had
+ a low and unadorned portico of squat columns half concealed by a few old
+ trees left in the approach. On the other the pavilion wings of the
+ new Colonial Treasury came out to the line of the street. But Captain
+ Whalley, who had now no ship and no home, remembered in passing that
+ on that very site when he first came out from England there had stood a
+ fishing village, a few mat huts erected on piles between a muddy tidal
+ creek and a miry pathway that went writhing into a tangled wilderness
+ without any docks or waterworks.</p>
+
+ <p>No ship--no home. And his poor Ivy away there had no home either. A
+ boarding-house is no sort of home though it may get you a living. His
+ feelings were horribly rasped by the idea of the boarding-house. In his
+ rank of life he had that truly aristocratic temperament characterized by
+ a scorn of vulgar gentility and by prejudiced views as to the derogatory
+ nature of certain occupations. For his own part he had always preferred
+ sailing merchant ships (which is a straightforward occupation) to buying
+ and selling merchandise, of which the essence is to get the better of
+ somebody in a bargain--an undignified trial of wits at best. His father
+ had been Colonel Whalley (retired) of the H. E. I. Company's service,
+ with very slender means besides his pension, but with distinguished
+ connections. He could remember as a boy how frequently waiters at the
+ inns, country tradesmen and small people of that sort, used to "My lord"
+ the old warrior on the strength of his appearance.</p>
+
+ <p>Captain Whalley himself (he would have entered the Navy if his father
+ had not died before he was fourteen) had something of a grand air which
+ would have suited an old and glorious admiral; but he became lost like
+ a straw in the eddy of a brook amongst the swarm of brown and yellow
+ humanity filling a thoroughfare, that by contrast with the vast and
+ empty avenue he had left seemed as narrow as a lane and absolutely
+ riotous with life. The walls of the houses were blue; the shops of the
+ Chinamen yawned like cavernous lairs; heaps of nondescript merchandise
+ overflowed the gloom of the long range of arcades, and the fiery
+ serenity of sunset took the middle of the street from end to end with a
+ glow like the reflection of a fire. It fell on the bright colors and the
+ dark faces of the bare-footed crowd, on the pallid yellow backs of the
+ half-naked jostling coolies, on the accouterments of a tall Sikh trooper
+ with a parted beard and fierce mustaches on sentry before the gate of
+ the police compound. Looming very big above the heads in a red haze of
+ dust, the tightly packed car of the cable tramway navigated cautiously
+ up the human stream, with the incessant blare of its horn, in the manner
+ of a steamer groping in a fog.</p>
+
+ <p>Captain Whalley emerged like a diver on the other side, and in the
+ desert shade between the walls of closed warehouses removed his hat to
+ cool his brow. A certain disrepute attached to the calling of a
+ landlady of a boarding-house. These women were said to be rapacious,
+ unscrupulous, untruthful; and though he contemned no class of his
+ fellow-creatures--God forbid!--these were suspicions to which it was
+ unseemly that a Whalley should lay herself open. He had not expostulated
+ with her, however. He was confident she shared his feelings; he was
+ sorry for her; he trusted her judgment; he considered it a merciful
+ dispensation that he could help her once more,--but in his aristocratic
+ heart of hearts he would have found it more easy to reconcile himself to
+ the idea of her turning seamstress. Vaguely he remembered reading years
+ ago a touching piece called the "Song of the Shirt." It was all very
+ well making songs about poor women. The granddaughter of Colonel
+ Whalley, the landlady of a boarding-house! Pooh! He replaced his hat,
+ dived into two pockets, and stopping a moment to apply a flaring match
+ to the end of a cheap cheroot, blew an embittered cloud of smoke at a
+ world that could hold such surprises.</p>
+
+ <p>Of one thing he was certain--that she was the own child of a clever
+ mother. Now he had got over the wrench of parting with his ship, he
+ perceived clearly that such a step had been unavoidable. Perhaps he had
+ been growing aware of it all along with an unconfessed knowledge. But
+ she, far away there, must have had an intuitive perception of it, with
+ the pluck to face that truth and the courage to speak out--all the
+ qualities which had made her mother a woman of such excellent counsel.</p>
+
+ <p>It would have had to come to that in the end! It was fortunate she had
+ forced his hand. In another year or two it would have been an utterly
+ barren sale. To keep the ship going he had been involving himself deeper
+ every year. He was defenseless before the insidious work of adversity,
+ to whose more open assaults he could present a firm front; like a
+ cliff that stands unmoved the open battering of the sea, with a lofty
+ ignorance of the treacherous backwash undermining its base. As it was,
+ every liability satisfied, her request answered, and owing no man a
+ penny, there remained to him from the proceeds a sum of five hundred
+ pounds put away safely. In addition he had upon his person some forty
+ odd dollars--enough to pay his hotel bill, providing he did not linger
+ too long in the modest bedroom where he had taken refuge.</p>
+
+ <p>Scantily furnished, and with a waxed floor, it opened into one of
+ the side-verandas. The straggling building of bricks, as airy as a
+ bird-cage, resounded with the incessant flapping of rattan screens
+ worried by the wind between the white-washed square pillars of the
+ sea-front. The rooms were lofty, a ripple of sunshine flowed over the
+ ceilings; and the periodical invasions of tourists from some passenger
+ steamer in the harbor flitted through the wind-swept dusk of the
+ apartments with the tumult of their unfamiliar voices and impermanent
+ presences, like relays of migratory shades condemned to speed headlong
+ round the earth without leaving a trace. The babble of their irruptions
+ ebbed out as suddenly as it had arisen; the draughty corridors and
+ the long chairs of the verandas knew their sight-seeing hurry or
+ their prostrate repose no more; and Captain Whalley, substantial and
+ dignified, left well-nigh alone in the vast hotel by each light-hearted
+ skurry, felt more and more like a stranded tourist with no aim in view,
+ like a forlorn traveler without a home. In the solitude of his room he
+ smoked thoughtfully, gazing at the two sea-chests which held all that he
+ could call his own in this world. A thick roll of charts in a sheath
+ of sailcloth leaned in a corner; the flat packing-case containing the
+ portrait in oils and the three carbon photographs had been pushed under
+ the bed. He was tired of discussing terms, of assisting at surveys, of
+ all the routine of the business. What to the other parties was merely
+ the sale of a ship was to him a momentous event involving a radically
+ new view of existence. He knew that after this ship there would be no
+ other; and the hopes of his youth, the exercise of his abilities, every
+ feeling and achievement of his manhood, had been indissolubly connected
+ with ships. He had served ships; he had owned ships; and even the years
+ of his actual retirement from the sea had been made bearable by the idea
+ that he had only to stretch out his hand full of money to get a ship. He
+ had been at liberty to feel as though he were the owner of all the
+ ships in the world. The selling of this one was weary work; but when
+ she passed from him at last, when he signed the last receipt, it was as
+ though all the ships had gone out of the world together, leaving him on
+ the shore of inaccessible oceans with seven hundred pounds in his hands.</p>
+
+ <p>Striding firmly, without haste, along the quay, Captain Whalley averted
+ his glances from the familiar roadstead. Two generations of seamen born
+ since his first day at sea stood between him and all these ships at the
+ anchorage. His own was sold, and he had been asking himself, What next?</p>
+
+ <p>From the feeling of loneliness, of inward emptiness,--and of loss
+ too, as if his very soul had been taken out of him forcibly,--there had
+ sprung at first a desire to start right off and join his daughter.
+ "Here are the last pence," he would say to her; "take them, my dear. And
+ here's your old father: you must take him too."</p>
+
+ <p>His soul recoiled, as if afraid of what lay hidden at the bottom of
+ this impulse. Give up! Never! When one is thoroughly weary all sorts of
+ nonsense come into one's head. A pretty gift it would have been for a
+ poor woman--this seven hundred pounds with the incumbrance of a hale old
+ fellow more than likely to last for years and years to come. Was he not
+ as fit to die in harness as any of the youngsters in charge of these
+ anchored ships out yonder? He was as solid now as ever he had been. But
+ as to who would give him work to do, that was another matter. Were he,
+ with his appearance and antecedents, to go about looking for a junior's
+ berth, people, he was afraid, would not take him seriously; or else if
+ he succeeded in impressing them, he would maybe obtain their pity, which
+ would be like stripping yourself naked to be kicked. He was not anxious
+ to give himself away for less than nothing. He had no use for anybody's
+ pity. On the other hand, a command--the only thing he could try for with
+ due regard for common decency--was not likely to be lying in wait
+ for him at the corner of the next street. Commands don't go a-begging
+ nowadays. Ever since he had come ashore to carry out the business of
+ the sale he had kept his ears open, but had heard no hint of one being
+ vacant in the port. And even if there had been one, his successful past
+ itself stood in his way. He had been his own employer too long. The only
+ credential he could produce was the testimony of his whole life. What
+ better recommendation could anyone require? But vaguely he felt that
+ the unique document would be looked upon as an archaic curiosity of the
+ Eastern waters, a screed traced in obsolete words--in a half-forgotten
+ language.</p>
+
+ <h3>Chapter IV</h3>
+
+ <p>Revolving these thoughts, he strolled on near the railings of the quay,
+ broad-chested, without a stoop, as though his big shoulders had never
+ felt the burden of the loads that must be carried between the cradle
+ and the grave. No single betraying fold or line of care disfigured the
+ reposeful modeling of his face. It was full and untanned; and the upper
+ part emerged, massively quiet, out of the downward flow of silvery hair,
+ with the striking delicacy of its clear complexion and the powerful
+ width of the forehead. The first cast of his glance fell on you candid
+ and swift, like a boy's; but because of the ragged snowy thatch of the
+ eyebrows the affability of his attention acquired the character of a
+ dark and searching scrutiny. With age he had put on flesh a little, had
+ increased his girth like an old tree presenting no symptoms of decay;
+ and even the opulent, lustrous ripple of white hairs upon his chest
+ seemed an attribute of unquenchable vitality and vigor.</p>
+
+ <p>Once rather proud of his great bodily strength, and even of his personal
+ appearance, conscious of his worth, and firm in his rectitude, there had
+ remained to him, like the heritage of departed prosperity, the tranquil
+ bearing of a man who had proved himself fit in every sort of way for the
+ life of his choice. He strode on squarely under the projecting brim of
+ an ancient Panama hat. It had a low crown, a crease through its whole
+ diameter, a narrow black ribbon. Imperishable and a little discolored,
+ this headgear made it easy to pick him out from afar on thronged wharves
+ and in the busy streets. He had never adopted the comparatively modern
+ fashion of pipeclayed cork helmets. He disliked the form; and he hoped
+ he could manage to keep a cool head to the end of his life without all
+ these contrivances for hygienic ventilation. His hair was cropped close,
+ his linen always of immaculate whiteness; a suit of thin gray flannel,
+ worn threadbare but scrupulously brushed, floated about his burly limbs,
+ adding to his bulk by the looseness of its cut. The years had mellowed
+ the good-humored, imperturbable audacity of his prime into a temper
+ carelessly serene; and the leisurely tapping of his iron-shod stick
+ accompanied his footfalls with a self-confident sound on the flagstones.
+ It was impossible to connect such a fine presence and this unruffled
+ aspect with the belittling troubles of poverty; the man's whole
+ existence appeared to pass before you, facile and large, in the freedom
+ of means as ample as the clothing of his body.</p>
+
+ <p>The irrational dread of having to break into his five hundred pounds for
+ personal expenses in the hotel disturbed the steady poise of his mind.
+ There was no time to lose. The bill was running up. He nourished the
+ hope that this five hundred would perhaps be the means, if everything
+ else failed, of obtaining some work which, keeping his body and soul
+ together (not a matter of great outlay), would enable him to be of use
+ to his daughter. To his mind it was her own money which he employed, as
+ it were, in backing her father and solely for her benefit. Once at work,
+ he would help her with the greater part of his earnings; he was good for
+ many years yet, and this boarding-house business, he argued to himself,
+ whatever the prospects, could not be much of a gold-mine from the first
+ start. But what work? He was ready to lay hold of anything in an honest
+ way so that it came quickly to his hand; because the five hundred pounds
+ must be preserved intact for eventual use. That was the great point.
+ With the entire five hundred one felt a substance at one's back; but
+ it seemed to him that should he let it dwindle to four-fifty or even
+ four-eighty, all the efficiency would be gone out of the money, as though
+ there were some magic power in the round figure. But what sort of work?</p>
+
+ <p>Confronted by that haunting question as by an uneasy ghost, for whom he
+ had no exorcising formula, Captain Whalley stopped short on the apex
+ of a small bridge spanning steeply the bed of a canalized creek with
+ granite shores. Moored between the square blocks a seagoing Malay prau
+ floated half hidden under the arch of masonry, with her spars lowered
+ down, without a sound of life on board, and covered from stem to stern
+ with a ridge of palm-leaf mats. He had left behind him the overheated
+ pavements bordered by the stone frontages that, like the sheer face of
+ cliffs, followed the sweep of the quays; and an unconfined spaciousness
+ of orderly and sylvan aspect opened before him its wide plots of rolled
+ grass, like pieces of green carpet smoothly pegged out, its long ranges
+ of trees lined up in colossal porticos of dark shafts roofed with a
+ vault of branches.</p>
+
+ <p>Some of these avenues ended at the sea. It was a terraced shore; and
+ beyond, upon the level expanse, profound and glistening like the gaze
+ of a dark-blue eye, an oblique band of stippled purple lengthened itself
+ indefinitely through the gap between a couple of verdant twin islets.
+ The masts and spars of a few ships far away, hull down in the outer
+ roads, sprang straight from the water in a fine maze of rosy lines
+ penciled on the clear shadow of the eastern board. Captain Whalley gave
+ them a long glance. The ship, once his own, was anchored out there. It
+ was staggering to think that it was open to him no longer to take a boat
+ at the jetty and get himself pulled off to her when the evening came. To
+ no ship. Perhaps never more. Before the sale was concluded, and till the
+ purchase-money had been paid, he had spent daily some time on board the
+ Fair Maid. The money had been paid this very morning, and now, all at
+ once, there was positively no ship that he could go on board of when he
+ liked; no ship that would need his presence in order to do her work--to
+ live. It seemed an incredible state of affairs, something too bizarre
+ to last. And the sea was full of craft of all sorts. There was that prau
+ lying so still swathed in her shroud of sewn palm-leaves--she too had
+ her indispensable man. They lived through each other, this Malay he had
+ never seen, and this high-sterned thing of no size that seemed to be
+ resting after a long journey. And of all the ships in sight, near and
+ far, each was provided with a man, the man without whom the finest ship
+ is a dead thing, a floating and purposeless log.</p>
+
+ <p>After his one glance at the roadstead he went on, since there was
+ nothing to turn back for, and the time must be got through somehow. The
+ avenues of big trees ran straight over the Esplanade, cutting each other
+ at diverse angles, columnar below and luxuriant above. The interlaced
+ boughs high up there seemed to slumber; not a leaf stirred overhead:
+ and the reedy cast-iron lampposts in the middle of the road, gilt like
+ scepters, diminished in a long perspective, with their globes of white
+ porcelain atop, resembling a barbarous decoration of ostriches' eggs
+ displayed in a row. The flaming sky kindled a tiny crimson spark upon
+ the glistening surface of each glassy shell.</p>
+
+ <p>With his chin sunk a little, his hands behind his back, and the end of
+ his stick marking the gravel with a faint wavering line at his heels,
+ Captain Whalley reflected that if a ship without a man was like a body
+ without a soul, a sailor without a ship was of not much more account
+ in this world than an aimless log adrift upon the sea. The log might be
+ sound enough by itself, tough of fiber, and hard to destroy--but what of
+ that! And a sudden sense of irremediable idleness weighted his feet like
+ a great fatigue.</p>
+
+ <p>A succession of open carriages came bowling along the newly opened
+ sea-road. You could see across the wide grass-plots the discs of
+ vibration made by the spokes. The bright domes of the parasols swayed
+ lightly outwards like full-blown blossoms on the rim of a vase; and
+ the quiet sheet of dark-blue water, crossed by a bar of purple, made a
+ background for the spinning wheels and the high action of the horses,
+ whilst the turbaned heads of the Indian servants elevated above the line
+ of the sea horizon glided rapidly on the paler blue of the sky. In an
+ open space near the little bridge each turn-out trotted smartly in a
+ wide curve away from the sunset; then pulling up sharp, entered the main
+ alley in a long slow-moving file with the great red stillness of the sky
+ at the back. The trunks of mighty trees stood all touched with red on
+ the same side, the air seemed aflame under the high foliage, the
+ very ground under the hoofs of the horses was red. The wheels turned
+ solemnly; one after another the sunshades drooped, folding their colors
+ like gorgeous flowers shutting their petals at the end of the day. In
+ the whole half-mile of human beings no voice uttered a distinct word,
+ only a faint thudding noise went on mingled with slight jingling sounds,
+ and the motionless heads and shoulders of men and women sitting in
+ couples emerged stolidly above the lowered hoods--as if wooden. But one
+ carriage and pair coming late did not join the line.</p>
+
+ <p>It fled along in a noiseless roll; but on entering the avenue one of the
+ dark bays snorted, arching his neck and shying against the steel-tipped
+ pole; a flake of foam fell from the bit upon the point of a satiny
+ shoulder, and the dusky face of the coachman leaned forward at once over
+ the hands taking a fresh grip of the reins. It was a long dark-green
+ landau, having a dignified and buoyant motion between the sharply
+ curved C-springs, and a sort of strictly official majesty in its supreme
+ elegance. It seemed more roomy than is usual, its horses seemed slightly
+ bigger, the appointments a shade more perfect, the servants perched
+ somewhat higher on the box. The dresses of three women--two young
+ and pretty, and one, handsome, large, of mature age--seemed to fill
+ completely the shallow body of the carriage. The fourth face was that
+ of a man, heavy lidded, distinguished and sallow, with a somber, thick,
+ iron-gray imperial and mustaches, which somehow had the air of solid
+ appendages. His Excellency--</p>
+
+ <p>The rapid motion of that one equipage made all the others appear utterly
+ inferior, blighted, and reduced to crawl painfully at a snail's pace.
+ The landau distanced the whole file in a sort of sustained rush; the
+ features of the occupant whirling out of sight left behind an impression
+ of fixed stares and impassive vacancy; and after it had vanished in full
+ flight as it were, notwithstanding the long line of vehicles hugging the
+ curb at a walk, the whole lofty vista of the avenue seemed to lie open
+ and emptied of life in the enlarged impression of an august solitude.</p>
+
+ <p>Captain Whalley had lifted his head to look, and his mind, disturbed in
+ its meditation, turned with wonder (as men's minds will do) to matters
+ of no importance. It struck him that it was to this port, where he had
+ just sold his last ship, that he had come with the very first he had
+ ever owned, and with his head full of a plan for opening a new trade
+ with a distant part of the Archipelago. The then governor had given
+ him no end of encouragement. No Excellency he--this Mr. Denham--this
+ governor with his jacket off; a man who tended night and day, so to
+ speak, the growing prosperity of the settlement with the self-forgetful
+ devotion of a nurse for a child she loves; a lone bachelor who lived as
+ in a camp with the few servants and his three dogs in what was called
+ then the Government Bungalow: a low-roofed structure on the half-cleared
+ slope of a hill, with a new flagstaff in front and a police orderly on
+ the veranda. He remembered toiling up that hill under a heavy sun for
+ his audience; the unfurnished aspect of the cool shaded room; the long
+ table covered at one end with piles of papers, and with two guns, a
+ brass telescope, a small bottle of oil with a feather stuck in the neck
+ at the other--and the flattering attention given to him by the man in
+ power. It was an undertaking full of risk he had come to expound, but a
+ twenty minutes' talk in the Government Bungalow on the hill had made it
+ go smoothly from the start. And as he was retiring Mr. Denham, already
+ seated before the papers, called out after him, "Next month the Dido
+ starts for a cruise that way, and I shall request her captain officially
+ to give you a look in and see how you get on." The Dido was one of the
+ smart frigates on the China station--and five-and-thirty years make a
+ big slice of time. Five-and-thirty years ago an enterprise like his had
+ for the colony enough importance to be looked after by a Queen's ship.
+ A big slice of time. Individuals were of some account then. Men like
+ himself; men, too, like poor Evans, for instance, with his red face,
+ his coal-black whiskers, and his restless eyes, who had set up the first
+ patent slip for repairing small ships, on the edge of the forest, in
+ a lonely bay three miles up the coast. Mr. Denham had encouraged that
+ enterprise too, and yet somehow poor Evans had ended by dying at
+ home deucedly hard up. His son, they said, was squeezing oil out of
+ cocoa-nuts for a living on some God-forsaken islet of the Indian Ocean;
+ but it was from that patent slip in a lonely wooded bay that had sprung
+ the workshops of the Consolidated Docks Company, with its three
+ graving basins carved out of solid rock, its wharves, its jetties,
+ its electric-light plant, its steam-power houses--with its gigantic
+ sheer-legs, fit to lift the heaviest weight ever carried afloat, and
+ whose head could be seen like the top of a queer white monument peeping
+ over bushy points of land and sandy promontories, as you approached the
+ New Harbor from the west.</p>
+
+ <p>There had been a time when men counted: there were not so many carriages
+ in the colony then, though Mr. Denham, he fancied, had a buggy. And
+ Captain Whalley seemed to be swept out of the great avenue by the swirl
+ of a mental backwash. He remembered muddy shores, a harbor without
+ quays, the one solitary wooden pier (but that was a public work) jutting
+ out crookedly, the first coal-sheds erected on Monkey Point, that caught
+ fire mysteriously and smoldered for days, so that amazed ships came
+ into a roadstead full of sulphurous smoke, and the sun hung blood-red
+ at midday. He remembered the things, the faces, and something more
+ besides--like the faint flavor of a cup quaffed to the bottom, like a
+ subtle sparkle of the air that was not to be found in the atmosphere of
+ to-day.</p>
+
+ <p>In this evocation, swift and full of detail like a flash of magnesium
+ light into the niches of a dark memorial hall, Captain Whalley
+ contemplated things once important, the efforts of small men, the growth
+ of a great place, but now robbed of all consequence by the greatness
+ of accomplished facts, by hopes greater still; and they gave him for a
+ moment such an almost physical grip upon time, such a comprehension of
+ our unchangeable feelings, that he stopped short, struck the ground with
+ his stick, and ejaculated mentally, "What the devil am I doing here!" He
+ seemed lost in a sort of surprise; but he heard his name called out in
+ wheezy tones once, twice--and turned on his heels slowly.</p>
+
+ <p>He beheld then, waddling towards him autocratically, a man of an
+ old-fashioned and gouty aspect, with hair as white as his own, but with
+ shaved, florid cheeks, wearing a necktie--almost a neckcloth--whose
+ stiff ends projected far beyond his chin; with round legs, round arms,
+ a round body, a round face--generally producing the effect of his short
+ figure having been distended by means of an air-pump as much as the
+ seams of his clothing would stand. This was the Master-Attendant of the
+ port. A master-attendant is a superior sort of harbor-master; a person,
+ out in the East, of some consequence in his sphere; a Government
+ official, a magistrate for the waters of the port, and possessed of vast
+ but ill-defined disciplinary authority over seamen of all classes.
+ This particular Master-Attendant was reported to consider it miserably
+ inadequate, on the ground that it did not include the power of life
+ and death. This was a jocular exaggeration. Captain Eliott was fairly
+ satisfied with his position, and nursed no inconsiderable sense of such
+ power as he had. His conceited and tyrannical disposition did not allow
+ him to let it dwindle in his hands for want of use. The uproarious,
+ choleric frankness of his comments on people's character and conduct
+ caused him to be feared at bottom; though in conversation many pretended
+ not to mind him in the least, others would only smile sourly at the
+ mention of his name, and there were even some who dared to pronounce him
+ "a meddlesome old ruffian." But for almost all of them one of Captain
+ Eliott's outbreaks was nearly as distasteful to face as a chance of
+ annihilation.</p>
+
+ <style>
+ body {
+ padding: 15px;
+ }
+
+ .pointer {
+ padding: 15px;
+ background-color: rgba(0, 0, 0, 0.4);
+ color: white;
+ border-radius: 10px;
+ pointer-events: none;
+ opacity: 0;
+
+ transition: opacity 300ms;
+ -webkit-transition: opacity 300ms;
+ }
+
+ .pointer.show {
+ opacity: 1;
+ }
+ </style>
+
+
+ <div class="pointer"></div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.pointer',
+ attachment: 'middle right',
+ targetAttachment: 'middle left',
+ targetModifier: 'scroll-handle',
+ target: document.body
+ });
+
+ var headers = document.querySelectorAll('h1,h2,h3,h4,h5,h6');
+ var hideTimeout = null;
+ var pointer = document.querySelector('.pointer')
+
+ var getSection = function(){
+ var closest, closestTop;
+ for (var i=0; i < headers.length; i++){
+ var rect = headers[i].getBoundingClientRect();
+
+ if (closestTop === undefined || (rect.top < 0 && rect.top > closestTop)){
+ closestTop = rect.top;
+ closest = headers[i];
+ }
+ }
+ return closest.innerHTML;
+ }
+
+ document.addEventListener('scroll', function(){
+ var percentage = Math.floor((100 * Math.max(0, pageYOffset)) / (document.body.scrollHeight - innerHeight)) + '%'
+ pointer.innerHTML = getSection() + ' - ' + percentage
+
+ pointer.classList.add('show');
+
+ if (hideTimeout)
+ clearTimeout(hideTimeout);
+
+ hideTimeout = setTimeout(function(){
+ pointer.classList.remove('show');
+ }, 1000);
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/simple/index.html b/afb-client/bower_components/tether/examples/simple/index.html
new file mode 100644
index 0000000..de3ac1e
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/simple/index.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ </head>
+ <body>
+ <div class="instructions">Resize the page to see the Tether flip.</div>
+
+ <div class="element"></div>
+ <div class="target"></div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: '.target',
+ attachment: 'top left',
+ targetAttachment: 'top right',
+ constraints: [{
+ to: 'window',
+ attachment: 'together'
+ }]
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/testbed/index.html b/afb-client/bower_components/tether/examples/testbed/index.html
new file mode 100644
index 0000000..720ce73
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/testbed/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="../common/css/style.css" />
+ </head>
+ <body>
+
+ <div class="element">
+ </div>
+
+ <div class="container">
+ <div class="pad"></div>
+ <div class="target"></div>
+ <div class="pad"></div>
+ <div class="pad"></div>
+ </div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: '.target',
+ attachment: 'top center',
+ targetAttachment: 'bottom center',
+ constraints: [{
+ to: 'scrollParent',
+ attachment: 'together'
+ }]
+ });
+ </script>
+ </body>
+ </html>
diff --git a/afb-client/bower_components/tether/examples/tooltip/index.html b/afb-client/bower_components/tether/examples/tooltip/index.html
new file mode 100644
index 0000000..fbf247f
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/tooltip/index.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <script type="text/javascript" src="//use.typekit.net/jbn8qxr.js"></script>
+ <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
+ <link rel="stylesheet" href="../../css/drop.css" />
+ <link rel="stylesheet" href="../../css/drop-tooltip-theme-arrows.css" />
+ <style>
+ body {
+ font-family: "proxima-nova", "Helvetica Neue", sans-serif;
+ color: #444;
+ }
+
+ .scroll-parent {
+ margin: 200px;
+ height: 300px;
+ width: 300px;
+ display: inline-block;
+ overflow: auto;
+ border: 2px solid #eee;
+ padding: 40px;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="scroll-parent">
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="top center">Tooltip on Top</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="bottom center">Tooltip on Bottom</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="left middle">Tooltip on Left</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="right middle">Tooltip on Right</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="bottom left">Tooltip on Bottom Left</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="bottom right">Tooltip on Bottom Right</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="top left">Tooltip on Top Left</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="top right">Tooltip on Top Right</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="left bottom">Tooltip on Left Bottom</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="left top">Tooltip on Left Top</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="right bottom">Tooltip on Right Bottom</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ <p><a href="javascript:;" class="drop-tooltip" data-tooltip-content="Whoa, I'm a tooltip" data-attach="right top">Tooltip on Right Top</a></p>
+ <p>This is a paragraph of text</p>
+ <p>This is a paragraph of text</p>
+ </div>
+
+ <script src="../resources/js/log.js"></script>
+ <script src="../resources/js/jquery.js"></script>
+ <script src="../../utils.js"></script>
+ <script src="../../tether.js"></script>
+ <script src="/drop/drop.min.js"></script>
+ <script src="../../tooltip.js"></script>
+ <script src="../../constraint.js"></script>
+ <script>
+ $('.drop-tooltip').each(function(){
+ new Tooltip({
+ el: this,
+ attach: $(this).data('attach')
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/examples/viewport/colors.css b/afb-client/bower_components/tether/examples/viewport/colors.css
new file mode 100644
index 0000000..64f8c1c
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/viewport/colors.css
@@ -0,0 +1,145 @@
+@charset "UTF-8";
+/****
+
+ colors.css v1.0 For a friendlier looking web
+ MIT License • http://clrs.cc • http://github.com/mrmrs/colors
+
+ Author: mrmrs
+ http://mrmrs.cc
+ @mrmrs_
+
+****/
+/*
+
+ SKINS
+ • Backgrounds
+ • Colors
+
+*/
+/* Backgrounds */
+.bg-navy {
+ background-color: #001f3f; }
+
+.bg-blue {
+ background-color: #0074d9; }
+
+.bg-aqua {
+ background-color: #7fdbff; }
+
+.bg-teal {
+ background-color: #39cccc; }
+
+.bg-olive {
+ background-color: #3d9970; }
+
+.bg-green {
+ background-color: #2ecc40; }
+
+.bg-lime {
+ background-color: #01ff70; }
+
+.bg-yellow {
+ background-color: #ffdc00; }
+
+.bg-orange {
+ background-color: #ff851b; }
+
+.bg-red {
+ background-color: #ff4136; }
+
+.bg-fuchsia {
+ background-color: #f012be; }
+
+.bg-purple {
+ background-color: #b10dc9; }
+
+.bg-maroon {
+ background-color: #85144b; }
+
+.bg-white {
+ background-color: white; }
+
+.bg-gray {
+ background-color: #aaaaaa; }
+
+.bg-silver {
+ background-color: #dddddd; }
+
+.bg-black {
+ background-color: #111111; }
+
+/* Colors */
+.navy {
+ color: #001f3f; }
+
+.blue {
+ color: #0074d9; }
+
+.aqua {
+ color: #7fdbff; }
+
+.teal {
+ color: #39cccc; }
+
+.olive {
+ color: #3d9970; }
+
+.green {
+ color: #2ecc40; }
+
+.lime {
+ color: #01ff70; }
+
+.yellow {
+ color: #ffdc00; }
+
+.orange {
+ color: #ff851b; }
+
+.red {
+ color: #ff4136; }
+
+.fuchsia {
+ color: #f012be; }
+
+.purple {
+ color: #b10dc9; }
+
+.maroon {
+ color: #85144b; }
+
+.white {
+ color: white; }
+
+.silver {
+ color: #dddddd; }
+
+.gray {
+ color: #aaaaaa; }
+
+.black {
+ color: #111111; }
+
+/* PRETTIER LINKS */
+a {
+ text-decoration: none;
+ -webkit-transition: color .3s ease-in-out;
+ transition: color .3s ease-in-out; }
+
+a:link {
+ color: #0074d9;
+ -webkit-transition: color .3s ease-in-out;
+ transition: color .3s ease-in-out; }
+
+a:visited {
+ color: #b10dc9; }
+
+a:hover {
+ color: #7fdbff;
+ -webkit-transition: color .3s ease-in-out;
+ transition: color .3s ease-in-out; }
+
+a:active {
+ color: #ff851b;
+ -webkit-transition: color .3s ease-in-out;
+ transition: color .3s ease-in-out; }
diff --git a/afb-client/bower_components/tether/examples/viewport/index.html b/afb-client/bower_components/tether/examples/viewport/index.html
new file mode 100644
index 0000000..ac0711b
--- /dev/null
+++ b/afb-client/bower_components/tether/examples/viewport/index.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" href="../resources/css/base.css" />
+ <link rel="stylesheet" href="./colors.css" />
+ <style>
+ * {
+ box-sizing: border-box;
+ }
+
+ .element {
+ background-color: #FFDC00;
+ width: 80%;
+ max-width: 300px;
+ padding: 0 15px;
+ font-size: 20px;
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
+ }
+
+ @media (max-width: 380px) {
+ .element {
+ font-size: 16px;
+ }
+ }
+
+ .bit {
+ width: 10vw;
+ height: 10vw;
+ float: left;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="element">
+ <p>This element is tethered to the middle of the visible part of the body.</p>
+
+ <p>Inspect the element to see how Tether decided
+ to use <code>position: fixed</code>.</p>
+ </div>
+
+ <script src="../../tether.js"></script>
+ <script>
+ new Tether({
+ element: '.element',
+ target: document.body,
+ attachment: 'middle center',
+ targetAttachment: 'middle center',
+ targetModifier: 'visible'
+ });
+ </script>
+
+ <script>
+ // Random colors bit, don't mind this
+ colors = ['navy', 'blue', 'aqua', 'teal', 'olive', 'green', 'lime',
+ 'yellow', 'orange', 'red', 'fuchsia', 'purple', 'maroon'];
+
+ curColors = null;
+ for(var i=300; i--;){
+ if (!curColors || !curColors.length)
+ curColors = colors.slice(0);
+
+ var bit = document.createElement('div')
+ var index = (Math.random() * curColors.length)|0;
+ bit.className = 'bit bg-' + curColors[index]
+ curColors.splice(index, 1);
+ document.body.appendChild(bit);
+ }
+ </script>
+ </body>
+</html>
diff --git a/afb-client/bower_components/tether/gulpfile.coffee b/afb-client/bower_components/tether/gulpfile.coffee
new file mode 100644
index 0000000..5b09c2b
--- /dev/null
+++ b/afb-client/bower_components/tether/gulpfile.coffee
@@ -0,0 +1,65 @@
+gulp = require('gulp')
+coffee = require('gulp-coffee')
+compass = require('gulp-compass')
+concat = require('gulp-concat')
+uglify = require('gulp-uglify')
+header = require('gulp-header')
+rename = require('gulp-rename')
+wrap = require('gulp-wrap-umd')
+
+pkg = require('./package.json')
+banner = "/*! #{ pkg.name } #{ pkg.version } */\n"
+
+gulp.task 'coffee', ->
+ gulp.src('./coffee/*')
+ .pipe(coffee())
+ .pipe(gulp.dest('./js/'))
+
+ gulp.src('./docs/coffee/*')
+ .pipe(coffee())
+ .pipe(gulp.dest('./docs/js/'))
+
+ gulp.src('./docs/welcome/coffee/*')
+ .pipe(coffee())
+ .pipe(gulp.dest('./docs/welcome/js/'))
+
+gulp.task 'concat', ->
+ gulp.src(['./js/utils.js', './js/tether.js', './js/constraint.js', './js/abutment.js', './js/shift.js'])
+ .pipe(concat('tether.js'))
+ .pipe(wrap(
+ namespace: 'Tether'
+ exports: 'this.Tether'
+ ))
+ .pipe(header(banner))
+ .pipe(gulp.dest('./'))
+
+gulp.task 'uglify', ->
+ gulp.src('./tether.js')
+ .pipe(uglify())
+ .pipe(header(banner))
+ .pipe(rename('tether.min.js'))
+ .pipe(gulp.dest('./'))
+
+gulp.task 'js', ->
+ gulp.run 'coffee', ->
+ gulp.run 'concat', ->
+ gulp.run 'uglify', ->
+
+gulp.task 'compass', ->
+ for path in ['', 'docs/', 'docs/welcome/']
+ gulp.src("./#{ path }sass/*")
+ .pipe(compass(
+ sass: "#{ path }sass"
+ css: "#{ path }css"
+ comments: false
+ ))
+ .pipe(gulp.dest("./#{ path }css"))
+
+gulp.task 'default', ->
+ gulp.run 'js', 'compass'
+
+ gulp.watch './**/*.coffee', ->
+ gulp.run 'js'
+
+ gulp.watch './**/*.sass', ->
+ gulp.run 'compass'
diff --git a/afb-client/bower_components/tether/gulpfile.js b/afb-client/bower_components/tether/gulpfile.js
new file mode 100644
index 0000000..cfbdf87
--- /dev/null
+++ b/afb-client/bower_components/tether/gulpfile.js
@@ -0,0 +1,2 @@
+require('coffee-script')
+require('./gulpfile.coffee')
diff --git a/afb-client/bower_components/tether/js/abutment.js b/afb-client/bower_components/tether/js/abutment.js
new file mode 100644
index 0000000..b3acaa0
--- /dev/null
+++ b/afb-client/bower_components/tether/js/abutment.js
@@ -0,0 +1,59 @@
+(function() {
+ var defer, getBounds, updateClasses, _ref;
+
+ _ref = this.Tether.Utils, getBounds = _ref.getBounds, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var abutted, addClasses, allClasses, bottom, height, left, right, side, sides, targetPos, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3, _ref4, _ref5,
+ _this = this;
+ top = _arg.top, left = _arg.left;
+ _ref1 = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ }), height = _ref1.height, width = _ref1.width;
+ targetPos = this.getTargetBounds();
+ bottom = top + height;
+ right = left + width;
+ abutted = [];
+ if (top <= targetPos.bottom && bottom >= targetPos.top) {
+ _ref2 = ['left', 'right'];
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ side = _ref2[_i];
+ if ((_ref3 = targetPos[side]) === left || _ref3 === right) {
+ abutted.push(side);
+ }
+ }
+ }
+ if (left <= targetPos.right && right >= targetPos.left) {
+ _ref4 = ['top', 'bottom'];
+ for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {
+ side = _ref4[_j];
+ if ((_ref5 = targetPos[side]) === top || _ref5 === bottom) {
+ abutted.push(side);
+ }
+ }
+ }
+ allClasses = [];
+ addClasses = [];
+ sides = ['left', 'top', 'right', 'bottom'];
+ allClasses.push(this.getClass('abutted'));
+ for (_k = 0, _len2 = sides.length; _k < _len2; _k++) {
+ side = sides[_k];
+ allClasses.push("" + (this.getClass('abutted')) + "-" + side);
+ }
+ if (abutted.length) {
+ addClasses.push(this.getClass('abutted'));
+ }
+ for (_l = 0, _len3 = abutted.length; _l < _len3; _l++) {
+ side = abutted[_l];
+ addClasses.push("" + (this.getClass('abutted')) + "-" + side);
+ }
+ defer(function() {
+ updateClasses(_this.target, addClasses, allClasses);
+ return updateClasses(_this.element, addClasses, allClasses);
+ });
+ return true;
+ }
+ });
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/js/constraint.js b/afb-client/bower_components/tether/js/constraint.js
new file mode 100644
index 0000000..69a2bde
--- /dev/null
+++ b/afb-client/bower_components/tether/js/constraint.js
@@ -0,0 +1,308 @@
+(function() {
+ var BOUNDS_FORMAT, MIRROR_ATTACH, defer, extend, getBoundingRect, getBounds, getOuterSize, getSize, updateClasses, _ref,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ _ref = this.Tether.Utils, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getSize = _ref.getSize, extend = _ref.extend, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+ MIRROR_ATTACH = {
+ left: 'right',
+ right: 'left',
+ top: 'bottom',
+ bottom: 'top',
+ middle: 'middle'
+ };
+
+ BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
+
+ getBoundingRect = function(tether, to) {
+ var i, pos, side, size, style, _i, _len;
+ if (to === 'scrollParent') {
+ to = tether.scrollParent;
+ } else if (to === 'window') {
+ to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
+ }
+ if (to === document) {
+ to = to.documentElement;
+ }
+ if (to.nodeType != null) {
+ pos = size = getBounds(to);
+ style = getComputedStyle(to);
+ to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
+ for (i = _i = 0, _len = BOUNDS_FORMAT.length; _i < _len; i = ++_i) {
+ side = BOUNDS_FORMAT[i];
+ side = side[0].toUpperCase() + side.substr(1);
+ if (side === 'Top' || side === 'Left') {
+ to[i] += parseFloat(style["border" + side + "Width"]);
+ } else {
+ to[i] -= parseFloat(style["border" + side + "Width"]);
+ }
+ }
+ }
+ return to;
+ };
+
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var addClasses, allClasses, attachment, bounds, changeAttachX, changeAttachY, cls, constraint, eAttachment, height, left, oob, oobClass, p, pin, pinned, pinnedClass, removeClass, side, tAttachment, targetAttachment, targetHeight, targetSize, targetWidth, to, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8,
+ _this = this;
+ top = _arg.top, left = _arg.left, targetAttachment = _arg.targetAttachment;
+ if (!this.options.constraints) {
+ return true;
+ }
+ removeClass = function(prefix) {
+ var side, _i, _len, _results;
+ _this.removeClass(prefix);
+ _results = [];
+ for (_i = 0, _len = BOUNDS_FORMAT.length; _i < _len; _i++) {
+ side = BOUNDS_FORMAT[_i];
+ _results.push(_this.removeClass("" + prefix + "-" + side));
+ }
+ return _results;
+ };
+ _ref1 = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ }), height = _ref1.height, width = _ref1.width;
+ if (width === 0 && height === 0 && (this.lastSize != null)) {
+ _ref2 = this.lastSize, width = _ref2.width, height = _ref2.height;
+ }
+ targetSize = this.cache('target-bounds', function() {
+ return _this.getTargetBounds();
+ });
+ targetHeight = targetSize.height;
+ targetWidth = targetSize.width;
+ tAttachment = {};
+ eAttachment = {};
+ allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
+ _ref3 = this.options.constraints;
+ for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+ constraint = _ref3[_i];
+ if (constraint.outOfBoundsClass) {
+ allClasses.push(constraint.outOfBoundsClass);
+ }
+ if (constraint.pinnedClass) {
+ allClasses.push(constraint.pinnedClass);
+ }
+ }
+ for (_j = 0, _len1 = allClasses.length; _j < _len1; _j++) {
+ cls = allClasses[_j];
+ _ref4 = ['left', 'top', 'right', 'bottom'];
+ for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
+ side = _ref4[_k];
+ allClasses.push("" + cls + "-" + side);
+ }
+ }
+ addClasses = [];
+ tAttachment = extend({}, targetAttachment);
+ eAttachment = extend({}, this.attachment);
+ _ref5 = this.options.constraints;
+ for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {
+ constraint = _ref5[_l];
+ to = constraint.to, attachment = constraint.attachment, pin = constraint.pin;
+ if (attachment == null) {
+ attachment = '';
+ }
+ if (__indexOf.call(attachment, ' ') >= 0) {
+ _ref6 = attachment.split(' '), changeAttachY = _ref6[0], changeAttachX = _ref6[1];
+ } else {
+ changeAttachX = changeAttachY = attachment;
+ }
+ bounds = getBoundingRect(this, to);
+ if (changeAttachY === 'target' || changeAttachY === 'both') {
+ if (top < bounds[1] && tAttachment.top === 'top') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ }
+ if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ }
+ }
+ if (changeAttachY === 'together') {
+ if (top < bounds[1] && tAttachment.top === 'top') {
+ if (eAttachment.top === 'bottom') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ top += height;
+ eAttachment.top = 'top';
+ } else if (eAttachment.top === 'top') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ top -= height;
+ eAttachment.top = 'bottom';
+ }
+ }
+ if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+ if (eAttachment.top === 'top') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ top -= height;
+ eAttachment.top = 'bottom';
+ } else if (eAttachment.top === 'bottom') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ top += height;
+ eAttachment.top = 'top';
+ }
+ }
+ if (tAttachment.top === 'middle') {
+ if (top + height > bounds[3] && eAttachment.top === 'top') {
+ top -= height;
+ eAttachment.top = 'bottom';
+ } else if (top < bounds[1] && eAttachment.top === 'bottom') {
+ top += height;
+ eAttachment.top = 'top';
+ }
+ }
+ }
+ if (changeAttachX === 'target' || changeAttachX === 'both') {
+ if (left < bounds[0] && tAttachment.left === 'left') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ }
+ if (left + width > bounds[2] && tAttachment.left === 'right') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ }
+ }
+ if (changeAttachX === 'together') {
+ if (left < bounds[0] && tAttachment.left === 'left') {
+ if (eAttachment.left === 'right') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ left += width;
+ eAttachment.left = 'left';
+ } else if (eAttachment.left === 'left') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ left -= width;
+ eAttachment.left = 'right';
+ }
+ } else if (left + width > bounds[2] && tAttachment.left === 'right') {
+ if (eAttachment.left === 'left') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ left -= width;
+ eAttachment.left = 'right';
+ } else if (eAttachment.left === 'right') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ left += width;
+ eAttachment.left = 'left';
+ }
+ } else if (tAttachment.left === 'center') {
+ if (left + width > bounds[2] && eAttachment.left === 'left') {
+ left -= width;
+ eAttachment.left = 'right';
+ } else if (left < bounds[0] && eAttachment.left === 'right') {
+ left += width;
+ eAttachment.left = 'left';
+ }
+ }
+ }
+ if (changeAttachY === 'element' || changeAttachY === 'both') {
+ if (top < bounds[1] && eAttachment.top === 'bottom') {
+ top += height;
+ eAttachment.top = 'top';
+ }
+ if (top + height > bounds[3] && eAttachment.top === 'top') {
+ top -= height;
+ eAttachment.top = 'bottom';
+ }
+ }
+ if (changeAttachX === 'element' || changeAttachX === 'both') {
+ if (left < bounds[0] && eAttachment.left === 'right') {
+ left += width;
+ eAttachment.left = 'left';
+ }
+ if (left + width > bounds[2] && eAttachment.left === 'left') {
+ left -= width;
+ eAttachment.left = 'right';
+ }
+ }
+ if (typeof pin === 'string') {
+ pin = (function() {
+ var _len4, _m, _ref7, _results;
+ _ref7 = pin.split(',');
+ _results = [];
+ for (_m = 0, _len4 = _ref7.length; _m < _len4; _m++) {
+ p = _ref7[_m];
+ _results.push(p.trim());
+ }
+ return _results;
+ })();
+ } else if (pin === true) {
+ pin = ['top', 'left', 'right', 'bottom'];
+ }
+ pin || (pin = []);
+ pinned = [];
+ oob = [];
+ if (top < bounds[1]) {
+ if (__indexOf.call(pin, 'top') >= 0) {
+ top = bounds[1];
+ pinned.push('top');
+ } else {
+ oob.push('top');
+ }
+ }
+ if (top + height > bounds[3]) {
+ if (__indexOf.call(pin, 'bottom') >= 0) {
+ top = bounds[3] - height;
+ pinned.push('bottom');
+ } else {
+ oob.push('bottom');
+ }
+ }
+ if (left < bounds[0]) {
+ if (__indexOf.call(pin, 'left') >= 0) {
+ left = bounds[0];
+ pinned.push('left');
+ } else {
+ oob.push('left');
+ }
+ }
+ if (left + width > bounds[2]) {
+ if (__indexOf.call(pin, 'right') >= 0) {
+ left = bounds[2] - width;
+ pinned.push('right');
+ } else {
+ oob.push('right');
+ }
+ }
+ if (pinned.length) {
+ pinnedClass = (_ref7 = this.options.pinnedClass) != null ? _ref7 : this.getClass('pinned');
+ addClasses.push(pinnedClass);
+ for (_m = 0, _len4 = pinned.length; _m < _len4; _m++) {
+ side = pinned[_m];
+ addClasses.push("" + pinnedClass + "-" + side);
+ }
+ }
+ if (oob.length) {
+ oobClass = (_ref8 = this.options.outOfBoundsClass) != null ? _ref8 : this.getClass('out-of-bounds');
+ addClasses.push(oobClass);
+ for (_n = 0, _len5 = oob.length; _n < _len5; _n++) {
+ side = oob[_n];
+ addClasses.push("" + oobClass + "-" + side);
+ }
+ }
+ if (__indexOf.call(pinned, 'left') >= 0 || __indexOf.call(pinned, 'right') >= 0) {
+ eAttachment.left = tAttachment.left = false;
+ }
+ if (__indexOf.call(pinned, 'top') >= 0 || __indexOf.call(pinned, 'bottom') >= 0) {
+ eAttachment.top = tAttachment.top = false;
+ }
+ if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== this.attachment.top || eAttachment.left !== this.attachment.left) {
+ this.updateAttachClasses(eAttachment, tAttachment);
+ }
+ }
+ defer(function() {
+ updateClasses(_this.target, addClasses, allClasses);
+ return updateClasses(_this.element, addClasses, allClasses);
+ });
+ return {
+ top: top,
+ left: left
+ };
+ }
+ });
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/js/markAttachment.js b/afb-client/bower_components/tether/js/markAttachment.js
new file mode 100644
index 0000000..a6d8f80
--- /dev/null
+++ b/afb-client/bower_components/tether/js/markAttachment.js
@@ -0,0 +1,46 @@
+(function() {
+ this.Tether.modules.push({
+ initialize: function() {
+ var dot, el, type, _i, _len, _ref, _results;
+ this.markers = {};
+ _ref = ['target', 'element'];
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ type = _ref[_i];
+ el = document.createElement('div');
+ el.className = this.getClass("" + type + "-marker");
+ dot = document.createElement('div');
+ dot.className = this.getClass('marker-dot');
+ el.appendChild(dot);
+ this[type].appendChild(el);
+ _results.push(this.markers[type] = {
+ dot: dot,
+ el: el
+ });
+ }
+ return _results;
+ },
+ position: function(_arg) {
+ var manualOffset, manualTargetOffset, offset, offsets, side, type, val;
+ manualOffset = _arg.manualOffset, manualTargetOffset = _arg.manualTargetOffset;
+ offsets = {
+ element: manualOffset,
+ target: manualTargetOffset
+ };
+ for (type in offsets) {
+ offset = offsets[type];
+ for (side in offset) {
+ val = offset[side];
+ if (typeof val !== 'string' || (val.indexOf('%') === -1 && val.indexOf('px') === -1)) {
+ val += 'px';
+ }
+ if (this.markers[type].dot.style[side] !== val) {
+ this.markers[type].dot.style[side] = val;
+ }
+ }
+ }
+ return true;
+ }
+ });
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/js/shift.js b/afb-client/bower_components/tether/js/shift.js
new file mode 100644
index 0000000..58b935f
--- /dev/null
+++ b/afb-client/bower_components/tether/js/shift.js
@@ -0,0 +1,38 @@
+(function() {
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var left, result, shift, shiftLeft, shiftTop, top, _ref;
+ top = _arg.top, left = _arg.left;
+ if (!this.options.shift) {
+ return;
+ }
+ result = function(val) {
+ if (typeof val === 'function') {
+ return val.call(this, {
+ top: top,
+ left: left
+ });
+ } else {
+ return val;
+ }
+ };
+ shift = result(this.options.shift);
+ if (typeof shift === 'string') {
+ shift = shift.split(' ');
+ shift[1] || (shift[1] = shift[0]);
+ shiftTop = shift[0], shiftLeft = shift[1];
+ shiftTop = parseFloat(shiftTop, 10);
+ shiftLeft = parseFloat(shiftLeft, 10);
+ } else {
+ _ref = [shift.top, shift.left], shiftTop = _ref[0], shiftLeft = _ref[1];
+ }
+ top += shiftTop;
+ left += shiftLeft;
+ return {
+ top: top,
+ left: left
+ };
+ }
+ });
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/js/tether.js b/afb-client/bower_components/tether/js/tether.js
new file mode 100644
index 0000000..92f6485
--- /dev/null
+++ b/afb-client/bower_components/tether/js/tether.js
@@ -0,0 +1,686 @@
+(function() {
+ var MIRROR_LR, MIRROR_TB, OFFSET_MAP, Tether, addClass, addOffset, attachmentToOffset, autoToFixedAttachment, defer, extend, flush, getBounds, getOffsetParent, getOuterSize, getScrollBarSize, getScrollParent, getSize, now, offsetToPx, parseAttachment, parseOffset, position, removeClass, tethers, transformKey, updateClasses, within, _Tether, _ref,
+ __slice = [].slice,
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+ if (this.Tether == null) {
+ throw new Error("You must include the utils.js file before tether.js");
+ }
+
+ Tether = this.Tether;
+
+ _ref = Tether.Utils, getScrollParent = _ref.getScrollParent, getSize = _ref.getSize, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getOffsetParent = _ref.getOffsetParent, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, updateClasses = _ref.updateClasses, defer = _ref.defer, flush = _ref.flush, getScrollBarSize = _ref.getScrollBarSize;
+
+ within = function(a, b, diff) {
+ if (diff == null) {
+ diff = 1;
+ }
+ return (a + diff >= b && b >= a - diff);
+ };
+
+ transformKey = (function() {
+ var el, key, _i, _len, _ref1;
+ el = document.createElement('div');
+ _ref1 = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ key = _ref1[_i];
+ if (el.style[key] !== void 0) {
+ return key;
+ }
+ }
+ })();
+
+ tethers = [];
+
+ position = function() {
+ var tether, _i, _len;
+ for (_i = 0, _len = tethers.length; _i < _len; _i++) {
+ tether = tethers[_i];
+ tether.position(false);
+ }
+ return flush();
+ };
+
+ now = function() {
+ var _ref1;
+ return (_ref1 = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref1 : +(new Date);
+ };
+
+ (function() {
+ var event, lastCall, lastDuration, pendingTimeout, tick, _i, _len, _ref1, _results;
+ lastCall = null;
+ lastDuration = null;
+ pendingTimeout = null;
+ tick = function() {
+ if ((lastDuration != null) && lastDuration > 16) {
+ lastDuration = Math.min(lastDuration - 16, 250);
+ pendingTimeout = setTimeout(tick, 250);
+ return;
+ }
+ if ((lastCall != null) && (now() - lastCall) < 10) {
+ return;
+ }
+ if (pendingTimeout != null) {
+ clearTimeout(pendingTimeout);
+ pendingTimeout = null;
+ }
+ lastCall = now();
+ position();
+ return lastDuration = now() - lastCall;
+ };
+ _ref1 = ['resize', 'scroll', 'touchmove'];
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ event = _ref1[_i];
+ _results.push(window.addEventListener(event, tick));
+ }
+ return _results;
+ })();
+
+ MIRROR_LR = {
+ center: 'center',
+ left: 'right',
+ right: 'left'
+ };
+
+ MIRROR_TB = {
+ middle: 'middle',
+ top: 'bottom',
+ bottom: 'top'
+ };
+
+ OFFSET_MAP = {
+ top: 0,
+ left: 0,
+ middle: '50%',
+ center: '50%',
+ bottom: '100%',
+ right: '100%'
+ };
+
+ autoToFixedAttachment = function(attachment, relativeToAttachment) {
+ var left, top;
+ left = attachment.left, top = attachment.top;
+ if (left === 'auto') {
+ left = MIRROR_LR[relativeToAttachment.left];
+ }
+ if (top === 'auto') {
+ top = MIRROR_TB[relativeToAttachment.top];
+ }
+ return {
+ left: left,
+ top: top
+ };
+ };
+
+ attachmentToOffset = function(attachment) {
+ var _ref1, _ref2;
+ return {
+ left: (_ref1 = OFFSET_MAP[attachment.left]) != null ? _ref1 : attachment.left,
+ top: (_ref2 = OFFSET_MAP[attachment.top]) != null ? _ref2 : attachment.top
+ };
+ };
+
+ addOffset = function() {
+ var left, offsets, out, top, _i, _len, _ref1;
+ offsets = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ out = {
+ top: 0,
+ left: 0
+ };
+ for (_i = 0, _len = offsets.length; _i < _len; _i++) {
+ _ref1 = offsets[_i], top = _ref1.top, left = _ref1.left;
+ if (typeof top === 'string') {
+ top = parseFloat(top, 10);
+ }
+ if (typeof left === 'string') {
+ left = parseFloat(left, 10);
+ }
+ out.top += top;
+ out.left += left;
+ }
+ return out;
+ };
+
+ offsetToPx = function(offset, size) {
+ if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
+ offset.left = parseFloat(offset.left, 10) / 100 * size.width;
+ }
+ if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
+ offset.top = parseFloat(offset.top, 10) / 100 * size.height;
+ }
+ return offset;
+ };
+
+ parseAttachment = parseOffset = function(value) {
+ var left, top, _ref1;
+ _ref1 = value.split(' '), top = _ref1[0], left = _ref1[1];
+ return {
+ top: top,
+ left: left
+ };
+ };
+
+ _Tether = (function() {
+ _Tether.modules = [];
+
+ function _Tether(options) {
+ this.position = __bind(this.position, this);
+ var module, _i, _len, _ref1, _ref2;
+ tethers.push(this);
+ this.history = [];
+ this.setOptions(options, false);
+ _ref1 = Tether.modules;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ module = _ref1[_i];
+ if ((_ref2 = module.initialize) != null) {
+ _ref2.call(this);
+ }
+ }
+ this.position();
+ }
+
+ _Tether.prototype.getClass = function(key) {
+ var _ref1, _ref2;
+ if ((_ref1 = this.options.classes) != null ? _ref1[key] : void 0) {
+ return this.options.classes[key];
+ } else if (((_ref2 = this.options.classes) != null ? _ref2[key] : void 0) !== false) {
+ if (this.options.classPrefix) {
+ return "" + this.options.classPrefix + "-" + key;
+ } else {
+ return key;
+ }
+ } else {
+ return '';
+ }
+ };
+
+ _Tether.prototype.setOptions = function(options, position) {
+ var defaults, key, _i, _len, _ref1, _ref2;
+ this.options = options;
+ if (position == null) {
+ position = true;
+ }
+ defaults = {
+ offset: '0 0',
+ targetOffset: '0 0',
+ targetAttachment: 'auto auto',
+ classPrefix: 'tether'
+ };
+ this.options = extend(defaults, this.options);
+ _ref1 = this.options, this.element = _ref1.element, this.target = _ref1.target, this.targetModifier = _ref1.targetModifier;
+ if (this.target === 'viewport') {
+ this.target = document.body;
+ this.targetModifier = 'visible';
+ } else if (this.target === 'scroll-handle') {
+ this.target = document.body;
+ this.targetModifier = 'scroll-handle';
+ }
+ _ref2 = ['element', 'target'];
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ key = _ref2[_i];
+ if (this[key] == null) {
+ throw new Error("Tether Error: Both element and target must be defined");
+ }
+ if (this[key].jquery != null) {
+ this[key] = this[key][0];
+ } else if (typeof this[key] === 'string') {
+ this[key] = document.querySelector(this[key]);
+ }
+ }
+ addClass(this.element, this.getClass('element'));
+ addClass(this.target, this.getClass('target'));
+ if (!this.options.attachment) {
+ throw new Error("Tether Error: You must provide an attachment");
+ }
+ this.targetAttachment = parseAttachment(this.options.targetAttachment);
+ this.attachment = parseAttachment(this.options.attachment);
+ this.offset = parseOffset(this.options.offset);
+ this.targetOffset = parseOffset(this.options.targetOffset);
+ if (this.scrollParent != null) {
+ this.disable();
+ }
+ if (this.targetModifier === 'scroll-handle') {
+ this.scrollParent = this.target;
+ } else {
+ this.scrollParent = getScrollParent(this.target);
+ }
+ if (this.options.enabled !== false) {
+ return this.enable(position);
+ }
+ };
+
+ _Tether.prototype.getTargetBounds = function() {
+ var bounds, fitAdj, hasBottomScroll, height, out, scrollBottom, scrollPercentage, style, target;
+ if (this.targetModifier != null) {
+ switch (this.targetModifier) {
+ case 'visible':
+ if (this.target === document.body) {
+ return {
+ top: pageYOffset,
+ left: pageXOffset,
+ height: innerHeight,
+ width: innerWidth
+ };
+ } else {
+ bounds = getBounds(this.target);
+ out = {
+ height: bounds.height,
+ width: bounds.width,
+ top: bounds.top,
+ left: bounds.left
+ };
+ out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
+ out.height = Math.min(out.height, bounds.height - ((bounds.top + bounds.height) - (pageYOffset + innerHeight)));
+ out.height = Math.min(innerHeight, out.height);
+ out.height -= 2;
+ out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
+ out.width = Math.min(out.width, bounds.width - ((bounds.left + bounds.width) - (pageXOffset + innerWidth)));
+ out.width = Math.min(innerWidth, out.width);
+ out.width -= 2;
+ if (out.top < pageYOffset) {
+ out.top = pageYOffset;
+ }
+ if (out.left < pageXOffset) {
+ out.left = pageXOffset;
+ }
+ return out;
+ }
+ break;
+ case 'scroll-handle':
+ target = this.target;
+ if (target === document.body) {
+ target = document.documentElement;
+ bounds = {
+ left: pageXOffset,
+ top: pageYOffset,
+ height: innerHeight,
+ width: innerWidth
+ };
+ } else {
+ bounds = getBounds(target);
+ }
+ style = getComputedStyle(target);
+ hasBottomScroll = target.scrollWidth > target.clientWidth || 'scroll' === [style.overflow, style.overflowX] || this.target !== document.body;
+ scrollBottom = 0;
+ if (hasBottomScroll) {
+ scrollBottom = 15;
+ }
+ height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
+ out = {
+ width: 15,
+ height: height * 0.975 * (height / target.scrollHeight),
+ left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
+ };
+ fitAdj = 0;
+ if (height < 408 && this.target === document.body) {
+ fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
+ }
+ if (this.target !== document.body) {
+ out.height = Math.max(out.height, 24);
+ }
+ scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
+ out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
+ if (this.target === document.body) {
+ out.height = Math.max(out.height, 24);
+ }
+ return out;
+ }
+ } else {
+ return getBounds(this.target);
+ }
+ };
+
+ _Tether.prototype.clearCache = function() {
+ return this._cache = {};
+ };
+
+ _Tether.prototype.cache = function(k, getter) {
+ if (this._cache == null) {
+ this._cache = {};
+ }
+ if (this._cache[k] == null) {
+ this._cache[k] = getter.call(this);
+ }
+ return this._cache[k];
+ };
+
+ _Tether.prototype.enable = function(position) {
+ if (position == null) {
+ position = true;
+ }
+ addClass(this.target, this.getClass('enabled'));
+ addClass(this.element, this.getClass('enabled'));
+ this.enabled = true;
+ if (this.scrollParent !== document) {
+ this.scrollParent.addEventListener('scroll', this.position);
+ }
+ if (position) {
+ return this.position();
+ }
+ };
+
+ _Tether.prototype.disable = function() {
+ removeClass(this.target, this.getClass('enabled'));
+ removeClass(this.element, this.getClass('enabled'));
+ this.enabled = false;
+ if (this.scrollParent != null) {
+ return this.scrollParent.removeEventListener('scroll', this.position);
+ }
+ };
+
+ _Tether.prototype.destroy = function() {
+ var i, tether, _i, _len, _results;
+ this.disable();
+ _results = [];
+ for (i = _i = 0, _len = tethers.length; _i < _len; i = ++_i) {
+ tether = tethers[i];
+ if (tether === this) {
+ tethers.splice(i, 1);
+ break;
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ };
+
+ _Tether.prototype.updateAttachClasses = function(elementAttach, targetAttach) {
+ var add, all, side, sides, _i, _j, _len, _len1, _ref1,
+ _this = this;
+ if (elementAttach == null) {
+ elementAttach = this.attachment;
+ }
+ if (targetAttach == null) {
+ targetAttach = this.targetAttachment;
+ }
+ sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
+ if ((_ref1 = this._addAttachClasses) != null ? _ref1.length : void 0) {
+ this._addAttachClasses.splice(0, this._addAttachClasses.length);
+ }
+ add = this._addAttachClasses != null ? this._addAttachClasses : this._addAttachClasses = [];
+ if (elementAttach.top) {
+ add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.top);
+ }
+ if (elementAttach.left) {
+ add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.left);
+ }
+ if (targetAttach.top) {
+ add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.top);
+ }
+ if (targetAttach.left) {
+ add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.left);
+ }
+ all = [];
+ for (_i = 0, _len = sides.length; _i < _len; _i++) {
+ side = sides[_i];
+ all.push("" + (this.getClass('element-attached')) + "-" + side);
+ }
+ for (_j = 0, _len1 = sides.length; _j < _len1; _j++) {
+ side = sides[_j];
+ all.push("" + (this.getClass('target-attached')) + "-" + side);
+ }
+ return defer(function() {
+ if (_this._addAttachClasses == null) {
+ return;
+ }
+ updateClasses(_this.element, _this._addAttachClasses, all);
+ updateClasses(_this.target, _this._addAttachClasses, all);
+ return _this._addAttachClasses = void 0;
+ });
+ };
+
+ _Tether.prototype.position = function(flushChanges) {
+ var elementPos, elementStyle, height, left, manualOffset, manualTargetOffset, module, next, offset, offsetBorder, offsetParent, offsetParentSize, offsetParentStyle, offsetPosition, ret, scrollLeft, scrollTop, scrollbarSize, side, targetAttachment, targetOffset, targetPos, targetSize, top, width, _i, _j, _len, _len1, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6,
+ _this = this;
+ if (flushChanges == null) {
+ flushChanges = true;
+ }
+ if (!this.enabled) {
+ return;
+ }
+ this.clearCache();
+ targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
+ this.updateAttachClasses(this.attachment, targetAttachment);
+ elementPos = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ });
+ width = elementPos.width, height = elementPos.height;
+ if (width === 0 && height === 0 && (this.lastSize != null)) {
+ _ref1 = this.lastSize, width = _ref1.width, height = _ref1.height;
+ } else {
+ this.lastSize = {
+ width: width,
+ height: height
+ };
+ }
+ targetSize = targetPos = this.cache('target-bounds', function() {
+ return _this.getTargetBounds();
+ });
+ offset = offsetToPx(attachmentToOffset(this.attachment), {
+ width: width,
+ height: height
+ });
+ targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
+ manualOffset = offsetToPx(this.offset, {
+ width: width,
+ height: height
+ });
+ manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
+ offset = addOffset(offset, manualOffset);
+ targetOffset = addOffset(targetOffset, manualTargetOffset);
+ left = targetPos.left + targetOffset.left - offset.left;
+ top = targetPos.top + targetOffset.top - offset.top;
+ _ref2 = Tether.modules;
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ module = _ref2[_i];
+ ret = module.position.call(this, {
+ left: left,
+ top: top,
+ targetAttachment: targetAttachment,
+ targetPos: targetPos,
+ attachment: this.attachment,
+ elementPos: elementPos,
+ offset: offset,
+ targetOffset: targetOffset,
+ manualOffset: manualOffset,
+ manualTargetOffset: manualTargetOffset,
+ scrollbarSize: scrollbarSize
+ });
+ if ((ret == null) || typeof ret !== 'object') {
+ continue;
+ } else if (ret === false) {
+ return false;
+ } else {
+ top = ret.top, left = ret.left;
+ }
+ }
+ next = {
+ page: {
+ top: top,
+ left: left
+ },
+ viewport: {
+ top: top - pageYOffset,
+ bottom: pageYOffset - top - height + innerHeight,
+ left: left - pageXOffset,
+ right: pageXOffset - left - width + innerWidth
+ }
+ };
+ if (document.body.scrollWidth > window.innerWidth) {
+ scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+ next.viewport.bottom -= scrollbarSize.height;
+ }
+ if (document.body.scrollHeight > window.innerHeight) {
+ scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+ next.viewport.right -= scrollbarSize.width;
+ }
+ if (((_ref3 = document.body.style.position) !== '' && _ref3 !== 'static') || ((_ref4 = document.body.parentElement.style.position) !== '' && _ref4 !== 'static')) {
+ next.page.bottom = document.body.scrollHeight - top - height;
+ next.page.right = document.body.scrollWidth - left - width;
+ }
+ if (((_ref5 = this.options.optimizations) != null ? _ref5.moveElement : void 0) !== false && (this.targetModifier == null)) {
+ offsetParent = this.cache('target-offsetparent', function() {
+ return getOffsetParent(_this.target);
+ });
+ offsetPosition = this.cache('target-offsetparent-bounds', function() {
+ return getBounds(offsetParent);
+ });
+ offsetParentStyle = getComputedStyle(offsetParent);
+ elementStyle = getComputedStyle(this.element);
+ offsetParentSize = offsetPosition;
+ offsetBorder = {};
+ _ref6 = ['Top', 'Left', 'Bottom', 'Right'];
+ for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) {
+ side = _ref6[_j];
+ offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle["border" + side + "Width"]);
+ }
+ offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
+ offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
+ if (next.page.top >= (offsetPosition.top + offsetBorder.top) && next.page.bottom >= offsetPosition.bottom) {
+ if (next.page.left >= (offsetPosition.left + offsetBorder.left) && next.page.right >= offsetPosition.right) {
+ scrollTop = offsetParent.scrollTop;
+ scrollLeft = offsetParent.scrollLeft;
+ next.offset = {
+ top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
+ left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
+ };
+ }
+ }
+ }
+ this.move(next);
+ this.history.unshift(next);
+ if (this.history.length > 3) {
+ this.history.pop();
+ }
+ if (flushChanges) {
+ flush();
+ }
+ return true;
+ };
+
+ _Tether.prototype.move = function(position) {
+ var css, elVal, found, key, moved, offsetParent, point, same, transcribe, type, val, write, writeCSS, _i, _len, _ref1, _ref2,
+ _this = this;
+ if (this.element.parentNode == null) {
+ return;
+ }
+ same = {};
+ for (type in position) {
+ same[type] = {};
+ for (key in position[type]) {
+ found = false;
+ _ref1 = this.history;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ point = _ref1[_i];
+ if (!within((_ref2 = point[type]) != null ? _ref2[key] : void 0, position[type][key])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ same[type][key] = true;
+ }
+ }
+ }
+ css = {
+ top: '',
+ left: '',
+ right: '',
+ bottom: ''
+ };
+ transcribe = function(same, pos) {
+ var xPos, yPos, _ref3;
+ if (((_ref3 = _this.options.optimizations) != null ? _ref3.gpu : void 0) !== false) {
+ if (same.top) {
+ css.top = 0;
+ yPos = pos.top;
+ } else {
+ css.bottom = 0;
+ yPos = -pos.bottom;
+ }
+ if (same.left) {
+ css.left = 0;
+ xPos = pos.left;
+ } else {
+ css.right = 0;
+ xPos = -pos.right;
+ }
+ css[transformKey] = "translateX(" + (Math.round(xPos)) + "px) translateY(" + (Math.round(yPos)) + "px)";
+ if (transformKey !== 'msTransform') {
+ return css[transformKey] += " translateZ(0)";
+ }
+ } else {
+ if (same.top) {
+ css.top = "" + pos.top + "px";
+ } else {
+ css.bottom = "" + pos.bottom + "px";
+ }
+ if (same.left) {
+ return css.left = "" + pos.left + "px";
+ } else {
+ return css.right = "" + pos.right + "px";
+ }
+ }
+ };
+ moved = false;
+ if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
+ css.position = 'absolute';
+ transcribe(same.page, position.page);
+ } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
+ css.position = 'fixed';
+ transcribe(same.viewport, position.viewport);
+ } else if ((same.offset != null) && same.offset.top && same.offset.left) {
+ css.position = 'absolute';
+ offsetParent = this.cache('target-offsetparent', function() {
+ return getOffsetParent(_this.target);
+ });
+ if (getOffsetParent(this.element) !== offsetParent) {
+ defer(function() {
+ _this.element.parentNode.removeChild(_this.element);
+ return offsetParent.appendChild(_this.element);
+ });
+ }
+ transcribe(same.offset, position.offset);
+ moved = true;
+ } else {
+ css.position = 'absolute';
+ transcribe({
+ top: true,
+ left: true
+ }, position.page);
+ }
+ if (!moved && this.element.parentNode.tagName !== 'BODY') {
+ this.element.parentNode.removeChild(this.element);
+ document.body.appendChild(this.element);
+ }
+ writeCSS = {};
+ write = false;
+ for (key in css) {
+ val = css[key];
+ elVal = this.element.style[key];
+ if (elVal !== '' && val !== '' && (key === 'top' || key === 'left' || key === 'bottom' || key === 'right')) {
+ elVal = parseFloat(elVal);
+ val = parseFloat(val);
+ }
+ if (elVal !== val) {
+ write = true;
+ writeCSS[key] = css[key];
+ }
+ }
+ if (write) {
+ return defer(function() {
+ return extend(_this.element.style, writeCSS);
+ });
+ }
+ };
+
+ return _Tether;
+
+ })();
+
+ Tether.position = position;
+
+ this.Tether = extend(_Tether, Tether);
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/js/tether.min.js b/afb-client/bower_components/tether/js/tether.min.js
new file mode 100644
index 0000000..e8993a1
--- /dev/null
+++ b/afb-client/bower_components/tether/js/tether.min.js
@@ -0,0 +1,2 @@
+/*! tether.js 0.2.9 */
+(function(){var a,b,c,d,e,f,g,h,i={}.hasOwnProperty,j=[].slice;null==window.Tether&&(window.Tether={}),f=function(a){var b,c,d,e,f;if(c=getComputedStyle(a).position,"fixed"===c)return a;for(d=void 0,b=a;b=b.parentNode;){if(!(e=getComputedStyle(b)))return b;if(/(auto|scroll)/.test(e.overflow+e["overflow-y"]+e["overflow-x"])&&("absolute"!==c||"relative"===(f=e.position)||"absolute"===f||"fixed"===f))return b}return document.body},d=function(a){var b,d,e,f;return d=a.ownerDocument,e=d.documentElement,b=c({},a.getBoundingClientRect()),b.top=b.top+window.pageYOffset-e.clientTop,b.left=b.left+window.pageXOffset-e.clientLeft,b.right=d.body.clientWidth-b.width-b.left,b.bottom=d.body.clientHeight-b.height-b.top,b.height&&b.width||(f=getComputedStyle(a),b.height||(b.height=parseFloat(f.height)),b.width||(b.width=parseFloat(f.width))),b},e=function(a){return a.offsetParent||document.documentElement},c=function(a){var b,c,d,e,f,g,h;for(null==a&&(a={}),b=[],Array.prototype.push.apply(b,arguments),h=b.slice(1),f=0,g=h.length;g>f;f++)if(d=h[f])for(c in d)i.call(d,c)&&(e=d[c],a[c]=e);return a},h=function(a,b){var c,d,e,f,g;if(null!=a.classList){for(f=b.split(" "),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(a.classList.remove(c));return g}return a.className=a.className.replace(new RegExp("(^| )"+b.split(" ").join("|")+"( |$)","gi")," ")},b=function(a,b){var c,d,e,f,g;if(null!=a.classList){for(f=b.split(" "),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(a.classList.add(c));return g}return h(a,b),a.className+=" "+b},g=function(a,b){return null!=a.classList?a.classList.contains(b):new RegExp("(^| )"+b+"( |$)","gi").test(a.className)},a=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];c<this.bindings[a].length;)this.bindings[a][c].handler===b?e.push(this.bindings[a].splice(c,1)):e.push(c++);return e}},a.prototype.trigger=function(){var a,b,c,d,e,f,g,h,i;if(c=arguments[0],a=2<=arguments.length?j.call(arguments,1):[],null!=(g=this.bindings)?g[c]:void 0){for(e=0,i=[];e<this.bindings[c].length;)h=this.bindings[c][e],d=h.handler,b=h.ctx,f=h.once,d.apply(null!=b?b:this,a),f?i.push(this.bindings[c].splice(e,1)):i.push(e++);return i}},a}(),Tether.Utils={getScrollParent:f,getBounds:d,getOffsetParent:e,extend:c,addClass:b,removeClass:h,hasClass:g,Evented:a}}).call(this),function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=[].slice,C=function(a,b){return function(){return a.apply(b,arguments)}};for(z=Tether.Utils,n=z.getScrollParent,o=z.getSize,m=z.getOuterSize,k=z.getBounds,l=z.getOffsetParent,j=z.extend,d=z.addClass,u=z.removeClass,h=function(a,b){var c;return null==b&&(b=16),c=!1,function(){var d,e=this;if(!c)return d=arguments,c=!0,setTimeout(function(){return c=!1,a.apply(e,d)},b)}},v=[],t=function(){var a,b,c,d;for(d=[],b=0,c=v.length;c>b;b++)a=v[b],d.push(a.position());return d},p=null,A=["resize","scroll"],x=0,y=A.length;y>x;x++)i=A[x],window.addEventListener(i,function(){return null==p||new Date-p>16?(p=+new Date,t()):void 0});a={center:"center",left:"right",right:"left"},b={middle:"middle",top:"bottom",bottom:"top"},c={top:0,left:0,middle:"50%",center:"50%",bottom:"100%",right:"100%"},g=function(c,d){var e,f;return e=c.left,f=c.top,"auto"===e&&(e=a[d.left]),"auto"===f&&(f=b[d.top]),{left:e,top:f}},f=function(a){var b,d;return{left:null!=(b=c[a.left])?b:a.left,top:null!=(d=c[a.top])?d:a.top}},e=function(){var a,b,c,d,e,f,g;for(b=1<=arguments.length?B.call(arguments,0):[],c={top:0,left:0},e=0,f=b.length;f>e;e++)g=b[e],d=g.top,a=g.left,"string"==typeof d&&(d=parseFloat(d,10)),"string"==typeof a&&(a=parseFloat(a,10)),c.top+=d,c.left+=a;return c},q=function(a,b){return"string"==typeof a.left&&-1!==a.left.indexOf("%")&&(a.left=parseFloat(a.left,10)/100*b.width),"string"==typeof a.top&&-1!==a.top.indexOf("%")&&(a.top=parseFloat(a.top,10)/100*b.height),a},r=s=function(a){var b,c,d;return d=a.split(" "),c=d[0],b=d[1],{top:c,left:b}},w=function(){function a(a){this.position=C(this.position,this);var b,c,d,e,f;for(v.push(this),this.history=[],this.setOptions(a,!1),e=Tether.modules,c=0,d=e.length;d>c;c++)b=e[c],null!=(f=b.initialize)&&f.call(this);this.position()}return a.modules=[],a.prototype.getClass=function(a){var b,c;return(null!=(b=this.options.classes)?b[a]:void 0)?this.options.classes[a]:(null!=(c=this.options.classes)?c[a]:void 0)!==!1?this.options.classPrefix?""+this.options.classPrefix+"-"+a:a:""},a.prototype.setOptions=function(a,b){var c,e,f,g,h,i;for(this.options=a,null==b&&(b=!0),c={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto",classPrefix:"tether"},this.options=j(c,this.options),h=this.options,this.element=h.element,this.target=h.target,this.targetModifier=h.targetModifier,"viewport"===this.target?(this.target=document.body,this.targetModifier="visible"):"scroll-handle"===this.target&&(this.target=document.body,this.targetModifier="scroll-handle"),i=["element","target"],f=0,g=i.length;g>f;f++)if(e=i[f],null!=this[e].jquery?this[e]=this[e][0]:"string"==typeof this[e]&&(this[e]=document.querySelector(this[e])),null==this[e])throw new Error("Tether Error: Both element and target must be defined");if(d(this.element,this.getClass("element")),d(this.target,this.getClass("target")),!this.options.attachment)throw new Error("Tether Error: You must provide an attachment");return this.targetAttachment=r(this.options.targetAttachment),this.attachment=r(this.options.attachment),this.offset=s(this.options.offset),this.targetOffset=s(this.options.targetOffset),null!=this.scrollParent&&this.disable(),this.scrollParent=n(this.target),this.options.enabled!==!1?this.enable(b):void 0},a.prototype.getTargetBounds=function(){if(null==this.targetModifier)return k(this.target);switch(this.targetModifier){case"visible":return{top:pageYOffset,left:pageXOffset,height:innerHeight,width:innerWidth};case"scroll-handle":return{top:pageYOffset+innerHeight*(pageYOffset/document.body.scrollHeight),left:innerWidth-15,height:.98*innerHeight*(innerHeight/document.body.scrollHeight),width:15}}},a.prototype.clearCache=function(){return this._cache={}},a.prototype.cache=function(a,b){return null==this._cache&&(this._cache={}),null==this._cache[a]&&(this._cache[a]=b.call(this)),this._cache[a]},a.prototype.enable=function(a){var b=this;return null==a&&(a=!0),this.addClass(this.getClass("enabled")),this.enabled=!0,this.scrollParent.addEventListener("scroll",this.position),a?setTimeout(function(){return b.position()}):void 0},a.prototype.disable=function(){return this.removeClass(this.getClass("enabled")),this.enabled=!1,null!=this.scrollParent?this.scrollParent.removeEventListener("scroll",this.position):void 0},a.prototype.destroy=function(){var a,b,c,d,e;for(this.disable(),e=[],a=c=0,d=v.length;d>c;a=++c){if(b=v[a],b===this){v.splice(a,1);break}e.push(void 0)}return e},a.prototype.updateAttachClasses=function(a,b){var c,d,e,f,g,h;for(null==a&&(a=this.attachment),null==b&&(b=this.targetAttachment),d=["left","top","bottom","right","middle","center"],e=0,g=d.length;g>e;e++)c=d[e],this.removeClass(""+this.getClass("element-attached")+"-"+c);for(a.top&&this.addClass(""+this.getClass("element-attached")+"-"+a.top),a.left&&this.addClass(""+this.getClass("element-attached")+"-"+a.left),f=0,h=d.length;h>f;f++)c=d[f],this.removeClass(""+this.getClass("target-attached")+"-"+c);return b.top&&this.addClass(""+this.getClass("target-attached")+"-"+b.top),b.left?this.addClass(""+this.getClass("target-attached")+"-"+b.left):void 0},a.prototype.addClass=function(a){return d(this.element,a),d(this.target,a)},a.prototype.removeClass=function(a){return u(this.element,a),u(this.target,a)},a.prototype.position=function(){var a,b,c,d,h,i,j,m,n,o,p,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K=this;if(this.enabled){for(this.clearCache(),x=g(this.targetAttachment,this.attachment),this.updateAttachClasses(this.attachment,x),a=this.cache("element-bounds",function(){return k(K.element)}),C=a.width,b=a.height,A=z=this.cache("target-bounds",function(){return K.getTargetBounds()}),m=q(f(this.attachment),{width:C,height:b}),y=q(f(x),A),d=q(this.offset,{width:C,height:b}),h=q(this.targetOffset,A),m=e(m,d),c=z.left+y.left-m.left,B=z.top+y.top-m.top,H=Tether.modules,D=0,F=H.length;F>D;D++)if(i=H[D],t=i.position.call(this,{left:c,top:B,targetAttachment:x,targetPos:z,elementPos:a,offset:m,targetOffset:y,manualOffset:d,manualTargetOffset:h}),null!=t&&"object"==typeof t){if(t===!1)return!1;B=t.top,c=t.left}if(j={page:{top:B,bottom:document.body.scrollHeight-B-b,left:c,right:document.body.scrollWidth-c-C},viewport:{top:B-pageYOffset,bottom:pageYOffset-B-b+innerHeight,left:c-pageXOffset,right:pageXOffset-c-C+innerWidth}},(null!=(I=this.options.optimizations)?I.moveElement:void 0)!==!1&&null==this.targetModifier){for(o=this.cache("target-offsetparent",function(){return l(K.target)}),s=this.cache("target-offsetparent-bounds",function(){return k(o)}),r=getComputedStyle(o),p=s,n={},J=["top","left","bottom","right"],E=0,G=J.length;G>E;E++)w=J[E],n[w]=parseFloat(r["border-"+w+"-width"]);s.left+=n.left,s.top+=n.top,s.right=document.body.scrollWidth-s.left-p.width,s.bottom=document.body.scrollHeight-s.top-p.height,j.page.top>=s.top&&j.page.bottom>=s.bottom&&j.page.left>=s.left&&j.page.right>=s.right&&(v=o.scrollTop,u=o.scrollLeft,j.offset={top:j.page.top-s.top+v+n.top,left:j.page.left-s.left+u+n.left,right:j.page.right-s.right+o.scrollWidth-u+n.right,bottom:j.page.bottom-s.bottom+o.scrollHeight-v+n.bottom})}return this.move(j),this.history.unshift(j),this.history.length>3&&this.history.pop(),!0}},a.prototype.move=function(a){var b,c,d,e,f,g,h,i,k,m,n,o,p,q,r,s,t,u,v,w,x,y=this;if(null!=this.element.parentNode){k={};for(o in a){k[o]={};for(d in a[o]){for(c=!1,v=this.history,r=0,t=v.length;t>r;r++)if(i=v[r],(null!=(w=i[o])?w[d]:void 0)!==a[o][d]){c=!0;break}c||(k[o][d]=!0)}}if(b={top:"",left:"",right:"",bottom:""},n=function(a,c){return a.top?b.top=""+c.top+"px":b.bottom=""+c.bottom+"px",a.left?b.left=""+c.left+"px":b.right=""+c.right+"px"},e=!1,(k.page.top||k.page.bottom)&&(k.page.left||k.page.right))b.position="absolute",n(k.page,a.page);else if((k.viewport.top||k.viewport.bottom)&&(k.viewport.left||k.viewport.right))b.position="fixed",n(k.viewport,a.viewport);else if(null!=k.offset&&(k.offset.top||k.offset.bottom)&&(k.offset.left||k.offset.right)){for(b.position="absolute",g=this.cache("target-offsetparent",function(){return l(y.target)}),l(this.element)!==g&&(this.element.parentNode.removeChild(this.element),g.appendChild(this.element)),h=getComputedStyle(g),f=j({},a.offset),x=["top","left","bottom","right"],s=0,u=x.length;u>s;s++)m=x[s],f[m]-=parseFloat(h["border-"+m+"-width"]);n(k.offset,f),e=!0}else b.position="absolute",b.top=""+a.page.top+"px",b.left=""+a.page.left+"px";e||"BODY"===this.element.parentNode.tagName||(this.element.parentNode.removeChild(this.element),document.body.appendChild(this.element)),q=!1;for(d in b)if(p=b[d],this.element.style[d]!==p){q=!0;break}return q?j(this.element.style,b):void 0}},a}(),window.Tether=j(w,Tether)}.call(this),function(){var a,b,c,d,e,f,g,h,i=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};h=Tether.Utils,f=h.getOuterSize,e=h.getBounds,g=h.getSize,c=h.extend,b={left:"right",right:"left",top:"bottom",bottom:"top",middle:"middle"},a=["left","top","right","bottom"],d=function(b,c){var d,f,g,h,i,j,k;if("scrollParent"===c?c=b.scrollParent:"window"===c&&(c=[pageXOffset,pageYOffset,innerWidth+pageXOffset,innerHeight+pageYOffset]),null!=c.nodeType)for(f=h=e(c),i=getComputedStyle(c),c=[f.left,f.top,h.width+f.left,h.height+f.top],d=j=0,k=a.length;k>j;d=++j)g=a[d],"top"===g||"left"===g?c[d]+=parseFloat(i["border-"+g+"-width"]):c[d]-=parseFloat(i["border-"+g+"-width"]);return c},Tether.modules.push({position:function(b){var f,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W=this;if(E=b.top,o=b.left,z=b.targetAttachment,!this.options.constraints)return!0;for(v=function(b){var c,d,e,f;for(W.removeClass(b),f=[],d=0,e=a.length;e>d;d++)c=a[d],f.push(W.removeClass(""+b+"-"+c));return f},Q=this.cache("element-bounds",function(){return e(W.element)}),n=Q.height,F=Q.width,B=this.cache("target-bounds",function(){return W.getTargetBounds()}),A=B.height,C=B.width,y={},m={},w=[this.getClass("pinned"),this.getClass("out-of-bounds")],R=this.options.constraints,G=0,K=R.length;K>G;G++)l=R[G],l.outOfBoundsClass&&w.push(l.outOfBoundsClass),l.pinnedClass&&w.push(l.pinnedClass);for(H=0,L=w.length;L>H;H++)k=w[H],v(k);for(y=c({},z),m=c({},this.attachment),S=this.options.constraints,I=0,M=S.length;M>I;I++){if(l=S[I],D=l.to,f=l.attachment,s=l.pin,null==f&&(f=""),i.call(f," ")>=0?(T=f.split(" "),j=T[0],h=T[1]):h=j=f,g=d(this,D),("target"===j||"both"===j)&&(E<g[1]&&"top"===y.top&&(E+=A,y.top="bottom"),E+n>g[3]&&"bottom"===y.top&&(E-=A,y.top="top")),"together"===j&&(E<g[1]&&"top"===y.top&&("bottom"===m.top?(E+=A,y.top="bottom",E+=n,m.top="top"):"top"===m.top&&(E+=A,y.top="bottom",E-=n,m.top="bottom")),E+n>g[3]&&"bottom"===y.top&&("top"===m.top?(E-=A,y.top="top",E-=n,m.top="bottom"):"bottom"===m.top&&(E-=A,y.top="top",E+=n,m.top="top"))),("target"===h||"both"===h)&&(o<g[0]&&"left"===y.left&&(o+=C,y.left="right"),o+F>g[2]&&"right"===y.left&&(o-=C,y.left="left")),"together"===h&&(o<g[0]&&"left"===y.left?"right"===m.left?(o+=C,y.left="right",o+=F,m.left="left"):"left"===m.left&&(o+=C,y.left="right",o-=F,m.left="right"):o+F>g[2]&&"right"===y.left&&("left"===m.left?(o-=C,y.left="left",o-=F,m.left="right"):"right"===m.left&&(o-=C,y.left="left",o+=F,m.left="left"))),("element"===j||"both"===j)&&(E<g[1]&&"bottom"===m.top&&(E+=n,m.top="top"),E+n>g[3]&&"top"===m.top&&(E-=n,m.top="bottom")),("element"===h||"both"===h)&&(o<g[0]&&"right"===m.left&&(o+=F,m.left="left"),o+F>g[2]&&"left"===m.left&&(o-=F,m.left="right")),"string"==typeof s?s=function(){var a,b,c,d;for(c=s.split(","),d=[],a=0,b=c.length;b>a;a++)r=c[a],d.push(r.trim());return d}():s===!0&&(s=["top","left","right","bottom"]),s||(s=[]),t=[],p=[],E<g[1]&&(i.call(s,"top")>=0?(E=g[1],t.push("top")):p.push("top")),E+n>g[3]&&(i.call(s,"bottom")>=0?(E=g[3]-n,t.push("bottom")):p.push("bottom")),o<g[0]&&(i.call(s,"left")>=0?(o=g[0],t.push("left")):p.push("left")),o+F>g[2]&&(i.call(s,"right")>=0?(o=g[2]-F,t.push("right")):p.push("right")),t.length)for(u=null!=(U=this.options.pinnedClass)?U:this.getClass("pinned"),this.addClass(u),J=0,N=t.length;N>J;J++)x=t[J],this.addClass(""+u+"-"+x);if(p.length)for(q=null!=(V=this.options.outOfBoundsClass)?V:this.getClass("out-of-bounds"),this.addClass(q),P=0,O=p.length;O>P;P++)x=p[P],this.addClass(""+q+"-"+x);(i.call(t,"left")>=0||i.call(t,"right")>=0)&&(m.left=y.left=!1),(i.call(t,"top")>=0||i.call(t,"bottom")>=0)&&(m.top=y.top=!1),(y.top!==z.top||y.left!==z.left||m.top!==this.attachment.top||m.left!==this.attachment.left)&&this.updateAttachClasses(m,y)}return{top:E,left:o}}})}.call(this),function(){var a;a=Tether.Utils.getBounds,Tether.modules.push({position:function(b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z=this;if(k=b.top,f=b.left,u=this.cache("element-bounds",function(){return a(z.element)}),e=u.height,l=u.width,j=this.getTargetBounds(),d=k+e,g=f+l,c=[],k<=j.bottom&&d>=j.top)for(v=["left","right"],m=0,q=v.length;q>m;m++)h=v[m],((w=j[h])===f||w===g)&&c.push(h);if(f<=j.right&&g>=j.left)for(x=["top","bottom"],n=0,r=x.length;r>n;n++)h=x[n],((y=j[h])===k||y===d)&&c.push(h);for(i=["left","top","right","bottom"],this.removeClass(this.getClass("abutted")),o=0,s=i.length;s>o;o++)h=i[o],this.removeClass(""+this.getClass("abutted")+"-"+h);for(c.length&&this.addClass(this.getClass("abutted")),p=0,t=c.length;t>p;p++)h=c[p],this.addClass(""+this.getClass("abutted")+"-"+h);return!0}})}.call(this),function(){Tether.modules.push({position:function(a){var b,c,d,e,f,g,h;return g=a.top,b=a.left,this.options.shift?(c=function(a){return"function"==typeof a?a.call(this,{top:g,left:b}):a},d=c(this.options.shift),"string"==typeof d?(d=d.split(" "),d[1]||(d[1]=d[0]),f=d[0],e=d[1],f=parseFloat(f,10),e=parseFloat(e,10)):(h=[d.top,d.left],f=h[0],e=h[1]),g+=f,b+=e,{top:g,left:b}):void 0}})}.call(this); \ No newline at end of file
diff --git a/afb-client/bower_components/tether/js/utils.js b/afb-client/bower_components/tether/js/utils.js
new file mode 100644
index 0000000..b255103
--- /dev/null
+++ b/afb-client/bower_components/tether/js/utils.js
@@ -0,0 +1,331 @@
+(function() {
+ var Evented, addClass, defer, deferred, extend, flush, getBounds, getOffsetParent, getOrigin, getScrollBarSize, getScrollParent, hasClass, node, removeClass, uniqueId, updateClasses, zeroPosCache,
+ __hasProp = {}.hasOwnProperty,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ __slice = [].slice;
+
+ if (this.Tether == null) {
+ this.Tether = {
+ modules: []
+ };
+ }
+
+ getScrollParent = function(el) {
+ var parent, position, scrollParent, style, _ref;
+ position = getComputedStyle(el).position;
+ if (position === 'fixed') {
+ return el;
+ }
+ scrollParent = void 0;
+ parent = el;
+ while (parent = parent.parentNode) {
+ try {
+ style = getComputedStyle(parent);
+ } catch (_error) {}
+ if (style == null) {
+ return parent;
+ }
+ if (/(auto|scroll)/.test(style['overflow'] + style['overflow-y'] + style['overflow-x'])) {
+ if (position !== 'absolute' || ((_ref = style['position']) === 'relative' || _ref === 'absolute' || _ref === 'fixed')) {
+ return parent;
+ }
+ }
+ }
+ return document.body;
+ };
+
+ uniqueId = (function() {
+ var id;
+ id = 0;
+ return function() {
+ return id++;
+ };
+ })();
+
+ zeroPosCache = {};
+
+ getOrigin = function(doc) {
+ var id, k, node, v, _ref;
+ node = doc._tetherZeroElement;
+ if (node == null) {
+ node = doc.createElement('div');
+ node.setAttribute('data-tether-id', uniqueId());
+ extend(node.style, {
+ top: 0,
+ left: 0,
+ position: 'absolute'
+ });
+ doc.body.appendChild(node);
+ doc._tetherZeroElement = node;
+ }
+ id = node.getAttribute('data-tether-id');
+ if (zeroPosCache[id] == null) {
+ zeroPosCache[id] = {};
+ _ref = node.getBoundingClientRect();
+ for (k in _ref) {
+ v = _ref[k];
+ zeroPosCache[id][k] = v;
+ }
+ defer(function() {
+ return zeroPosCache[id] = void 0;
+ });
+ }
+ return zeroPosCache[id];
+ };
+
+ node = null;
+
+ getBounds = function(el) {
+ var box, doc, docEl, k, origin, v, _ref;
+ if (el === document) {
+ doc = document;
+ el = document.documentElement;
+ } else {
+ doc = el.ownerDocument;
+ }
+ docEl = doc.documentElement;
+ box = {};
+ _ref = el.getBoundingClientRect();
+ for (k in _ref) {
+ v = _ref[k];
+ box[k] = v;
+ }
+ origin = getOrigin(doc);
+ box.top -= origin.top;
+ box.left -= origin.left;
+ if (box.width == null) {
+ box.width = document.body.scrollWidth - box.left - box.right;
+ }
+ if (box.height == null) {
+ box.height = document.body.scrollHeight - box.top - box.bottom;
+ }
+ box.top = box.top - docEl.clientTop;
+ box.left = box.left - docEl.clientLeft;
+ box.right = doc.body.clientWidth - box.width - box.left;
+ box.bottom = doc.body.clientHeight - box.height - box.top;
+ return box;
+ };
+
+ getOffsetParent = function(el) {
+ return el.offsetParent || document.documentElement;
+ };
+
+ getScrollBarSize = function() {
+ var inner, outer, width, widthContained, widthScroll;
+ inner = document.createElement('div');
+ inner.style.width = '100%';
+ inner.style.height = '200px';
+ outer = document.createElement('div');
+ extend(outer.style, {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ pointerEvents: 'none',
+ visibility: 'hidden',
+ width: '200px',
+ height: '150px',
+ overflow: 'hidden'
+ });
+ outer.appendChild(inner);
+ document.body.appendChild(outer);
+ widthContained = inner.offsetWidth;
+ outer.style.overflow = 'scroll';
+ widthScroll = inner.offsetWidth;
+ if (widthContained === widthScroll) {
+ widthScroll = outer.clientWidth;
+ }
+ document.body.removeChild(outer);
+ width = widthContained - widthScroll;
+ return {
+ width: width,
+ height: width
+ };
+ };
+
+ extend = function(out) {
+ var args, key, obj, val, _i, _len, _ref;
+ if (out == null) {
+ out = {};
+ }
+ args = [];
+ Array.prototype.push.apply(args, arguments);
+ _ref = args.slice(1);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ obj = _ref[_i];
+ if (obj) {
+ for (key in obj) {
+ if (!__hasProp.call(obj, key)) continue;
+ val = obj[key];
+ out[key] = val;
+ }
+ }
+ }
+ return out;
+ };
+
+ removeClass = function(el, name) {
+ var cls, _i, _len, _ref, _results;
+ if (el.classList != null) {
+ _ref = name.split(' ');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ cls = _ref[_i];
+ if (cls.trim()) {
+ _results.push(el.classList.remove(cls));
+ }
+ }
+ return _results;
+ } else {
+ return el.className = el.className.replace(new RegExp("(^| )" + (name.split(' ').join('|')) + "( |$)", 'gi'), ' ');
+ }
+ };
+
+ addClass = function(el, name) {
+ var cls, _i, _len, _ref, _results;
+ if (el.classList != null) {
+ _ref = name.split(' ');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ cls = _ref[_i];
+ if (cls.trim()) {
+ _results.push(el.classList.add(cls));
+ }
+ }
+ return _results;
+ } else {
+ removeClass(el, name);
+ return el.className += " " + name;
+ }
+ };
+
+ hasClass = function(el, name) {
+ if (el.classList != null) {
+ return el.classList.contains(name);
+ } else {
+ return new RegExp("(^| )" + name + "( |$)", 'gi').test(el.className);
+ }
+ };
+
+ updateClasses = function(el, add, all) {
+ var cls, _i, _j, _len, _len1, _results;
+ for (_i = 0, _len = all.length; _i < _len; _i++) {
+ cls = all[_i];
+ if (__indexOf.call(add, cls) < 0) {
+ if (hasClass(el, cls)) {
+ removeClass(el, cls);
+ }
+ }
+ }
+ _results = [];
+ for (_j = 0, _len1 = add.length; _j < _len1; _j++) {
+ cls = add[_j];
+ if (!hasClass(el, cls)) {
+ _results.push(addClass(el, cls));
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ };
+
+ deferred = [];
+
+ defer = function(fn) {
+ return deferred.push(fn);
+ };
+
+ flush = function() {
+ var fn, _results;
+ _results = [];
+ while (fn = deferred.pop()) {
+ _results.push(fn());
+ }
+ return _results;
+ };
+
+ Evented = (function() {
+ function Evented() {}
+
+ Evented.prototype.on = function(event, handler, ctx, once) {
+ var _base;
+ if (once == null) {
+ once = false;
+ }
+ if (this.bindings == null) {
+ this.bindings = {};
+ }
+ if ((_base = this.bindings)[event] == null) {
+ _base[event] = [];
+ }
+ return this.bindings[event].push({
+ handler: handler,
+ ctx: ctx,
+ once: once
+ });
+ };
+
+ Evented.prototype.once = function(event, handler, ctx) {
+ return this.on(event, handler, ctx, true);
+ };
+
+ Evented.prototype.off = function(event, handler) {
+ var i, _ref, _results;
+ if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) {
+ return;
+ }
+ if (handler == null) {
+ return delete this.bindings[event];
+ } else {
+ i = 0;
+ _results = [];
+ while (i < this.bindings[event].length) {
+ if (this.bindings[event][i].handler === handler) {
+ _results.push(this.bindings[event].splice(i, 1));
+ } else {
+ _results.push(i++);
+ }
+ }
+ return _results;
+ }
+ };
+
+ Evented.prototype.trigger = function() {
+ var args, ctx, event, handler, i, once, _ref, _ref1, _results;
+ event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ if ((_ref = this.bindings) != null ? _ref[event] : void 0) {
+ i = 0;
+ _results = [];
+ while (i < this.bindings[event].length) {
+ _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once;
+ handler.apply(ctx != null ? ctx : this, args);
+ if (once) {
+ _results.push(this.bindings[event].splice(i, 1));
+ } else {
+ _results.push(i++);
+ }
+ }
+ return _results;
+ }
+ };
+
+ return Evented;
+
+ })();
+
+ this.Tether.Utils = {
+ getScrollParent: getScrollParent,
+ getBounds: getBounds,
+ getOffsetParent: getOffsetParent,
+ extend: extend,
+ addClass: addClass,
+ removeClass: removeClass,
+ hasClass: hasClass,
+ updateClasses: updateClasses,
+ defer: defer,
+ flush: flush,
+ uniqueId: uniqueId,
+ Evented: Evented,
+ getScrollBarSize: getScrollBarSize
+ };
+
+}).call(this);
diff --git a/afb-client/bower_components/tether/package.json b/afb-client/bower_components/tether/package.json
new file mode 100644
index 0000000..ca4b80d
--- /dev/null
+++ b/afb-client/bower_components/tether/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "tether",
+ "version": "0.6.5",
+ "description": "A client-side library to make absolutely positioned elements attach to elements in the page efficiently.",
+ "authors": [
+ "Zack Bloom <zackbloom@gmail.com>",
+ "Adam Schwartz <adam.flynn.schwartz@gmail.com>"
+ ],
+ "license": "MIT",
+ "devDependencies": {
+ "coffee-script": "~1.6.3",
+ "gulp": "~3.3.0",
+ "gulp-header": "~1.0.2",
+ "gulp-uglify": "~0.1.0",
+ "gulp-compass": "~1.0.3",
+ "gulp-coffee": "~1.2.5",
+ "gulp-concat": "~2.1.7",
+ "gulp-rename": "~0.2.1",
+ "gulp-wrap-umd": "~0.1.0"
+ }
+}
diff --git a/afb-client/bower_components/tether/sass/helpers/_tether-theme-arrows.sass b/afb-client/bower_components/tether/sass/helpers/_tether-theme-arrows.sass
new file mode 100644
index 0000000..999ae4c
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/helpers/_tether-theme-arrows.sass
@@ -0,0 +1,136 @@
+@import compass/css3
+
+=tether-theme-arrows($themePrefix: "tether", $themeName: "arrows", $arrowSize: 16px, $backgroundColor: #fff, $color: inherit, $useDropShadow: false)
+ .#{ $themePrefix }-element.#{ $themePrefix }-theme-#{ $themeName }
+ max-width: 100%
+ max-height: 100%
+
+ .#{ $themePrefix }-content
+ +border-radius(5px)
+ position: relative
+ font-family: inherit
+ background: $backgroundColor
+ color: $color
+ padding: 1em
+ font-size: 1.1em
+ line-height: 1.5em
+
+ @if $useDropShadow
+ +transform(translateZ(0))
+ +filter(drop-shadow(0 1px 4px rgba(0, 0, 0, .2)))
+
+ &:before
+ content: ""
+ display: block
+ position: absolute
+ width: 0
+ height: 0
+ border-color: transparent
+ border-width: $arrowSize
+ border-style: solid
+
+ // Centers and middles
+
+ &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-center .#{ $themePrefix }-content
+ margin-bottom: $arrowSize
+
+ &:before
+ top: 100%
+ left: 50%
+ margin-left: - $arrowSize
+ border-top-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-center .#{ $themePrefix }-content
+ margin-top: $arrowSize
+
+ &:before
+ bottom: 100%
+ left: 50%
+ margin-left: - $arrowSize
+ border-bottom-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-element-attached-middle .#{ $themePrefix }-content
+ margin-right: $arrowSize
+
+ &:before
+ left: 100%
+ top: 50%
+ margin-top: - $arrowSize
+ border-left-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-element-attached-middle .#{ $themePrefix }-content
+ margin-left: $arrowSize
+
+ &:before
+ right: 100%
+ top: 50%
+ margin-top: - $arrowSize
+ border-right-color: $backgroundColor
+
+ // Top and bottom corners
+
+ &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-bottom .#{ $themePrefix }-content
+ margin-top: $arrowSize
+
+ &:before
+ bottom: 100%
+ left: $arrowSize
+ border-bottom-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-bottom .#{ $themePrefix }-content
+ margin-top: $arrowSize
+
+ &:before
+ bottom: 100%
+ right: $arrowSize
+ border-bottom-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-top .#{ $themePrefix }-content
+ margin-bottom: $arrowSize
+
+ &:before
+ top: 100%
+ left: $arrowSize
+ border-top-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-top .#{ $themePrefix }-content
+ margin-bottom: $arrowSize
+
+ &:before
+ top: 100%
+ right: $arrowSize
+ border-top-color: $backgroundColor
+
+ // Side corners
+
+ &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-left .#{ $themePrefix }-content
+ margin-right: $arrowSize
+
+ &:before
+ top: $arrowSize
+ left: 100%
+ border-left-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-right .#{ $themePrefix }-content
+ margin-left: $arrowSize
+
+ &:before
+ top: $arrowSize
+ right: 100%
+ border-right-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-left .#{ $themePrefix }-content
+ margin-right: $arrowSize
+
+ &:before
+ bottom: $arrowSize
+ left: 100%
+ border-left-color: $backgroundColor
+
+ &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-right .#{ $themePrefix }-content
+ margin-left: $arrowSize
+
+ &:before
+ bottom: $arrowSize
+ right: 100%
+ border-right-color: $backgroundColor
diff --git a/afb-client/bower_components/tether/sass/helpers/_tether-theme-basic.sass b/afb-client/bower_components/tether/sass/helpers/_tether-theme-basic.sass
new file mode 100644
index 0000000..34642c2
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/helpers/_tether-theme-basic.sass
@@ -0,0 +1,16 @@
+@import compass/css3
+
+=tether-theme-basic($themePrefix: "tether", $themeName: "basic", $backgroundColor: #fff, $color: inherit)
+ .#{ $themePrefix }-element.#{ $themePrefix }-theme-#{ $themeName }
+ max-width: 100%
+ max-height: 100%
+
+ .#{ $themePrefix }-content
+ +border-radius(5px)
+ +box-shadow(0 2px 8px rgba(0, 0, 0, .2))
+ font-family: inherit
+ background: $backgroundColor
+ color: $color
+ padding: 1em
+ font-size: 1.1em
+ line-height: 1.5em \ No newline at end of file
diff --git a/afb-client/bower_components/tether/sass/helpers/_tether.sass b/afb-client/bower_components/tether/sass/helpers/_tether.sass
new file mode 100644
index 0000000..fc50993
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/helpers/_tether.sass
@@ -0,0 +1,14 @@
+@import compass/css3
+
+=tether($themePrefix: "tether")
+ .#{ $themePrefix }-element, .#{ $themePrefix }-element *
+
+ &, &:after, &:before
+ +box-sizing(border-box)
+
+ .#{ $themePrefix }-element
+ position: absolute
+ display: none
+
+ &.#{ $themePrefix }-open
+ display: block
diff --git a/afb-client/bower_components/tether/sass/mixins/_pointer-events.scss b/afb-client/bower_components/tether/sass/mixins/_pointer-events.scss
new file mode 100644
index 0000000..66c7e77
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/mixins/_pointer-events.scss
@@ -0,0 +1,6 @@
+@mixin pointer-events($type: none) {
+ $type: unquote($type);
+ @include experimental(pointer-events, $type,
+ -moz, -webkit, not -o, not -ms, -khtml, official
+ );
+} \ No newline at end of file
diff --git a/afb-client/bower_components/tether/sass/tether-theme-arrows-dark.sass b/afb-client/bower_components/tether/sass/tether-theme-arrows-dark.sass
new file mode 100644
index 0000000..ad1caf0
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/tether-theme-arrows-dark.sass
@@ -0,0 +1,12 @@
+@import helpers/tether
+@import helpers/tether-theme-arrows
+
+$themePrefix: "tether"
+$themeName: "arrows-dark"
+$arrowSize: 16px
+$backgroundColor: #000
+$color: #fff
+$useDropShadow: false
+
++tether($themePrefix: $themePrefix)
++tether-theme-arrows($themePrefix: $themePrefix, $themeName: $themeName, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow)
diff --git a/afb-client/bower_components/tether/sass/tether-theme-arrows.sass b/afb-client/bower_components/tether/sass/tether-theme-arrows.sass
new file mode 100644
index 0000000..87765b2
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/tether-theme-arrows.sass
@@ -0,0 +1,12 @@
+@import helpers/tether
+@import helpers/tether-theme-arrows
+
+$themePrefix: "tether"
+$themeName: "arrows"
+$arrowSize: 16px
+$backgroundColor: #fff
+$color: inherit
+$useDropShadow: true
+
++tether($themePrefix: $themePrefix)
++tether-theme-arrows($themePrefix: $themePrefix, $themeName: $themeName, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow)
diff --git a/afb-client/bower_components/tether/sass/tether-theme-basic.sass b/afb-client/bower_components/tether/sass/tether-theme-basic.sass
new file mode 100644
index 0000000..9a2be06
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/tether-theme-basic.sass
@@ -0,0 +1,10 @@
+@import helpers/tether
+@import helpers/tether-theme-basic
+
+$themePrefix: "tether"
+$themeName: "basic"
+$backgroundColor: #fff
+$color: inherit
+
++tether($themePrefix: $themePrefix)
++tether-theme-basic($themePrefix: $themePrefix, $themeName: $themeName, $backgroundColor: $backgroundColor, $color: $color) \ No newline at end of file
diff --git a/afb-client/bower_components/tether/sass/tether.sass b/afb-client/bower_components/tether/sass/tether.sass
new file mode 100644
index 0000000..6421016
--- /dev/null
+++ b/afb-client/bower_components/tether/sass/tether.sass
@@ -0,0 +1,5 @@
+@import helpers/tether
+
+$themePrefix: "tether"
+
++tether($themePrefix: $themePrefix) \ No newline at end of file
diff --git a/afb-client/bower_components/tether/tether.js b/afb-client/bower_components/tether/tether.js
new file mode 100644
index 0000000..d5d0261
--- /dev/null
+++ b/afb-client/bower_components/tether/tether.js
@@ -0,0 +1,1443 @@
+/*! tether 0.6.5 */
+
+
+(function(root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(factory);
+ } else if (typeof exports === 'object') {
+ module.exports = factory(require,exports,module);
+ } else {
+ root.Tether = factory();
+ }
+}(this, function(require,exports,module) {
+
+(function() {
+ var Evented, addClass, defer, deferred, extend, flush, getBounds, getOffsetParent, getOrigin, getScrollBarSize, getScrollParent, hasClass, node, removeClass, uniqueId, updateClasses, zeroPosCache,
+ __hasProp = {}.hasOwnProperty,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ __slice = [].slice;
+
+ if (this.Tether == null) {
+ this.Tether = {
+ modules: []
+ };
+ }
+
+ getScrollParent = function(el) {
+ var parent, position, scrollParent, style, _ref;
+ position = getComputedStyle(el).position;
+ if (position === 'fixed') {
+ return el;
+ }
+ scrollParent = void 0;
+ parent = el;
+ while (parent = parent.parentNode) {
+ try {
+ style = getComputedStyle(parent);
+ } catch (_error) {}
+ if (style == null) {
+ return parent;
+ }
+ if (/(auto|scroll)/.test(style['overflow'] + style['overflow-y'] + style['overflow-x'])) {
+ if (position !== 'absolute' || ((_ref = style['position']) === 'relative' || _ref === 'absolute' || _ref === 'fixed')) {
+ return parent;
+ }
+ }
+ }
+ return document.body;
+ };
+
+ uniqueId = (function() {
+ var id;
+ id = 0;
+ return function() {
+ return id++;
+ };
+ })();
+
+ zeroPosCache = {};
+
+ getOrigin = function(doc) {
+ var id, k, node, v, _ref;
+ node = doc._tetherZeroElement;
+ if (node == null) {
+ node = doc.createElement('div');
+ node.setAttribute('data-tether-id', uniqueId());
+ extend(node.style, {
+ top: 0,
+ left: 0,
+ position: 'absolute'
+ });
+ doc.body.appendChild(node);
+ doc._tetherZeroElement = node;
+ }
+ id = node.getAttribute('data-tether-id');
+ if (zeroPosCache[id] == null) {
+ zeroPosCache[id] = {};
+ _ref = node.getBoundingClientRect();
+ for (k in _ref) {
+ v = _ref[k];
+ zeroPosCache[id][k] = v;
+ }
+ defer(function() {
+ return zeroPosCache[id] = void 0;
+ });
+ }
+ return zeroPosCache[id];
+ };
+
+ node = null;
+
+ getBounds = function(el) {
+ var box, doc, docEl, k, origin, v, _ref;
+ if (el === document) {
+ doc = document;
+ el = document.documentElement;
+ } else {
+ doc = el.ownerDocument;
+ }
+ docEl = doc.documentElement;
+ box = {};
+ _ref = el.getBoundingClientRect();
+ for (k in _ref) {
+ v = _ref[k];
+ box[k] = v;
+ }
+ origin = getOrigin(doc);
+ box.top -= origin.top;
+ box.left -= origin.left;
+ if (box.width == null) {
+ box.width = document.body.scrollWidth - box.left - box.right;
+ }
+ if (box.height == null) {
+ box.height = document.body.scrollHeight - box.top - box.bottom;
+ }
+ box.top = box.top - docEl.clientTop;
+ box.left = box.left - docEl.clientLeft;
+ box.right = doc.body.clientWidth - box.width - box.left;
+ box.bottom = doc.body.clientHeight - box.height - box.top;
+ return box;
+ };
+
+ getOffsetParent = function(el) {
+ return el.offsetParent || document.documentElement;
+ };
+
+ getScrollBarSize = function() {
+ var inner, outer, width, widthContained, widthScroll;
+ inner = document.createElement('div');
+ inner.style.width = '100%';
+ inner.style.height = '200px';
+ outer = document.createElement('div');
+ extend(outer.style, {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ pointerEvents: 'none',
+ visibility: 'hidden',
+ width: '200px',
+ height: '150px',
+ overflow: 'hidden'
+ });
+ outer.appendChild(inner);
+ document.body.appendChild(outer);
+ widthContained = inner.offsetWidth;
+ outer.style.overflow = 'scroll';
+ widthScroll = inner.offsetWidth;
+ if (widthContained === widthScroll) {
+ widthScroll = outer.clientWidth;
+ }
+ document.body.removeChild(outer);
+ width = widthContained - widthScroll;
+ return {
+ width: width,
+ height: width
+ };
+ };
+
+ extend = function(out) {
+ var args, key, obj, val, _i, _len, _ref;
+ if (out == null) {
+ out = {};
+ }
+ args = [];
+ Array.prototype.push.apply(args, arguments);
+ _ref = args.slice(1);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ obj = _ref[_i];
+ if (obj) {
+ for (key in obj) {
+ if (!__hasProp.call(obj, key)) continue;
+ val = obj[key];
+ out[key] = val;
+ }
+ }
+ }
+ return out;
+ };
+
+ removeClass = function(el, name) {
+ var cls, _i, _len, _ref, _results;
+ if (el.classList != null) {
+ _ref = name.split(' ');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ cls = _ref[_i];
+ if (cls.trim()) {
+ _results.push(el.classList.remove(cls));
+ }
+ }
+ return _results;
+ } else {
+ return el.className = el.className.replace(new RegExp("(^| )" + (name.split(' ').join('|')) + "( |$)", 'gi'), ' ');
+ }
+ };
+
+ addClass = function(el, name) {
+ var cls, _i, _len, _ref, _results;
+ if (el.classList != null) {
+ _ref = name.split(' ');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ cls = _ref[_i];
+ if (cls.trim()) {
+ _results.push(el.classList.add(cls));
+ }
+ }
+ return _results;
+ } else {
+ removeClass(el, name);
+ return el.className += " " + name;
+ }
+ };
+
+ hasClass = function(el, name) {
+ if (el.classList != null) {
+ return el.classList.contains(name);
+ } else {
+ return new RegExp("(^| )" + name + "( |$)", 'gi').test(el.className);
+ }
+ };
+
+ updateClasses = function(el, add, all) {
+ var cls, _i, _j, _len, _len1, _results;
+ for (_i = 0, _len = all.length; _i < _len; _i++) {
+ cls = all[_i];
+ if (__indexOf.call(add, cls) < 0) {
+ if (hasClass(el, cls)) {
+ removeClass(el, cls);
+ }
+ }
+ }
+ _results = [];
+ for (_j = 0, _len1 = add.length; _j < _len1; _j++) {
+ cls = add[_j];
+ if (!hasClass(el, cls)) {
+ _results.push(addClass(el, cls));
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ };
+
+ deferred = [];
+
+ defer = function(fn) {
+ return deferred.push(fn);
+ };
+
+ flush = function() {
+ var fn, _results;
+ _results = [];
+ while (fn = deferred.pop()) {
+ _results.push(fn());
+ }
+ return _results;
+ };
+
+ Evented = (function() {
+ function Evented() {}
+
+ Evented.prototype.on = function(event, handler, ctx, once) {
+ var _base;
+ if (once == null) {
+ once = false;
+ }
+ if (this.bindings == null) {
+ this.bindings = {};
+ }
+ if ((_base = this.bindings)[event] == null) {
+ _base[event] = [];
+ }
+ return this.bindings[event].push({
+ handler: handler,
+ ctx: ctx,
+ once: once
+ });
+ };
+
+ Evented.prototype.once = function(event, handler, ctx) {
+ return this.on(event, handler, ctx, true);
+ };
+
+ Evented.prototype.off = function(event, handler) {
+ var i, _ref, _results;
+ if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) {
+ return;
+ }
+ if (handler == null) {
+ return delete this.bindings[event];
+ } else {
+ i = 0;
+ _results = [];
+ while (i < this.bindings[event].length) {
+ if (this.bindings[event][i].handler === handler) {
+ _results.push(this.bindings[event].splice(i, 1));
+ } else {
+ _results.push(i++);
+ }
+ }
+ return _results;
+ }
+ };
+
+ Evented.prototype.trigger = function() {
+ var args, ctx, event, handler, i, once, _ref, _ref1, _results;
+ event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ if ((_ref = this.bindings) != null ? _ref[event] : void 0) {
+ i = 0;
+ _results = [];
+ while (i < this.bindings[event].length) {
+ _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once;
+ handler.apply(ctx != null ? ctx : this, args);
+ if (once) {
+ _results.push(this.bindings[event].splice(i, 1));
+ } else {
+ _results.push(i++);
+ }
+ }
+ return _results;
+ }
+ };
+
+ return Evented;
+
+ })();
+
+ this.Tether.Utils = {
+ getScrollParent: getScrollParent,
+ getBounds: getBounds,
+ getOffsetParent: getOffsetParent,
+ extend: extend,
+ addClass: addClass,
+ removeClass: removeClass,
+ hasClass: hasClass,
+ updateClasses: updateClasses,
+ defer: defer,
+ flush: flush,
+ uniqueId: uniqueId,
+ Evented: Evented,
+ getScrollBarSize: getScrollBarSize
+ };
+
+}).call(this);
+
+(function() {
+ var MIRROR_LR, MIRROR_TB, OFFSET_MAP, Tether, addClass, addOffset, attachmentToOffset, autoToFixedAttachment, defer, extend, flush, getBounds, getOffsetParent, getOuterSize, getScrollBarSize, getScrollParent, getSize, now, offsetToPx, parseAttachment, parseOffset, position, removeClass, tethers, transformKey, updateClasses, within, _Tether, _ref,
+ __slice = [].slice,
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+ if (this.Tether == null) {
+ throw new Error("You must include the utils.js file before tether.js");
+ }
+
+ Tether = this.Tether;
+
+ _ref = Tether.Utils, getScrollParent = _ref.getScrollParent, getSize = _ref.getSize, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getOffsetParent = _ref.getOffsetParent, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, updateClasses = _ref.updateClasses, defer = _ref.defer, flush = _ref.flush, getScrollBarSize = _ref.getScrollBarSize;
+
+ within = function(a, b, diff) {
+ if (diff == null) {
+ diff = 1;
+ }
+ return (a + diff >= b && b >= a - diff);
+ };
+
+ transformKey = (function() {
+ var el, key, _i, _len, _ref1;
+ el = document.createElement('div');
+ _ref1 = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ key = _ref1[_i];
+ if (el.style[key] !== void 0) {
+ return key;
+ }
+ }
+ })();
+
+ tethers = [];
+
+ position = function() {
+ var tether, _i, _len;
+ for (_i = 0, _len = tethers.length; _i < _len; _i++) {
+ tether = tethers[_i];
+ tether.position(false);
+ }
+ return flush();
+ };
+
+ now = function() {
+ var _ref1;
+ return (_ref1 = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref1 : +(new Date);
+ };
+
+ (function() {
+ var event, lastCall, lastDuration, pendingTimeout, tick, _i, _len, _ref1, _results;
+ lastCall = null;
+ lastDuration = null;
+ pendingTimeout = null;
+ tick = function() {
+ if ((lastDuration != null) && lastDuration > 16) {
+ lastDuration = Math.min(lastDuration - 16, 250);
+ pendingTimeout = setTimeout(tick, 250);
+ return;
+ }
+ if ((lastCall != null) && (now() - lastCall) < 10) {
+ return;
+ }
+ if (pendingTimeout != null) {
+ clearTimeout(pendingTimeout);
+ pendingTimeout = null;
+ }
+ lastCall = now();
+ position();
+ return lastDuration = now() - lastCall;
+ };
+ _ref1 = ['resize', 'scroll', 'touchmove'];
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ event = _ref1[_i];
+ _results.push(window.addEventListener(event, tick));
+ }
+ return _results;
+ })();
+
+ MIRROR_LR = {
+ center: 'center',
+ left: 'right',
+ right: 'left'
+ };
+
+ MIRROR_TB = {
+ middle: 'middle',
+ top: 'bottom',
+ bottom: 'top'
+ };
+
+ OFFSET_MAP = {
+ top: 0,
+ left: 0,
+ middle: '50%',
+ center: '50%',
+ bottom: '100%',
+ right: '100%'
+ };
+
+ autoToFixedAttachment = function(attachment, relativeToAttachment) {
+ var left, top;
+ left = attachment.left, top = attachment.top;
+ if (left === 'auto') {
+ left = MIRROR_LR[relativeToAttachment.left];
+ }
+ if (top === 'auto') {
+ top = MIRROR_TB[relativeToAttachment.top];
+ }
+ return {
+ left: left,
+ top: top
+ };
+ };
+
+ attachmentToOffset = function(attachment) {
+ var _ref1, _ref2;
+ return {
+ left: (_ref1 = OFFSET_MAP[attachment.left]) != null ? _ref1 : attachment.left,
+ top: (_ref2 = OFFSET_MAP[attachment.top]) != null ? _ref2 : attachment.top
+ };
+ };
+
+ addOffset = function() {
+ var left, offsets, out, top, _i, _len, _ref1;
+ offsets = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ out = {
+ top: 0,
+ left: 0
+ };
+ for (_i = 0, _len = offsets.length; _i < _len; _i++) {
+ _ref1 = offsets[_i], top = _ref1.top, left = _ref1.left;
+ if (typeof top === 'string') {
+ top = parseFloat(top, 10);
+ }
+ if (typeof left === 'string') {
+ left = parseFloat(left, 10);
+ }
+ out.top += top;
+ out.left += left;
+ }
+ return out;
+ };
+
+ offsetToPx = function(offset, size) {
+ if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
+ offset.left = parseFloat(offset.left, 10) / 100 * size.width;
+ }
+ if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
+ offset.top = parseFloat(offset.top, 10) / 100 * size.height;
+ }
+ return offset;
+ };
+
+ parseAttachment = parseOffset = function(value) {
+ var left, top, _ref1;
+ _ref1 = value.split(' '), top = _ref1[0], left = _ref1[1];
+ return {
+ top: top,
+ left: left
+ };
+ };
+
+ _Tether = (function() {
+ _Tether.modules = [];
+
+ function _Tether(options) {
+ this.position = __bind(this.position, this);
+ var module, _i, _len, _ref1, _ref2;
+ tethers.push(this);
+ this.history = [];
+ this.setOptions(options, false);
+ _ref1 = Tether.modules;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ module = _ref1[_i];
+ if ((_ref2 = module.initialize) != null) {
+ _ref2.call(this);
+ }
+ }
+ this.position();
+ }
+
+ _Tether.prototype.getClass = function(key) {
+ var _ref1, _ref2;
+ if ((_ref1 = this.options.classes) != null ? _ref1[key] : void 0) {
+ return this.options.classes[key];
+ } else if (((_ref2 = this.options.classes) != null ? _ref2[key] : void 0) !== false) {
+ if (this.options.classPrefix) {
+ return "" + this.options.classPrefix + "-" + key;
+ } else {
+ return key;
+ }
+ } else {
+ return '';
+ }
+ };
+
+ _Tether.prototype.setOptions = function(options, position) {
+ var defaults, key, _i, _len, _ref1, _ref2;
+ this.options = options;
+ if (position == null) {
+ position = true;
+ }
+ defaults = {
+ offset: '0 0',
+ targetOffset: '0 0',
+ targetAttachment: 'auto auto',
+ classPrefix: 'tether'
+ };
+ this.options = extend(defaults, this.options);
+ _ref1 = this.options, this.element = _ref1.element, this.target = _ref1.target, this.targetModifier = _ref1.targetModifier;
+ if (this.target === 'viewport') {
+ this.target = document.body;
+ this.targetModifier = 'visible';
+ } else if (this.target === 'scroll-handle') {
+ this.target = document.body;
+ this.targetModifier = 'scroll-handle';
+ }
+ _ref2 = ['element', 'target'];
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ key = _ref2[_i];
+ if (this[key] == null) {
+ throw new Error("Tether Error: Both element and target must be defined");
+ }
+ if (this[key].jquery != null) {
+ this[key] = this[key][0];
+ } else if (typeof this[key] === 'string') {
+ this[key] = document.querySelector(this[key]);
+ }
+ }
+ addClass(this.element, this.getClass('element'));
+ addClass(this.target, this.getClass('target'));
+ if (!this.options.attachment) {
+ throw new Error("Tether Error: You must provide an attachment");
+ }
+ this.targetAttachment = parseAttachment(this.options.targetAttachment);
+ this.attachment = parseAttachment(this.options.attachment);
+ this.offset = parseOffset(this.options.offset);
+ this.targetOffset = parseOffset(this.options.targetOffset);
+ if (this.scrollParent != null) {
+ this.disable();
+ }
+ if (this.targetModifier === 'scroll-handle') {
+ this.scrollParent = this.target;
+ } else {
+ this.scrollParent = getScrollParent(this.target);
+ }
+ if (this.options.enabled !== false) {
+ return this.enable(position);
+ }
+ };
+
+ _Tether.prototype.getTargetBounds = function() {
+ var bounds, fitAdj, hasBottomScroll, height, out, scrollBottom, scrollPercentage, style, target;
+ if (this.targetModifier != null) {
+ switch (this.targetModifier) {
+ case 'visible':
+ if (this.target === document.body) {
+ return {
+ top: pageYOffset,
+ left: pageXOffset,
+ height: innerHeight,
+ width: innerWidth
+ };
+ } else {
+ bounds = getBounds(this.target);
+ out = {
+ height: bounds.height,
+ width: bounds.width,
+ top: bounds.top,
+ left: bounds.left
+ };
+ out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
+ out.height = Math.min(out.height, bounds.height - ((bounds.top + bounds.height) - (pageYOffset + innerHeight)));
+ out.height = Math.min(innerHeight, out.height);
+ out.height -= 2;
+ out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
+ out.width = Math.min(out.width, bounds.width - ((bounds.left + bounds.width) - (pageXOffset + innerWidth)));
+ out.width = Math.min(innerWidth, out.width);
+ out.width -= 2;
+ if (out.top < pageYOffset) {
+ out.top = pageYOffset;
+ }
+ if (out.left < pageXOffset) {
+ out.left = pageXOffset;
+ }
+ return out;
+ }
+ break;
+ case 'scroll-handle':
+ target = this.target;
+ if (target === document.body) {
+ target = document.documentElement;
+ bounds = {
+ left: pageXOffset,
+ top: pageYOffset,
+ height: innerHeight,
+ width: innerWidth
+ };
+ } else {
+ bounds = getBounds(target);
+ }
+ style = getComputedStyle(target);
+ hasBottomScroll = target.scrollWidth > target.clientWidth || 'scroll' === [style.overflow, style.overflowX] || this.target !== document.body;
+ scrollBottom = 0;
+ if (hasBottomScroll) {
+ scrollBottom = 15;
+ }
+ height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
+ out = {
+ width: 15,
+ height: height * 0.975 * (height / target.scrollHeight),
+ left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
+ };
+ fitAdj = 0;
+ if (height < 408 && this.target === document.body) {
+ fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
+ }
+ if (this.target !== document.body) {
+ out.height = Math.max(out.height, 24);
+ }
+ scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
+ out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
+ if (this.target === document.body) {
+ out.height = Math.max(out.height, 24);
+ }
+ return out;
+ }
+ } else {
+ return getBounds(this.target);
+ }
+ };
+
+ _Tether.prototype.clearCache = function() {
+ return this._cache = {};
+ };
+
+ _Tether.prototype.cache = function(k, getter) {
+ if (this._cache == null) {
+ this._cache = {};
+ }
+ if (this._cache[k] == null) {
+ this._cache[k] = getter.call(this);
+ }
+ return this._cache[k];
+ };
+
+ _Tether.prototype.enable = function(position) {
+ if (position == null) {
+ position = true;
+ }
+ addClass(this.target, this.getClass('enabled'));
+ addClass(this.element, this.getClass('enabled'));
+ this.enabled = true;
+ if (this.scrollParent !== document) {
+ this.scrollParent.addEventListener('scroll', this.position);
+ }
+ if (position) {
+ return this.position();
+ }
+ };
+
+ _Tether.prototype.disable = function() {
+ removeClass(this.target, this.getClass('enabled'));
+ removeClass(this.element, this.getClass('enabled'));
+ this.enabled = false;
+ if (this.scrollParent != null) {
+ return this.scrollParent.removeEventListener('scroll', this.position);
+ }
+ };
+
+ _Tether.prototype.destroy = function() {
+ var i, tether, _i, _len, _results;
+ this.disable();
+ _results = [];
+ for (i = _i = 0, _len = tethers.length; _i < _len; i = ++_i) {
+ tether = tethers[i];
+ if (tether === this) {
+ tethers.splice(i, 1);
+ break;
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ };
+
+ _Tether.prototype.updateAttachClasses = function(elementAttach, targetAttach) {
+ var add, all, side, sides, _i, _j, _len, _len1, _ref1,
+ _this = this;
+ if (elementAttach == null) {
+ elementAttach = this.attachment;
+ }
+ if (targetAttach == null) {
+ targetAttach = this.targetAttachment;
+ }
+ sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
+ if ((_ref1 = this._addAttachClasses) != null ? _ref1.length : void 0) {
+ this._addAttachClasses.splice(0, this._addAttachClasses.length);
+ }
+ add = this._addAttachClasses != null ? this._addAttachClasses : this._addAttachClasses = [];
+ if (elementAttach.top) {
+ add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.top);
+ }
+ if (elementAttach.left) {
+ add.push("" + (this.getClass('element-attached')) + "-" + elementAttach.left);
+ }
+ if (targetAttach.top) {
+ add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.top);
+ }
+ if (targetAttach.left) {
+ add.push("" + (this.getClass('target-attached')) + "-" + targetAttach.left);
+ }
+ all = [];
+ for (_i = 0, _len = sides.length; _i < _len; _i++) {
+ side = sides[_i];
+ all.push("" + (this.getClass('element-attached')) + "-" + side);
+ }
+ for (_j = 0, _len1 = sides.length; _j < _len1; _j++) {
+ side = sides[_j];
+ all.push("" + (this.getClass('target-attached')) + "-" + side);
+ }
+ return defer(function() {
+ if (_this._addAttachClasses == null) {
+ return;
+ }
+ updateClasses(_this.element, _this._addAttachClasses, all);
+ updateClasses(_this.target, _this._addAttachClasses, all);
+ return _this._addAttachClasses = void 0;
+ });
+ };
+
+ _Tether.prototype.position = function(flushChanges) {
+ var elementPos, elementStyle, height, left, manualOffset, manualTargetOffset, module, next, offset, offsetBorder, offsetParent, offsetParentSize, offsetParentStyle, offsetPosition, ret, scrollLeft, scrollTop, scrollbarSize, side, targetAttachment, targetOffset, targetPos, targetSize, top, width, _i, _j, _len, _len1, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6,
+ _this = this;
+ if (flushChanges == null) {
+ flushChanges = true;
+ }
+ if (!this.enabled) {
+ return;
+ }
+ this.clearCache();
+ targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
+ this.updateAttachClasses(this.attachment, targetAttachment);
+ elementPos = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ });
+ width = elementPos.width, height = elementPos.height;
+ if (width === 0 && height === 0 && (this.lastSize != null)) {
+ _ref1 = this.lastSize, width = _ref1.width, height = _ref1.height;
+ } else {
+ this.lastSize = {
+ width: width,
+ height: height
+ };
+ }
+ targetSize = targetPos = this.cache('target-bounds', function() {
+ return _this.getTargetBounds();
+ });
+ offset = offsetToPx(attachmentToOffset(this.attachment), {
+ width: width,
+ height: height
+ });
+ targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
+ manualOffset = offsetToPx(this.offset, {
+ width: width,
+ height: height
+ });
+ manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
+ offset = addOffset(offset, manualOffset);
+ targetOffset = addOffset(targetOffset, manualTargetOffset);
+ left = targetPos.left + targetOffset.left - offset.left;
+ top = targetPos.top + targetOffset.top - offset.top;
+ _ref2 = Tether.modules;
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ module = _ref2[_i];
+ ret = module.position.call(this, {
+ left: left,
+ top: top,
+ targetAttachment: targetAttachment,
+ targetPos: targetPos,
+ attachment: this.attachment,
+ elementPos: elementPos,
+ offset: offset,
+ targetOffset: targetOffset,
+ manualOffset: manualOffset,
+ manualTargetOffset: manualTargetOffset,
+ scrollbarSize: scrollbarSize
+ });
+ if ((ret == null) || typeof ret !== 'object') {
+ continue;
+ } else if (ret === false) {
+ return false;
+ } else {
+ top = ret.top, left = ret.left;
+ }
+ }
+ next = {
+ page: {
+ top: top,
+ left: left
+ },
+ viewport: {
+ top: top - pageYOffset,
+ bottom: pageYOffset - top - height + innerHeight,
+ left: left - pageXOffset,
+ right: pageXOffset - left - width + innerWidth
+ }
+ };
+ if (document.body.scrollWidth > window.innerWidth) {
+ scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+ next.viewport.bottom -= scrollbarSize.height;
+ }
+ if (document.body.scrollHeight > window.innerHeight) {
+ scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+ next.viewport.right -= scrollbarSize.width;
+ }
+ if (((_ref3 = document.body.style.position) !== '' && _ref3 !== 'static') || ((_ref4 = document.body.parentElement.style.position) !== '' && _ref4 !== 'static')) {
+ next.page.bottom = document.body.scrollHeight - top - height;
+ next.page.right = document.body.scrollWidth - left - width;
+ }
+ if (((_ref5 = this.options.optimizations) != null ? _ref5.moveElement : void 0) !== false && (this.targetModifier == null)) {
+ offsetParent = this.cache('target-offsetparent', function() {
+ return getOffsetParent(_this.target);
+ });
+ offsetPosition = this.cache('target-offsetparent-bounds', function() {
+ return getBounds(offsetParent);
+ });
+ offsetParentStyle = getComputedStyle(offsetParent);
+ elementStyle = getComputedStyle(this.element);
+ offsetParentSize = offsetPosition;
+ offsetBorder = {};
+ _ref6 = ['Top', 'Left', 'Bottom', 'Right'];
+ for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) {
+ side = _ref6[_j];
+ offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle["border" + side + "Width"]);
+ }
+ offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
+ offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
+ if (next.page.top >= (offsetPosition.top + offsetBorder.top) && next.page.bottom >= offsetPosition.bottom) {
+ if (next.page.left >= (offsetPosition.left + offsetBorder.left) && next.page.right >= offsetPosition.right) {
+ scrollTop = offsetParent.scrollTop;
+ scrollLeft = offsetParent.scrollLeft;
+ next.offset = {
+ top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
+ left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
+ };
+ }
+ }
+ }
+ this.move(next);
+ this.history.unshift(next);
+ if (this.history.length > 3) {
+ this.history.pop();
+ }
+ if (flushChanges) {
+ flush();
+ }
+ return true;
+ };
+
+ _Tether.prototype.move = function(position) {
+ var css, elVal, found, key, moved, offsetParent, point, same, transcribe, type, val, write, writeCSS, _i, _len, _ref1, _ref2,
+ _this = this;
+ if (this.element.parentNode == null) {
+ return;
+ }
+ same = {};
+ for (type in position) {
+ same[type] = {};
+ for (key in position[type]) {
+ found = false;
+ _ref1 = this.history;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ point = _ref1[_i];
+ if (!within((_ref2 = point[type]) != null ? _ref2[key] : void 0, position[type][key])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ same[type][key] = true;
+ }
+ }
+ }
+ css = {
+ top: '',
+ left: '',
+ right: '',
+ bottom: ''
+ };
+ transcribe = function(same, pos) {
+ var xPos, yPos, _ref3;
+ if (((_ref3 = _this.options.optimizations) != null ? _ref3.gpu : void 0) !== false) {
+ if (same.top) {
+ css.top = 0;
+ yPos = pos.top;
+ } else {
+ css.bottom = 0;
+ yPos = -pos.bottom;
+ }
+ if (same.left) {
+ css.left = 0;
+ xPos = pos.left;
+ } else {
+ css.right = 0;
+ xPos = -pos.right;
+ }
+ css[transformKey] = "translateX(" + (Math.round(xPos)) + "px) translateY(" + (Math.round(yPos)) + "px)";
+ if (transformKey !== 'msTransform') {
+ return css[transformKey] += " translateZ(0)";
+ }
+ } else {
+ if (same.top) {
+ css.top = "" + pos.top + "px";
+ } else {
+ css.bottom = "" + pos.bottom + "px";
+ }
+ if (same.left) {
+ return css.left = "" + pos.left + "px";
+ } else {
+ return css.right = "" + pos.right + "px";
+ }
+ }
+ };
+ moved = false;
+ if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
+ css.position = 'absolute';
+ transcribe(same.page, position.page);
+ } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
+ css.position = 'fixed';
+ transcribe(same.viewport, position.viewport);
+ } else if ((same.offset != null) && same.offset.top && same.offset.left) {
+ css.position = 'absolute';
+ offsetParent = this.cache('target-offsetparent', function() {
+ return getOffsetParent(_this.target);
+ });
+ if (getOffsetParent(this.element) !== offsetParent) {
+ defer(function() {
+ _this.element.parentNode.removeChild(_this.element);
+ return offsetParent.appendChild(_this.element);
+ });
+ }
+ transcribe(same.offset, position.offset);
+ moved = true;
+ } else {
+ css.position = 'absolute';
+ transcribe({
+ top: true,
+ left: true
+ }, position.page);
+ }
+ if (!moved && this.element.parentNode.tagName !== 'BODY') {
+ this.element.parentNode.removeChild(this.element);
+ document.body.appendChild(this.element);
+ }
+ writeCSS = {};
+ write = false;
+ for (key in css) {
+ val = css[key];
+ elVal = this.element.style[key];
+ if (elVal !== '' && val !== '' && (key === 'top' || key === 'left' || key === 'bottom' || key === 'right')) {
+ elVal = parseFloat(elVal);
+ val = parseFloat(val);
+ }
+ if (elVal !== val) {
+ write = true;
+ writeCSS[key] = css[key];
+ }
+ }
+ if (write) {
+ return defer(function() {
+ return extend(_this.element.style, writeCSS);
+ });
+ }
+ };
+
+ return _Tether;
+
+ })();
+
+ Tether.position = position;
+
+ this.Tether = extend(_Tether, Tether);
+
+}).call(this);
+
+(function() {
+ var BOUNDS_FORMAT, MIRROR_ATTACH, defer, extend, getBoundingRect, getBounds, getOuterSize, getSize, updateClasses, _ref,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ _ref = this.Tether.Utils, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getSize = _ref.getSize, extend = _ref.extend, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+ MIRROR_ATTACH = {
+ left: 'right',
+ right: 'left',
+ top: 'bottom',
+ bottom: 'top',
+ middle: 'middle'
+ };
+
+ BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
+
+ getBoundingRect = function(tether, to) {
+ var i, pos, side, size, style, _i, _len;
+ if (to === 'scrollParent') {
+ to = tether.scrollParent;
+ } else if (to === 'window') {
+ to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
+ }
+ if (to === document) {
+ to = to.documentElement;
+ }
+ if (to.nodeType != null) {
+ pos = size = getBounds(to);
+ style = getComputedStyle(to);
+ to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
+ for (i = _i = 0, _len = BOUNDS_FORMAT.length; _i < _len; i = ++_i) {
+ side = BOUNDS_FORMAT[i];
+ side = side[0].toUpperCase() + side.substr(1);
+ if (side === 'Top' || side === 'Left') {
+ to[i] += parseFloat(style["border" + side + "Width"]);
+ } else {
+ to[i] -= parseFloat(style["border" + side + "Width"]);
+ }
+ }
+ }
+ return to;
+ };
+
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var addClasses, allClasses, attachment, bounds, changeAttachX, changeAttachY, cls, constraint, eAttachment, height, left, oob, oobClass, p, pin, pinned, pinnedClass, removeClass, side, tAttachment, targetAttachment, targetHeight, targetSize, targetWidth, to, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8,
+ _this = this;
+ top = _arg.top, left = _arg.left, targetAttachment = _arg.targetAttachment;
+ if (!this.options.constraints) {
+ return true;
+ }
+ removeClass = function(prefix) {
+ var side, _i, _len, _results;
+ _this.removeClass(prefix);
+ _results = [];
+ for (_i = 0, _len = BOUNDS_FORMAT.length; _i < _len; _i++) {
+ side = BOUNDS_FORMAT[_i];
+ _results.push(_this.removeClass("" + prefix + "-" + side));
+ }
+ return _results;
+ };
+ _ref1 = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ }), height = _ref1.height, width = _ref1.width;
+ if (width === 0 && height === 0 && (this.lastSize != null)) {
+ _ref2 = this.lastSize, width = _ref2.width, height = _ref2.height;
+ }
+ targetSize = this.cache('target-bounds', function() {
+ return _this.getTargetBounds();
+ });
+ targetHeight = targetSize.height;
+ targetWidth = targetSize.width;
+ tAttachment = {};
+ eAttachment = {};
+ allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
+ _ref3 = this.options.constraints;
+ for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+ constraint = _ref3[_i];
+ if (constraint.outOfBoundsClass) {
+ allClasses.push(constraint.outOfBoundsClass);
+ }
+ if (constraint.pinnedClass) {
+ allClasses.push(constraint.pinnedClass);
+ }
+ }
+ for (_j = 0, _len1 = allClasses.length; _j < _len1; _j++) {
+ cls = allClasses[_j];
+ _ref4 = ['left', 'top', 'right', 'bottom'];
+ for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
+ side = _ref4[_k];
+ allClasses.push("" + cls + "-" + side);
+ }
+ }
+ addClasses = [];
+ tAttachment = extend({}, targetAttachment);
+ eAttachment = extend({}, this.attachment);
+ _ref5 = this.options.constraints;
+ for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {
+ constraint = _ref5[_l];
+ to = constraint.to, attachment = constraint.attachment, pin = constraint.pin;
+ if (attachment == null) {
+ attachment = '';
+ }
+ if (__indexOf.call(attachment, ' ') >= 0) {
+ _ref6 = attachment.split(' '), changeAttachY = _ref6[0], changeAttachX = _ref6[1];
+ } else {
+ changeAttachX = changeAttachY = attachment;
+ }
+ bounds = getBoundingRect(this, to);
+ if (changeAttachY === 'target' || changeAttachY === 'both') {
+ if (top < bounds[1] && tAttachment.top === 'top') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ }
+ if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ }
+ }
+ if (changeAttachY === 'together') {
+ if (top < bounds[1] && tAttachment.top === 'top') {
+ if (eAttachment.top === 'bottom') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ top += height;
+ eAttachment.top = 'top';
+ } else if (eAttachment.top === 'top') {
+ top += targetHeight;
+ tAttachment.top = 'bottom';
+ top -= height;
+ eAttachment.top = 'bottom';
+ }
+ }
+ if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+ if (eAttachment.top === 'top') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ top -= height;
+ eAttachment.top = 'bottom';
+ } else if (eAttachment.top === 'bottom') {
+ top -= targetHeight;
+ tAttachment.top = 'top';
+ top += height;
+ eAttachment.top = 'top';
+ }
+ }
+ if (tAttachment.top === 'middle') {
+ if (top + height > bounds[3] && eAttachment.top === 'top') {
+ top -= height;
+ eAttachment.top = 'bottom';
+ } else if (top < bounds[1] && eAttachment.top === 'bottom') {
+ top += height;
+ eAttachment.top = 'top';
+ }
+ }
+ }
+ if (changeAttachX === 'target' || changeAttachX === 'both') {
+ if (left < bounds[0] && tAttachment.left === 'left') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ }
+ if (left + width > bounds[2] && tAttachment.left === 'right') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ }
+ }
+ if (changeAttachX === 'together') {
+ if (left < bounds[0] && tAttachment.left === 'left') {
+ if (eAttachment.left === 'right') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ left += width;
+ eAttachment.left = 'left';
+ } else if (eAttachment.left === 'left') {
+ left += targetWidth;
+ tAttachment.left = 'right';
+ left -= width;
+ eAttachment.left = 'right';
+ }
+ } else if (left + width > bounds[2] && tAttachment.left === 'right') {
+ if (eAttachment.left === 'left') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ left -= width;
+ eAttachment.left = 'right';
+ } else if (eAttachment.left === 'right') {
+ left -= targetWidth;
+ tAttachment.left = 'left';
+ left += width;
+ eAttachment.left = 'left';
+ }
+ } else if (tAttachment.left === 'center') {
+ if (left + width > bounds[2] && eAttachment.left === 'left') {
+ left -= width;
+ eAttachment.left = 'right';
+ } else if (left < bounds[0] && eAttachment.left === 'right') {
+ left += width;
+ eAttachment.left = 'left';
+ }
+ }
+ }
+ if (changeAttachY === 'element' || changeAttachY === 'both') {
+ if (top < bounds[1] && eAttachment.top === 'bottom') {
+ top += height;
+ eAttachment.top = 'top';
+ }
+ if (top + height > bounds[3] && eAttachment.top === 'top') {
+ top -= height;
+ eAttachment.top = 'bottom';
+ }
+ }
+ if (changeAttachX === 'element' || changeAttachX === 'both') {
+ if (left < bounds[0] && eAttachment.left === 'right') {
+ left += width;
+ eAttachment.left = 'left';
+ }
+ if (left + width > bounds[2] && eAttachment.left === 'left') {
+ left -= width;
+ eAttachment.left = 'right';
+ }
+ }
+ if (typeof pin === 'string') {
+ pin = (function() {
+ var _len4, _m, _ref7, _results;
+ _ref7 = pin.split(',');
+ _results = [];
+ for (_m = 0, _len4 = _ref7.length; _m < _len4; _m++) {
+ p = _ref7[_m];
+ _results.push(p.trim());
+ }
+ return _results;
+ })();
+ } else if (pin === true) {
+ pin = ['top', 'left', 'right', 'bottom'];
+ }
+ pin || (pin = []);
+ pinned = [];
+ oob = [];
+ if (top < bounds[1]) {
+ if (__indexOf.call(pin, 'top') >= 0) {
+ top = bounds[1];
+ pinned.push('top');
+ } else {
+ oob.push('top');
+ }
+ }
+ if (top + height > bounds[3]) {
+ if (__indexOf.call(pin, 'bottom') >= 0) {
+ top = bounds[3] - height;
+ pinned.push('bottom');
+ } else {
+ oob.push('bottom');
+ }
+ }
+ if (left < bounds[0]) {
+ if (__indexOf.call(pin, 'left') >= 0) {
+ left = bounds[0];
+ pinned.push('left');
+ } else {
+ oob.push('left');
+ }
+ }
+ if (left + width > bounds[2]) {
+ if (__indexOf.call(pin, 'right') >= 0) {
+ left = bounds[2] - width;
+ pinned.push('right');
+ } else {
+ oob.push('right');
+ }
+ }
+ if (pinned.length) {
+ pinnedClass = (_ref7 = this.options.pinnedClass) != null ? _ref7 : this.getClass('pinned');
+ addClasses.push(pinnedClass);
+ for (_m = 0, _len4 = pinned.length; _m < _len4; _m++) {
+ side = pinned[_m];
+ addClasses.push("" + pinnedClass + "-" + side);
+ }
+ }
+ if (oob.length) {
+ oobClass = (_ref8 = this.options.outOfBoundsClass) != null ? _ref8 : this.getClass('out-of-bounds');
+ addClasses.push(oobClass);
+ for (_n = 0, _len5 = oob.length; _n < _len5; _n++) {
+ side = oob[_n];
+ addClasses.push("" + oobClass + "-" + side);
+ }
+ }
+ if (__indexOf.call(pinned, 'left') >= 0 || __indexOf.call(pinned, 'right') >= 0) {
+ eAttachment.left = tAttachment.left = false;
+ }
+ if (__indexOf.call(pinned, 'top') >= 0 || __indexOf.call(pinned, 'bottom') >= 0) {
+ eAttachment.top = tAttachment.top = false;
+ }
+ if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== this.attachment.top || eAttachment.left !== this.attachment.left) {
+ this.updateAttachClasses(eAttachment, tAttachment);
+ }
+ }
+ defer(function() {
+ updateClasses(_this.target, addClasses, allClasses);
+ return updateClasses(_this.element, addClasses, allClasses);
+ });
+ return {
+ top: top,
+ left: left
+ };
+ }
+ });
+
+}).call(this);
+
+(function() {
+ var defer, getBounds, updateClasses, _ref;
+
+ _ref = this.Tether.Utils, getBounds = _ref.getBounds, updateClasses = _ref.updateClasses, defer = _ref.defer;
+
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var abutted, addClasses, allClasses, bottom, height, left, right, side, sides, targetPos, top, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3, _ref4, _ref5,
+ _this = this;
+ top = _arg.top, left = _arg.left;
+ _ref1 = this.cache('element-bounds', function() {
+ return getBounds(_this.element);
+ }), height = _ref1.height, width = _ref1.width;
+ targetPos = this.getTargetBounds();
+ bottom = top + height;
+ right = left + width;
+ abutted = [];
+ if (top <= targetPos.bottom && bottom >= targetPos.top) {
+ _ref2 = ['left', 'right'];
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ side = _ref2[_i];
+ if ((_ref3 = targetPos[side]) === left || _ref3 === right) {
+ abutted.push(side);
+ }
+ }
+ }
+ if (left <= targetPos.right && right >= targetPos.left) {
+ _ref4 = ['top', 'bottom'];
+ for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {
+ side = _ref4[_j];
+ if ((_ref5 = targetPos[side]) === top || _ref5 === bottom) {
+ abutted.push(side);
+ }
+ }
+ }
+ allClasses = [];
+ addClasses = [];
+ sides = ['left', 'top', 'right', 'bottom'];
+ allClasses.push(this.getClass('abutted'));
+ for (_k = 0, _len2 = sides.length; _k < _len2; _k++) {
+ side = sides[_k];
+ allClasses.push("" + (this.getClass('abutted')) + "-" + side);
+ }
+ if (abutted.length) {
+ addClasses.push(this.getClass('abutted'));
+ }
+ for (_l = 0, _len3 = abutted.length; _l < _len3; _l++) {
+ side = abutted[_l];
+ addClasses.push("" + (this.getClass('abutted')) + "-" + side);
+ }
+ defer(function() {
+ updateClasses(_this.target, addClasses, allClasses);
+ return updateClasses(_this.element, addClasses, allClasses);
+ });
+ return true;
+ }
+ });
+
+}).call(this);
+
+(function() {
+ this.Tether.modules.push({
+ position: function(_arg) {
+ var left, result, shift, shiftLeft, shiftTop, top, _ref;
+ top = _arg.top, left = _arg.left;
+ if (!this.options.shift) {
+ return;
+ }
+ result = function(val) {
+ if (typeof val === 'function') {
+ return val.call(this, {
+ top: top,
+ left: left
+ });
+ } else {
+ return val;
+ }
+ };
+ shift = result(this.options.shift);
+ if (typeof shift === 'string') {
+ shift = shift.split(' ');
+ shift[1] || (shift[1] = shift[0]);
+ shiftTop = shift[0], shiftLeft = shift[1];
+ shiftTop = parseFloat(shiftTop, 10);
+ shiftLeft = parseFloat(shiftLeft, 10);
+ } else {
+ _ref = [shift.top, shift.left], shiftTop = _ref[0], shiftLeft = _ref[1];
+ }
+ top += shiftTop;
+ left += shiftLeft;
+ return {
+ top: top,
+ left: left
+ };
+ }
+ });
+
+}).call(this);
+
+return this.Tether;
+
+}));
diff --git a/afb-client/bower_components/tether/tether.min.js b/afb-client/bower_components/tether/tether.min.js
new file mode 100644
index 0000000..065085e
--- /dev/null
+++ b/afb-client/bower_components/tether/tether.min.js
@@ -0,0 +1,2 @@
+/*! tether 0.6.5 */
+!function(t,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e(require,exports,module):t.Tether=e()}(this,function(){return function(){var t,e,o,i,n,s,l,r,h,a,f,p,u,d,g,c,m,b={}.hasOwnProperty,v=[].indexOf||function(t){for(var e=0,o=this.length;o>e;e++)if(e in this&&this[e]===t)return e;return-1},y=[].slice;null==this.Tether&&(this.Tether={modules:[]}),f=function(t){var e,o,i,n,s;if(o=getComputedStyle(t).position,"fixed"===o)return t;for(i=void 0,e=t;e=e.parentNode;){try{n=getComputedStyle(e)}catch(l){}if(null==n)return e;if(/(auto|scroll)/.test(n.overflow+n["overflow-y"]+n["overflow-x"])&&("absolute"!==o||"relative"===(s=n.position)||"absolute"===s||"fixed"===s))return e}return document.body},g=function(){var t;return t=0,function(){return t++}}(),m={},h=function(t){var e,i,s,l,r;if(s=t._tetherZeroElement,null==s&&(s=t.createElement("div"),s.setAttribute("data-tether-id",g()),n(s.style,{top:0,left:0,position:"absolute"}),t.body.appendChild(s),t._tetherZeroElement=s),e=s.getAttribute("data-tether-id"),null==m[e]){m[e]={},r=s.getBoundingClientRect();for(i in r)l=r[i],m[e][i]=l;o(function(){return m[e]=void 0})}return m[e]},u=null,l=function(t){var e,o,i,n,s,l,r;t===document?(o=document,t=document.documentElement):o=t.ownerDocument,i=o.documentElement,e={},r=t.getBoundingClientRect();for(n in r)l=r[n],e[n]=l;return s=h(o),e.top-=s.top,e.left-=s.left,null==e.width&&(e.width=document.body.scrollWidth-e.left-e.right),null==e.height&&(e.height=document.body.scrollHeight-e.top-e.bottom),e.top=e.top-i.clientTop,e.left=e.left-i.clientLeft,e.right=o.body.clientWidth-e.width-e.left,e.bottom=o.body.clientHeight-e.height-e.top,e},r=function(t){return t.offsetParent||document.documentElement},a=function(){var t,e,o,i,s;return t=document.createElement("div"),t.style.width="100%",t.style.height="200px",e=document.createElement("div"),n(e.style,{position:"absolute",top:0,left:0,pointerEvents:"none",visibility:"hidden",width:"200px",height:"150px",overflow:"hidden"}),e.appendChild(t),document.body.appendChild(e),i=t.offsetWidth,e.style.overflow="scroll",s=t.offsetWidth,i===s&&(s=e.clientWidth),document.body.removeChild(e),o=i-s,{width:o,height:o}},n=function(t){var e,o,i,n,s,l,r;for(null==t&&(t={}),e=[],Array.prototype.push.apply(e,arguments),r=e.slice(1),s=0,l=r.length;l>s;s++)if(i=r[s])for(o in i)b.call(i,o)&&(n=i[o],t[o]=n);return t},d=function(t,e){var o,i,n,s,l;if(null!=t.classList){for(s=e.split(" "),l=[],i=0,n=s.length;n>i;i++)o=s[i],o.trim()&&l.push(t.classList.remove(o));return l}return t.className=t.className.replace(new RegExp("(^| )"+e.split(" ").join("|")+"( |$)","gi")," ")},e=function(t,e){var o,i,n,s,l;if(null!=t.classList){for(s=e.split(" "),l=[],i=0,n=s.length;n>i;i++)o=s[i],o.trim()&&l.push(t.classList.add(o));return l}return d(t,e),t.className+=" "+e},p=function(t,e){return null!=t.classList?t.classList.contains(e):new RegExp("(^| )"+e+"( |$)","gi").test(t.className)},c=function(t,o,i){var n,s,l,r,h,a;for(s=0,r=i.length;r>s;s++)n=i[s],v.call(o,n)<0&&p(t,n)&&d(t,n);for(a=[],l=0,h=o.length;h>l;l++)n=o[l],a.push(p(t,n)?void 0:e(t,n));return a},i=[],o=function(t){return i.push(t)},s=function(){var t,e;for(e=[];t=i.pop();)e.push(t());return e},t=function(){function t(){}return t.prototype.on=function(t,e,o,i){var n;return null==i&&(i=!1),null==this.bindings&&(this.bindings={}),null==(n=this.bindings)[t]&&(n[t]=[]),this.bindings[t].push({handler:e,ctx:o,once:i})},t.prototype.once=function(t,e,o){return this.on(t,e,o,!0)},t.prototype.off=function(t,e){var o,i,n;if(null!=(null!=(i=this.bindings)?i[t]:void 0)){if(null==e)return delete this.bindings[t];for(o=0,n=[];o<this.bindings[t].length;)n.push(this.bindings[t][o].handler===e?this.bindings[t].splice(o,1):o++);return n}},t.prototype.trigger=function(){var t,e,o,i,n,s,l,r,h;if(o=arguments[0],t=2<=arguments.length?y.call(arguments,1):[],null!=(l=this.bindings)?l[o]:void 0){for(n=0,h=[];n<this.bindings[o].length;)r=this.bindings[o][n],i=r.handler,e=r.ctx,s=r.once,i.apply(null!=e?e:this,t),h.push(s?this.bindings[o].splice(n,1):n++);return h}},t}(),this.Tether.Utils={getScrollParent:f,getBounds:l,getOffsetParent:r,extend:n,addClass:e,removeClass:d,hasClass:p,updateClasses:c,defer:o,flush:s,uniqueId:g,Evented:t,getScrollBarSize:a}}.call(this),function(){var t,e,o,i,n,s,l,r,h,a,f,p,u,d,g,c,m,b,v,y,w,C,O,T,x,E,W,A,S,M=[].slice,z=function(t,e){return function(){return t.apply(e,arguments)}};if(null==this.Tether)throw new Error("You must include the utils.js file before tether.js");i=this.Tether,S=i.Utils,c=S.getScrollParent,m=S.getSize,d=S.getOuterSize,p=S.getBounds,u=S.getOffsetParent,a=S.extend,n=S.addClass,O=S.removeClass,E=S.updateClasses,h=S.defer,f=S.flush,g=S.getScrollBarSize,W=function(t,e,o){return null==o&&(o=1),t+o>=e&&e>=t-o},x=function(){var t,e,o,i,n;for(t=document.createElement("div"),n=["transform","webkitTransform","OTransform","MozTransform","msTransform"],o=0,i=n.length;i>o;o++)if(e=n[o],void 0!==t.style[e])return e}(),T=[],C=function(){var t,e,o;for(e=0,o=T.length;o>e;e++)t=T[e],t.position(!1);return f()},b=function(){var t;return null!=(t="undefined"!=typeof performance&&null!==performance?"function"==typeof performance.now?performance.now():void 0:void 0)?t:+new Date},function(){var t,e,o,i,n,s,l,r,h;for(e=null,o=null,i=null,n=function(){if(null!=o&&o>16)return o=Math.min(o-16,250),void(i=setTimeout(n,250));if(!(null!=e&&b()-e<10))return null!=i&&(clearTimeout(i),i=null),e=b(),C(),o=b()-e},r=["resize","scroll","touchmove"],h=[],s=0,l=r.length;l>s;s++)t=r[s],h.push(window.addEventListener(t,n));return h}(),t={center:"center",left:"right",right:"left"},e={middle:"middle",top:"bottom",bottom:"top"},o={top:0,left:0,middle:"50%",center:"50%",bottom:"100%",right:"100%"},r=function(o,i){var n,s;return n=o.left,s=o.top,"auto"===n&&(n=t[i.left]),"auto"===s&&(s=e[i.top]),{left:n,top:s}},l=function(t){var e,i;return{left:null!=(e=o[t.left])?e:t.left,top:null!=(i=o[t.top])?i:t.top}},s=function(){var t,e,o,i,n,s,l;for(e=1<=arguments.length?M.call(arguments,0):[],o={top:0,left:0},n=0,s=e.length;s>n;n++)l=e[n],i=l.top,t=l.left,"string"==typeof i&&(i=parseFloat(i,10)),"string"==typeof t&&(t=parseFloat(t,10)),o.top+=i,o.left+=t;return o},v=function(t,e){return"string"==typeof t.left&&-1!==t.left.indexOf("%")&&(t.left=parseFloat(t.left,10)/100*e.width),"string"==typeof t.top&&-1!==t.top.indexOf("%")&&(t.top=parseFloat(t.top,10)/100*e.height),t},y=w=function(t){var e,o,i;return i=t.split(" "),o=i[0],e=i[1],{top:o,left:e}},A=function(){function t(t){this.position=z(this.position,this);var e,o,n,s,l;for(T.push(this),this.history=[],this.setOptions(t,!1),s=i.modules,o=0,n=s.length;n>o;o++)e=s[o],null!=(l=e.initialize)&&l.call(this);this.position()}return t.modules=[],t.prototype.getClass=function(t){var e,o;return(null!=(e=this.options.classes)?e[t]:void 0)?this.options.classes[t]:(null!=(o=this.options.classes)?o[t]:void 0)!==!1?this.options.classPrefix?""+this.options.classPrefix+"-"+t:t:""},t.prototype.setOptions=function(t,e){var o,i,s,l,r,h;for(this.options=t,null==e&&(e=!0),o={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto",classPrefix:"tether"},this.options=a(o,this.options),r=this.options,this.element=r.element,this.target=r.target,this.targetModifier=r.targetModifier,"viewport"===this.target?(this.target=document.body,this.targetModifier="visible"):"scroll-handle"===this.target&&(this.target=document.body,this.targetModifier="scroll-handle"),h=["element","target"],s=0,l=h.length;l>s;s++){if(i=h[s],null==this[i])throw new Error("Tether Error: Both element and target must be defined");null!=this[i].jquery?this[i]=this[i][0]:"string"==typeof this[i]&&(this[i]=document.querySelector(this[i]))}if(n(this.element,this.getClass("element")),n(this.target,this.getClass("target")),!this.options.attachment)throw new Error("Tether Error: You must provide an attachment");return this.targetAttachment=y(this.options.targetAttachment),this.attachment=y(this.options.attachment),this.offset=w(this.options.offset),this.targetOffset=w(this.options.targetOffset),null!=this.scrollParent&&this.disable(),this.scrollParent="scroll-handle"===this.targetModifier?this.target:c(this.target),this.options.enabled!==!1?this.enable(e):void 0},t.prototype.getTargetBounds=function(){var t,e,o,i,n,s,l,r,h;if(null==this.targetModifier)return p(this.target);switch(this.targetModifier){case"visible":return this.target===document.body?{top:pageYOffset,left:pageXOffset,height:innerHeight,width:innerWidth}:(t=p(this.target),n={height:t.height,width:t.width,top:t.top,left:t.left},n.height=Math.min(n.height,t.height-(pageYOffset-t.top)),n.height=Math.min(n.height,t.height-(t.top+t.height-(pageYOffset+innerHeight))),n.height=Math.min(innerHeight,n.height),n.height-=2,n.width=Math.min(n.width,t.width-(pageXOffset-t.left)),n.width=Math.min(n.width,t.width-(t.left+t.width-(pageXOffset+innerWidth))),n.width=Math.min(innerWidth,n.width),n.width-=2,n.top<pageYOffset&&(n.top=pageYOffset),n.left<pageXOffset&&(n.left=pageXOffset),n);case"scroll-handle":return h=this.target,h===document.body?(h=document.documentElement,t={left:pageXOffset,top:pageYOffset,height:innerHeight,width:innerWidth}):t=p(h),r=getComputedStyle(h),o=h.scrollWidth>h.clientWidth||"scroll"===[r.overflow,r.overflowX]||this.target!==document.body,s=0,o&&(s=15),i=t.height-parseFloat(r.borderTopWidth)-parseFloat(r.borderBottomWidth)-s,n={width:15,height:.975*i*(i/h.scrollHeight),left:t.left+t.width-parseFloat(r.borderLeftWidth)-15},e=0,408>i&&this.target===document.body&&(e=-11e-5*Math.pow(i,2)-.00727*i+22.58),this.target!==document.body&&(n.height=Math.max(n.height,24)),l=this.target.scrollTop/(h.scrollHeight-i),n.top=l*(i-n.height-e)+t.top+parseFloat(r.borderTopWidth),this.target===document.body&&(n.height=Math.max(n.height,24)),n}},t.prototype.clearCache=function(){return this._cache={}},t.prototype.cache=function(t,e){return null==this._cache&&(this._cache={}),null==this._cache[t]&&(this._cache[t]=e.call(this)),this._cache[t]},t.prototype.enable=function(t){return null==t&&(t=!0),n(this.target,this.getClass("enabled")),n(this.element,this.getClass("enabled")),this.enabled=!0,this.scrollParent!==document&&this.scrollParent.addEventListener("scroll",this.position),t?this.position():void 0},t.prototype.disable=function(){return O(this.target,this.getClass("enabled")),O(this.element,this.getClass("enabled")),this.enabled=!1,null!=this.scrollParent?this.scrollParent.removeEventListener("scroll",this.position):void 0},t.prototype.destroy=function(){var t,e,o,i,n;for(this.disable(),n=[],t=o=0,i=T.length;i>o;t=++o){if(e=T[t],e===this){T.splice(t,1);break}n.push(void 0)}return n},t.prototype.updateAttachClasses=function(t,e){var o,i,n,s,l,r,a,f,p,u=this;for(null==t&&(t=this.attachment),null==e&&(e=this.targetAttachment),s=["left","top","bottom","right","middle","center"],(null!=(p=this._addAttachClasses)?p.length:void 0)&&this._addAttachClasses.splice(0,this._addAttachClasses.length),o=null!=this._addAttachClasses?this._addAttachClasses:this._addAttachClasses=[],t.top&&o.push(""+this.getClass("element-attached")+"-"+t.top),t.left&&o.push(""+this.getClass("element-attached")+"-"+t.left),e.top&&o.push(""+this.getClass("target-attached")+"-"+e.top),e.left&&o.push(""+this.getClass("target-attached")+"-"+e.left),i=[],l=0,a=s.length;a>l;l++)n=s[l],i.push(""+this.getClass("element-attached")+"-"+n);for(r=0,f=s.length;f>r;r++)n=s[r],i.push(""+this.getClass("target-attached")+"-"+n);return h(function(){return null!=u._addAttachClasses?(E(u.element,u._addAttachClasses,i),E(u.target,u._addAttachClasses,i),u._addAttachClasses=void 0):void 0})},t.prototype.position=function(t){var e,o,n,h,a,d,c,m,b,y,w,C,O,T,x,E,W,A,S,M,z,B,P,_,F,L,H,Y,X,N,j,R,U,q,k,D=this;if(null==t&&(t=!0),this.enabled){for(this.clearCache(),M=r(this.targetAttachment,this.attachment),this.updateAttachClasses(this.attachment,M),e=this.cache("element-bounds",function(){return p(D.element)}),F=e.width,n=e.height,0===F&&0===n&&null!=this.lastSize?(N=this.lastSize,F=N.width,n=N.height):this.lastSize={width:F,height:n},P=B=this.cache("target-bounds",function(){return D.getTargetBounds()}),b=v(l(this.attachment),{width:F,height:n}),z=v(l(M),P),a=v(this.offset,{width:F,height:n}),d=v(this.targetOffset,P),b=s(b,a),z=s(z,d),h=B.left+z.left-b.left,_=B.top+z.top-b.top,j=i.modules,L=0,Y=j.length;Y>L;L++)if(c=j[L],x=c.position.call(this,{left:h,top:_,targetAttachment:M,targetPos:B,attachment:this.attachment,elementPos:e,offset:b,targetOffset:z,manualOffset:a,manualTargetOffset:d,scrollbarSize:A}),null!=x&&"object"==typeof x){if(x===!1)return!1;_=x.top,h=x.left}if(m={page:{top:_,left:h},viewport:{top:_-pageYOffset,bottom:pageYOffset-_-n+innerHeight,left:h-pageXOffset,right:pageXOffset-h-F+innerWidth}},document.body.scrollWidth>window.innerWidth&&(A=this.cache("scrollbar-size",g),m.viewport.bottom-=A.height),document.body.scrollHeight>window.innerHeight&&(A=this.cache("scrollbar-size",g),m.viewport.right-=A.width),(""!==(R=document.body.style.position)&&"static"!==R||""!==(U=document.body.parentElement.style.position)&&"static"!==U)&&(m.page.bottom=document.body.scrollHeight-_-n,m.page.right=document.body.scrollWidth-h-F),(null!=(q=this.options.optimizations)?q.moveElement:void 0)!==!1&&null==this.targetModifier){for(w=this.cache("target-offsetparent",function(){return u(D.target)}),T=this.cache("target-offsetparent-bounds",function(){return p(w)}),O=getComputedStyle(w),o=getComputedStyle(this.element),C=T,y={},k=["Top","Left","Bottom","Right"],H=0,X=k.length;X>H;H++)S=k[H],y[S.toLowerCase()]=parseFloat(O["border"+S+"Width"]);T.right=document.body.scrollWidth-T.left-C.width+y.right,T.bottom=document.body.scrollHeight-T.top-C.height+y.bottom,m.page.top>=T.top+y.top&&m.page.bottom>=T.bottom&&m.page.left>=T.left+y.left&&m.page.right>=T.right&&(W=w.scrollTop,E=w.scrollLeft,m.offset={top:m.page.top-T.top+W-y.top,left:m.page.left-T.left+E-y.left})}return this.move(m),this.history.unshift(m),this.history.length>3&&this.history.pop(),t&&f(),!0}},t.prototype.move=function(t){var e,o,i,n,s,l,r,f,p,d,g,c,m,b,v,y,w,C=this;if(null!=this.element.parentNode){f={};for(d in t){f[d]={};for(n in t[d]){for(i=!1,y=this.history,b=0,v=y.length;v>b;b++)if(r=y[b],!W(null!=(w=r[d])?w[n]:void 0,t[d][n])){i=!0;break}i||(f[d][n]=!0)}}e={top:"",left:"",right:"",bottom:""},p=function(t,o){var i,n,s;return(null!=(s=C.options.optimizations)?s.gpu:void 0)===!1?(t.top?e.top=""+o.top+"px":e.bottom=""+o.bottom+"px",t.left?e.left=""+o.left+"px":e.right=""+o.right+"px"):(t.top?(e.top=0,n=o.top):(e.bottom=0,n=-o.bottom),t.left?(e.left=0,i=o.left):(e.right=0,i=-o.right),e[x]="translateX("+Math.round(i)+"px) translateY("+Math.round(n)+"px)","msTransform"!==x?e[x]+=" translateZ(0)":void 0)},s=!1,(f.page.top||f.page.bottom)&&(f.page.left||f.page.right)?(e.position="absolute",p(f.page,t.page)):(f.viewport.top||f.viewport.bottom)&&(f.viewport.left||f.viewport.right)?(e.position="fixed",p(f.viewport,t.viewport)):null!=f.offset&&f.offset.top&&f.offset.left?(e.position="absolute",l=this.cache("target-offsetparent",function(){return u(C.target)}),u(this.element)!==l&&h(function(){return C.element.parentNode.removeChild(C.element),l.appendChild(C.element)}),p(f.offset,t.offset),s=!0):(e.position="absolute",p({top:!0,left:!0},t.page)),s||"BODY"===this.element.parentNode.tagName||(this.element.parentNode.removeChild(this.element),document.body.appendChild(this.element)),m={},c=!1;for(n in e)g=e[n],o=this.element.style[n],""===o||""===g||"top"!==n&&"left"!==n&&"bottom"!==n&&"right"!==n||(o=parseFloat(o),g=parseFloat(g)),o!==g&&(c=!0,m[n]=e[n]);return c?h(function(){return a(C.element.style,m)}):void 0}},t}(),i.position=C,this.Tether=a(A,i)}.call(this),function(){var t,e,o,i,n,s,l,r,h,a,f=[].indexOf||function(t){for(var e=0,o=this.length;o>e;e++)if(e in this&&this[e]===t)return e;return-1};a=this.Tether.Utils,l=a.getOuterSize,s=a.getBounds,r=a.getSize,i=a.extend,h=a.updateClasses,o=a.defer,e={left:"right",right:"left",top:"bottom",bottom:"top",middle:"middle"},t=["left","top","right","bottom"],n=function(e,o){var i,n,l,r,h,a,f;if("scrollParent"===o?o=e.scrollParent:"window"===o&&(o=[pageXOffset,pageYOffset,innerWidth+pageXOffset,innerHeight+pageYOffset]),o===document&&(o=o.documentElement),null!=o.nodeType)for(n=r=s(o),h=getComputedStyle(o),o=[n.left,n.top,r.width+n.left,r.height+n.top],i=a=0,f=t.length;f>a;i=++a)l=t[i],l=l[0].toUpperCase()+l.substr(1),"Top"===l||"Left"===l?o[i]+=parseFloat(h["border"+l+"Width"]):o[i]-=parseFloat(h["border"+l+"Width"]);return o},this.Tether.modules.push({position:function(e){var l,r,a,p,u,d,g,c,m,b,v,y,w,C,O,T,x,E,W,A,S,M,z,B,P,_,F,L,H,Y,X,N,j,R,U,q,k,D,Z,$,I,G,J,K,Q,V,te,ee=this;if(_=e.top,v=e.left,S=e.targetAttachment,!this.options.constraints)return!0;for(E=function(e){var o,i,n,s;for(ee.removeClass(e),s=[],i=0,n=t.length;n>i;i++)o=t[i],s.push(ee.removeClass(""+e+"-"+o));return s},$=this.cache("element-bounds",function(){return s(ee.element)}),b=$.height,F=$.width,0===F&&0===b&&null!=this.lastSize&&(I=this.lastSize,F=I.width,b=I.height),z=this.cache("target-bounds",function(){return ee.getTargetBounds()}),M=z.height,B=z.width,A={},m={},r=[this.getClass("pinned"),this.getClass("out-of-bounds")],G=this.options.constraints,L=0,N=G.length;N>L;L++)c=G[L],c.outOfBoundsClass&&r.push(c.outOfBoundsClass),c.pinnedClass&&r.push(c.pinnedClass);for(H=0,j=r.length;j>H;H++)for(g=r[H],J=["left","top","right","bottom"],Y=0,R=J.length;R>Y;Y++)W=J[Y],r.push(""+g+"-"+W);for(l=[],A=i({},S),m=i({},this.attachment),K=this.options.constraints,X=0,U=K.length;U>X;X++){if(c=K[X],P=c.to,a=c.attachment,O=c.pin,null==a&&(a=""),f.call(a," ")>=0?(Q=a.split(" "),d=Q[0],u=Q[1]):u=d=a,p=n(this,P),("target"===d||"both"===d)&&(_<p[1]&&"top"===A.top&&(_+=M,A.top="bottom"),_+b>p[3]&&"bottom"===A.top&&(_-=M,A.top="top")),"together"===d&&(_<p[1]&&"top"===A.top&&("bottom"===m.top?(_+=M,A.top="bottom",_+=b,m.top="top"):"top"===m.top&&(_+=M,A.top="bottom",_-=b,m.top="bottom")),_+b>p[3]&&"bottom"===A.top&&("top"===m.top?(_-=M,A.top="top",_-=b,m.top="bottom"):"bottom"===m.top&&(_-=M,A.top="top",_+=b,m.top="top")),"middle"===A.top&&(_+b>p[3]&&"top"===m.top?(_-=b,m.top="bottom"):_<p[1]&&"bottom"===m.top&&(_+=b,m.top="top"))),("target"===u||"both"===u)&&(v<p[0]&&"left"===A.left&&(v+=B,A.left="right"),v+F>p[2]&&"right"===A.left&&(v-=B,A.left="left")),"together"===u&&(v<p[0]&&"left"===A.left?"right"===m.left?(v+=B,A.left="right",v+=F,m.left="left"):"left"===m.left&&(v+=B,A.left="right",v-=F,m.left="right"):v+F>p[2]&&"right"===A.left?"left"===m.left?(v-=B,A.left="left",v-=F,m.left="right"):"right"===m.left&&(v-=B,A.left="left",v+=F,m.left="left"):"center"===A.left&&(v+F>p[2]&&"left"===m.left?(v-=F,m.left="right"):v<p[0]&&"right"===m.left&&(v+=F,m.left="left"))),("element"===d||"both"===d)&&(_<p[1]&&"bottom"===m.top&&(_+=b,m.top="top"),_+b>p[3]&&"top"===m.top&&(_-=b,m.top="bottom")),("element"===u||"both"===u)&&(v<p[0]&&"right"===m.left&&(v+=F,m.left="left"),v+F>p[2]&&"left"===m.left&&(v-=F,m.left="right")),"string"==typeof O?O=function(){var t,e,o,i;for(o=O.split(","),i=[],e=0,t=o.length;t>e;e++)C=o[e],i.push(C.trim());return i}():O===!0&&(O=["top","left","right","bottom"]),O||(O=[]),T=[],y=[],_<p[1]&&(f.call(O,"top")>=0?(_=p[1],T.push("top")):y.push("top")),_+b>p[3]&&(f.call(O,"bottom")>=0?(_=p[3]-b,T.push("bottom")):y.push("bottom")),v<p[0]&&(f.call(O,"left")>=0?(v=p[0],T.push("left")):y.push("left")),v+F>p[2]&&(f.call(O,"right")>=0?(v=p[2]-F,T.push("right")):y.push("right")),T.length)for(x=null!=(V=this.options.pinnedClass)?V:this.getClass("pinned"),l.push(x),D=0,q=T.length;q>D;D++)W=T[D],l.push(""+x+"-"+W);if(y.length)for(w=null!=(te=this.options.outOfBoundsClass)?te:this.getClass("out-of-bounds"),l.push(w),Z=0,k=y.length;k>Z;Z++)W=y[Z],l.push(""+w+"-"+W);(f.call(T,"left")>=0||f.call(T,"right")>=0)&&(m.left=A.left=!1),(f.call(T,"top")>=0||f.call(T,"bottom")>=0)&&(m.top=A.top=!1),(A.top!==S.top||A.left!==S.left||m.top!==this.attachment.top||m.left!==this.attachment.left)&&this.updateAttachClasses(m,A)}return o(function(){return h(ee.target,l,r),h(ee.element,l,r)}),{top:_,left:v}}})}.call(this),function(){var t,e,o,i;i=this.Tether.Utils,e=i.getBounds,o=i.updateClasses,t=i.defer,this.Tether.modules.push({position:function(i){var n,s,l,r,h,a,f,p,u,d,g,c,m,b,v,y,w,C,O,T,x,E,W,A,S,M=this;if(g=i.top,a=i.left,x=this.cache("element-bounds",function(){return e(M.element)}),h=x.height,c=x.width,d=this.getTargetBounds(),r=g+h,f=a+c,n=[],g<=d.bottom&&r>=d.top)for(E=["left","right"],m=0,w=E.length;w>m;m++)p=E[m],((W=d[p])===a||W===f)&&n.push(p);if(a<=d.right&&f>=d.left)for(A=["top","bottom"],b=0,C=A.length;C>b;b++)p=A[b],((S=d[p])===g||S===r)&&n.push(p);for(l=[],s=[],u=["left","top","right","bottom"],l.push(this.getClass("abutted")),v=0,O=u.length;O>v;v++)p=u[v],l.push(""+this.getClass("abutted")+"-"+p);for(n.length&&s.push(this.getClass("abutted")),y=0,T=n.length;T>y;y++)p=n[y],s.push(""+this.getClass("abutted")+"-"+p);return t(function(){return o(M.target,s,l),o(M.element,s,l)}),!0}})}.call(this),function(){this.Tether.modules.push({position:function(t){var e,o,i,n,s,l,r;return l=t.top,e=t.left,this.options.shift?(o=function(t){return"function"==typeof t?t.call(this,{top:l,left:e}):t},i=o(this.options.shift),"string"==typeof i?(i=i.split(" "),i[1]||(i[1]=i[0]),s=i[0],n=i[1],s=parseFloat(s,10),n=parseFloat(n,10)):(r=[i.top,i.left],s=r[0],n=r[1]),l+=s,e+=n,{top:l,left:e}):void 0}})}.call(this),this.Tether}); \ No newline at end of file
diff --git a/afb-client/bower_components/viewport-units-buggyfill/.bower.json b/afb-client/bower_components/viewport-units-buggyfill/.bower.json
new file mode 100644
index 0000000..ca2be55
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/.bower.json
@@ -0,0 +1,30 @@
+{
+ "name": "viewport-units-buggyfill",
+ "version": "0.4.1",
+ "main": [
+ "./viewport-units-buggyfill.js",
+ "./viewport-units-buggyfill.hacks.js"
+ ],
+ "ignore": [
+ "**/.*",
+ "examples",
+ "*.html",
+ "*.css",
+ "*.md"
+ ],
+ "keywords": [
+ "ios",
+ "safari",
+ "viewport"
+ ],
+ "homepage": "https://github.com/rodneyrehm/viewport-units-buggyfill",
+ "_release": "0.4.1",
+ "_resolution": {
+ "type": "version",
+ "tag": "v0.4.1",
+ "commit": "78773d57c98637e1461da53c4917ca44dc1b3d33"
+ },
+ "_source": "git://github.com/rodneyrehm/viewport-units-buggyfill.git",
+ "_target": "~0.4.1",
+ "_originalSource": "viewport-units-buggyfill"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/viewport-units-buggyfill/Gruntfile.js b/afb-client/bower_components/viewport-units-buggyfill/Gruntfile.js
new file mode 100755
index 0000000..a8e10ee
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/Gruntfile.js
@@ -0,0 +1,19 @@
+module.exports = function(grunt) {
+ 'use strict';
+
+ var jshintOptions = grunt.file.readJSON('.jshintrc');
+ jshintOptions.reporter = require('jshint-stylish');
+
+ grunt.initConfig({
+ jshint: {
+ options: jshintOptions,
+ target: [
+ 'Gruntfile.js',
+ 'viewport-units-buggyfill.js'
+ ]
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.registerTask('lint', 'jshint');
+};
diff --git a/afb-client/bower_components/viewport-units-buggyfill/bower.json b/afb-client/bower_components/viewport-units-buggyfill/bower.json
new file mode 100755
index 0000000..3b3c4da
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/bower.json
@@ -0,0 +1,20 @@
+{
+ "name": "viewport-units-buggyfill",
+ "version": "0.4.1",
+ "main": [
+ "./viewport-units-buggyfill.js",
+ "./viewport-units-buggyfill.hacks.js"
+ ],
+ "ignore": [
+ "**/.*",
+ "examples",
+ "*.html",
+ "*.css",
+ "*.md"
+ ],
+ "keywords": [
+ "ios",
+ "safari",
+ "viewport"
+ ]
+} \ No newline at end of file
diff --git a/afb-client/bower_components/viewport-units-buggyfill/package.json b/afb-client/bower_components/viewport-units-buggyfill/package.json
new file mode 100755
index 0000000..d7803fc
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "viewport-units-buggyfill",
+ "version": "0.4.1",
+ "title": "Viewport Units Buggyfill for Mobile Safari",
+ "description": "Making viewport units (vh|vw|vmin|vmax) work properly in Mobile Safari",
+ "homepage": "http://github.com/rodneyrehm/viewport-units-buggyfill/",
+ "author": {
+ "name": "Rodney Rehm",
+ "url": "http://rodneyrehm.de"
+ },
+ "contributors": [{
+ "name": "Zoltan Hawryluk",
+ "url": "http://www.useragentman.com"
+ }],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/rodneyrehm/viewport-units-buggyfill.git"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://www.opensource.org/licenses/mit-license"
+ }
+ ],
+ "keywords": [
+ "ios",
+ "safari",
+ "viewport"
+ ],
+ "main": "./viewport-units-buggyfill.js",
+ "files": [
+ "viewport-units-buggyfill.js",
+ "viewport-units-buggyfill.hacks.js"
+ ],
+ "scripts": {
+ "lint": "grunt lint"
+ },
+ "devDependencies": {
+ "jshint-stylish": "~0.1.5",
+ "grunt": "~0.4.2",
+ "grunt-contrib-jshint": "~0.8.0"
+ }
+}
diff --git a/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.hacks.js b/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.hacks.js
new file mode 100644
index 0000000..b931629
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.hacks.js
@@ -0,0 +1,138 @@
+/*!
+ * viewport-units-buggyfill.hacks v0.4.1
+ * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
+ * @author: Zoltan Hawryluk - http://www.useragentman.com/
+ */
+
+(function (root, factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([], factory);
+ } else if (typeof exports === 'object') {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like enviroments that support module.exports,
+ // like Node.
+ module.exports = factory();
+ } else {
+ // Browser globals (root is window)
+ root.viewportUnitsBuggyfillHacks = factory();
+ }
+}(this, function () {
+ 'use strict';
+
+ var options;
+ var calcExpression = /calc\(/g;
+ var quoteExpression = /[\"\']/g;
+ var urlExpression = /url\([^\)]*\)/g;
+ var isOldInternetExplorer = false;
+ var supportsVminmax = true;
+ var supportsVminmaxCalc = true;
+
+ // WARNING!
+ // Do not remove the following conditional comment.
+ // It is required to identify the current version of IE
+
+ /*@cc_on
+
+ @if (@_jscript_version <= 10)
+ isOldInternetExplorer = true;
+ supportsVminmaxCalc = false;
+ supportsVminmax = false;
+ @end
+
+ @*/
+
+ // iOS SAFARI, IE9: abuse "content" if "use_css_content_hack" specified
+ // IE9: abuse "behavior" if "use_css_behavior_hack" specified
+ function checkHacks(declarations, rule, name, value) {
+ if (!options.contentHack && !options.behaviorHack) {
+ return;
+ }
+
+ if (name !== 'content' && name !== 'behavior') {
+ return;
+ }
+
+ var needsCalcFix = (options.contentHack && !supportsVminmaxCalc && name === 'content' && value.indexOf('use_css_content_hack') > -1);
+ var needsVminVmaxFix = (options.behaviorHack && !supportsVminmax && name === 'behavior' && value.indexOf('use_css_behavior_hack') > -1);
+ if (!needsCalcFix && !needsVminVmaxFix) {
+ return;
+ }
+
+ var fakeRules = value.replace(quoteExpression, '');
+ if (needsVminVmaxFix) {
+ fakeRules = fakeRules.replace(urlExpression, '');
+ }
+
+ fakeRules.split(';').forEach(function(fakeRuleElement) {
+ var fakeRule = fakeRuleElement.split(':');
+ if (fakeRule.length !== 2) {
+ return;
+ }
+
+ var name = fakeRule[0].trim();
+ var value = fakeRule[1].trim();
+ if (name === 'use_css_content_hack' || name === 'use_css_behavior_hack') {
+ return;
+ }
+
+ declarations.push([rule, name, value]);
+ if (calcExpression.test(value)) {
+ var webkitValue = value.replace(calcExpression, '-webkit-calc(');
+ declarations.push([rule, name, webkitValue]);
+ }
+ });
+ }
+
+ return {
+ required: function(options) {
+ return options.isMobileSafari || isOldInternetExplorer;
+ },
+
+ initialize: function(initOptions) {
+ options = initOptions;
+
+ // Test viewport units support in calc() expressions
+ var div = document.createElement('div');
+ div.style.width = '1vmax';
+ supportsVminmax = div.style.width !== '';
+
+ // there is no accurate way to detect this programmatically.
+ if (options.isMobileSafari) {
+ supportsVminmaxCalc = false;
+ }
+ },
+
+ initializeEvents: function(options, refresh, _refresh) {
+ if (options.force) {
+ return;
+ }
+
+ if (isOldInternetExplorer && !options._listeningToResize) {
+ window.addEventListener('resize', _refresh, true);
+ options._listeningToResize = true;
+ }
+ },
+
+ findDeclarations: function(declarations, rule, name, value) {
+ if (name === null) {
+ // KeyframesRule does not have a CSS-PropertyName
+ return;
+ }
+
+ checkHacks(declarations, rule, name, value);
+ },
+
+ overwriteDeclaration: function(rule, name, _value) {
+ if (isOldInternetExplorer && name === 'filter') {
+ // remove unit "px" from complex value, e.g.:
+ // filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=5.4px, OffY=3.9px, Color=#000000);
+ _value = _value.replace(/px/g, '');
+ }
+
+ return _value;
+ }
+ };
+
+}));
diff --git a/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js b/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js
new file mode 100755
index 0000000..242af2a
--- /dev/null
+++ b/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js
@@ -0,0 +1,347 @@
+/*!
+ * viewport-units-buggyfill v0.4.1
+ * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
+ * @author: Rodney Rehm - http://rodneyrehm.de/en/
+ */
+
+(function (root, factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([], factory);
+ } else if (typeof exports === 'object') {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like enviroments that support module.exports,
+ // like Node.
+ module.exports = factory();
+ } else {
+ // Browser globals (root is window)
+ root.viewportUnitsBuggyfill = factory();
+ }
+}(this, function () {
+ 'use strict';
+ /*global document, window, location, XMLHttpRequest, XDomainRequest*/
+
+ var initialized = false;
+ var options;
+ var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(window.navigator.userAgent);
+ var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
+ var forEach = [].forEach;
+ var dimensions;
+ var declarations;
+ var styleNode;
+ var isOldInternetExplorer = false;
+
+ // Do not remove the following comment!
+ // It is a conditional comment used to
+ // identify old Internet Explorer versions
+
+ /*@cc_on
+
+ @if (@_jscript_version <= 10)
+ isOldInternetExplorer = true;
+ @end
+
+ @*/
+
+ function debounce(func, wait) {
+ var timeout;
+ return function() {
+ var context = this;
+ var args = arguments;
+ var callback = function() {
+ func.apply(context, args);
+ };
+
+ clearTimeout(timeout);
+ timeout = setTimeout(callback, wait);
+ };
+ }
+
+ // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
+ function inIframe() {
+ try {
+ return window.self !== window.top;
+ } catch (e) {
+ return true;
+ }
+ }
+
+ function initialize(initOptions) {
+ if (initialized) {
+ return;
+ }
+
+ if (initOptions === true) {
+ initOptions = {
+ force: true
+ };
+ }
+
+ options = initOptions || {};
+ options.isMobileSafari = isMobileSafari;
+
+ if (!options.force && !isMobileSafari && !isOldInternetExplorer && (!options.hacks || !options.hacks.required(options))) {
+ // this buggyfill only applies to mobile safari
+ return;
+ }
+
+ options.hacks && options.hacks.initialize(options);
+
+ initialized = true;
+ styleNode = document.createElement('style');
+ styleNode.id = 'patched-viewport';
+ document.head.appendChild(styleNode);
+
+ // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
+ // therefore download and inject them as <style> to circumvent SOP.
+ importCrossOriginLinks(function() {
+ var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
+ // doing a full refresh rather than updateStyles because an orientationchange
+ // could activate different stylesheets
+ window.addEventListener('orientationchange', _refresh, true);
+ // orientationchange might have happened while in a different window
+ window.addEventListener('pageshow', _refresh, true);
+
+ if (options.force || isOldInternetExplorer || inIframe()) {
+ window.addEventListener('resize', _refresh, true);
+ options._listeningToResize = true;
+ }
+
+ options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);
+
+ refresh();
+ });
+ }
+
+ function updateStyles() {
+ styleNode.textContent = getReplacedViewportUnits();
+ }
+
+ function refresh() {
+ if (!initialized) {
+ return;
+ }
+
+ findProperties();
+
+ // iOS Safari will report window.innerWidth and .innerHeight as 0
+ // unless a timeout is used here.
+ // TODO: figure out WHY innerWidth === 0
+ setTimeout(function() {
+ updateStyles();
+ }, 1);
+ }
+
+ function findProperties() {
+ declarations = [];
+ forEach.call(document.styleSheets, function(sheet) {
+ if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
+ // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
+ return;
+ }
+
+ if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
+ // skip entire sheet because media attribute doesn't match
+ return;
+ }
+
+ forEach.call(sheet.cssRules, findDeclarations);
+ });
+
+ return declarations;
+ }
+
+ function findDeclarations(rule) {
+ if (rule.type === 7) {
+ var value = rule.cssText;
+ viewportUnitExpression.lastIndex = 0;
+ if (viewportUnitExpression.test(value)) {
+ // KeyframesRule does not have a CSS-PropertyName
+ declarations.push([rule, null, value]);
+ options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
+ }
+
+ return;
+ }
+
+ if (!rule.style) {
+ if (!rule.cssRules) {
+ return;
+ }
+
+ forEach.call(rule.cssRules, function(_rule) {
+ findDeclarations(_rule);
+ });
+
+ return;
+ }
+
+ forEach.call(rule.style, function(name) {
+ var value = rule.style.getPropertyValue(name);
+ viewportUnitExpression.lastIndex = 0;
+ if (viewportUnitExpression.test(value)) {
+ declarations.push([rule, name, value]);
+ options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
+ }
+ });
+ }
+
+ function getReplacedViewportUnits() {
+ dimensions = getViewport();
+
+ var css = [];
+ var buffer = [];
+ var open;
+ var close;
+
+ declarations.forEach(function(item) {
+ var _item = overwriteDeclaration.apply(null, item);
+ var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
+ var _close = new Array(_item.selector.length + 1).join('\n}');
+
+ if (!_open || _open !== open) {
+ if (buffer.length) {
+ css.push(open + buffer.join('\n') + close);
+ buffer.length = 0;
+ }
+
+ if (_open) {
+ open = _open;
+ close = _close;
+ buffer.push(_item.content);
+ } else {
+ css.push(_item.content);
+ open = null;
+ close = null;
+ }
+
+ return;
+ }
+
+ if (_open && !open) {
+ open = _open;
+ close = _close;
+ }
+
+ buffer.push(_item.content);
+ });
+
+ if (buffer.length) {
+ css.push(open + buffer.join('\n') + close);
+ }
+
+ return css.join('\n\n');
+ }
+
+ function overwriteDeclaration(rule, name, value) {
+ var _value = value.replace(viewportUnitExpression, replaceValues);
+ var _selectors = [];
+
+ if (options.hacks) {
+ _value = options.hacks.overwriteDeclaration(rule, name, _value);
+ }
+
+ if (name) {
+ // skipping KeyframesRule
+ _selectors.push(rule.selectorText);
+ _value = name + ': ' + _value + ';';
+ }
+
+ var _rule = rule.parentRule;
+ while (_rule) {
+ _selectors.unshift('@media ' + _rule.media.mediaText);
+ _rule = _rule.parentRule;
+ }
+
+ return {
+ selector: _selectors,
+ content: _value
+ };
+ }
+
+ function replaceValues(match, number, unit) {
+ var _base = dimensions[unit];
+ var _number = parseFloat(number) / 100;
+ return (_number * _base) + 'px';
+ }
+
+ function getViewport() {
+ var vh = window.innerHeight;
+ var vw = window.innerWidth;
+
+ return {
+ vh: vh,
+ vw: vw,
+ vmax: Math.max(vw, vh),
+ vmin: Math.min(vw, vh)
+ };
+ }
+
+ function importCrossOriginLinks(next) {
+ var _waiting = 0;
+ var decrease = function() {
+ _waiting--;
+ if (!_waiting) {
+ next();
+ }
+ };
+
+ forEach.call(document.styleSheets, function(sheet) {
+ if (!sheet.href || origin(sheet.href) === origin(location.href)) {
+ // skip <style> and <link> from same origin
+ return;
+ }
+
+ _waiting++;
+ convertLinkToStyle(sheet.ownerNode, decrease);
+ });
+
+ if (!_waiting) {
+ next();
+ }
+ }
+
+ function origin(url) {
+ return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
+ }
+
+ function convertLinkToStyle(link, next) {
+ getCors(link.href, function() {
+ var style = document.createElement('style');
+ style.media = link.media;
+ style.setAttribute('data-href', link.href);
+ style.textContent = this.responseText;
+ link.parentNode.replaceChild(style, link);
+ next();
+ }, next);
+ }
+
+ function getCors(url, success, error) {
+ var xhr = new XMLHttpRequest();
+ if ('withCredentials' in xhr) {
+ // XHR for Chrome/Firefox/Opera/Safari.
+ xhr.open('GET', url, true);
+ } else if (typeof XDomainRequest !== 'undefined') {
+ // XDomainRequest for IE.
+ xhr = new XDomainRequest();
+ xhr.open('GET', url);
+ } else {
+ throw new Error('cross-domain XHR not supported');
+ }
+
+ xhr.onload = success;
+ xhr.onerror = error;
+ xhr.send();
+ return xhr;
+ }
+
+ return {
+ version: '0.4.1',
+ findProperties: findProperties,
+ getCss: getReplacedViewportUnits,
+ init: initialize,
+ refresh: refresh
+ };
+
+}));