<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link data-require="bootstrap-css@3.2.0" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<link href="http://fonts.googleapis.com/css?family=Roboto:400,500,700,300,100" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="input.css" />
<link rel="stylesheet" href="checkbox.css" />
<script data-require="angular.js@1.3.0-beta.17" data-semver="1.3.0-beta.17" src="https://code.angularjs.org/1.3.0-beta.17/angular.js"></script>
<script data-require="ui-bootstrap@0.11.0" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<script src="script.js"></script>
<script type="text/ng-template" id="paperInput">
<div ng-form="inputForm">
<div class="group paper-input">
<input type="{{ type }}" ng-model="modelRef" name="modelName" ng-required="isRequired">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{ label }}</label>
</div>
<div>
</script>
<script type="text/ng-template" id="paperCheckbox">
<div ng-form="checkboxForm" id="check-awesome" class="form-group paper-checkbox">
<input type="checkbox" id="{{ idx }}" ng-model="model" name="modelName">
<label for="{{ idx }}" ng-click="invokeAnimation()">
<span></span>
<span class="check"></span>
<span class="box"></span>
{{ label }}
</label>
<div ng-transclude></div>
</div>
</script>
</head>
<body class="container-fluid" ng-controller="AppController as appCtrl">
<div class="container">
<h2>Google Material Design in CSS3 <small>Inputs</small>
</h2>
<section>
<form name="materialForm" novalidate="">
<paper-input label="Name" type="text" model-ref="appCtrl.user.name" required=""></paper-input>
<paper-input label="Email" type="email" model-ref="appCtrl.user.email"></paper-input>
<paper-input label="Number input" type="number" model-ref="appCtrl.user.age" required=""></paper-input>
<paper-input-date label="Date" type="text" model-ref="appCtrl.user.birth" date=""></paper-input-date>
<paper-checkbox idx="pc1" label="Notifications" model="appCtrl.user.checkMe">
<p>Notify me about how great I am every hour.</p>
</paper-checkbox>
<paper-checkbox idx="pc2" label="Check me" model="appCtrl.user.checkMe2">
<p>check me</p>
</paper-checkbox>
</form>
</section>
<hr />
<h4>Form model:</h4>
<pre class="pre-scrollable">{{ appCtrl.user | json }}</pre>
<p class="footer">
a <a href="http://scotch.io/tutorials/css/google-material-design-input-boxes-in-css3" target="_blank">tutorial</a>
by <a href="http://scotch.io" target="_blank">scotch.io</a>
</p>
</div>
</body>
</html>
// Code goes here
var app = angular.module('myApp', ['ui.bootstrap']);
function AppController() {
var appCtrl = this;
appCtrl.user = {
name: '',
email: '',
age: '',
birth: ''
};
}
function paperInput($templateCache) {
function linkFn(scope, element, attrs) {
scope.isRequired = angular.isDefined(attrs.required);
scope.isDatepicker = angular.isDefined(attrs.date);
scope.state = {
opened : false
};
if (scope.isDatepicker) {
scope.openDatePicker = function($event) {
// event.preventDefault(event);
// event.stopPropagation();
scope.state.opened = true;
};
}
}
return {
link: linkFn,
template: $templateCache.get('paperInput'),
scope: {
label: '@',
type: '@',
modelRef: '='
}
}
}
function paperInputDate($templateCache) {
function linkFn(scope, element, attrs) {
scope.isRequired = angular.isDefined(attrs.required);
scope.state = {
opened : false
};
scope.openDatePicker = function($event) {
event.preventDefault(event);
event.stopPropagation();
scope.state.opened = true;
};
}
return {
compile: function(tElement,tAttrs){
var groupEl = tElement[0].querySelector('.paper-input');
var input = tElement[0].querySelector('input')
// if(tAttrs.date){
groupEl.setAttribute('ng-click','openDatePicker($event)');
input.setAttribute('is-open','state.opened');
input.setAttribute('datepicker-popup','dd.MM.yyyy');
// }
return linkFn;
},
template:$templateCache.get('paperInput'),
scope: {
label: '@',
type: '@',
modelRef: '='
}
}
}
function paperCheckbox($templateCache) {
function linkFn(scope, element, attrs) {
var label = element.find('label');
var input = element.find('input');
scope.cssClass = '';
scope.animationDir = '';
scope.invokeAnimation = function() {
scope.cssClass = scope.cssClass === '' ? 'circle' : '';
scope.animationDir = scope.animationDir === '' ? true : !scope.animationDir
};
label.on('click', function(evt) {
// find the first span which is our circle/bubble
var el = angular.element(this).children().eq(0),
newone = null,
circleSpanElements = null;
// add the bubble class (we do this so it doesnt show on page load)
el.addClass('circle');
// clone it
newone = el.clone(true);
// add the cloned version before our original
el.after(newone);
// el[0].insertAdjacentHTML('beforebegin', newone[0]);
// remove the original so that it is ready to run on next click
circleSpanElements = label[0].querySelectorAll('.circle');
angular.element(circleSpanElements).eq(0).remove();
// scope.$apply(function(){});
});
}
return {
link: linkFn,
transclude: true,
template: $templateCache.get('paperCheckbox'),
scope: {
label: '@',
model: '=',
idx: '@'
}
}
}
app
.controller('AppController', AppController)
.directive('paperInput', paperInput)
.directive('paperInputDate', paperInputDate)
.directive('paperCheckbox', paperCheckbox);
body{ background-image:url(http://scotch.io/wp-content/uploads/2014/07/61.jpg); }
.container{
font-family:'Roboto';
width:600px;
margin:30px auto 0;
display:block;
background:#FFF;
padding:10px 50px 50px;
}
h2{
text-align:center;
margin-bottom:50px;
}
h2 > small{
font-weight:normal;
color:#888;
display:block;
}
.footer { text-align:center; }
.footer a { color:#53B2C8; }
/* basic css */
.paper-checkbox {
position: relative;
}
.paper-checkbox > input[type=checkbox] {
display: none;
}
.paper-checkbox > label,
.paper-checkbox p {
padding-left: 50px;
}
/* checkbox css */
.paper-checkbox > label {
cursor: pointer;
}
.paper-checkbox label > span {
display: block;
position: absolute;
left: 0;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
transition-duration: 0.3s;
}
.paper-checkbox label > .circle{
background-color: transparent;
left: -30px;
top: -30px;
height: 80px;
width: 80px;
/* z-index: -1; */
border-radius: 50%;
-webkit-animation: growCircle 0.3s ease;
-moz-animation: growCircle 0.3s ease;
animation: growCircle 0.3s ease;
}
.paper-checkbox label > .box {
border: 2px solid #000;
height: 20px;
width: 20px;
z-index: 888;
-webkit-transition-delay: 0.2s;
-moz-transition-delay: 0.2s;
transition-delay: 0.2s;
}
.paper-checkbox label > .check {
top: -7px;
left: 6px;
width: 12px;
height: 24px;
border: 2px solid #0f9d58;
border-top: none;
border-left: none;
opacity: 0;
z-index: 888;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
transform: rotate(180deg);
-webkit-transition-delay: 0.3s;
-moz-transition-delay: 0.3s;
transition-delay: 0.3s;
}
/* handling click events */
/* when checkbox is checked */
.paper-checkbox input[type=checkbox]:checked ~ label > .box {
opacity: 0;
-webkit-transform: scale(0) rotate(-180deg);
-moz-transform: scale(0) rotate(-180deg);
transform: scale(0) rotate(-180deg);
}
.paper-checkbox input[type=checkbox]:checked ~ label > .check {
opacity: 1;
-webkit-transform: scale(1) rotate(45deg);
-moz-transform: scale(1) rotate(45deg);
transform: scale(1) rotate(45deg);
}
/* bubble animation */
@-webkit-keyframes growCircle {
0%,
100% {
-webkit-transform: scale(0);
transform: scale(0);
}
70% {
opacity: 0.5;
background: #ddd;
-webkit-transform: scale(1.25);
transform: scale(1.25);
}
}
@-moz-keyframes growCircle {
0%,
100% {
-moz-transform: scale(0);
}
70% {
opacity: 0.5;
background: #DDD;
-moz-transform: scale(1.25);
}
}
@keyframes growCircle {
0%,
100% {
transform: scale(0);
}
70% {
opacity: 0.5;
background: #DDD;
transform: scale(1.25);
}
}
/* form starting stylings ------------------------------- */
.group {
position: relative;
margin-bottom: 45px;
}
.paper-input input {
font-size: 18px;
padding: 10px 10px 10px 5px;
display: block;
width: 300px;
border: none;
border-bottom: 1px solid #757575;
}
.paper-input input:focus {
outline: none;
}
/* LABEL ======================================= */
.paper-input label {
color: #999;
font-size: 18px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 5px;
top: 10px;
transition:0.2s ease all;
-moz-transition:0.2s ease all;
-webkit-transition:0.2s ease all;
}
/* active state */
.paper-input input:focus ~ label/*, input:valid ~ label*/,
.paper-input input.ng-dirty ~ label {
top: -20px;
font-size: 14px;
color: #5264AE;
}
/* BOTTOM BARS ================================= */
.bar { position:relative; display:block; width:300px; }
.bar:before, .bar:after {
content:'';
height:2px;
width:0;
bottom:1px;
position:absolute;
background:#5264AE;
transition:0.2s ease all;
-moz-transition:0.2s ease all;
-webkit-transition:0.2s ease all;
}
.bar:before {
left:50%;
}
.bar:after {
right:50%;
}
/* active state */
.paper-input input:focus ~ .bar:before,
.paper-input input:focus ~ .bar:after {
width:50%;
}
/* HIGHLIGHTER ================================== */
.highlight {
position:absolute;
height:60%;
width:225px;
top:25%;
left:0;
pointer-events:none;
opacity:0.5;
}
/* active state */
.paper-input input:focus ~ .highlight {
-webkit-animation:inputHighlighter 0.3s ease;
-moz-animation:inputHighlighter 0.3s ease;
animation:inputHighlighter 0.3s ease;
}
/* ANIMATIONS ================ */
@-webkit-keyframes inputHighlighter {
from { background:#5264AE; }
to { width:0; background:transparent; }
}
@-moz-keyframes inputHighlighter {
from { background:#5264AE; }
to { width:0; background:transparent; }
}
@keyframes inputHighlighter {
from { background:#5264AE; }
to { width:0; background:transparent; }
}
/* === VALIDATION ==== */
/* VALID */
.paper-input input.ng-valid.ng-dirty { border-bottom: 1px solid #4fc24f;}
.paper-input input.ng-valid.ng-dirty ~ .bar:before,
.paper-input input.ng-valid.ng-dirty ~ .bar:after{
background: #4fc24f !important;
}
.paper-input input.ng-valid.ng-dirty ~ label{
color: #4fc24f;
}
.paper-input input.ng-valid.ng-dirty:focus ~ .highlight {
-webkit-animation:validHighlighter 0.3s ease !important;
-moz-animation:validHighlighter 0.3s ease !important;
animation:validHighlighter 0.3s ease;
}
@-webkit-keyframes validHighlighter {
from { background:#4fc24f; }
to { width:0; background:transparent; }
}
@-moz-keyframes validHighlighter {
from { background:#4fc24f; }
to { width:0; background:transparent; }
}
@keyframes validHighlighter {
from { background:#4fc24f; }
to { width:0; background:transparent; }
}
/* INVALID */
.paper-input input.ng-invalid.ng-dirty{ border-bottom: 1px solid #d34336;}
.paper-input input.ng-invalid.ng-dirty ~ .bar:before,
.paper-input input.ng-invalid.ng-dirty ~ .bar:after{
background: #d34336 !important;
}
.paper-input input.ng-invalid.ng-dirty ~ label {
color: #d34336;
}
.paper-input input.ng-invalid.ng-dirty:focus ~ .highlight {
-webkit-animation:invalidHighlighter 0.3s ease;
-moz-animation:invalidHighlighter 0.3s ease;
animation:invalidHighlighter 0.3s ease;
}
@-webkit-keyframes invalidHighlighter {
from { background:#d34336; }
to { width:0; background:transparent; }
}
@-moz-keyframes invalidHighlighter {
from { background:#d34336; }
to { width:0; background:transparent; }
}
@keyframes invalidHighlighter {
from { background:#d34336; }
to { width:0; background:transparent; }
}