├── js ├── README.md ├── angular-cookie.min.js ├── ng-ckeditor.js ├── app.js ├── angular-ui-router.min.js └── jquery.min.js ├── LICENSE ├── README.md ├── index.html ├── partials ├── createAccountModal.html ├── main.html └── navbar.html ├── css └── app.css └── bootstrap └── bootstrap.js /js/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Scotho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /js/angular-cookie.min.js: -------------------------------------------------------------------------------- 1 | angular.module("ivpusic.cookie",["ipCookie"]),angular.module("ipCookie",["ng"]).factory("ipCookie",["$document",function(e){"use strict";function i(e){try{return decodeURIComponent(e)}catch(i){}}return function(){function t(t,n,r){var o,s,p,u,a,c,x,d,f;if(r=r||{},void 0!==n)return n="object"==typeof n?JSON.stringify(n):n+"","number"==typeof r.expires&&(f=r.expires,r.expires=new Date,-1===f?r.expires=new Date("Thu, 01 Jan 1970 00:00:00 GMT"):void 0!==r.expirationUnit?"hours"===r.expirationUnit?r.expires.setHours(r.expires.getHours()+f):"minutes"===r.expirationUnit?r.expires.setMinutes(r.expires.getMinutes()+f):"seconds"===r.expirationUnit?r.expires.setSeconds(r.expires.getSeconds()+f):r.expires.setDate(r.expires.getDate()+f):r.expires.setDate(r.expires.getDate()+f)),e[0].cookie=[encodeURIComponent(t),"=",encodeURIComponent(n),r.expires?"; expires="+r.expires.toUTCString():"",r.path?"; path="+r.path:"",r.domain?"; domain="+r.domain:"",r.secure?"; secure":""].join("");for(s=[],d=e[0].cookie,d&&(s=d.split("; ")),o={},x=!1,p=0;s.length>p;++p)if(s[p]){if(u=s[p],a=u.indexOf("="),c=u.substring(0,a),n=i(u.substring(a+1)),angular.isUndefined(n))continue;if(void 0===t||t===c){try{o[c]=JSON.parse(n)}catch(g){o[c]=n}if(t===c)return o[c];x=!0}}return x&&void 0===t?o:void 0}return t.remove=function(e,i){var n=void 0!==t(e);return n&&(i||(i={}),i.expires=-1,t(e,"",i)),n},t}()}]); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | What's it do? 3 | --------------------- 4 | *Firebased was designed to be a starting point for any AngularFire (AngularJS+Firebase) web application. Here are a few feature highlights...* 5 | 6 | - Account handling (includes cookie session storage) 7 | - [Dead simple three way data binding](https://www.firebase.com/blog/2013-10-04-firebase-angular-data-binding.html) on user-specific arrays. *(Confused? Open 2 demo pages simultaneously and modify some text)* 8 | - A functional and responsive bootstrap template 9 | - Implements a wide range of Angular, Firebase, and MVC concepts out of the box. 10 | 11 | Depends on [Bootstrap](http://getbootstrap.com/), [jQuery](https://jquery.com/), [firebase](https://www.firebase.com/), [angularfire](https://www.firebase.com/docs/web/libraries/angular/), and [angular-cookie](https://github.com/ivpusic/angular-cookie) 12 | 13 | [Click here to see the demo](http://craigryansmith.com/firebased/) 14 | 15 | 16 | How do I get started? 17 | --------------------- 18 | *To get started, simply change "appName" at the top of app.js to your [firebase](https://www.firebase.com) appName and run index.html. Currently, all logic is contained in the controllers found in app.js* 19 | 20 | - Please note that this is a beta version of which is still under developmet. Any and all contributions are greatly appreciated! 21 | 22 | *Documentation coming soon!* 23 | 24 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /partials/createAccountModal.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /partials/main.html: -------------------------------------------------------------------------------- 1 | 2 |
6 | 7 | 8 |
13 | 14 | 15 |
18 | 19 |
24 |
25 | 26 | 27 | 32 | 33 | 34 | 35 | 36 |
41 |
42 |
43 | index: {{$index}} 44 |
45 | address: {{this.bullet.address}} 46 |
47 | hasChild: {{this.bullet.hasChild}} 48 |
49 | Tab Index: {{this.bullet.tabIndex}} 50 |
51 | Parent Address: {{this.bullet.parentPointer.address}} 52 |
53 |
54 |
55 |
56 | 57 | 58 | 59 | 72 | 73 | 74 |
75 | 76 | 77 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
-------------------------------------------------------------------------------- /partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/app.css: -------------------------------------------------------------------------------- 1 | /*---------------NAVBAR-------------*/ 2 | .navstatic{ 3 | z-index:1030; 4 | top:0; 5 | right:0; 6 | left:0; 7 | position:fixed; 8 | width:100%; 9 | height:80px; 10 | background-color:white; 11 | } 12 | .pulled-left{ 13 | float:left; 14 | } 15 | .pulled-right{ 16 | float:right; 17 | height:45px; 18 | margin-bottom:0px; 19 | } 20 | .rich-toolbar{ 21 | z-index:1035; 22 | display:none; 23 | } 24 | .focussed{ 25 | display:block; 26 | } 27 | .navbarcontainer{ 28 | z-index:1030; 29 | display:inline-block; 30 | position:fixed; 31 | background-color:#f8f8f8; 32 | width:100%; 33 | height:45px; 34 | } 35 | .navwell{ 36 | position:relative; 37 | left:1%; 38 | width:98%; 39 | height:80px; 40 | -webkit-border-radius: 10px; 41 | -moz-border-radius: 10px; 42 | border-radius: 10px; 43 | border:1px solid #DDDDDD; 44 | background-color:#f0f0f0; 45 | } 46 | .navgroup{ 47 | margin-right:15px; 48 | margin-left:15px; 49 | margin-top:10px; 50 | } 51 | .navaddress{ 52 | height:30px; 53 | margin-top:50px; 54 | text-align:center; 55 | font-style:italic; 56 | z-index:1035; 57 | } 58 | .navdropdown{ 59 | padding:5px; 60 | width:100%; 61 | text-align:center; 62 | } 63 | .navaddressinput{ 64 | text-align:center; 65 | } 66 | .dropshadow{ 67 | box-shadow: 5px 5px 2.5px #888888; 68 | } 69 | .dropdown{ 70 | width:100%; 71 | } 72 | .dropdown-menu{ 73 | right:0; 74 | left:0; 75 | top:0; 76 | width:auto; 77 | position:fixed; 78 | margin-top:45px; 79 | margin-right:1px; 80 | margin-left:8px; 81 | } 82 | .navuser{ 83 | color:grey; 84 | font-style:italic; 85 | font-size:15px; 86 | } 87 | .navelement{ 88 | color:black; 89 | } 90 | .globalsearch{ 91 | background-color:transparent; 92 | margin-top:3px; 93 | width:50px; 94 | font-style:italic; 95 | font-size:12px; 96 | } 97 | 98 | /*---------------/NAVBAR--------------*/ 99 | 100 | 101 | /*---------------BULLETGROUP-------------*/ 102 | 103 | .bulletgroup{ 104 | padding-top:85px; 105 | padding-bottom:180px; 106 | z-index:1005; 107 | overflow-y:scroll; 108 | height:auto; 109 | position:relative; 110 | } 111 | 112 | .bullet{ 113 | position:absolute; 114 | float:left; 115 | margin-top:6.2px; 116 | width:10px; 117 | height:10px; 118 | border-radius:11px; 119 | border:2px double #ccc; 120 | font-size:5px; 121 | color:#666; 122 | line-height:20px; 123 | vertical-align:center; 124 | text-decoration:none; 125 | text-shadow:0 1px 0 #fff; 126 | background:#F2F5F2 127 | } 128 | 129 | .bullet:hover{ 130 | border:4px double #bbb; 131 | color:#aaa; 132 | background:#e6e6e6; 133 | z-index: -1; 134 | } 135 | 136 | .bulletinput { 137 | width:90%; 138 | margin-left:15px; 139 | } 140 | 141 | /*--MENU--*/ 142 | 143 | .menuspacer{ 144 | width:30px; 145 | position:absolute; 146 | height:20px; 147 | background-color:transparent; 148 | } 149 | 150 | .bulletmenu{ 151 | margin-top:20px; 152 | width:100px; 153 | height:180px; 154 | position:absolute; 155 | background-color:#F5F5F5; 156 | box-shadow: 5px 5px 2.5px #888888; 157 | text-align:center; 158 | z-index: 100; 159 | } 160 | /*--/MENU--/ 161 | 162 | /*--------------/BULLETGROUP-------------*/ 163 | 164 | 165 | 166 | /*---------------MISC-------------*/ 167 | 168 | 169 | .smallshadow{ 170 | box-shadow: 1px 1px 3px #888888; 171 | } 172 | 173 | input.form-control { 174 | position:relative; 175 | margin-bottom: 0; 176 | border-radius: 0; 177 | border: 2px; 178 | padding-right: 20px; 179 | } 180 | html,body{ 181 | width:100%; 182 | height:0px; 183 | position:relative; 184 | } 185 | #main{ 186 | margin-top:100px; 187 | } 188 | .inline { 189 | display: inline; 190 | } 191 | 192 | .footer { 193 | z-index:1030; 194 | bottom:0; 195 | right:0; 196 | left:0; 197 | position:fixed; 198 | width:100%; 199 | height:90px; 200 | background-color:#F2F2F2; 201 | } 202 | 203 | .footerAd { 204 | margin:8px;; 205 | background-color:#FFFFFF; 206 | height:50px; 207 | width:98% 208 | 209 | } 210 | .footerText { 211 | height:20px; 212 | width:100%; 213 | text-align:center; 214 | font-style:italic; 215 | font-size:12px; 216 | 217 | } 218 | input { 219 | border: none; 220 | /* Good browsers universal rule */ 221 | outline: none; 222 | /* safari and its variants */ 223 | outline-offset: 0; 224 | /* IE and its variants */ 225 | -webkit-appearance: none; 226 | /* Chrome and its variants */ 227 | } -------------------------------------------------------------------------------- /js/ng-ckeditor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function (angular, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | define(['angular', 'ckeditor'], function (angular) { 6 | return factory(angular); 7 | }); 8 | } else { 9 | return factory(angular); 10 | } 11 | }(angular || null, function (angular) { 12 | var app = angular.module('ngCkeditor', []); 13 | var $defer, loaded = false; 14 | 15 | app.run(['$q', '$timeout', function ($q, $timeout) { 16 | $defer = $q.defer(); 17 | 18 | if (angular.isUndefined(CKEDITOR)) { 19 | throw new Error('CKEDITOR not found'); 20 | } 21 | CKEDITOR.disableAutoInline = true; 22 | function checkLoaded() { 23 | if (CKEDITOR.status === 'loaded') { 24 | loaded = true; 25 | $defer.resolve(); 26 | } else { 27 | checkLoaded(); 28 | } 29 | } 30 | 31 | CKEDITOR.on('loaded', checkLoaded); 32 | $timeout(checkLoaded, 100); 33 | }]); 34 | 35 | app.directive('ckeditor', ['$timeout', '$q', function ($timeout, $q) { 36 | 37 | return { 38 | restrict: 'AC', 39 | require: ['ngModel', '^?form'], 40 | scope: false, 41 | link: function (scope, element, attrs, ctrls) { 42 | var ngModel = ctrls[0]; 43 | var form = ctrls[1] || null; 44 | var EMPTY_HTML = '

', 45 | isTextarea = element[0].tagName.toLowerCase() === 'textarea', 46 | data = [], 47 | isReady = false; 48 | 49 | if (!isTextarea) { 50 | element.attr('contenteditable', true); 51 | } 52 | 53 | var onLoad = function () { 54 | var options = { 55 | toolbar: 'full', 56 | toolbar_full: [ //jshint ignore:line 57 | { 58 | name: 'basicstyles', 59 | items: ['Bold', 'Italic', 'Strike', 'Underline'] 60 | }, 61 | {name: 'paragraph', items: ['BulletedList', 'NumberedList', 'Blockquote']}, 62 | {name: 'editing', items: ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']}, 63 | {name: 'links', items: ['Link', 'Unlink', 'Anchor']}, 64 | {name: 'tools', items: ['SpellChecker', 'Maximize']}, 65 | '/', 66 | { 67 | name: 'styles', 68 | items: ['Format', 'FontSize', 'TextColor', 'PasteText', 'PasteFromWord', 'RemoveFormat'] 69 | }, 70 | {name: 'insert', items: ['Image', 'Table', 'SpecialChar']}, 71 | {name: 'forms', items: ['Outdent', 'Indent']}, 72 | {name: 'clipboard', items: ['Undo', 'Redo']}, 73 | {name: 'document', items: ['PageBreak', 'Source']} 74 | ], 75 | disableNativeSpellChecker: false, 76 | uiColor: '#FAFAFA', 77 | height: '400px', 78 | width: '100%' 79 | }; 80 | options = angular.extend(options, scope[attrs.ckeditor]); 81 | 82 | var instance = (isTextarea) ? CKEDITOR.replace(element[0], options) : CKEDITOR.inline(element[0], options), 83 | configLoaderDef = $q.defer(); 84 | 85 | element.bind('$destroy', function () { 86 | if (instance && CKEDITOR.instances[instance.name]) { 87 | CKEDITOR.instances[instance.name].destroy(); 88 | } 89 | }); 90 | var setModelData = function (setPristine) { 91 | var data = instance.getData(); 92 | if (data === '') { 93 | data = null; 94 | } 95 | $timeout(function () { // for key up event 96 | if (setPristine !== true || data !== ngModel.$viewValue) { 97 | ngModel.$setViewValue(data); 98 | } 99 | 100 | if (setPristine === true && form) { 101 | form.$setPristine(); 102 | } 103 | }, 0); 104 | }, onUpdateModelData = function (setPristine) { 105 | if (!data.length) { 106 | return; 107 | } 108 | 109 | var item = data.pop() || EMPTY_HTML; 110 | isReady = false; 111 | instance.setData(item, function () { 112 | setModelData(setPristine); 113 | isReady = true; 114 | }); 115 | }; 116 | 117 | //instance.on('pasteState', setModelData); 118 | instance.on('change', setModelData); 119 | instance.on('blur', setModelData); 120 | //instance.on('key', setModelData); // for source view 121 | 122 | instance.on('instanceReady', function () { 123 | scope.$broadcast('ckeditor.ready'); 124 | scope.$apply(function () { 125 | onUpdateModelData(true); 126 | }); 127 | 128 | instance.document.on('keyup', setModelData); 129 | }); 130 | instance.on('customConfigLoaded', function () { 131 | configLoaderDef.resolve(); 132 | }); 133 | 134 | ngModel.$render = function () { 135 | data.push(ngModel.$viewValue); 136 | if (isReady) { 137 | onUpdateModelData(); 138 | } 139 | }; 140 | }; 141 | 142 | if (CKEDITOR.status === 'loaded') { 143 | loaded = true; 144 | } 145 | if (loaded) { 146 | onLoad(); 147 | } else { 148 | $defer.promise.then(onLoad); 149 | } 150 | } 151 | }; 152 | }]); 153 | 154 | return app; 155 | })); -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var appName = ''; //Your firebase app name 3 | var app = angular.module("app", ['firebase', 'ipCookie', 'ui.router']); 4 | app.config(function config($stateProvider) { 5 | $stateProvider.state("index", { 6 | url: "", 7 | }) 8 | }); 9 | 10 | //COOKIE CONTROLLER---------------------------------- 11 | app.controller('NavController', ['$scope', '$document', 'ipCookie', '$firebase', function ($scope, $document, ipCookie, $firebase) { 12 | { 13 | $scope.appName = appName; 14 | $scope.currentID = ipCookie('checkAuth'); 15 | //Check to see if current account is undefined or guest 16 | //------------------------------// 17 | //Get UserData, set $scope.userName 18 | var accountRef = new Firebase('https://' + appName + '.firebaseio.com/accounts/createdAccounts/' + $scope.currentID + '/accountDetails/'); 19 | var syncAccount = $firebase(accountRef); 20 | var accountDetails = syncAccount.$asObject(); 21 | //get current object data, store current userName 22 | if ($scope.currentID === undefined || $scope.currentID === 'Guest') { 23 | $scope.userName = 'Guest'; 24 | $scope.currentID = 'Guest'; 25 | } else { 26 | accountDetails.$loaded(function (accData) { 27 | $scope.userName = accData.userName; 28 | }); 29 | } 30 | } //get cookie, set currentID and $scope.userName 31 | 32 | //------------------------------// 33 | var setMessage = function (message, messageStyle) { 34 | $scope.message = message ? message : null; 35 | $scope.messageStyle = messageStyle ? messageStyle : 'success'; 36 | }; 37 | //------------------------------// 38 | var checkAccount = function (email, pass) { 39 | setMessage(); 40 | var ref = new Firebase('https://' + appName + '.firebaseio.com/'); 41 | ref.authWithPassword({ 42 | email: email, 43 | password: pass 44 | }, function (error, authData) { 45 | if (error) { 46 | alert('invalid username/password'); 47 | } else { 48 | alert("Successfully logged in! Credentials saved for 24 hours."); 49 | $scope.currentID = authData.uid; 50 | saveCookie(); 51 | setTimeout(function () { 52 | location.reload(); 53 | }, 500); 54 | } 55 | }); 56 | }; 57 | //------------------------------// 58 | 59 | //------------------------------// 60 | $scope.createAccount = function (userName, email, pass) { 61 | var ref = new Firebase('https://' + appName + '.firebaseio.com/'); 62 | ref.createUser({ 63 | email: email, 64 | password: pass 65 | }, function (error) { 66 | if (error === null) { 67 | var ref2 = new Firebase('https://' + appName + '.firebaseio.com/'); 68 | ref2.authWithPassword({ 69 | email: email, 70 | password: pass 71 | }, function (error, authData) { 72 | if (error) { 73 | alert('account created, but login failed. Please refresh and try again.'); 74 | } else { 75 | $scope.currentID = authData.uid; 76 | setNewUser(userName, email); 77 | saveCookie(); 78 | alert('Account Created Successfully! Welcome to appName, ' + userName + '.'); 79 | 80 | setTimeout(function () { 81 | location.reload(); 82 | }, 500); 83 | } 84 | }); 85 | 86 | } else { 87 | alert("Error creating user:", error); 88 | } 89 | }); 90 | }; //register user 91 | 92 | var setNewUser = function (username, email) { 93 | var newAccountRef = new Firebase('https://' + appName + '.firebaseio.com/accounts/createdAccounts/' + $scope.currentID + '/accountDetails/'); 94 | var syncNewAccount = $firebase(newAccountRef); 95 | var newAccountDetails = syncNewAccount.$asObject(); 96 | newAccountDetails.userName = username; 97 | newAccountDetails.email = email; 98 | newAccountDetails.$save(); 99 | }; 100 | //------------------------------// 101 | var saveCookie = function () { 102 | setMessage(); 103 | $scope.messageStyle = 'success'; 104 | setMessage("Succesfully logged in! Reloading page..."); 105 | // key, value, options 106 | ipCookie('checkAuth', $scope.currentID, { 107 | expires: 24, 108 | expirationUnit: 'hours' 109 | }); 110 | }; 111 | //------------------------------// 112 | $scope.deleteCookie = function () { 113 | setMessage(); 114 | ipCookie.remove('checkAuth'); 115 | if (ipCookie() === undefined) { 116 | setMessage('Successfully logged out.'); 117 | setTimeout(function () { 118 | location.reload(); 119 | }, 500); 120 | } else { 121 | setMessage('Unable to log out', 'danger'); 122 | } 123 | }; 124 | //------------------------------// 125 | $scope.logIn = function (email, pass) { 126 | checkAccount(email, pass); 127 | }; 128 | }]); 129 | 130 | 131 | //MAIN CONTROLLER--------------------------------------- 132 | app.controller("MainCtrl", function ($scope, $firebase, ipCookie) { 133 | $scope.currentID = ipCookie('checkAuth'); 134 | 135 | { 136 | if ($scope.currentID === undefined || $scope.currentID === 'Guest') { 137 | $scope.userName = 'Guest'; 138 | $scope.currentID = 'Guest'; 139 | } 140 | } //Check to see if current account is undefined or guest 141 | 142 | //SYNC DATA FROM SERVER 143 | var currentView = new Firebase('https://' + appName + '.firebaseio.com/accounts/' + $scope.currentID); 144 | var syncBullets = $firebase(currentView); 145 | $scope.bullets = syncBullets.$asArray(); 146 | 147 | 148 | //4.0: BULLET BEHAVIOUR 149 | //--------------------------------------------------- 150 | $scope.NextLine = function (indx) { 151 | angular.element(document.querySelector('#f_' + indx))[0].focus(); 152 | }; //called by ngDown 153 | $scope.BackLine = function (indx) { 154 | angular.element(document.querySelector('#f_' + indx))[0].focus(); 155 | }; //called by Up 156 | 157 | $scope.AddBulletManually = function (indx) { 158 | $scope.bullets.$add({ 159 | 'primaryKey': '', 160 | 'text': '', 161 | 'address': indx, 162 | 'childPointer': null, 163 | 'parentPointer': null, 164 | 'contentCheck': false, 165 | 'content': '' 166 | }); 167 | }; 168 | $scope.AddInLine = function (bulobj, indx) { 169 | $scope.bullets.$add({ 170 | 'primaryKey': '', 171 | 'text': '', 172 | 'address': bulobj.address + 1, 173 | 'hasChild': false, 174 | 'tabIndex': 0, 175 | 'parentPointer': null, 176 | 'contentCheck': false, 177 | 'content': '', 178 | }); 179 | 180 | for (i = 0; i < $scope.bullets.length; i++) { 181 | if ($scope.bullets[i].address > bulobj.address) { 182 | $scope.bullets[i].address++; 183 | $scope.bullets.$save($scope.bullets[i]); 184 | } 185 | 186 | } 187 | 188 | setTimeout(function () { 189 | angular.element(document.querySelector('#f_' + (indx + 2)))[0].focus(); 190 | }, 50); 191 | } 192 | $scope.DeleteCheck = function (bulobj, msg, indx, address) { 193 | if (bulobj.text === '' && $scope.bullets.length > 1) { 194 | $scope.bullets.$remove(bulobj); 195 | setTimeout(function () { 196 | angular.element(document.querySelector('#f_' + (indx)))[0].focus(); 197 | }, 15); 198 | 199 | for (i = 0; i <= $scope.bullets.length - 1; i++) { 200 | if ($scope.bullets[i].address > address) { 201 | $scope.bullets[i].address--; 202 | $scope.bullets.$save($scope.bullets[i]); 203 | } 204 | } 205 | } 206 | }; //called by ngDelete 207 | //--------------------------------------------------- 208 | 209 | }); 210 | 211 | //KEYPRESS DIRECTIVES 212 | //--------------------------------------------------- 213 | app.directive('ngDelete', function () { 214 | return function (scope, element, attrs) { 215 | element.bind("keydown keypress", function (event) { 216 | if (event.which === 8) { 217 | scope.$apply(function () { 218 | scope.$eval(attrs.ngDelete); 219 | }); 220 | 221 | } 222 | }); 223 | }; 224 | }); 225 | app.directive('ngEnter', function () { 226 | return function (scope, element, attrs) { 227 | element.bind("keydown keypress", function (event) { 228 | if (event.which === 13) { 229 | scope.$apply(function () { 230 | scope.$eval(attrs.ngEnter); 231 | }); 232 | event.stopPropagation(); 233 | 234 | event.preventDefault(); 235 | } 236 | }); 237 | }; 238 | }); 239 | //directive for keypress down 240 | app.directive('ngDown', function () { 241 | return function (scope, element, attrs) { 242 | element.bind("keydown keypress", function (event) { 243 | if (event.which === 40) { 244 | scope.$apply(function () { 245 | scope.$eval(attrs.ngDown); 246 | }); 247 | 248 | event.preventDefault(); 249 | } 250 | }); 251 | }; 252 | }); 253 | app.directive('ngUp', function () { 254 | return function (scope, element, attrs) { 255 | element.bind("keydown keypress", function (event) { 256 | if (event.which === 38) { 257 | scope.$apply(function () { 258 | scope.$eval(attrs.ngUp); 259 | }); 260 | 261 | event.preventDefault(); 262 | } 263 | }); 264 | }; 265 | }); 266 | })(); -------------------------------------------------------------------------------- /js/angular-ui-router.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * State-based routing for AngularJS 3 | * @version v0.2.13 4 | * @link http://angular-ui.github.com/ 5 | * @license MIT License, http://www.opensource.org/licenses/MIT 6 | */ 7 | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return M(new(M(function(){},{prototype:a})),b)}function e(a){return L(arguments,function(b){b!==a&&L(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 c=[];return b.forEach(a,function(a,b){c.push(b)}),c}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].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 M({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,I(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);L(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 J(a)&&a.then&&a.$$promises}if(!J(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return L(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(!G(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;L(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(!J(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=m;var n=a.defer(),r=n.promise,s=r.$$promises={},t=M({},d),u=1+q.length/3,v=!1;if(G(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,l(f.$$inheritedValues,p)),M(s,f.$$promises),f.$$values?(v=e(t,l(f.$$values,p)),r.$$inheritedValues=l(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=l(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 p(a,b,c){this.fromConfig=function(a,b,c){return G(a.template)?this.fromString(a.template,b):G(a.templateUrl)?this.fromUrl(a.templateUrl,b):G(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return H(a)?a(b):a},this.fromUrl=function(c,d){return H(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 q(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 O.Param(b,c,d,e),p[b]}function g(a,b,c){var d=["",""],e=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return e;switch(c){case!1:d=["(",")"];break;case!0:d=["?(",")?"];break;default:d=["("+c+"|",")?"]}return e+d[0]+b+d[1]}function h(c,e){var f,g,h,i,j;return f=c[2]||c[3],j=b.params[f],h=a.substring(m,c.index),g=e?c[4]:c[4]||("*"==c[1]?".*":null),i=O.type(g||"string")||d(O.type("string"),{pattern:new RegExp(g)}),{id:f,regexp:g,segment:h,type:i,cfg:j}}b=M({params:{}},J(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new O.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),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 r(a){M(this,a)}function s(){function a(a){return null!=a?a.toString().replace(/\//g,"%2F"):a}function e(a){return null!=a?a.toString().replace(/%2F/g,"/"):a}function f(a){return this.pattern.test(a)}function i(){return{strict:t,caseInsensitive:p}}function j(a){return H(a)||K(a)&&H(a[a.length-1])}function k(){for(;x.length;){var a=x.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(v[a.name],o.invoke(a.def))}}function l(a){M(this,a||{})}O=this;var o,p=!1,t=!0,u=!1,v={},w=!0,x=[],y={string:{encode:a,decode:e,is:f,pattern:/[^/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return G(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,is:b.identity,equals:b.equals,pattern:/.*/}};s.$$getDefaultValue=function(a){if(!j(a.value))return a.value;if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(a.value)},this.caseInsensitive=function(a){return G(a)&&(p=a),p},this.strictMode=function(a){return G(a)&&(t=a),t},this.defaultSquashPolicy=function(a){if(!G(a))return u;if(a!==!0&&a!==!1&&!I(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return u=a,a},this.compile=function(a,b){return new q(a,M(i(),b))},this.isMatcher=function(a){if(!J(a))return!1;var b=!0;return L(q.prototype,function(c,d){H(c)&&(b=b&&G(a[d])&&H(a[d]))}),b},this.type=function(a,b,c){if(!G(b))return v[a];if(v.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return v[a]=new r(M({name:a},b)),c&&(x.push({name:a,def:c}),w||k()),this},L(y,function(a,b){v[b]=new r(M({name:b},a))}),v=d(v,{}),this.$get=["$injector",function(a){return o=a,w=!1,k(),L(y,function(a,b){v[b]||(v[b]=new r(a))}),this}],this.Param=function(a,b,d,e){function f(a){var b=J(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=j(a.value)?a.value:function(){return a.value},a}function i(b,c,d){if(b.type&&c)throw new Error("Param '"+a+"' has two type configurations.");return c?c:b.type?b.type instanceof r?b.type:new r(b.type):"config"===d?v.any:v.string}function k(){var b={array:"search"===e?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return M(b,c,d).array}function l(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!G(c)||null==c)return u;if(c===!0||I(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function p(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=K(a.replace)?a.replace:[],I(e)&&f.push({from:e,to:c}),g=n(f,function(a){return a.from}),m(i,function(a){return-1===h(g,a.from)}).concat(f)}function q(){if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(d.$$fn)}function s(a){function b(a){return function(b){return b.from===a}}function c(a){var c=n(m(w.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),G(a)?w.type.decode(a):q()}function t(){return"{Param:"+a+" "+b+" squash: '"+z+"' optional: "+y+"}"}var w=this;d=f(d),b=i(d,b,e);var x=k();b=x?b.$asArray(x,"search"===e):b,"string"!==b.name||x||"path"!==e||d.value!==c||(d.value="");var y=d.value!==c,z=l(d,y),A=p(d,x,y,z);M(this,{id:a,type:b,location:e,array:x,squash:z,replace:A,isOptional:y,value:s,dynamic:c,config:d,toString:t})},l.prototype={$$new:function(){return d(this,M(new l,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(l.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),L(b,function(b){L(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return L(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return L(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 b,c,d,e=!0,f=this;return L(this.$$keys(),function(g){d=f[g],c=a[g],b=!c&&d.isOptional,e=e&&(b||!!d.type.is(c))}),e},$$parent:c},this.ParamSet=l}function t(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 G(d)?d:!0}function h(d,e,f,g){function h(a,b,c){return"/"===p?a:b?p.slice(0,-1)+a:c?p.slice(1)+a:a}function m(a){function b(a){var b=a(f,d);return b?(I(b)&&d.replace().url(b),!0):!1}if(!a||!a.defaultPrevented){var e=o&&d.url()===o;if(o=c,e)return!0;var g,h=j.length;for(g=0;h>g;g++)if(b(j[g]))return;k&&b(k)}}function n(){return i=i||e.$on("$locationChangeSuccess",m)}var o,p=g.baseHref(),q=d.url();return l||n(),{sync:function(){m()},listen:function(){return n()},update:function(a){return a?void(q=d.url()):void(d.url()!==q&&(d.url(q),d.replace()))},push:function(a,b,e){d.url(a.format(b||{})),o=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);var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),i=h(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(!H(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(I(a)){var b=a;a=function(){return b}}else if(!H(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=I(b);if(I(a)&&(a=d.compile(a)),!h&&!H(b)&&!K(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)}]),M(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:I(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)}]),M(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"]}function u(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){if(!a)return c;var d=I(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=l(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 m=y[e];return!m||!d&&(d||m!==a&&m.self!==a)?c:m}function m(a,b){z[a]||(z[a]=[]),z[a].push(b)}function o(a){for(var b=z[a]||[];b.length;)p(b.shift())}function p(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!I(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(y.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):I(b.parent)?b.parent:J(b.parent)&&I(b.parent.name)?b.parent.name:"";if(e&&!y[e])return m(e,b.self);for(var f in B)H(B[f])&&(b[f]=B[f](b,B.$delegates[f]));return y[c]=b,!b[A]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){x.$current.navigable==b&&j(a,c)||x.transitionTo(b,a,{inherit:!0,location:!1})}]),o(c),b}function q(a){return a.indexOf("*")>-1}function r(a){var b=a.split("."),c=x.$current.name.split(".");if("**"===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)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function s(a,b){return I(a)&&!G(b)?B[a]:H(b)&&I(a)?(B[a]&&!B.$delegates[a]&&(B.$delegates[a]=B[a]),B[a]=b,this):this}function t(a,b){return J(a)?b=a:b.name=a,p(b),this}function u(a,e,f,h,m,o,p){function s(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),B;if(!g.retry)return null;if(f.$retry)return p.update(),C;var h=x.transition=e.when(g.retry);return h.then(function(){return h!==x.transition?u:(b.options.$retry=!0,x.transitionTo(b.to,b.toParams,b.options))},function(){return B}),p.update(),h}function t(a,c,d,g,i,j){var l=d?c:k(a.params.$$keys(),c),n={$stateParams:l};i.resolve=m.resolve(a.resolve,n,i.resolve,a);var o=[i.resolve.then(function(a){i.globals=a})];return g&&o.push(g),L(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return f.load(d,{view:c,locals:n,params:l,notify:j.notify})||""}],o.push(m.resolve(e,n,i.resolve,a).then(function(f){if(H(c.controllerProvider)||K(c.controllerProvider)){var g=b.extend({},e,n);f.$$controller=h.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,i[d]=f}))}),e.all(o).then(function(){return i})}var u=e.reject(new Error("transition superseded")),z=e.reject(new Error("transition prevented")),B=e.reject(new Error("transition aborted")),C=e.reject(new Error("transition failed"));return w.locals={resolve:null,globals:{$stateParams:{}}},x={params:{},current:w.self,$current:w,transition:null},x.reload=function(){return x.transitionTo(x.current,o,{reload:!0,inherit:!1,notify:!0})},x.go=function(a,b,c){return x.transitionTo(a,b,M({inherit:!0,relative:x.$current},c))},x.transitionTo=function(b,c,f){c=c||{},f=M({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=x.$current,m=x.params,n=j.path,q=l(b,f.relative);if(!G(q)){var r={to:b,toParams:c,options:f},y=s(r,j.self,m,f);if(y)return y;if(b=r.to,c=r.toParams,f=r.options,q=l(b,f.relative),!G(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[A])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(o,c||{},x.$current,q)),!q.params.$$validates(c))return C;c=q.params.$$values(c),b=q;var B=b.path,D=0,E=B[D],F=w.locals,H=[];if(!f.reload)for(;E&&E===n[D]&&E.ownParams.$$equals(c,m);)F=H[D]=E.locals,D++,E=B[D];if(v(b,j,F,f))return b.self.reloadOnSearch!==!1&&p.update(),x.transition=null,e.when(x.current);if(c=k(b.params.$$keys(),c||{}),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,m).defaultPrevented)return p.update(),z;for(var I=e.when(F),J=D;J=D;d--)g=n[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d=0?e:e+"@"+(f?f.state.name:"")}function A(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 B(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function C(a,c){var d=["location","inherit","reload"];return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(e,f,g,h){var i=A(g.uiSref,a.current.name),j=null,k=B(f)||a.$current,l=null,m="A"===f.prop("tagName"),n="FORM"===f[0].nodeName,o=n?"action":"href",p=!0,q={relative:k,inherit:!0},r=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in r&&(q[a]=r[a])});var s=function(c){if(c&&(j=b.copy(c)),p){l=a.href(i.state,j,q);var d=h[1]||h[0];return d&&d.$$setStateInfo(i.state,j),null===l?(p=!1,!1):void g.$set(o,l)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a){a!==j&&s(a)},!0),j=b.copy(e.$eval(i.paramExpr))),s(),n||f.bind("click",function(b){var d=b.which||b.button;if(!(d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target"))){var e=c(function(){a.go(i.state,j,q)});b.preventDefault();var g=m&&!l?1:0;b.preventDefault=function(){g--<=0&&c.cancel(e)}}})}}}function D(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(b,d,e){function f(){g()?d.addClass(j):d.removeClass(j)}function g(){return"undefined"!=typeof e.uiSrefActiveEq?h&&a.is(h.name,i):h&&a.includes(h.name,i)}var h,i,j;j=c(e.uiSrefActiveEq||e.uiSrefActive||"",!1)(b),this.$$setStateInfo=function(b,c){h=a.get(b,B(d)),i=c,f()},b.$on("$stateChangeSuccess",f)}]}}function E(a){var b=function(b){return a.is(b)};return b.$stateful=!0,b}function F(a){var b=function(b){return a.includes(b)};return b.$stateful=!0,b}var G=b.isDefined,H=b.isFunction,I=b.isString,J=b.isObject,K=b.isArray,L=b.forEach,M=b.extend,N=b.copy;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"]),o.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",o),p.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",p);var O;q.prototype.concat=function(a,b){var c={caseInsensitive:O.caseInsensitive(),strict:O.strictMode(),squash:O.defaultSquashPolicy()};return new q(this.sourcePath+a+this.sourceSearch,M(c,b),this)},q.prototype.toString=function(){return this.source},q.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/,"-")}var d=b(a).split(/-(?!\\)/),e=n(d,b);return n(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+"'");for(e=0;j>e;e++){g=h[e];var l=this.params[g],m=d[e+1];for(f=0;fe;e++)g=h[e],k[g]=this.params[g].value(b[g]);return k},q.prototype.parameters=function(a){return G(a)?this.params[a]||null:this.$$paramNames},q.prototype.validates=function(a){return this.params.$$validates(a)},q.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],o=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),o),q=p?m.squash:!1,r=m.type.encode(o);if(k){var s=c[f+1];if(q===!1)null!=r&&(j+=K(r)?n(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var t=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(t)[1]}else I(q)&&(j+=q+s)}else{if(null==r||p&&q!==!1)continue;K(r)||(r=[r]),r=n(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},r.prototype.is=function(){return!0},r.prototype.encode=function(a){return a},r.prototype.decode=function(a){return a},r.prototype.equals=function(a,b){return a==b},r.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},r.prototype.pattern=/.*/,r.prototype.toString=function(){return"{Type:"+this.name+"}"},r.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 K(a)?a:G(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){c=e(c);var d=n(c,a);return b===!0?0===m(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 (this.$items.length - 1) || pos < 0) return 377 | 378 | if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 379 | if (activeIndex == pos) return this.pause().cycle() 380 | 381 | return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 382 | } 383 | 384 | Carousel.prototype.pause = function (e) { 385 | e || (this.paused = true) 386 | 387 | if (this.$element.find('.next, .prev').length && $.support.transition) { 388 | this.$element.trigger($.support.transition.end) 389 | this.cycle(true) 390 | } 391 | 392 | this.interval = clearInterval(this.interval) 393 | 394 | return this 395 | } 396 | 397 | Carousel.prototype.next = function () { 398 | if (this.sliding) return 399 | return this.slide('next') 400 | } 401 | 402 | Carousel.prototype.prev = function () { 403 | if (this.sliding) return 404 | return this.slide('prev') 405 | } 406 | 407 | Carousel.prototype.slide = function (type, next) { 408 | var $active = this.$element.find('.item.active') 409 | var $next = next || this.getItemForDirection(type, $active) 410 | var isCycling = this.interval 411 | var direction = type == 'next' ? 'left' : 'right' 412 | var that = this 413 | 414 | if ($next.hasClass('active')) return (this.sliding = false) 415 | 416 | var relatedTarget = $next[0] 417 | var slideEvent = $.Event('slide.bs.carousel', { 418 | relatedTarget: relatedTarget, 419 | direction: direction 420 | }) 421 | this.$element.trigger(slideEvent) 422 | if (slideEvent.isDefaultPrevented()) return 423 | 424 | this.sliding = true 425 | 426 | isCycling && this.pause() 427 | 428 | if (this.$indicators.length) { 429 | this.$indicators.find('.active').removeClass('active') 430 | var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 431 | $nextIndicator && $nextIndicator.addClass('active') 432 | } 433 | 434 | var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 435 | if ($.support.transition && this.$element.hasClass('slide')) { 436 | $next.addClass(type) 437 | $next[0].offsetWidth // force reflow 438 | $active.addClass(direction) 439 | $next.addClass(direction) 440 | $active 441 | .one('bsTransitionEnd', function () { 442 | $next.removeClass([type, direction].join(' ')).addClass('active') 443 | $active.removeClass(['active', direction].join(' ')) 444 | that.sliding = false 445 | setTimeout(function () { 446 | that.$element.trigger(slidEvent) 447 | }, 0) 448 | }) 449 | .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 450 | } else { 451 | $active.removeClass('active') 452 | $next.addClass('active') 453 | this.sliding = false 454 | this.$element.trigger(slidEvent) 455 | } 456 | 457 | isCycling && this.cycle() 458 | 459 | return this 460 | } 461 | 462 | 463 | // CAROUSEL PLUGIN DEFINITION 464 | // ========================== 465 | 466 | function Plugin(option) { 467 | return this.each(function () { 468 | var $this = $(this) 469 | var data = $this.data('bs.carousel') 470 | var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 471 | var action = typeof option == 'string' ? option : options.slide 472 | 473 | if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 474 | if (typeof option == 'number') data.to(option) 475 | else if (action) data[action]() 476 | else if (options.interval) data.pause().cycle() 477 | }) 478 | } 479 | 480 | var old = $.fn.carousel 481 | 482 | $.fn.carousel = Plugin 483 | $.fn.carousel.Constructor = Carousel 484 | 485 | 486 | // CAROUSEL NO CONFLICT 487 | // ==================== 488 | 489 | $.fn.carousel.noConflict = function () { 490 | $.fn.carousel = old 491 | return this 492 | } 493 | 494 | 495 | // CAROUSEL DATA-API 496 | // ================= 497 | 498 | var clickHandler = function (e) { 499 | var href 500 | var $this = $(this) 501 | var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 502 | if (!$target.hasClass('carousel')) return 503 | var options = $.extend({}, $target.data(), $this.data()) 504 | var slideIndex = $this.attr('data-slide-to') 505 | if (slideIndex) options.interval = false 506 | 507 | Plugin.call($target, options) 508 | 509 | if (slideIndex) { 510 | $target.data('bs.carousel').to(slideIndex) 511 | } 512 | 513 | e.preventDefault() 514 | } 515 | 516 | $(document) 517 | .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 518 | .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 519 | 520 | $(window).on('load', function () { 521 | $('[data-ride="carousel"]').each(function () { 522 | var $carousel = $(this) 523 | Plugin.call($carousel, $carousel.data()) 524 | }) 525 | }) 526 | 527 | }(jQuery); 528 | 529 | /* ======================================================================== 530 | * Bootstrap: collapse.js v3.3.2 531 | * http://getbootstrap.com/javascript/#collapse 532 | * ======================================================================== 533 | * Copyright 2011-2015 Twitter, Inc. 534 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 535 | * ======================================================================== */ 536 | 537 | 538 | +function ($) { 539 | 'use strict'; 540 | 541 | // COLLAPSE PUBLIC CLASS DEFINITION 542 | // ================================ 543 | 544 | var Collapse = function (element, options) { 545 | this.$element = $(element) 546 | this.options = $.extend({}, Collapse.DEFAULTS, options) 547 | this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]') 548 | this.transitioning = null 549 | 550 | if (this.options.parent) { 551 | this.$parent = this.getParent() 552 | } else { 553 | this.addAriaAndCollapsedClass(this.$element, this.$trigger) 554 | } 555 | 556 | if (this.options.toggle) this.toggle() 557 | } 558 | 559 | Collapse.VERSION = '3.3.2' 560 | 561 | Collapse.TRANSITION_DURATION = 350 562 | 563 | Collapse.DEFAULTS = { 564 | toggle: true, 565 | trigger: '[data-toggle="collapse"]' 566 | } 567 | 568 | Collapse.prototype.dimension = function () { 569 | var hasWidth = this.$element.hasClass('width') 570 | return hasWidth ? 'width' : 'height' 571 | } 572 | 573 | Collapse.prototype.show = function () { 574 | if (this.transitioning || this.$element.hasClass('in')) return 575 | 576 | var activesData 577 | var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 578 | 579 | if (actives && actives.length) { 580 | activesData = actives.data('bs.collapse') 581 | if (activesData && activesData.transitioning) return 582 | } 583 | 584 | var startEvent = $.Event('show.bs.collapse') 585 | this.$element.trigger(startEvent) 586 | if (startEvent.isDefaultPrevented()) return 587 | 588 | if (actives && actives.length) { 589 | Plugin.call(actives, 'hide') 590 | activesData || actives.data('bs.collapse', null) 591 | } 592 | 593 | var dimension = this.dimension() 594 | 595 | this.$element 596 | .removeClass('collapse') 597 | .addClass('collapsing')[dimension](0) 598 | .attr('aria-expanded', true) 599 | 600 | this.$trigger 601 | .removeClass('collapsed') 602 | .attr('aria-expanded', true) 603 | 604 | this.transitioning = 1 605 | 606 | var complete = function () { 607 | this.$element 608 | .removeClass('collapsing') 609 | .addClass('collapse in')[dimension]('') 610 | this.transitioning = 0 611 | this.$element 612 | .trigger('shown.bs.collapse') 613 | } 614 | 615 | if (!$.support.transition) return complete.call(this) 616 | 617 | var scrollSize = $.camelCase(['scroll', dimension].join('-')) 618 | 619 | this.$element 620 | .one('bsTransitionEnd', $.proxy(complete, this)) 621 | .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 622 | } 623 | 624 | Collapse.prototype.hide = function () { 625 | if (this.transitioning || !this.$element.hasClass('in')) return 626 | 627 | var startEvent = $.Event('hide.bs.collapse') 628 | this.$element.trigger(startEvent) 629 | if (startEvent.isDefaultPrevented()) return 630 | 631 | var dimension = this.dimension() 632 | 633 | this.$element[dimension](this.$element[dimension]())[0].offsetHeight 634 | 635 | this.$element 636 | .addClass('collapsing') 637 | .removeClass('collapse in') 638 | .attr('aria-expanded', false) 639 | 640 | this.$trigger 641 | .addClass('collapsed') 642 | .attr('aria-expanded', false) 643 | 644 | this.transitioning = 1 645 | 646 | var complete = function () { 647 | this.transitioning = 0 648 | this.$element 649 | .removeClass('collapsing') 650 | .addClass('collapse') 651 | .trigger('hidden.bs.collapse') 652 | } 653 | 654 | if (!$.support.transition) return complete.call(this) 655 | 656 | this.$element 657 | [dimension](0) 658 | .one('bsTransitionEnd', $.proxy(complete, this)) 659 | .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 660 | } 661 | 662 | Collapse.prototype.toggle = function () { 663 | this[this.$element.hasClass('in') ? 'hide' : 'show']() 664 | } 665 | 666 | Collapse.prototype.getParent = function () { 667 | return $(this.options.parent) 668 | .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 669 | .each($.proxy(function (i, element) { 670 | var $element = $(element) 671 | this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 672 | }, this)) 673 | .end() 674 | } 675 | 676 | Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 677 | var isOpen = $element.hasClass('in') 678 | 679 | $element.attr('aria-expanded', isOpen) 680 | $trigger 681 | .toggleClass('collapsed', !isOpen) 682 | .attr('aria-expanded', isOpen) 683 | } 684 | 685 | function getTargetFromTrigger($trigger) { 686 | var href 687 | var target = $trigger.attr('data-target') 688 | || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 689 | 690 | return $(target) 691 | } 692 | 693 | 694 | // COLLAPSE PLUGIN DEFINITION 695 | // ========================== 696 | 697 | function Plugin(option) { 698 | return this.each(function () { 699 | var $this = $(this) 700 | var data = $this.data('bs.collapse') 701 | var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 702 | 703 | if (!data && options.toggle && option == 'show') options.toggle = false 704 | if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 705 | if (typeof option == 'string') data[option]() 706 | }) 707 | } 708 | 709 | var old = $.fn.collapse 710 | 711 | $.fn.collapse = Plugin 712 | $.fn.collapse.Constructor = Collapse 713 | 714 | 715 | // COLLAPSE NO CONFLICT 716 | // ==================== 717 | 718 | $.fn.collapse.noConflict = function () { 719 | $.fn.collapse = old 720 | return this 721 | } 722 | 723 | 724 | // COLLAPSE DATA-API 725 | // ================= 726 | 727 | $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 728 | var $this = $(this) 729 | 730 | if (!$this.attr('data-target')) e.preventDefault() 731 | 732 | var $target = getTargetFromTrigger($this) 733 | var data = $target.data('bs.collapse') 734 | var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this }) 735 | 736 | Plugin.call($target, option) 737 | }) 738 | 739 | }(jQuery); 740 | 741 | /* ======================================================================== 742 | * Bootstrap: dropdown.js v3.3.2 743 | * http://getbootstrap.com/javascript/#dropdowns 744 | * ======================================================================== 745 | * Copyright 2011-2015 Twitter, Inc. 746 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 747 | * ======================================================================== */ 748 | 749 | 750 | +function ($) { 751 | 'use strict'; 752 | 753 | // DROPDOWN CLASS DEFINITION 754 | // ========================= 755 | 756 | var backdrop = '.dropdown-backdrop' 757 | var toggle = '[data-toggle="dropdown"]' 758 | var Dropdown = function (element) { 759 | $(element).on('click.bs.dropdown', this.toggle) 760 | } 761 | 762 | Dropdown.VERSION = '3.3.2' 763 | 764 | Dropdown.prototype.toggle = function (e) { 765 | var $this = $(this) 766 | 767 | if ($this.is('.disabled, :disabled')) return 768 | 769 | var $parent = getParent($this) 770 | var isActive = $parent.hasClass('open') 771 | 772 | clearMenus() 773 | 774 | if (!isActive) { 775 | if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 776 | // if mobile we use a backdrop because click events don't delegate 777 | $('