Implement material design
This commit is contained in:
Родитель
0ddca1061c
Коммит
ea1eee056b
|
@ -247,6 +247,10 @@
|
|||
"message": "Done",
|
||||
"description": "Done"
|
||||
},
|
||||
"list": {
|
||||
"message": "List",
|
||||
"description": "List"
|
||||
},
|
||||
"finish": {
|
||||
"message": "Finish",
|
||||
"description": "Finish"
|
||||
|
@ -263,6 +267,10 @@
|
|||
"message": "Prev",
|
||||
"description": "Previous"
|
||||
},
|
||||
"copy": {
|
||||
"message": "Copy",
|
||||
"description": "Copy"
|
||||
},
|
||||
"next": {
|
||||
"message": "Next",
|
||||
"description": "Next"
|
||||
|
@ -300,7 +308,7 @@
|
|||
"description": "One time password"
|
||||
},
|
||||
"settings": {
|
||||
"message": "settings",
|
||||
"message": "Settings",
|
||||
"description": "Settings"
|
||||
},
|
||||
"search": {
|
||||
|
|
12
css/main.css
12
css/main.css
|
@ -150,13 +150,13 @@ input[type="password"], input[type="text"] {
|
|||
left: 10px;
|
||||
top: 6px;
|
||||
position: relative;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #d6dadc;
|
||||
border-radius: 50%; }
|
||||
.radial-progress .circle .mask, .radial-progress .circle .fill {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
-webkit-transition: -webkit-transform 0.5s;
|
||||
|
@ -165,9 +165,9 @@ input[type="password"], input[type="text"] {
|
|||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden; }
|
||||
.radial-progress .circle .mask {
|
||||
clip: rect(0px, 25px, 25px, 12.5px); }
|
||||
clip: rect(0px, 10px, 10px, 5px); }
|
||||
.radial-progress .circle .mask .fill {
|
||||
clip: rect(0px, 12.5px, 25px, 0px);
|
||||
clip: rect(0px, 5px, 10px, 0px);
|
||||
background-color: #97a71d; }
|
||||
|
||||
.ng-hide {
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
body, html {
|
||||
min-height: 250px;
|
||||
width: 450px; }
|
||||
|
||||
.md-content {
|
||||
height: 100%;
|
||||
max-height: auto; }
|
||||
|
||||
.addFab {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
bottom: 10px; }
|
||||
|
||||
.menu {
|
||||
padding: 0; }
|
||||
.menu ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%; }
|
||||
.menu ul li {
|
||||
list-style-type: none;
|
||||
width: 100%; }
|
||||
.menu ul li md-icon {
|
||||
margin-right: 16px;
|
||||
min-width: 40px;
|
||||
width: 40px; }
|
||||
.menu ul li a {
|
||||
color: #000;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
display: block;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
padding: 0;
|
||||
padding-left: 16px;
|
||||
padding-right: 56px;
|
||||
text-decoration: none;
|
||||
clear: both;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-o-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out; }
|
||||
.menu ul li a:hover {
|
||||
background-color: #e0e0e0; }
|
||||
|
||||
.password-list {
|
||||
padding: 0; }
|
||||
|
||||
/*/*/
|
||||
.radial-progress {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #d6dadc;
|
||||
border-radius: 50%; }
|
||||
.radial-progress .circle .mask, .radial-progress .circle .fill {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
-webkit-transition: -webkit-transform 0.5s;
|
||||
-moz-transition: -moz-transform 0.5s;
|
||||
transition: transform 0.5s;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden; }
|
||||
.radial-progress .circle .mask {
|
||||
clip: rect(0px, 12px, 12px, 6px); }
|
||||
.radial-progress .circle .mask .fill {
|
||||
clip: rect(0px, 6px, 12px, 0px);
|
||||
background-color: #0277bd; }
|
||||
|
||||
.ng-hide {
|
||||
display: none; }
|
||||
|
||||
.unlock-container {
|
||||
height: 350px; }
|
||||
.unlock-container .unlock {
|
||||
padding: 20px;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); }
|
||||
.unlock-container .unlock md-input-container {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0; }
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,587 +0,0 @@
|
|||
/*!
|
||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
.btn-default,
|
||||
.btn-primary,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-primary:active,
|
||||
.btn-success:active,
|
||||
.btn-info:active,
|
||||
.btn-warning:active,
|
||||
.btn-danger:active,
|
||||
.btn-default.active,
|
||||
.btn-primary.active,
|
||||
.btn-success.active,
|
||||
.btn-info.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active {
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-primary.disabled,
|
||||
.btn-success.disabled,
|
||||
.btn-info.disabled,
|
||||
.btn-warning.disabled,
|
||||
.btn-danger.disabled,
|
||||
.btn-default[disabled],
|
||||
.btn-primary[disabled],
|
||||
.btn-success[disabled],
|
||||
.btn-info[disabled],
|
||||
.btn-warning[disabled],
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
fieldset[disabled] .btn-primary,
|
||||
fieldset[disabled] .btn-success,
|
||||
fieldset[disabled] .btn-info,
|
||||
fieldset[disabled] .btn-warning,
|
||||
fieldset[disabled] .btn-danger {
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.btn-default .badge,
|
||||
.btn-primary .badge,
|
||||
.btn-success .badge,
|
||||
.btn-info .badge,
|
||||
.btn-warning .badge,
|
||||
.btn-danger .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.btn:active,
|
||||
.btn.active {
|
||||
background-image: none;
|
||||
}
|
||||
.btn-default {
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
||||
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dbdbdb;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.btn-default:hover,
|
||||
.btn-default:focus {
|
||||
background-color: #e0e0e0;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #dbdbdb;
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-default[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
.btn-default.disabled:hover,
|
||||
.btn-default[disabled]:hover,
|
||||
fieldset[disabled] .btn-default:hover,
|
||||
.btn-default.disabled:focus,
|
||||
.btn-default[disabled]:focus,
|
||||
fieldset[disabled] .btn-default:focus,
|
||||
.btn-default.disabled.focus,
|
||||
.btn-default[disabled].focus,
|
||||
fieldset[disabled] .btn-default.focus,
|
||||
.btn-default.disabled:active,
|
||||
.btn-default[disabled]:active,
|
||||
fieldset[disabled] .btn-default:active,
|
||||
.btn-default.disabled.active,
|
||||
.btn-default[disabled].active,
|
||||
fieldset[disabled] .btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-primary {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus {
|
||||
background-color: #265a88;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-primary:active,
|
||||
.btn-primary.active {
|
||||
background-color: #265a88;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary.disabled,
|
||||
.btn-primary[disabled],
|
||||
fieldset[disabled] .btn-primary,
|
||||
.btn-primary.disabled:hover,
|
||||
.btn-primary[disabled]:hover,
|
||||
fieldset[disabled] .btn-primary:hover,
|
||||
.btn-primary.disabled:focus,
|
||||
.btn-primary[disabled]:focus,
|
||||
fieldset[disabled] .btn-primary:focus,
|
||||
.btn-primary.disabled.focus,
|
||||
.btn-primary[disabled].focus,
|
||||
fieldset[disabled] .btn-primary.focus,
|
||||
.btn-primary.disabled:active,
|
||||
.btn-primary[disabled]:active,
|
||||
fieldset[disabled] .btn-primary:active,
|
||||
.btn-primary.disabled.active,
|
||||
.btn-primary[disabled].active,
|
||||
fieldset[disabled] .btn-primary.active {
|
||||
background-color: #265a88;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success:hover,
|
||||
.btn-success:focus {
|
||||
background-color: #419641;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-success:active,
|
||||
.btn-success.active {
|
||||
background-color: #419641;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success.disabled,
|
||||
.btn-success[disabled],
|
||||
fieldset[disabled] .btn-success,
|
||||
.btn-success.disabled:hover,
|
||||
.btn-success[disabled]:hover,
|
||||
fieldset[disabled] .btn-success:hover,
|
||||
.btn-success.disabled:focus,
|
||||
.btn-success[disabled]:focus,
|
||||
fieldset[disabled] .btn-success:focus,
|
||||
.btn-success.disabled.focus,
|
||||
.btn-success[disabled].focus,
|
||||
fieldset[disabled] .btn-success.focus,
|
||||
.btn-success.disabled:active,
|
||||
.btn-success[disabled]:active,
|
||||
fieldset[disabled] .btn-success:active,
|
||||
.btn-success.disabled.active,
|
||||
.btn-success[disabled].active,
|
||||
fieldset[disabled] .btn-success.active {
|
||||
background-color: #419641;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info:hover,
|
||||
.btn-info:focus {
|
||||
background-color: #2aabd2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-info:active,
|
||||
.btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info.disabled,
|
||||
.btn-info[disabled],
|
||||
fieldset[disabled] .btn-info,
|
||||
.btn-info.disabled:hover,
|
||||
.btn-info[disabled]:hover,
|
||||
fieldset[disabled] .btn-info:hover,
|
||||
.btn-info.disabled:focus,
|
||||
.btn-info[disabled]:focus,
|
||||
fieldset[disabled] .btn-info:focus,
|
||||
.btn-info.disabled.focus,
|
||||
.btn-info[disabled].focus,
|
||||
fieldset[disabled] .btn-info.focus,
|
||||
.btn-info.disabled:active,
|
||||
.btn-info[disabled]:active,
|
||||
fieldset[disabled] .btn-info:active,
|
||||
.btn-info.disabled.active,
|
||||
.btn-info[disabled].active,
|
||||
fieldset[disabled] .btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning:hover,
|
||||
.btn-warning:focus {
|
||||
background-color: #eb9316;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-warning:active,
|
||||
.btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning.disabled,
|
||||
.btn-warning[disabled],
|
||||
fieldset[disabled] .btn-warning,
|
||||
.btn-warning.disabled:hover,
|
||||
.btn-warning[disabled]:hover,
|
||||
fieldset[disabled] .btn-warning:hover,
|
||||
.btn-warning.disabled:focus,
|
||||
.btn-warning[disabled]:focus,
|
||||
fieldset[disabled] .btn-warning:focus,
|
||||
.btn-warning.disabled.focus,
|
||||
.btn-warning[disabled].focus,
|
||||
fieldset[disabled] .btn-warning.focus,
|
||||
.btn-warning.disabled:active,
|
||||
.btn-warning[disabled]:active,
|
||||
fieldset[disabled] .btn-warning:active,
|
||||
.btn-warning.disabled.active,
|
||||
.btn-warning[disabled].active,
|
||||
fieldset[disabled] .btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger:hover,
|
||||
.btn-danger:focus {
|
||||
background-color: #c12e2a;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-danger:active,
|
||||
.btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger.disabled,
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-danger,
|
||||
.btn-danger.disabled:hover,
|
||||
.btn-danger[disabled]:hover,
|
||||
fieldset[disabled] .btn-danger:hover,
|
||||
.btn-danger.disabled:focus,
|
||||
.btn-danger[disabled]:focus,
|
||||
fieldset[disabled] .btn-danger:focus,
|
||||
.btn-danger.disabled.focus,
|
||||
.btn-danger[disabled].focus,
|
||||
fieldset[disabled] .btn-danger.focus,
|
||||
.btn-danger.disabled:active,
|
||||
.btn-danger[disabled]:active,
|
||||
fieldset[disabled] .btn-danger:active,
|
||||
.btn-danger.disabled.active,
|
||||
.btn-danger[disabled].active,
|
||||
fieldset[disabled] .btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
background-image: none;
|
||||
}
|
||||
.thumbnail,
|
||||
.img-thumbnail {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||
}
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-color: #e8e8e8;
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.dropdown-menu > .active > a,
|
||||
.dropdown-menu > .active > a:hover,
|
||||
.dropdown-menu > .active > a:focus {
|
||||
background-color: #2e6da4;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.navbar-default {
|
||||
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
||||
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
|
||||
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
||||
}
|
||||
.navbar-default .navbar-nav > .open > a,
|
||||
.navbar-default .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
||||
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
||||
}
|
||||
.navbar-brand,
|
||||
.navbar-nav > li > a {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
|
||||
}
|
||||
.navbar-inverse {
|
||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > .open > a,
|
||||
.navbar-inverse .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
||||
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
||||
}
|
||||
.navbar-inverse .navbar-brand,
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
|
||||
}
|
||||
.navbar-static-top,
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
border-radius: 0;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
||||
color: #fff;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
}
|
||||
.alert {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
||||
}
|
||||
.alert-success {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b2dba1;
|
||||
}
|
||||
.alert-info {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #9acfea;
|
||||
}
|
||||
.alert-warning {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #f5e79e;
|
||||
}
|
||||
.alert-danger {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dca7a7;
|
||||
}
|
||||
.progress {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-striped {
|
||||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||
}
|
||||
.list-group {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||
}
|
||||
.list-group-item.active,
|
||||
.list-group-item.active:hover,
|
||||
.list-group-item.active:focus {
|
||||
text-shadow: 0 -1px 0 #286090;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
.list-group-item.active .badge,
|
||||
.list-group-item.active:hover .badge,
|
||||
.list-group-item.active:focus .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.panel {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
||||
}
|
||||
.panel-default > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-primary > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-success > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-info > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-warning > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-danger > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.well {
|
||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dcdcdc;
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-theme.css.map */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,56 +1,130 @@
|
|||
<!doctype html>
|
||||
<html ng-app="passmanExtension" ng-csp>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Passman rules</title>
|
||||
<script src="/js/vendor/jquery/jquery.js"></script>
|
||||
<script src="/js/vendor/bootstrap/bootstrap.js"></script>
|
||||
<script src="/js/vendor/angular/framework.js"></script>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Passman rules</title>
|
||||
<script src="/js/vendor/jquery/jquery.js"></script>
|
||||
<script src="/js/vendor/angular/framework.js"></script>
|
||||
|
||||
<script src="/js/lib/promise.js"></script>
|
||||
<script src="/js/lib/API/base.js"></script>
|
||||
<script src="/js/lib/API/storage.js"></script>
|
||||
<script src="/js/lib/API/runtime.js"></script>
|
||||
<script src="/js/lib/API/tabs.js"></script>
|
||||
<script src="/js/lib/API/cookies.js"></script>
|
||||
<script src="/js/lib/API/extension.js"></script>
|
||||
<script src="/js/lib/API/i18n.js"></script>
|
||||
<script src="/js/lib/otp.js"></script>
|
||||
<script src="/js/lib/font-awesome.js"></script>
|
||||
<script src="/js/vendor/sjcl/sjcl.js"></script>
|
||||
<script src="/js/vendor/angular-resource/angular-resource.js"></script>
|
||||
<script src="/js/lib/promise.js"></script>
|
||||
<script src="/js/lib/API/base.js"></script>
|
||||
<script src="/js/lib/API/storage.js"></script>
|
||||
<script src="/js/lib/API/runtime.js"></script>
|
||||
<script src="/js/lib/API/tabs.js"></script>
|
||||
<script src="/js/lib/API/cookies.js"></script>
|
||||
<script src="/js/lib/API/extension.js"></script>
|
||||
<script src="/js/lib/API/i18n.js"></script>
|
||||
<script src="/js/lib/otp.js"></script>
|
||||
<script src="/js/lib/font-awesome.js"></script>
|
||||
<script src="/js/vendor/sjcl/sjcl.js"></script>
|
||||
<script src="/js/vendor/angular-resource/angular-resource.js"></script>
|
||||
|
||||
<script src="/js/vendor/angular-route/angular-route.js"></script>
|
||||
<script src="/js/vendor/angular-sanitize/angular-sanitize.js"></script>
|
||||
<script src="/js/vendor/angular-translate/angular-translate.js"></script>
|
||||
<script src="/js/vendor/angular-steps/angular-steps.js"></script>
|
||||
<script src="/js/vendor/sha/sha.js"></script>
|
||||
<script src="/js/vendor/angular-route/angular-route.js"></script>
|
||||
<script src="/js/vendor/angular-aria/angular-aria.js"></script>
|
||||
<script src="/js/vendor/angular-messages/angular-messages.js"></script>
|
||||
<script src="/js/vendor/angular-animate/angular-animate.js"></script>
|
||||
<script src="/js/vendor/angular-sanitize/angular-sanitize.js"></script>
|
||||
<script src="/js/vendor/angular-translate/angular-translate.js"></script>
|
||||
<script src="/js/vendor/angular-steps/angular-steps.js"></script>
|
||||
<script src="/js/vendor/angular-material/angular-material.min.js"></script>
|
||||
<script src="/js/vendor/sha/sha.js"></script>
|
||||
|
||||
<script src="/js/lib/api.js"></script>
|
||||
|
||||
<script src="/js/ui/popup/app.js"></script>
|
||||
|
||||
<script src="/js/ui/popup/factories/storage.js"></script>
|
||||
<script src="/js/ui/popup/factories/debounce.js"></script>
|
||||
|
||||
<script src="/js/ui/popup/controllers/main.js"></script>
|
||||
<script src="/js/ui/popup/controllers/settings.js"></script>
|
||||
<script src="/js/ui/popup/controllers/password_prompt.js"></script>
|
||||
<script src="/js/ui/popup/controllers/search.js"></script>
|
||||
<script src="/js/ui/popup/controllers/setup.js"></script>
|
||||
<script src="/js/ui/popup/directives/otp.js"></script>
|
||||
<script src="/js/ui/popup/directives/ngenter.js"></script>
|
||||
<script src="/js/ui/popup/filters/translate.js"></script>
|
||||
<script src="/js/lib/api.js"></script>
|
||||
|
||||
|
||||
<link href="/css/vendor/bootstrap.css" media="all" rel="stylesheet" />
|
||||
<link href="/css/vendor/bootstrap-theme.css" media="all" rel="stylesheet" />
|
||||
<link href="/css/vendor/font-awesome.css" media="all" rel="stylesheet" />
|
||||
<link href="/css/main.css" media="all" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainPopup" ng-view>
|
||||
<script src="/js/ui/popup/app.js"></script>
|
||||
|
||||
<script src="/js/ui/popup/factories/storage.js"></script>
|
||||
<script src="/js/ui/popup/factories/debounce.js"></script>
|
||||
|
||||
<script src="/js/ui/popup/controllers/main.js"></script>
|
||||
<script src="/js/ui/popup/controllers/list.js"></script>
|
||||
<script src="/js/ui/popup/controllers/settings.js"></script>
|
||||
<script src="/js/ui/popup/controllers/password_prompt.js"></script>
|
||||
<script src="/js/ui/popup/controllers/search.js"></script>
|
||||
<script src="/js/ui/popup/controllers/setup.js"></script>
|
||||
<script src="/js/ui/popup/directives/otp.js"></script>
|
||||
<script src="/js/ui/popup/directives/ngenter.js"></script>
|
||||
<script src="/js/ui/popup/filters/translate.js"></script>
|
||||
|
||||
|
||||
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="/css/vendor/font-awesome.css" media="all" rel="stylesheet"/>
|
||||
<link href="/css/vendor/angular-material.min.css" media="all" rel="stylesheet"/>
|
||||
<link href="/css/material.css" media="all" rel="stylesheet"/>
|
||||
<!--<link href="/css/main.css" media="all" rel="stylesheet" /> -->
|
||||
</head>
|
||||
<body ng-controller="MainCtrl">
|
||||
<section layout="column" flex="">
|
||||
<md-toolbar class="md-hue-2" ng-if="toolbarShown">
|
||||
<div class="md-toolbar-tools">
|
||||
<md-button class="md-icon-button" aria-label="menu" ng-click="toggleLeft()">
|
||||
<md-icon>menu</md-icon>
|
||||
</md-button>
|
||||
<h2>
|
||||
<span>Passman</span>
|
||||
</h2>
|
||||
<span flex></span>
|
||||
<md-button class="md-icon-button" aria-label="Lock" ng-click="lockExtension()">
|
||||
<md-tooltip md-direction="bottom">{{'lock_extension' | translate}}</md-tooltip>
|
||||
<md-icon>lock</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</body>
|
||||
</md-toolbar>
|
||||
|
||||
<md-sidenav class="md-sidenav-left" md-component-id="left" md-is-locked-open="$mdMedia('gt-md')" ng-if="toolbarShown"
|
||||
md-disable-backdrop="" md-whiteframe="4">
|
||||
|
||||
<md-toolbar class="md-hue-2">
|
||||
<div class="md-toolbar-tools">
|
||||
<h2>
|
||||
<span>Menu</span>
|
||||
</h2>
|
||||
<span flex></span>
|
||||
<md-button class="md-icon-button" aria-label="Close" ng-click="toggleLeft()">
|
||||
<md-icon>close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<md-content class="menu" layout-padding="">
|
||||
<ul>
|
||||
<li>
|
||||
<a ng-click="goto_list()">
|
||||
<md-icon>list</md-icon>
|
||||
{{'list' | translate}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a ng-click="goto_search()">
|
||||
<md-icon>search</md-icon>
|
||||
{{'search' | translate}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a ng-click="goto_settings()">
|
||||
<md-icon>settings</md-icon>
|
||||
{{'settings' | translate}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank">
|
||||
<md-icon>payment</md-icon>
|
||||
Donate
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</md-content>
|
||||
|
||||
</md-sidenav>
|
||||
|
||||
|
||||
<md-content layout="column" class="container" layout-fill>
|
||||
<div ng-view></div>
|
||||
</md-content>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,32 +1,37 @@
|
|||
<div class="col-xs-12 nopadding pwcontainer">
|
||||
<div ng-show="found_credentials.length === 0">
|
||||
{{ 'no_credentials_found_for_site' | translate}}
|
||||
</div>
|
||||
<div ng-show="found_credentials.length > 0">{{'credentials_found_for_site' | translate:found_credentials.length.toString() }}</div>
|
||||
<div class="credential" ng-repeat="credential in found_credentials">
|
||||
<div class="col-xs-7 nopadding">{{credential.label}}<br/>
|
||||
<small>{{credential.username}}</small>
|
||||
<md-list class="password-list" flex>
|
||||
<md-list-item class="md-3-line" ng-repeat="credential in found_credentials">
|
||||
<!--<img ng-src="{{item.face}}?{{$index}}" class="md-avatar" alt="{{item.who}}"/>-->
|
||||
<div class="md-list-item-text" layout="column">
|
||||
<h3>{{credential.label}}</h3>
|
||||
<h4>{{credential.username}}</h4>
|
||||
<p ng-if="credential.otp.secret">OTP: <span otp-generator secret="credential.otp.secret"></span></p>
|
||||
</div>
|
||||
<div class="col-xs-5 OTP" ng-if="credential.otp.secret">
|
||||
{{'one_time_password' | translate}}: <div otp-generator secret="credential.otp.secret"></div>
|
||||
</md-list-item>
|
||||
<md-list-item ng-if="found_credentials.length === 0">
|
||||
<div class="md-list-item-text" layout="column">
|
||||
<h3>{{ 'no_credentials_found_for_site' | translate}}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div style="position: absolute; left: 50%; margin-top: -7px; width: 110px;">
|
||||
<div style="position: relative; left: -50%; margin-top: 1.3em;">
|
||||
<small>{{'credentials_in_db' | translate:credential_amount}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottomBtn" ng-click="goto_settings()" title="{{'settings' | translate}}"><i class="fa fa-gears"></i></div>
|
||||
<div class="bottomBtn" ng-click="goto_search()" title="{{'search' | translate}}"><i class="fa fa-search"></i></div>
|
||||
<div class="bottomBtn" ng-click="refresh()" title="{{'refresh_credential_list' | translate}}"><i class="fa fa-refresh" ng-class="{'fa-spin': refreshing_credentials}"></i></div>
|
||||
<div class="bottomBtn pull-right"> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank"
|
||||
title="{{'donate_button_title' | translate}}"
|
||||
rel="nofollow noopener noreferrer"
|
||||
><i class="fa fa-paypal"></i> </a>
|
||||
</div>
|
||||
<div class="bottomBtn pull-right" ng-click="lockExtension()" title="{{'lock_extension' | translate}}"><i class="fa fa-lock"></i></div>
|
||||
<!-- <a class="btn btn-success pull-right"
|
||||
>Donate</a> -->
|
||||
</div>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
<md-button class="md-fab addFab" aria-label="Eat cake">
|
||||
<md-icon>add</md-icon>
|
||||
</md-button>
|
||||
<!--<div class="footer">-->
|
||||
<!--<div style="position: absolute; left: 50%; margin-top: -7px; width: 110px;">-->
|
||||
<!--<div style="position: relative; left: -50%; margin-top: 1.3em;">-->
|
||||
<!--<small>{{'credentials_in_db' | translate:credential_amount}}</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<!–-->
|
||||
<!--<div class="bottomBtn" ng-click="goto_settings()" title="{{'settings' | translate}}"><i class="fa fa-gears"></i></div>-->
|
||||
<!--<div class="bottomBtn" ng-click="goto_search()" title="{{'search' | translate}}"><i class="fa fa-search"></i></div>-->
|
||||
<!--<div class="bottomBtn" ng-click="refresh()" title="{{'refresh_credential_list' | translate}}"><i class="fa fa-refresh" ng-class="{'fa-spin': refreshing_credentials}"></i></div>-->
|
||||
<!--<div class="bottomBtn pull-right"> <a -->
|
||||
<!--title="{{'donate_button_title' | translate}}"-->
|
||||
<!--rel="nofollow noopener noreferrer"-->
|
||||
<!--><i class="fa fa-paypal"></i> </a>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="bottomBtn pull-right" ng-click="lockExtension()" title="{{'lock_extension' | translate}}"><i class="fa fa-lock"></i></div>-->
|
||||
<!--<!– <a class="btn btn-success pull-right"-->
|
||||
<!-->Donate</a> –>-->
|
||||
<!--</div>-->
|
|
@ -1,15 +1,43 @@
|
|||
<div class="content unlock" style="max-height: 160px; overflow: auto">
|
||||
<div>
|
||||
<i class="fa fa-lock fa-5x"></i>
|
||||
<div>{{'extension_locked'| translate}}:</div>
|
||||
<input class="form-control" type="password" ng-enter="apply_settings()" ng-model="master_password" />
|
||||
<label><input type="checkbox" ng-model="master_password_remember">Remember master password</label>
|
||||
</div>
|
||||
<div layout="row" layout-align="center center" class="unlock-container">
|
||||
|
||||
<div class="unlock">
|
||||
<div style="width: 100%; text-align: center; margin-bottom: 15px;">
|
||||
<img src="/icons/Passman_Color_Horizontal.png" height="40"/>
|
||||
</div>
|
||||
<div>
|
||||
<span >{{'extension_locked'| translate}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<md-input-container style="width: 100%;">
|
||||
|
||||
<input class="form-control" aria-label="password" type="password" ng-enter="apply_settings()" ng-model="master_password" style="width: 100%;"/>
|
||||
</md-input-container>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-show="inValidPassword" class="error">
|
||||
{{'invalid_master_password' | translate}}
|
||||
{{'invalid_master_password' | translate}}
|
||||
</div>
|
||||
<button class="btn btn-default stepNext" ng-click="apply_settings()" ng-disabled="saving"><i ng-show="saving" ng-class="{'fa-spinner fa-spin': saving}" class="fa"></i><i ng-show="!saving" class="fa fa-unlock"></i> {{'unlock' | translate}}</button>
|
||||
</div>
|
||||
|
||||
<div layout="row" layout-sm="column" layout-align="space-around">
|
||||
<md-button class="md-raised md-primary" ng-click="apply_settings()" ng-disabled="saving"></span>
|
||||
<i ng-show="saving"
|
||||
ng-class="{'fa-spinner fa-spin': saving}"
|
||||
class="fa"></i><i
|
||||
ng-show="!saving" class="fa fa-unlock"></i>
|
||||
{{'unlock' | translate}}
|
||||
</md-button>
|
||||
|
||||
</div>
|
||||
<br />
|
||||
<div layout="row" layout-sm="column" layout-align="space-around">
|
||||
<md-input-container>
|
||||
<md-checkbox class="md-primary" md-no-ink aria-label=" {{'remember_master_password'| translate}}" ng-model="master_password_remember">
|
||||
{{'remember_master_password'| translate}}
|
||||
</md-checkbox>
|
||||
</md-input-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,38 +1,21 @@
|
|||
<div class="col-xs-12 nopadding pwcontainer">
|
||||
<div class="searchContainer">
|
||||
<input type="text" ng-model="searchText" placeholder="{{'search_for' | translate }}..." class="form-control" ng-enter="search()"/>
|
||||
</div>
|
||||
<div ng-show="found_credentials.length === 0">
|
||||
{{'no_credentials_found' | translate}}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="credential" ng-repeat="credential in found_credentials">
|
||||
<div class="col-xs-7 nopadding">{{credential.label}}<br/>
|
||||
<small>{{credential.username}}</small>
|
||||
<small>{{credential.email}}</small>
|
||||
<div layout-padding>
|
||||
<md-input-container class="md-block">
|
||||
<label>{{'search_for' | translate }}</label>
|
||||
<input ng-model="searchText" ng-enter="search()">
|
||||
</md-input-container>
|
||||
<md-list class="password-list" ng-show="found_credentials.length > 0">
|
||||
<md-list-item class="md-3-line" ng-repeat="credential in found_credentials">
|
||||
<!--<img ng-src="{{item.face}}?{{$index}}" class="md-avatar" alt="{{item.who}}"/>-->
|
||||
<div class="md-list-item-text" layout="column">
|
||||
<h3>{{credential.label}}</h3>
|
||||
<h4>{{credential.username}}</h4>
|
||||
<p ng-if="credential.otp.secret">OTP: <span otp-generator secret="credential.otp.secret"></span></p>
|
||||
</div>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
<md-list-item ng-if="found_credentials.length === 0">
|
||||
<div class="md-list-item-text" layout="column">
|
||||
<h3>{{ 'no_credentials_found' | translate}}</h3>
|
||||
</div>
|
||||
<div class="col-xs-5 OTP" ng-if="credential.otp.secret">
|
||||
{{'one_time_password' | translate}}: <div otp-generator secret="credential.otp.secret"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div style="position: absolute; left: 50%; margin-top: -7px; width: 110px;">
|
||||
<div style="position: relative; left: -50%; margin-top: 1.3em;">
|
||||
<small>{{'credentials_in_db' | translate:credential_amount}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottomBtn" ng-click="goto_settings()" title="{{'settings' | translate}}"><i class="fa fa-gears"></i></div>
|
||||
<div class="bottomBtn" ng-click="goto_search()" title="{{'search' | translate}}"><i class="fa fa-search"></i></div>
|
||||
<div class="bottomBtn" ng-click="refresh()" title="{{'refresh_credential_list' | translate}}"><i class="fa fa-refresh" ng-class="{'fa-spin': refreshing_credentials}"></i></div>
|
||||
<div class="bottomBtn pull-right"> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank"
|
||||
title="{{'donate_button_title' | translate}}"
|
||||
rel="nofollow noopener noreferrer"
|
||||
><i class="fa fa-paypal"></i> </a>
|
||||
</div>
|
||||
<div class="bottomBtn pull-right" ng-click="lockExtension()" title="{{'lock_extension' | translate}}"><i class="fa fa-lock"></i></div>
|
||||
<!-- <a class="btn btn-success pull-right"
|
||||
>Donate</a> -->
|
||||
</md-list-item>
|
||||
</div>
|
|
@ -1,10 +1,80 @@
|
|||
|
||||
<h4 align="center">{{'please_enter_nextcloud_credentials' | translate}}:</h4>
|
||||
<div class="alerts alert alert-warning" ng-if="errors.length > 0">
|
||||
<li ng-repeat="error in errors">{{error}}</li>
|
||||
</div>
|
||||
<div style="max-height: 350px; overflow-y: auto;">
|
||||
<table class="table">
|
||||
|
||||
<h4 align="center">{{'please_enter_nextcloud_credentials' | translate}}:</h4>
|
||||
<md-content layout-padding>
|
||||
<div layout-gt-sm="row">
|
||||
<md-input-container class="md-block" flex-gt-sm>
|
||||
<label>{{'server_url' | translate}}</label>
|
||||
<input ng-model="settings.nextcloud_host" required ng-debounce="1000">
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<label>{{'username' | translate}}</label>
|
||||
<input ng-model="settings.nextcloud_username" required ng-debounce="1000">
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container class="md-block">
|
||||
<label>{{'password' | translate}}</label>
|
||||
<input type="password" ng-model="settings.nextcloud_password" required ng-debounce="1000">
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container class="md-block" ng-if="vaults">
|
||||
<label>{{'select_default_vault' | translate}}</label>
|
||||
<md-select ng-model="settings.default_vault.guid">
|
||||
<md-option ng-repeat="vault in vaults" value="{{vault.guid}}"
|
||||
ng-selected="settings.default_vault.vault_id === vault.vault_id">
|
||||
{{vault.name}}
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block" ng-show="settings.default_vault != ''">
|
||||
<label>{{'vault_password' | translate}}</label>
|
||||
<input type="password" ng-model="settings.vault_password" required>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<label>{{'refresh_timer' | translate}}</label>
|
||||
<input type="text" ng-model="settings.refreshTime" required>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.ignoreProtocol">
|
||||
{{'ignore_protocol' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.ignoreSubdomain">
|
||||
{{'ignore_subdomain' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.ignorePort">
|
||||
{{'ignore_port' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.disableAutoFill">
|
||||
{{'disable_autofill' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.disablePasswordPicker">
|
||||
{{'disable_password_picker' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block">
|
||||
<md-switch class="md-primary" name="special" ng-model="settings.debug">
|
||||
{{'enable_debug' | translate}}
|
||||
</md-switch>
|
||||
</md-input-container>
|
||||
<div layout="row" layout-sm="column" layout-align="space-around">
|
||||
<md-button class="md-raised md-primary" ng-click="saveSettings()" ng-disabled="saving"></span>{{'save' |
|
||||
translate}}
|
||||
</md-button>
|
||||
<md-button class="md-raised" ng-click="cancel()">{{'cancel' | translate}}</md-button>
|
||||
</div>
|
||||
</div>
|
||||
</md-content>
|
||||
<!-- <table class="table">
|
||||
<tr>
|
||||
<td><small>{{'server_url' | translate}}:</small></td>
|
||||
<td><input type="url" class="form-control input-sm" id="host" ng-model="settings.nextcloud_host" required ng-debounce="1000">
|
||||
|
@ -74,8 +144,8 @@
|
|||
<button class="btn btn-warning" ng-click="cancel()">{{'cancel' | translate}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="version">
|
||||
{{extension}}
|
||||
</div>
|
||||
</table> -->
|
||||
<div class="version">
|
||||
{{extension}}
|
||||
</div>
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 15 KiB |
|
@ -37,13 +37,14 @@
|
|||
'ngRoute',
|
||||
'ngSanitize',
|
||||
'pascalprecht.translate',
|
||||
'angular-steps'
|
||||
'angular-steps',
|
||||
'ngMaterial'
|
||||
])
|
||||
.config(function ($routeProvider, $locationProvider) {
|
||||
$routeProvider
|
||||
.when('/', {
|
||||
templateUrl: 'views/main.html',
|
||||
controller: 'MainCtrl'
|
||||
controller: 'ListCtrl'
|
||||
})
|
||||
.when('/search', {
|
||||
templateUrl: 'views/search.html',
|
||||
|
@ -79,6 +80,9 @@
|
|||
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|moz-extension):/);
|
||||
// Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)
|
||||
}
|
||||
]);
|
||||
]).config(function($mdThemingProvider) {
|
||||
$mdThemingProvider.theme('default')
|
||||
.primaryPalette('blue');
|
||||
});
|
||||
|
||||
}());
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* global API */
|
||||
|
||||
/**
|
||||
* Nextcloud - passman
|
||||
*
|
||||
* @copyright Copyright (c) 2016, Sander Brand (brantje@gmail.com)
|
||||
* @copyright Copyright (c) 2016, Marcos Zuriaga Miguel (wolfi@wolfi.es)
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name passmanApp.controller:MainCtrl
|
||||
* @description
|
||||
* # MainCtrl
|
||||
* Controller of the passmanApp
|
||||
*/
|
||||
angular.module('passmanExtension')
|
||||
.controller('ListCtrl', ['$scope', 'Settings', '$location', '$rootScope', function ($scope, Settings, $window, $rootScope) {
|
||||
$scope.app = 'passman';
|
||||
var port = API.runtime.connect(null, {
|
||||
name: "PassmanCommunication"
|
||||
});
|
||||
|
||||
var messageParser = function (message) {
|
||||
var e = message.split(':');
|
||||
|
||||
switch (e[0]) {
|
||||
case "credential_amount":
|
||||
$scope.credential_amount = e[1];
|
||||
$scope.refreshing_credentials = false;
|
||||
}
|
||||
|
||||
$scope.$apply();
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the background service
|
||||
*/
|
||||
var initApp = function () {
|
||||
port.onMessage.addListener(messageParser);
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getMasterPasswordSet"}).then(function (isPasswordSet) {
|
||||
function redirectToPrompt() {
|
||||
window.location = '#!/locked';
|
||||
return;
|
||||
}
|
||||
|
||||
//First check attributes
|
||||
if (!isPasswordSet) {
|
||||
redirectToPrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
getActiveTab();
|
||||
$scope.refreshing_credentials = true;
|
||||
setTimeout(function () {
|
||||
port.postMessage("credential_amount");
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.refreshing_credentials = false;
|
||||
$scope.refresh = function () {
|
||||
$scope.refreshing_credentials = true;
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getCredentials"}).then(function () {
|
||||
setTimeout(function () {
|
||||
port.postMessage("credential_amount");
|
||||
}, 2000);
|
||||
});
|
||||
};
|
||||
|
||||
var getActiveTab = function (cb) {
|
||||
API.tabs.query({currentWindow: true, active: true}).then(function (tab) {
|
||||
API.runtime.sendMessage(API.runtime.id, {
|
||||
method: "getCredentialsByUrl",
|
||||
args: [tab[0].url]
|
||||
}).then(function (_logins) {
|
||||
//var url = backgroundPage.processURL(tab.url, $rootScope.app_settings.ignoreProtocol, $rootScope.app_settings.ignoreSubdomain, $rootScope.app_settings.ignorePath);
|
||||
$scope.found_credentials = _logins;
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
initApp();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}]);
|
||||
}());
|
||||
|
|
@ -33,100 +33,56 @@
|
|||
* Controller of the passmanApp
|
||||
*/
|
||||
angular.module('passmanExtension')
|
||||
.controller('MainCtrl', ['$scope', 'Settings', '$location', '$rootScope', function ($scope, Settings, $window, $rootScope) {
|
||||
$scope.app = 'passman';
|
||||
var port = API.runtime.connect(null, {
|
||||
name: "PassmanCommunication"
|
||||
.controller('MainCtrl', ['$scope', '$mdSidenav', '$rootScope', function ($scope, $mdSidenav, $rootScope) {
|
||||
function buildToggler(navID) {
|
||||
return function() {
|
||||
// Component lookup should always be available since we are not using `ng-if`
|
||||
$mdSidenav(navID)
|
||||
.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.toolbarShown = true;
|
||||
|
||||
$rootScope.$on('lockExtension', function () {
|
||||
$scope.lockExtension();
|
||||
});
|
||||
|
||||
var messageParser = function (message) {
|
||||
var e = message.split(':');
|
||||
$rootScope.$on('unlocked', function () {
|
||||
$scope.toolbarShown = true;
|
||||
});
|
||||
|
||||
switch (e[0]) {
|
||||
case "credential_amount":
|
||||
$scope.credential_amount = e[1];
|
||||
$scope.refreshing_credentials = false;
|
||||
}
|
||||
|
||||
$scope.$apply();
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the background service
|
||||
*/
|
||||
var initApp = function () {
|
||||
port.onMessage.addListener(messageParser);
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getMasterPasswordSet"}).then(function (isPasswordSet) {
|
||||
function redirectToPrompt() {
|
||||
window.location = '#!/locked';
|
||||
return;
|
||||
}
|
||||
|
||||
//First check attributes
|
||||
if (!isPasswordSet) {
|
||||
redirectToPrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
getActiveTab();
|
||||
$scope.refreshing_credentials = true;
|
||||
setTimeout(function () {
|
||||
port.postMessage("credential_amount");
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.refreshing_credentials = false;
|
||||
$scope.refresh = function () {
|
||||
$scope.refreshing_credentials = true;
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getCredentials"}).then(function () {
|
||||
setTimeout(function () {
|
||||
port.postMessage("credential_amount");
|
||||
}, 2000);
|
||||
});
|
||||
};
|
||||
|
||||
var getActiveTab = function (cb) {
|
||||
API.tabs.query({currentWindow: true, active: true}).then(function (tab) {
|
||||
API.runtime.sendMessage(API.runtime.id, {
|
||||
method: "getCredentialsByUrl",
|
||||
args: [tab[0].url]
|
||||
}).then(function (_logins) {
|
||||
//var url = backgroundPage.processURL(tab.url, $rootScope.app_settings.ignoreProtocol, $rootScope.app_settings.ignoreSubdomain, $rootScope.app_settings.ignorePath);
|
||||
$scope.found_credentials = _logins;
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
};
|
||||
$scope.toggleLeft = buildToggler('left');
|
||||
|
||||
$scope.lockExtension = function () {
|
||||
$scope.toolbarShown = false;
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "setMasterPassword", args: {password: null}}).then(function () {
|
||||
window.location = '#!/locked';
|
||||
});
|
||||
};
|
||||
|
||||
API.runtime.sendMessage(API.runtime.id, {'method': 'getRuntimeSettings'}).then(function (settings) {
|
||||
|
||||
$rootScope.app_settings = settings;
|
||||
if (!settings || Object.keys(settings).length === 0) {
|
||||
window.location = '#!/setup';
|
||||
} else if (settings.hasOwnProperty('isInstalled')) {
|
||||
window.location = '#!/locked';
|
||||
} else {
|
||||
initApp();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
$scope.goto_list = function () {
|
||||
window.location = '#!/';
|
||||
$mdSidenav('left').close();
|
||||
};
|
||||
$scope.goto_settings = function () {
|
||||
window.location = '#!/settings';
|
||||
$mdSidenav('left').close();
|
||||
};
|
||||
|
||||
$scope.goto_search = function () {
|
||||
window.location = '#!/search';
|
||||
$mdSidenav('left').close();
|
||||
};
|
||||
|
||||
API.runtime.sendMessage(API.runtime.id, {'method': 'getRuntimeSettings'}).then(function (settings) {
|
||||
$rootScope.app_settings = settings;
|
||||
if (!settings || Object.keys(settings).length === 0) {
|
||||
window.location = '#!/setup';
|
||||
} else if (settings.hasOwnProperty('isInstalled')) {
|
||||
$scope.lockExtension();
|
||||
}
|
||||
});
|
||||
|
||||
}]);
|
||||
}());
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getMasterPasswordSet"}).then(function(isSet) {
|
||||
$scope.masterPwSet = isSet;
|
||||
$rootScope.$broadcast('lockExtension');
|
||||
$scope.$apply();
|
||||
});
|
||||
API.runtime.sendMessage(API.runtime.id, {method: "getSettings"});
|
||||
|
@ -51,6 +52,7 @@
|
|||
API.runtime.sendMessage(API.runtime.id, {method: "setMasterPassword", args: {password: $scope.master_password, savePassword: $scope.master_password_remember} }).then(function () {
|
||||
setTimeout(function () {
|
||||
window.location = '#!/';
|
||||
$rootScope.$emit('unlocked');
|
||||
$scope.saving = false;
|
||||
$scope.saving = false;
|
||||
},1500);
|
||||
|
|
|
@ -102,6 +102,14 @@
|
|||
$scope.saveSettings = function () {
|
||||
$scope.errors = [];
|
||||
var settings = angular.copy($scope.settings);
|
||||
for (var i =0; i < $scope.vaults.length; i++){
|
||||
var vault = $scope.vaults[i];
|
||||
if(vault.guid == settings.default_vault.guid){
|
||||
settings.default_vault = angular.copy(vault);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
/** global: PAPI */
|
||||
PAPI.decryptString(settings.default_vault.challenge_password, settings.vault_password);
|
||||
|
|
|
@ -68,10 +68,12 @@
|
|||
return str;
|
||||
}
|
||||
|
||||
var strCopy = API.i18n.getMessage('copy');
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
// template: '<span class="otp_generator">{{otp}} <span ng-bind="timeleft"></span></span>',
|
||||
template: '<span class="otp_generator"><span class="code">{{otp}}</span> <div class="radial-progress"><div class="circle"><div class="mask full"><div class="fill"></div></div><div class="mask half"><div class="fill"></div><div class="fill fix"></div></div></div></div></span>',
|
||||
//template: '<span class="otp_generator">{{otp}} <i class="fa fa-copy" ng-click="copyOTP(otp)"><md-tooltip md-direction="top">'+ strCopy +'</md-tooltip></i></md-button> </span>',
|
||||
template: '<span class="otp_generator"><span class="code">{{otp}}</span> <i class="fa fa-copy" ng-click="copyOTP(otp)"><md-tooltip md-direction="top">'+ strCopy +'</md-tooltip></i></md-button> <div class="radial-progress"><div class="circle"><div class="mask full"><div class="fill"></div></div><div class="mask half"><div class="fill"></div><div class="fill fix"></div></div></div></div></span>',
|
||||
transclude: false,
|
||||
scope: {
|
||||
secret: '='
|
||||
|
@ -127,6 +129,16 @@
|
|||
$timeout.cancel(scope.timer);
|
||||
}
|
||||
);
|
||||
|
||||
scope.copyOTP = function (otp) {
|
||||
var txtToCopy = document.createElement('input');
|
||||
|
||||
txtToCopy.value = otp;
|
||||
document.body.appendChild(txtToCopy);
|
||||
txtToCopy.select();
|
||||
document.execCommand('copy');
|
||||
txtToCopy.parentNode.removeChild(txtToCopy);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,402 @@
|
|||
/**
|
||||
* @license AngularJS v1.6.1
|
||||
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular) {'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name ngAria
|
||||
* @description
|
||||
*
|
||||
* The `ngAria` module provides support for common
|
||||
* [<abbr title="Accessible Rich Internet Applications">ARIA</abbr>](http://www.w3.org/TR/wai-aria/)
|
||||
* attributes that convey state or semantic information about the application for users
|
||||
* of assistive technologies, such as screen readers.
|
||||
*
|
||||
* <div doc-module-components="ngAria"></div>
|
||||
*
|
||||
* ## Usage
|
||||
*
|
||||
* For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following
|
||||
* directives are supported:
|
||||
* `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`,
|
||||
* `ngDblClick`, and `ngMessages`.
|
||||
*
|
||||
* Below is a more detailed breakdown of the attributes handled by ngAria:
|
||||
*
|
||||
* | Directive | Supported Attributes |
|
||||
* |---------------------------------------------|-----------------------------------------------------------------------------------------------------|
|
||||
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
|
||||
* | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
|
||||
* | {@link ng.directive:ngRequired ngRequired} | aria-required |
|
||||
* | {@link ng.directive:ngChecked ngChecked} | aria-checked |
|
||||
* | {@link ng.directive:ngReadonly ngReadonly} | aria-readonly |
|
||||
* | {@link ng.directive:ngValue ngValue} | aria-checked |
|
||||
* | {@link ng.directive:ngShow ngShow} | aria-hidden |
|
||||
* | {@link ng.directive:ngHide ngHide} | aria-hidden |
|
||||
* | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
|
||||
* | {@link module:ngMessages ngMessages} | aria-live |
|
||||
* | {@link ng.directive:ngClick ngClick} | tabindex, keydown event, button role |
|
||||
*
|
||||
* Find out more information about each directive by reading the
|
||||
* {@link guide/accessibility ngAria Developer Guide}.
|
||||
*
|
||||
* ## Example
|
||||
* Using ngDisabled with ngAria:
|
||||
* ```html
|
||||
* <md-checkbox ng-disabled="disabled">
|
||||
* ```
|
||||
* Becomes:
|
||||
* ```html
|
||||
* <md-checkbox ng-disabled="disabled" aria-disabled="true">
|
||||
* ```
|
||||
*
|
||||
* ## Disabling Attributes
|
||||
* It's possible to disable individual attributes added by ngAria with the
|
||||
* {@link ngAria.$ariaProvider#config config} method. For more details, see the
|
||||
* {@link guide/accessibility Developer Guide}.
|
||||
*/
|
||||
var ngAriaModule = angular.module('ngAria', ['ng']).
|
||||
provider('$aria', $AriaProvider);
|
||||
|
||||
/**
|
||||
* Internal Utilities
|
||||
*/
|
||||
var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA', 'SELECT', 'DETAILS', 'SUMMARY'];
|
||||
|
||||
var isNodeOneOf = function(elem, nodeTypeArray) {
|
||||
if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @ngdoc provider
|
||||
* @name $ariaProvider
|
||||
* @this
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Used for configuring the ARIA attributes injected and managed by ngAria.
|
||||
*
|
||||
* ```js
|
||||
* angular.module('myApp', ['ngAria'], function config($ariaProvider) {
|
||||
* $ariaProvider.config({
|
||||
* ariaValue: true,
|
||||
* tabindex: false
|
||||
* });
|
||||
* });
|
||||
*```
|
||||
*
|
||||
* ## Dependencies
|
||||
* Requires the {@link ngAria} module to be installed.
|
||||
*
|
||||
*/
|
||||
function $AriaProvider() {
|
||||
var config = {
|
||||
ariaHidden: true,
|
||||
ariaChecked: true,
|
||||
ariaReadonly: true,
|
||||
ariaDisabled: true,
|
||||
ariaRequired: true,
|
||||
ariaInvalid: true,
|
||||
ariaValue: true,
|
||||
tabindex: true,
|
||||
bindKeydown: true,
|
||||
bindRoleForClick: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ariaProvider#config
|
||||
*
|
||||
* @param {object} config object to enable/disable specific ARIA attributes
|
||||
*
|
||||
* - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags
|
||||
* - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags
|
||||
* - **ariaReadonly** – `{boolean}` – Enables/disables aria-readonly tags
|
||||
* - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags
|
||||
* - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags
|
||||
* - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags
|
||||
* - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and
|
||||
* aria-valuenow tags
|
||||
* - **tabindex** – `{boolean}` – Enables/disables tabindex tags
|
||||
* - **bindKeydown** – `{boolean}` – Enables/disables keyboard event binding on non-interactive
|
||||
* elements (such as `div` or `li`) using ng-click, making them more accessible to users of
|
||||
* assistive technologies
|
||||
* - **bindRoleForClick** – `{boolean}` – Adds role=button to non-interactive elements (such as
|
||||
* `div` or `li`) using ng-click, making them more accessible to users of assistive
|
||||
* technologies
|
||||
*
|
||||
* @description
|
||||
* Enables/disables various ARIA attributes
|
||||
*/
|
||||
this.config = function(newConfig) {
|
||||
config = angular.extend(config, newConfig);
|
||||
};
|
||||
|
||||
function watchExpr(attrName, ariaAttr, nodeBlackList, negate) {
|
||||
return function(scope, elem, attr) {
|
||||
var ariaCamelName = attr.$normalize(ariaAttr);
|
||||
if (config[ariaCamelName] && !isNodeOneOf(elem, nodeBlackList) && !attr[ariaCamelName]) {
|
||||
scope.$watch(attr[attrName], function(boolVal) {
|
||||
// ensure boolean value
|
||||
boolVal = negate ? !boolVal : !!boolVal;
|
||||
elem.attr(ariaAttr, boolVal);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $aria
|
||||
*
|
||||
* @description
|
||||
* @priority 200
|
||||
*
|
||||
* The $aria service contains helper methods for applying common
|
||||
* [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
|
||||
*
|
||||
* ngAria injects common accessibility attributes that tell assistive technologies when HTML
|
||||
* elements are enabled, selected, hidden, and more. To see how this is performed with ngAria,
|
||||
* let's review a code snippet from ngAria itself:
|
||||
*
|
||||
*```js
|
||||
* ngAriaModule.directive('ngDisabled', ['$aria', function($aria) {
|
||||
* return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
|
||||
* }])
|
||||
*```
|
||||
* Shown above, the ngAria module creates a directive with the same signature as the
|
||||
* traditional `ng-disabled` directive. But this ngAria version is dedicated to
|
||||
* solely managing accessibility attributes on custom elements. The internal `$aria` service is
|
||||
* used to watch the boolean attribute `ngDisabled`. If it has not been explicitly set by the
|
||||
* developer, `aria-disabled` is injected as an attribute with its value synchronized to the
|
||||
* value in `ngDisabled`.
|
||||
*
|
||||
* Because ngAria hooks into the `ng-disabled` directive, developers do not have to do
|
||||
* anything to enable this feature. The `aria-disabled` attribute is automatically managed
|
||||
* simply as a silent side-effect of using `ng-disabled` with the ngAria module.
|
||||
*
|
||||
* The full list of directives that interface with ngAria:
|
||||
* * **ngModel**
|
||||
* * **ngChecked**
|
||||
* * **ngReadonly**
|
||||
* * **ngRequired**
|
||||
* * **ngDisabled**
|
||||
* * **ngValue**
|
||||
* * **ngShow**
|
||||
* * **ngHide**
|
||||
* * **ngClick**
|
||||
* * **ngDblclick**
|
||||
* * **ngMessages**
|
||||
*
|
||||
* Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each
|
||||
* directive.
|
||||
*
|
||||
*
|
||||
* ## Dependencies
|
||||
* Requires the {@link ngAria} module to be installed.
|
||||
*/
|
||||
this.$get = function() {
|
||||
return {
|
||||
config: function(key) {
|
||||
return config[key];
|
||||
},
|
||||
$$watchExpr: watchExpr
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngShow', 'aria-hidden', [], true);
|
||||
}])
|
||||
.directive('ngHide', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngHide', 'aria-hidden', [], false);
|
||||
}])
|
||||
.directive('ngValue', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngValue', 'aria-checked', nodeBlackList, false);
|
||||
}])
|
||||
.directive('ngChecked', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngChecked', 'aria-checked', nodeBlackList, false);
|
||||
}])
|
||||
.directive('ngReadonly', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngReadonly', 'aria-readonly', nodeBlackList, false);
|
||||
}])
|
||||
.directive('ngRequired', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngRequired', 'aria-required', nodeBlackList, false);
|
||||
}])
|
||||
.directive('ngModel', ['$aria', function($aria) {
|
||||
|
||||
function shouldAttachAttr(attr, normalizedAttr, elem, allowBlacklistEls) {
|
||||
return $aria.config(normalizedAttr) && !elem.attr(attr) && (allowBlacklistEls || !isNodeOneOf(elem, nodeBlackList));
|
||||
}
|
||||
|
||||
function shouldAttachRole(role, elem) {
|
||||
// if element does not have role attribute
|
||||
// AND element type is equal to role (if custom element has a type equaling shape) <-- remove?
|
||||
// AND element is not in nodeBlackList
|
||||
return !elem.attr('role') && (elem.attr('type') === role) && !isNodeOneOf(elem, nodeBlackList);
|
||||
}
|
||||
|
||||
function getShape(attr, elem) {
|
||||
var type = attr.type,
|
||||
role = attr.role;
|
||||
|
||||
return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' :
|
||||
((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' :
|
||||
(type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' : '';
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
|
||||
compile: function(elem, attr) {
|
||||
var shape = getShape(attr, elem);
|
||||
|
||||
return {
|
||||
post: function(scope, elem, attr, ngModel) {
|
||||
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem, false);
|
||||
|
||||
function ngAriaWatchModelValue() {
|
||||
return ngModel.$modelValue;
|
||||
}
|
||||
|
||||
function getRadioReaction(newVal) {
|
||||
// Strict comparison would cause a BC
|
||||
// eslint-disable-next-line eqeqeq
|
||||
var boolVal = (attr.value == ngModel.$viewValue);
|
||||
elem.attr('aria-checked', boolVal);
|
||||
}
|
||||
|
||||
function getCheckboxReaction() {
|
||||
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
|
||||
}
|
||||
|
||||
switch (shape) {
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
if (shouldAttachRole(shape, elem)) {
|
||||
elem.attr('role', shape);
|
||||
}
|
||||
if (shouldAttachAttr('aria-checked', 'ariaChecked', elem, false)) {
|
||||
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
|
||||
getRadioReaction : getCheckboxReaction);
|
||||
}
|
||||
if (needsTabIndex) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
break;
|
||||
case 'range':
|
||||
if (shouldAttachRole(shape, elem)) {
|
||||
elem.attr('role', 'slider');
|
||||
}
|
||||
if ($aria.config('ariaValue')) {
|
||||
var needsAriaValuemin = !elem.attr('aria-valuemin') &&
|
||||
(attr.hasOwnProperty('min') || attr.hasOwnProperty('ngMin'));
|
||||
var needsAriaValuemax = !elem.attr('aria-valuemax') &&
|
||||
(attr.hasOwnProperty('max') || attr.hasOwnProperty('ngMax'));
|
||||
var needsAriaValuenow = !elem.attr('aria-valuenow');
|
||||
|
||||
if (needsAriaValuemin) {
|
||||
attr.$observe('min', function ngAriaValueMinReaction(newVal) {
|
||||
elem.attr('aria-valuemin', newVal);
|
||||
});
|
||||
}
|
||||
if (needsAriaValuemax) {
|
||||
attr.$observe('max', function ngAriaValueMinReaction(newVal) {
|
||||
elem.attr('aria-valuemax', newVal);
|
||||
});
|
||||
}
|
||||
if (needsAriaValuenow) {
|
||||
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
|
||||
elem.attr('aria-valuenow', newVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (needsTabIndex) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!attr.hasOwnProperty('ngRequired') && ngModel.$validators.required
|
||||
&& shouldAttachAttr('aria-required', 'ariaRequired', elem, false)) {
|
||||
// ngModel.$error.required is undefined on custom controls
|
||||
attr.$observe('required', function() {
|
||||
elem.attr('aria-required', !!attr['required']);
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem, true)) {
|
||||
scope.$watch(function ngAriaInvalidWatch() {
|
||||
return ngModel.$invalid;
|
||||
}, function ngAriaInvalidReaction(newVal) {
|
||||
elem.attr('aria-invalid', !!newVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}])
|
||||
.directive('ngDisabled', ['$aria', function($aria) {
|
||||
return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
|
||||
}])
|
||||
.directive('ngMessages', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: '?ngMessages',
|
||||
link: function(scope, elem, attr, ngMessages) {
|
||||
if (!elem.attr('aria-live')) {
|
||||
elem.attr('aria-live', 'assertive');
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('ngClick',['$aria', '$parse', function($aria, $parse) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function(elem, attr) {
|
||||
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
|
||||
return function(scope, elem, attr) {
|
||||
|
||||
if (!isNodeOneOf(elem, nodeBlackList)) {
|
||||
|
||||
if ($aria.config('bindRoleForClick') && !elem.attr('role')) {
|
||||
elem.attr('role', 'button');
|
||||
}
|
||||
|
||||
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
|
||||
if ($aria.config('bindKeydown') && !attr.ngKeydown && !attr.ngKeypress && !attr.ngKeyup) {
|
||||
elem.on('keydown', function(event) {
|
||||
var keyCode = event.which || event.keyCode;
|
||||
if (keyCode === 32 || keyCode === 13) {
|
||||
scope.$apply(callback);
|
||||
}
|
||||
|
||||
function callback() {
|
||||
fn(scope, { $event: event });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}])
|
||||
.directive('ngDblclick', ['$aria', function($aria) {
|
||||
return function(scope, elem, attr) {
|
||||
if ($aria.config('tabindex') && !elem.attr('tabindex') && !isNodeOneOf(elem, nodeBlackList)) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
})(window, window.angular);
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,739 @@
|
|||
/**
|
||||
* @license AngularJS v1.6.1
|
||||
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular) {'use strict';
|
||||
|
||||
var forEach;
|
||||
var isArray;
|
||||
var isString;
|
||||
var jqLite;
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name ngMessages
|
||||
* @description
|
||||
*
|
||||
* The `ngMessages` module provides enhanced support for displaying messages within templates
|
||||
* (typically within forms or when rendering message objects that return key/value data).
|
||||
* Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
|
||||
* show and hide error messages specific to the state of an input field, the `ngMessages` and
|
||||
* `ngMessage` directives are designed to handle the complexity, inheritance and priority
|
||||
* sequencing based on the order of how the messages are defined in the template.
|
||||
*
|
||||
* Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude`
|
||||
* `ngMessage` and `ngMessageExp` directives.
|
||||
*
|
||||
* # Usage
|
||||
* The `ngMessages` directive allows keys in a key/value collection to be associated with a child element
|
||||
* (or 'message') that will show or hide based on the truthiness of that key's value in the collection. A common use
|
||||
* case for `ngMessages` is to display error messages for inputs using the `$error` object exposed by the
|
||||
* {@link ngModel ngModel} directive.
|
||||
*
|
||||
* The child elements of the `ngMessages` directive are matched to the collection keys by a `ngMessage` or
|
||||
* `ngMessageExp` directive. The value of these attributes must match a key in the collection that is provided by
|
||||
* the `ngMessages` directive.
|
||||
*
|
||||
* Consider the following example, which illustrates a typical use case of `ngMessages`. Within the form `myForm` we
|
||||
* have a text input named `myField` which is bound to the scope variable `field` using the {@link ngModel ngModel}
|
||||
* directive.
|
||||
*
|
||||
* The `myField` field is a required input of type `email` with a maximum length of 15 characters.
|
||||
*
|
||||
* ```html
|
||||
* <form name="myForm">
|
||||
* <label>
|
||||
* Enter text:
|
||||
* <input type="email" ng-model="field" name="myField" required maxlength="15" />
|
||||
* </label>
|
||||
* <div ng-messages="myForm.myField.$error" role="alert">
|
||||
* <div ng-message="required">Please enter a value for this field.</div>
|
||||
* <div ng-message="email">This field must be a valid email address.</div>
|
||||
* <div ng-message="maxlength">This field can be at most 15 characters long.</div>
|
||||
* </div>
|
||||
* </form>
|
||||
* ```
|
||||
*
|
||||
* In order to show error messages corresponding to `myField` we first create an element with an `ngMessages` attribute
|
||||
* set to the `$error` object owned by the `myField` input in our `myForm` form.
|
||||
*
|
||||
* Within this element we then create separate elements for each of the possible errors that `myField` could have.
|
||||
* The `ngMessage` attribute is used to declare which element(s) will appear for which error - for example,
|
||||
* setting `ng-message="required"` specifies that this particular element should be displayed when there
|
||||
* is no value present for the required field `myField` (because the key `required` will be `true` in the object
|
||||
* `myForm.myField.$error`).
|
||||
*
|
||||
* ### Message order
|
||||
*
|
||||
* By default, `ngMessages` will only display one message for a particular key/value collection at any time. If more
|
||||
* than one message (or error) key is currently true, then which message is shown is determined by the order of messages
|
||||
* in the HTML template code (messages declared first are prioritised). This mechanism means the developer does not have
|
||||
* to prioritize messages using custom JavaScript code.
|
||||
*
|
||||
* Given the following error object for our example (which informs us that the field `myField` currently has both the
|
||||
* `required` and `email` errors):
|
||||
*
|
||||
* ```javascript
|
||||
* <!-- keep in mind that ngModel automatically sets these error flags -->
|
||||
* myField.$error = { required : true, email: true, maxlength: false };
|
||||
* ```
|
||||
* The `required` message will be displayed to the user since it appears before the `email` message in the DOM.
|
||||
* Once the user types a single character, the `required` message will disappear (since the field now has a value)
|
||||
* but the `email` message will be visible because it is still applicable.
|
||||
*
|
||||
* ### Displaying multiple messages at the same time
|
||||
*
|
||||
* While `ngMessages` will by default only display one error element at a time, the `ng-messages-multiple` attribute can
|
||||
* be applied to the `ngMessages` container element to cause it to display all applicable error messages at once:
|
||||
*
|
||||
* ```html
|
||||
* <!-- attribute-style usage -->
|
||||
* <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
|
||||
*
|
||||
* <!-- element-style usage -->
|
||||
* <ng-messages for="myForm.myField.$error" multiple>...</ng-messages>
|
||||
* ```
|
||||
*
|
||||
* ## Reusing and Overriding Messages
|
||||
* In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
|
||||
* template. This allows for generic collection of messages to be reused across multiple parts of an
|
||||
* application.
|
||||
*
|
||||
* ```html
|
||||
* <script type="text/ng-template" id="error-messages">
|
||||
* <div ng-message="required">This field is required</div>
|
||||
* <div ng-message="minlength">This field is too short</div>
|
||||
* </script>
|
||||
*
|
||||
* <div ng-messages="myForm.myField.$error" role="alert">
|
||||
* <div ng-messages-include="error-messages"></div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* However, including generic messages may not be useful enough to match all input fields, therefore,
|
||||
* `ngMessages` provides the ability to override messages defined in the remote template by redefining
|
||||
* them within the directive container.
|
||||
*
|
||||
* ```html
|
||||
* <!-- a generic template of error messages known as "my-custom-messages" -->
|
||||
* <script type="text/ng-template" id="my-custom-messages">
|
||||
* <div ng-message="required">This field is required</div>
|
||||
* <div ng-message="minlength">This field is too short</div>
|
||||
* </script>
|
||||
*
|
||||
* <form name="myForm">
|
||||
* <label>
|
||||
* Email address
|
||||
* <input type="email"
|
||||
* id="email"
|
||||
* name="myEmail"
|
||||
* ng-model="email"
|
||||
* minlength="5"
|
||||
* required />
|
||||
* </label>
|
||||
* <!-- any ng-message elements that appear BEFORE the ng-messages-include will
|
||||
* override the messages present in the ng-messages-include template -->
|
||||
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||
* <!-- this required message has overridden the template message -->
|
||||
* <div ng-message="required">You did not enter your email address</div>
|
||||
*
|
||||
* <!-- this is a brand new message and will appear last in the prioritization -->
|
||||
* <div ng-message="email">Your email address is invalid</div>
|
||||
*
|
||||
* <!-- and here are the generic error messages -->
|
||||
* <div ng-messages-include="my-custom-messages"></div>
|
||||
* </div>
|
||||
* </form>
|
||||
* ```
|
||||
*
|
||||
* In the example HTML code above the message that is set on required will override the corresponding
|
||||
* required message defined within the remote template. Therefore, with particular input fields (such
|
||||
* email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
|
||||
* while more generic messages can be used to handle other, more general input errors.
|
||||
*
|
||||
* ## Dynamic Messaging
|
||||
* ngMessages also supports using expressions to dynamically change key values. Using arrays and
|
||||
* repeaters to list messages is also supported. This means that the code below will be able to
|
||||
* fully adapt itself and display the appropriate message when any of the expression data changes:
|
||||
*
|
||||
* ```html
|
||||
* <form name="myForm">
|
||||
* <label>
|
||||
* Email address
|
||||
* <input type="email"
|
||||
* name="myEmail"
|
||||
* ng-model="email"
|
||||
* minlength="5"
|
||||
* required />
|
||||
* </label>
|
||||
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||
* <div ng-message="required">You did not enter your email address</div>
|
||||
* <div ng-repeat="errorMessage in errorMessages">
|
||||
* <!-- use ng-message-exp for a message whose key is given by an expression -->
|
||||
* <div ng-message-exp="errorMessage.type">{{ errorMessage.text }}</div>
|
||||
* </div>
|
||||
* </div>
|
||||
* </form>
|
||||
* ```
|
||||
*
|
||||
* The `errorMessage.type` expression can be a string value or it can be an array so
|
||||
* that multiple errors can be associated with a single error message:
|
||||
*
|
||||
* ```html
|
||||
* <label>
|
||||
* Email address
|
||||
* <input type="email"
|
||||
* ng-model="data.email"
|
||||
* name="myEmail"
|
||||
* ng-minlength="5"
|
||||
* ng-maxlength="100"
|
||||
* required />
|
||||
* </label>
|
||||
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||
* <div ng-message-exp="'required'">You did not enter your email address</div>
|
||||
* <div ng-message-exp="['minlength', 'maxlength']">
|
||||
* Your email must be between 5 and 100 characters long
|
||||
* </div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* Feel free to use other structural directives such as ng-if and ng-switch to further control
|
||||
* what messages are active and when. Be careful, if you place ng-message on the same element
|
||||
* as these structural directives, Angular may not be able to determine if a message is active
|
||||
* or not. Therefore it is best to place the ng-message on a child element of the structural
|
||||
* directive.
|
||||
*
|
||||
* ```html
|
||||
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||
* <div ng-if="showRequiredError">
|
||||
* <div ng-message="required">Please enter something</div>
|
||||
* </div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* ## Animations
|
||||
* If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and
|
||||
* `ngMessageExp` directives will trigger animations whenever any messages are added and removed from
|
||||
* the DOM by the `ngMessages` directive.
|
||||
*
|
||||
* Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
|
||||
* class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
|
||||
* messages present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
|
||||
* hook into the animations whenever these classes are added/removed.
|
||||
*
|
||||
* Let's say that our HTML code for our messages container looks like so:
|
||||
*
|
||||
* ```html
|
||||
* <div ng-messages="myMessages" class="my-messages" role="alert">
|
||||
* <div ng-message="alert" class="some-message">...</div>
|
||||
* <div ng-message="fail" class="some-message">...</div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* Then the CSS animation code for the message container looks like so:
|
||||
*
|
||||
* ```css
|
||||
* .my-messages {
|
||||
* transition:1s linear all;
|
||||
* }
|
||||
* .my-messages.ng-active {
|
||||
* // messages are visible
|
||||
* }
|
||||
* .my-messages.ng-inactive {
|
||||
* // messages are hidden
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
|
||||
* and leave animation is triggered for each particular element bound to the `ngMessage` directive.
|
||||
*
|
||||
* Therefore, the CSS code for the inner messages looks like so:
|
||||
*
|
||||
* ```css
|
||||
* .some-message {
|
||||
* transition:1s linear all;
|
||||
* }
|
||||
*
|
||||
* .some-message.ng-enter {}
|
||||
* .some-message.ng-enter.ng-enter-active {}
|
||||
*
|
||||
* .some-message.ng-leave {}
|
||||
* .some-message.ng-leave.ng-leave-active {}
|
||||
* ```
|
||||
*
|
||||
* {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
|
||||
*/
|
||||
angular.module('ngMessages', [], function initAngularHelpers() {
|
||||
// Access helpers from angular core.
|
||||
// Do it inside a `config` block to ensure `window.angular` is available.
|
||||
forEach = angular.forEach;
|
||||
isArray = angular.isArray;
|
||||
isString = angular.isString;
|
||||
jqLite = angular.element;
|
||||
})
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @module ngMessages
|
||||
* @name ngMessages
|
||||
* @restrict AE
|
||||
*
|
||||
* @description
|
||||
* `ngMessages` is a directive that is designed to show and hide messages based on the state
|
||||
* of a key/value object that it listens on. The directive itself complements error message
|
||||
* reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
|
||||
*
|
||||
* `ngMessages` manages the state of internal messages within its container element. The internal
|
||||
* messages use the `ngMessage` directive and will be inserted/removed from the page depending
|
||||
* on if they're present within the key/value object. By default, only one message will be displayed
|
||||
* at a time and this depends on the prioritization of the messages within the template. (This can
|
||||
* be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
|
||||
*
|
||||
* A remote template can also be used to promote message reusability and messages can also be
|
||||
* overridden.
|
||||
*
|
||||
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <!-- using attribute directives -->
|
||||
* <ANY ng-messages="expression" role="alert">
|
||||
* <ANY ng-message="stringValue">...</ANY>
|
||||
* <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
|
||||
* <ANY ng-message-exp="expressionValue">...</ANY>
|
||||
* </ANY>
|
||||
*
|
||||
* <!-- or by using element directives -->
|
||||
* <ng-messages for="expression" role="alert">
|
||||
* <ng-message when="stringValue">...</ng-message>
|
||||
* <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
|
||||
* <ng-message when-exp="expressionValue">...</ng-message>
|
||||
* </ng-messages>
|
||||
* ```
|
||||
*
|
||||
* @param {string} ngMessages an angular expression evaluating to a key/value object
|
||||
* (this is typically the $error object on an ngModel instance).
|
||||
* @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
|
||||
*
|
||||
* @example
|
||||
* <example name="ngMessages-directive" module="ngMessagesExample"
|
||||
* deps="angular-messages.js"
|
||||
* animations="true" fixBase="true">
|
||||
* <file name="index.html">
|
||||
* <form name="myForm">
|
||||
* <label>
|
||||
* Enter your name:
|
||||
* <input type="text"
|
||||
* name="myName"
|
||||
* ng-model="name"
|
||||
* ng-minlength="5"
|
||||
* ng-maxlength="20"
|
||||
* required />
|
||||
* </label>
|
||||
* <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
|
||||
*
|
||||
* <div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
|
||||
* <div ng-message="required">You did not enter a field</div>
|
||||
* <div ng-message="minlength">Your field is too short</div>
|
||||
* <div ng-message="maxlength">Your field is too long</div>
|
||||
* </div>
|
||||
* </form>
|
||||
* </file>
|
||||
* <file name="script.js">
|
||||
* angular.module('ngMessagesExample', ['ngMessages']);
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
.directive('ngMessages', ['$animate', function($animate) {
|
||||
var ACTIVE_CLASS = 'ng-active';
|
||||
var INACTIVE_CLASS = 'ng-inactive';
|
||||
|
||||
return {
|
||||
require: 'ngMessages',
|
||||
restrict: 'AE',
|
||||
controller: ['$element', '$scope', '$attrs', function NgMessagesCtrl($element, $scope, $attrs) {
|
||||
var ctrl = this;
|
||||
var latestKey = 0;
|
||||
var nextAttachId = 0;
|
||||
|
||||
this.getAttachId = function getAttachId() { return nextAttachId++; };
|
||||
|
||||
var messages = this.messages = {};
|
||||
var renderLater, cachedCollection;
|
||||
|
||||
this.render = function(collection) {
|
||||
collection = collection || {};
|
||||
|
||||
renderLater = false;
|
||||
cachedCollection = collection;
|
||||
|
||||
// this is true if the attribute is empty or if the attribute value is truthy
|
||||
var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
|
||||
isAttrTruthy($scope, $attrs.multiple);
|
||||
|
||||
var unmatchedMessages = [];
|
||||
var matchedKeys = {};
|
||||
var messageItem = ctrl.head;
|
||||
var messageFound = false;
|
||||
var totalMessages = 0;
|
||||
|
||||
// we use != instead of !== to allow for both undefined and null values
|
||||
while (messageItem != null) {
|
||||
totalMessages++;
|
||||
var messageCtrl = messageItem.message;
|
||||
|
||||
var messageUsed = false;
|
||||
if (!messageFound) {
|
||||
forEach(collection, function(value, key) {
|
||||
if (!messageUsed && truthy(value) && messageCtrl.test(key)) {
|
||||
// this is to prevent the same error name from showing up twice
|
||||
if (matchedKeys[key]) return;
|
||||
matchedKeys[key] = true;
|
||||
|
||||
messageUsed = true;
|
||||
messageCtrl.attach();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (messageUsed) {
|
||||
// unless we want to display multiple messages then we should
|
||||
// set a flag here to avoid displaying the next message in the list
|
||||
messageFound = !multiple;
|
||||
} else {
|
||||
unmatchedMessages.push(messageCtrl);
|
||||
}
|
||||
|
||||
messageItem = messageItem.next;
|
||||
}
|
||||
|
||||
forEach(unmatchedMessages, function(messageCtrl) {
|
||||
messageCtrl.detach();
|
||||
});
|
||||
|
||||
if (unmatchedMessages.length !== totalMessages) {
|
||||
$animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS);
|
||||
} else {
|
||||
$animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
|
||||
|
||||
// If the element is destroyed, proactively destroy all the currently visible messages
|
||||
$element.on('$destroy', function() {
|
||||
forEach(messages, function(item) {
|
||||
item.message.detach();
|
||||
});
|
||||
});
|
||||
|
||||
this.reRender = function() {
|
||||
if (!renderLater) {
|
||||
renderLater = true;
|
||||
$scope.$evalAsync(function() {
|
||||
if (renderLater && cachedCollection) {
|
||||
ctrl.render(cachedCollection);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.register = function(comment, messageCtrl) {
|
||||
var nextKey = latestKey.toString();
|
||||
messages[nextKey] = {
|
||||
message: messageCtrl
|
||||
};
|
||||
insertMessageNode($element[0], comment, nextKey);
|
||||
comment.$$ngMessageNode = nextKey;
|
||||
latestKey++;
|
||||
|
||||
ctrl.reRender();
|
||||
};
|
||||
|
||||
this.deregister = function(comment) {
|
||||
var key = comment.$$ngMessageNode;
|
||||
delete comment.$$ngMessageNode;
|
||||
removeMessageNode($element[0], comment, key);
|
||||
delete messages[key];
|
||||
ctrl.reRender();
|
||||
};
|
||||
|
||||
function findPreviousMessage(parent, comment) {
|
||||
var prevNode = comment;
|
||||
var parentLookup = [];
|
||||
|
||||
while (prevNode && prevNode !== parent) {
|
||||
var prevKey = prevNode.$$ngMessageNode;
|
||||
if (prevKey && prevKey.length) {
|
||||
return messages[prevKey];
|
||||
}
|
||||
|
||||
// dive deeper into the DOM and examine its children for any ngMessage
|
||||
// comments that may be in an element that appears deeper in the list
|
||||
if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) === -1) {
|
||||
parentLookup.push(prevNode);
|
||||
prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
|
||||
} else if (prevNode.previousSibling) {
|
||||
prevNode = prevNode.previousSibling;
|
||||
} else {
|
||||
prevNode = prevNode.parentNode;
|
||||
parentLookup.push(prevNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insertMessageNode(parent, comment, key) {
|
||||
var messageNode = messages[key];
|
||||
if (!ctrl.head) {
|
||||
ctrl.head = messageNode;
|
||||
} else {
|
||||
var match = findPreviousMessage(parent, comment);
|
||||
if (match) {
|
||||
messageNode.next = match.next;
|
||||
match.next = messageNode;
|
||||
} else {
|
||||
messageNode.next = ctrl.head;
|
||||
ctrl.head = messageNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeMessageNode(parent, comment, key) {
|
||||
var messageNode = messages[key];
|
||||
|
||||
var match = findPreviousMessage(parent, comment);
|
||||
if (match) {
|
||||
match.next = messageNode.next;
|
||||
} else {
|
||||
ctrl.head = messageNode.next;
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
function isAttrTruthy(scope, attr) {
|
||||
return (isString(attr) && attr.length === 0) || //empty attribute
|
||||
truthy(scope.$eval(attr));
|
||||
}
|
||||
|
||||
function truthy(val) {
|
||||
return isString(val) ? val.length : !!val;
|
||||
}
|
||||
}])
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngMessagesInclude
|
||||
* @restrict AE
|
||||
* @scope
|
||||
*
|
||||
* @description
|
||||
* `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
|
||||
* code from a remote template and place the downloaded template code into the exact spot
|
||||
* that the ngMessagesInclude directive is placed within the ngMessages container. This allows
|
||||
* for a series of pre-defined messages to be reused and also allows for the developer to
|
||||
* determine what messages are overridden due to the placement of the ngMessagesInclude directive.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <!-- using attribute directives -->
|
||||
* <ANY ng-messages="expression" role="alert">
|
||||
* <ANY ng-messages-include="remoteTplString">...</ANY>
|
||||
* </ANY>
|
||||
*
|
||||
* <!-- or by using element directives -->
|
||||
* <ng-messages for="expression" role="alert">
|
||||
* <ng-messages-include src="expressionValue1">...</ng-messages-include>
|
||||
* </ng-messages>
|
||||
* ```
|
||||
*
|
||||
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
||||
*
|
||||
* @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
|
||||
*/
|
||||
.directive('ngMessagesInclude',
|
||||
['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {
|
||||
|
||||
return {
|
||||
restrict: 'AE',
|
||||
require: '^^ngMessages', // we only require this for validation sake
|
||||
link: function($scope, element, attrs) {
|
||||
var src = attrs.ngMessagesInclude || attrs.src;
|
||||
$templateRequest(src).then(function(html) {
|
||||
if ($scope.$$destroyed) return;
|
||||
|
||||
if (isString(html) && !html.trim()) {
|
||||
// Empty template - nothing to compile
|
||||
replaceElementWithMarker(element, src);
|
||||
} else {
|
||||
// Non-empty template - compile and link
|
||||
$compile(html)($scope, function(contents) {
|
||||
element.after(contents);
|
||||
replaceElementWithMarker(element, src);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Helpers
|
||||
function replaceElementWithMarker(element, src) {
|
||||
// A comment marker is placed for debugging purposes
|
||||
var comment = $compile.$$createComment ?
|
||||
$compile.$$createComment('ngMessagesInclude', src) :
|
||||
$document[0].createComment(' ngMessagesInclude: ' + src + ' ');
|
||||
var marker = jqLite(comment);
|
||||
element.after(marker);
|
||||
|
||||
// Don't pollute the DOM anymore by keeping an empty directive element
|
||||
element.remove();
|
||||
}
|
||||
}])
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngMessage
|
||||
* @restrict AE
|
||||
* @scope
|
||||
*
|
||||
* @description
|
||||
* `ngMessage` is a directive with the purpose to show and hide a particular message.
|
||||
* For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
|
||||
* must be situated since it determines which messages are visible based on the state
|
||||
* of the provided key/value map that `ngMessages` listens on.
|
||||
*
|
||||
* More information about using `ngMessage` can be found in the
|
||||
* {@link module:ngMessages `ngMessages` module documentation}.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <!-- using attribute directives -->
|
||||
* <ANY ng-messages="expression" role="alert">
|
||||
* <ANY ng-message="stringValue">...</ANY>
|
||||
* <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
|
||||
* </ANY>
|
||||
*
|
||||
* <!-- or by using element directives -->
|
||||
* <ng-messages for="expression" role="alert">
|
||||
* <ng-message when="stringValue">...</ng-message>
|
||||
* <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
|
||||
* </ng-messages>
|
||||
* ```
|
||||
*
|
||||
* @param {expression} ngMessage|when a string value corresponding to the message key.
|
||||
*/
|
||||
.directive('ngMessage', ngMessageDirectiveFactory())
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngMessageExp
|
||||
* @restrict AE
|
||||
* @priority 1
|
||||
* @scope
|
||||
*
|
||||
* @description
|
||||
* `ngMessageExp` is the same as {@link directive:ngMessage `ngMessage`}, but instead of a static
|
||||
* value, it accepts an expression to be evaluated for the message key.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <!-- using attribute directives -->
|
||||
* <ANY ng-messages="expression">
|
||||
* <ANY ng-message-exp="expressionValue">...</ANY>
|
||||
* </ANY>
|
||||
*
|
||||
* <!-- or by using element directives -->
|
||||
* <ng-messages for="expression">
|
||||
* <ng-message when-exp="expressionValue">...</ng-message>
|
||||
* </ng-messages>
|
||||
* ```
|
||||
*
|
||||
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
||||
*
|
||||
* @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
|
||||
*/
|
||||
.directive('ngMessageExp', ngMessageDirectiveFactory());
|
||||
|
||||
function ngMessageDirectiveFactory() {
|
||||
return ['$animate', function($animate) {
|
||||
return {
|
||||
restrict: 'AE',
|
||||
transclude: 'element',
|
||||
priority: 1, // must run before ngBind, otherwise the text is set on the comment
|
||||
terminal: true,
|
||||
require: '^^ngMessages',
|
||||
link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
|
||||
var commentNode = element[0];
|
||||
|
||||
var records;
|
||||
var staticExp = attrs.ngMessage || attrs.when;
|
||||
var dynamicExp = attrs.ngMessageExp || attrs.whenExp;
|
||||
var assignRecords = function(items) {
|
||||
records = items
|
||||
? (isArray(items)
|
||||
? items
|
||||
: items.split(/[\s,]+/))
|
||||
: null;
|
||||
ngMessagesCtrl.reRender();
|
||||
};
|
||||
|
||||
if (dynamicExp) {
|
||||
assignRecords(scope.$eval(dynamicExp));
|
||||
scope.$watchCollection(dynamicExp, assignRecords);
|
||||
} else {
|
||||
assignRecords(staticExp);
|
||||
}
|
||||
|
||||
var currentElement, messageCtrl;
|
||||
ngMessagesCtrl.register(commentNode, messageCtrl = {
|
||||
test: function(name) {
|
||||
return contains(records, name);
|
||||
},
|
||||
attach: function() {
|
||||
if (!currentElement) {
|
||||
$transclude(function(elm, newScope) {
|
||||
$animate.enter(elm, null, element);
|
||||
currentElement = elm;
|
||||
|
||||
// Each time we attach this node to a message we get a new id that we can match
|
||||
// when we are destroying the node later.
|
||||
var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();
|
||||
|
||||
// in the event that the element or a parent element is destroyed
|
||||
// by another structural directive then it's time
|
||||
// to deregister the message from the controller
|
||||
currentElement.on('$destroy', function() {
|
||||
if (currentElement && currentElement.$$attachId === $$attachId) {
|
||||
ngMessagesCtrl.deregister(commentNode);
|
||||
messageCtrl.detach();
|
||||
}
|
||||
newScope.$destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
detach: function() {
|
||||
if (currentElement) {
|
||||
var elm = currentElement;
|
||||
currentElement = null;
|
||||
$animate.leave(elm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
function contains(collection, key) {
|
||||
if (collection) {
|
||||
return isArray(collection)
|
||||
? collection.indexOf(key) >= 0
|
||||
: collection.hasOwnProperty(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})(window, window.angular);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -187,7 +187,7 @@ input[type="password"], input[type="text"] {
|
|||
|
||||
|
||||
.radial-progress {
|
||||
$circle-size : 25px;
|
||||
$circle-size : 10px;
|
||||
$circle-background : #d6dadc;
|
||||
$circle-color : #97a71d;
|
||||
$transition-length : 0.5s;
|
||||
|
@ -210,7 +210,7 @@ input[type="password"], input[type="text"] {
|
|||
|
||||
@include transition(transform $transition-length);
|
||||
@include backface-visibility(hidden);
|
||||
|
||||
|
||||
}
|
||||
.mask {
|
||||
clip: rect(0px, $circle-size, $circle-size, $circle-size/2);
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
@import "bourbon/bourbon";
|
||||
$height: auto;
|
||||
body,html {
|
||||
min-height: 250px;
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
.md-content {
|
||||
height: 100%;
|
||||
max-height: $height;
|
||||
}
|
||||
|
||||
.addFab{
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
}
|
||||
.menu {
|
||||
padding: 0;
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
li {
|
||||
list-style-type: none;
|
||||
width: 100%;
|
||||
md-icon {
|
||||
margin-right: 16px;
|
||||
min-width: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
a {
|
||||
color: #000;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
display: block;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
padding: 0;
|
||||
padding-left: 16px;
|
||||
padding-right: 56px;
|
||||
text-decoration: none;
|
||||
clear: both;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-o-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
a:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.password-list {
|
||||
padding: 0;
|
||||
}
|
||||
/*/*/
|
||||
|
||||
|
||||
.radial-progress {
|
||||
$circle-size : 12px;
|
||||
$circle-background : #d6dadc;
|
||||
$circle-color : rgb(2,119,189);
|
||||
$transition-length : 0.5s;
|
||||
display: inline-block;
|
||||
|
||||
position: relative;
|
||||
width: $circle-size;
|
||||
height: $circle-size;
|
||||
|
||||
background-color: $circle-background;
|
||||
border-radius: 50%;
|
||||
.circle {
|
||||
.mask, .fill {
|
||||
width: $circle-size;
|
||||
height: $circle-size;
|
||||
position: absolute;
|
||||
|
||||
border-radius: 50%;
|
||||
|
||||
@include transition(transform $transition-length);
|
||||
@include backface-visibility(hidden);
|
||||
|
||||
}
|
||||
.mask {
|
||||
clip: rect(0px, $circle-size, $circle-size, $circle-size/2);
|
||||
.fill {
|
||||
clip: rect(0px, $circle-size/2, $circle-size, 0px);
|
||||
background-color: $circle-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ng-hide{
|
||||
display: none;
|
||||
}
|
||||
.unlock-container {
|
||||
height: 350px;
|
||||
|
||||
.unlock {
|
||||
padding: 20px;
|
||||
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
|
||||
md-input-container {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче