<!DOCTYPE html>
<html ng-app="ngMailChimp">

<head>
  <link data-require="bootstrap@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
  <script data-require="angular.js@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
  <script data-require="angular-messages@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular-messages.js"></script>
  <script data-require="angular-animate@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular-animate.js"></script>
  <script data-require="angular-aria@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular-aria.js"></script>
  <link rel="stylesheet" href="style.css" />
  <link rel="stylesheet" href="animations.css" />
  <script src="script.js"></script>
</head>

<body ng-controller="SignUpController as ctrl">
  <div class="signup-wrapper">
    <div class="logo">
      <img src="http://i.imgur.com/SbhUmwh.png" alt="Logo" />
    </div>
    <div class="alert alert-success message-animation" role="alert" ng-if="ctrl.showSubmittedPrompt">
      Thank you! Your account has been created.
    </div>
    <form name="ctrl.signupForm" ng-submit="ctrl.signup()" novalidate>
      <div class="form-group" ng-class="{'has-error':ctrl.hasErrorClass('email')}">
        <label for="email">Email</label>
        <input id="email" name="email" class="form-control" type="email" required ng-model="ctrl.newCustomer.email" ng-model-options="{ updateOn : 'default blur' }" ng-focus="ctrl.toggleEmailPrompt(true)" ng-blur="ctrl.toggleEmailPrompt(false)" />


        <div class="my-messages">
          <div class="prompt message-animation" ng-if="ctrl.showEmailPrompt">
            What's your email address?
          </div>
        </div>

        <div class="my-messages" ng-messages="ctrl.signupForm.email.$error" ng-if="ctrl.showMessages('email')">
          <div class="message-animation" ng-message="required">
            <strong>This field is required.</strong>
          </div>
          <div class="message-animation" ng-message="email">
            <strong>Please format your email correctly.</strong>
          </div>
        </div>

      </div>
      <div class="form-group" ng-class="{'has-error':ctrl.hasErrorClass('userName')}">
        <label for="userName">Username</label>
        <input id="userName" name="userName" class="form-control" type="text" required ng-model="ctrl.newCustomer.userName" ng-model-options="{ updateOn : 'default blur' }" ng-focus="ctrl.toggleUsernamePrompt(true)" ng-blur="ctrl.toggleUsernamePrompt(false)"
        />

        <div class="my-messages">
          <div class="prompt message-animation" ng-if="ctrl.showUsernamePrompt">
            Choose a username that contains only letters and numbers, or use your email address.
          </div>
        </div>

        <div class="my-messages" ng-messages="ctrl.signupForm.userName.$error" ng-if="ctrl.showMessages('userName')">
          <div class="message-animation" ng-message="required">
            <strong>This field is required.</strong>
          </div>
        </div>

      </div>
      <div class="form-group">
        <label for="password">Password</label>

        <div class="input-group" ng-class="{'has-error':ctrl.hasErrorClass('password')}">
          <input id="password" name="password" class="form-control" required type="{{ctrl.getPasswordType()}}" ng-model-options="{ updateOn : 'default blur' }" ng-model="ctrl.newCustomer.password" validate-password-characters/>
          <span class="input-group-addon">
                            <input type="checkbox" ng-model="ctrl.signupForm.showPassword"> Show
                        </span>
        </div>

        <div class="my-messages" ng-messages="ctrl.signupForm.password.$error" ng-if="ctrl.showMessages('password')">
          <div class="message-animation" ng-message="required">
            <strong>This field is required.</strong>
          </div>
        </div>

        <div class="password-requirements" ng-if="!ctrl.signupForm.password.$valid">
          <ul class="float-left">
            <li ng-class="{'completed':!ctrl.signupForm.password.$error.lowerCase}">One lowercase character</li>
            <li ng-class="{'completed':!ctrl.signupForm.password.$error.upperCase}">One uppercase character</li>
            <li ng-class="{'completed':!ctrl.signupForm.password.$error.number}">One number</li>
          </ul>
          <ul class="selfclear clearfix">
            <li ng-class="{'completed':!ctrl.signupForm.password.$error.specialCharacter}">One special character</li>
            <li ng-class="{'completed':!ctrl.signupForm.password.$error.eightCharacters}">Eight characters minimum</li>
          </ul>
        </div>

        <div class="alert alert-success message-animation" role="alert" ng-if="ctrl.signupForm.password.$valid">
          Your password is secure and you are good to go!
        </div>
      </div>

      <button class="btn btn-primary" type="submit">Create My Account</button>
    </form>
  </div>
</body>

</html>
angular.module('ngMailChimp', ['ngAria', 'ngMessages', 'ngAnimate'])
    .controller('SignUpController', function () {
        var ctrl = this,
            newCustomer = { email:'', userName:'', password:'' };

        var signup = function () {
            if( ctrl.signupForm.$valid) {
                ctrl.showSubmittedPrompt = true;
                clearForm();
            }
        };

        var clearForm = function () {
            ctrl.newCustomer = { email:'', userName:'', password:'' }
            ctrl.signupForm.$setUntouched();
            ctrl.signupForm.$setPristine();
        };

        var getPasswordType = function () {
            return ctrl.signupForm.showPassword ? 'text' : 'password';
        };

        var toggleEmailPrompt = function (value) {
            ctrl.showEmailPrompt = value;
        };

        var toggleUsernamePrompt = function (value) {
            ctrl.showUsernamePrompt = value;
        };

        var hasErrorClass = function (field) {
            return ctrl.signupForm[field].$touched && ctrl.signupForm[field].$invalid;
        };

        var showMessages = function (field) {
            return ctrl.signupForm[field].$touched || ctrl.signupForm.$submitted
        };

        ctrl.showEmailPrompt = false;
        ctrl.showUsernamePrompt = false;
        ctrl.showSubmittedPrompt = false;
        ctrl.toggleEmailPrompt = toggleEmailPrompt;
        ctrl.toggleUsernamePrompt = toggleUsernamePrompt;
        ctrl.getPasswordType = getPasswordType;
        ctrl.hasErrorClass = hasErrorClass;
        ctrl.showMessages = showMessages;
        ctrl.newCustomer = newCustomer;
        ctrl.signup = signup;
        ctrl.clearForm = clearForm;
    })
    .directive('validatePasswordCharacters', function () {
        return {
            require: 'ngModel',
            link: function ($scope, element, attrs, ngModel) {
                ngModel.$validators.lowerCase = function (value) {
                    var pattern = /[a-z]+/;
                    return (typeof value !== 'undefined') && pattern.test(value);
                };
                ngModel.$validators.upperCase = function (value) {
                    var pattern = /[A-Z]+/;
                    return (typeof value !== 'undefined') && pattern.test(value);
                };
                ngModel.$validators.number = function (value) {
                    var pattern = /\d+/;
                    return (typeof value !== 'undefined') && pattern.test(value);
                };
                ngModel.$validators.specialCharacter = function (value) {
                    var pattern = /\W+/;
                    return (typeof value !== 'undefined') && pattern.test(value);
                };
                ngModel.$validators.eightCharacters = function (value) {
                    return (typeof value !== 'undefined') && value.length >= 8;
                };
            }
        }
    })
;
body {
    background-color: #f9f9f9;
}

.signup-wrapper {
    top: 36px;
    max-width: 430px;
    min-width: 320px;
    margin-left: auto;
    margin-right: auto;
}

.signup-wrapper .alert {
    margin-top: 10px;
}

.signup-wrapper input[text] {
    padding: 0 .4em 0 .4em;
    margin-bottom: 2em;
    vertical-align: middle;
    border-radius: 3px;
    min-width: 50px;
    max-width: 550px;
    width: 100%;
    min-height: 36px;
    background-color: #fff;
    border: 3px solid #c9c9c9 !important;
}

.signup-wrapper label {
    color: #595959;
    font-weight: 500;
    display: block;
    max-width: 550px;
    padding-bottom: .4em;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
    font-size: 15px;
    line-height: 18px;
}

.prompt {
    margin-top: 10px;
    white-space: normal;
    word-wrap: break-word;
    width: 100%;
    max-width: 550px;
    position: relative;
    color: #959595;
}

.logo {
    position: relative;
    height: 46px;
    width: 320px;
    margin-left: auto;
    margin-right: auto;
    margin-top: 80px;
    margin-bottom: 30px;
    z-index: 1;
}

.float-left {
    float: left;
}

.password-requirements {
    margin-top: 10px;
}

.password-requirements .selfclear {
    margin-left: 20px;
}

.password-requirements ul {
    list-style: none;
    padding-left: 0px;
}

.password-requirements ul:first-child {
    margin-right: 15px;
}

.password-requirements ul li:before {
    position: relative;
    top: -1px;
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-left: 6px;
    margin-right: 10px;
    border-radius: 8px;
    background: #52bad5;
}

.password-requirements ul li.completed {
    opacity: .5;
}

.btn-primary {
    color: #fff !important;
    padding: 10px 30px !important;
    background-color: #40A3FD !important;
    border-color: #0086FC;
}

.btn-primary:hover {
    background-color: #4F94D3 !important;
}


div[ng-messages] {
    margin-top: 10px;
    white-space: normal;
    word-wrap: break-word;
    width: 100%;
    max-width: 550px;
    position: relative;
    color: #FF0000;
}
Animations with AngularJS Example One
==============

This is an example of a MailChimp style signup form built with AngularJS. 

#Challenge#
1. Create a new CSS file called ```workshop.css``` and add a reference to it in ```index.html```
2. Change the ```message-animation``` class references in ```index.html``` to ```workshop-animation```
3. Using ```animations.css``` as a reference, build out the ```workshop-animation``` classes to fade messages in and out

#Bonus#
Animate an addtional property to make the animation more interesting

Resources
========================

One Hungry Mind
http://onehungrymind.com/

Year of Moo
http://www.yearofmoo.com/

Greensock
http://www.greensock.com/
.my-messages {
    position: relative;
}

.message-animation {
    transition: 0.2s ease-in-out all;
}

.message-animation.ng-enter.ng-enter-active {
    opacity: 1;
    margin-top: 0;
}

.message-animation.ng-enter {
    opacity: 0;
    margin-top: -20px;
}

.message-animation.ng-leave {
    opacity: 1;
    margin-top: 0;
}

.message-animation.ng-leave-active {
    opacity: 0;
    margin-top: -20px;
}