This commit is contained in:
brantje 2017-05-02 00:01:38 +02:00
Родитель 0ddca1061c
Коммит ea1eee056b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 5FF1D117F918687F
25 изменённых файлов: 6003 добавлений и 9942 удалений

Просмотреть файл

@ -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": {

Просмотреть файл

@ -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 {

88
css/material.css Normal file
Просмотреть файл

@ -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; }

7
css/vendor/angular-material.min.css поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

587
css/vendor/bootstrap-theme.css поставляемый
Просмотреть файл

@ -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 */

6757
css/vendor/bootstrap.css поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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>-->
<!--&lt;!&ndash;-->
<!--<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"-->
<!--&gt;<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>-->
<!--&lt;!&ndash; <a class="btn btn-success pull-right"-->
<!--&gt;Donate</a> &ndash;&gt;-->
<!--</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>

Двоичные данные
icons/Passman_Color_Horizontal.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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);
}
}
};
}

4154
js/vendor/angular-animate/angular-animate.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

402
js/vendor/angular-aria/angular-aria.js поставляемый Normal file
Просмотреть файл

@ -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);

17
js/vendor/angular-material/angular-material.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

739
js/vendor/angular-messages/angular-messages.js поставляемый Normal file
Просмотреть файл

@ -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);

2377
js/vendor/bootstrap/bootstrap.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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);

115
style/material.scss Normal file
Просмотреть файл

@ -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;
}
}
}