<body ng-app="ThankfulApp" ng-cloak layout="column">
<div ng-controller="MainCtrl as mCtrl" layout="column">
<div class="content-container" layout="column">
<div class="home" layout="column" ng-show="!mCtrl.trending" md-theme="t9" md-theme-watch ng-controller="HomeCtrl as homeCtrl">
<md-toolbar>
<div class="md-toolbar-tools">
<div class="ripple-dark thankful-icon" style="margin: 4px;padding: 4px;width:42px;"><img height="30" style="transform: translate3d(2px,3px,0);" src="data:image/svg+xml;base64,Cgk8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+CgoKCQk8ZGVmcz4KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJHcmFkaWVudF8yIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwIiB5MT0iMCIgeDI9IjUwIiB5Mj0iNDAiIHNwcmVhZE1ldGhvZD0icGFkIj4KCQkJPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI0ZGRkZGRiIgc3RvcC1vcGFjaXR5PSIwLjIiLz4KCQkJPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjRkZGRkZGIi8+CgkJPC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkdyYWRpZW50XzMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iOTAiIHkxPSI1MyIgeDI9IjQ1IiB5Mj0iMjAiIHNwcmVhZE1ldGhvZD0icGFkIj4KCQkJPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI0ZGRkZGRiIgc3RvcC1vcGFjaXR5PSIwLjIiLz4KCQkJPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjRkZGRkZGIi8+CgkJPC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkdyYWRpZW50XzQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMTAiIHkxPSIyMCIgeDI9IjU1IiB5Mj0iNTMiIHNwcmVhZE1ldGhvZD0icGFkIj4KCQkJPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI0ZGRkZGRiIgc3RvcC1vcGFjaXR5PSIwLjIiLz4KCQkJPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjRkZGRkZGIi8+CgkJPC9saW5lYXJHcmFkaWVudD48ZyBpZD0iYmFja2dyb3VuZCI+CgkJCTxwYXRoIGZpbGw9InVybCgjYmFja2dyb3VuZC1ncmFkaWVudCkiIHN0cm9rZT0ibm9uZSIgZD0iIE0gOTYuMDUgMzAuNiBRIDkyLjI1IDIxLjYgODUuMzUgMTQuNyA3OC40NSA3Ljc1IDY5LjQ1IDMuOTUgNjAuMTUgMCA1MCAwIDM5Ljg1IDAgMzAuNTUgMy45NSAyMS42IDcuNzUgMTQuNyAxNC43IDcuNzUgMjEuNiAzLjk1IDMwLjYgMCAzOS45IDAgNTAgMCA2MC4xNSAzLjk1IDY5LjQ1IDcuNzUgNzguNDUgMTQuNyA4NS4zNSAyMS42IDkyLjI1IDMwLjU1IDk2LjEgMzkuODUgMTAwIDUwIDEwMCA2MC4xNSAxMDAgNjkuNDUgOTYuMSA3OC40NSA5Mi4yNSA4NS4zNSA4NS4zNSA5Mi4yNSA3OC40NSA5Ni4wNSA2OS40NSAxMDAgNjAuMTUgMTAwIDUwIDEwMCAzOS45IDk2LjA1IDMwLjYgTSA4Mi4yIDE3Ljg1IFEgODguNSAyNC4xNSA5MS45NSAzMi4zIDk1LjU1IDQwLjggOTUuNTUgNTAgOTUuNTUgNTkuMjUgOTEuOTUgNjcuNzUgODguNSA3NS45IDgyLjIgODIuMiA3NS44NSA4OC41IDY3Ljc1IDkxLjk1IDU5LjI1IDk1LjU1IDUwIDk1LjU1IDQwLjggOTUuNTUgMzIuMyA5MS45NSAyNC4xNSA4OC41IDE3Ljg1IDgyLjIgMTEuNTUgNzUuOSA4LjEgNjcuNzUgNC41IDU5LjI1IDQuNSA1MCA0LjUgNDAuOCA4LjEgMzIuMyAxMS41IDI0LjE1IDE3Ljg1IDE3Ljg1IDI0LjE1IDExLjU1IDMyLjMgOC4xIDQwLjggNC41IDUwIDQuNSA1OS4yNSA0LjUgNjcuNzUgOC4xIDc1Ljg1IDExLjU1IDgyLjIgMTcuODUgWiIvPgoJCTwvZz48bWFzayBpZD0ibWFzayI+CgkJCTxwYXRoIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgZD0iIE0gOTEuOTUgMzIuMyBRIDg4LjUgMjQuMTUgODIuMiAxNy44NSA3NS44NSAxMS41NSA2Ny43NSA4LjEgNTkuMjUgNC41IDUwIDQuNSA0MC44IDQuNSAzMi4zIDguMSAyNC4xNSAxMS41NSAxNy44NSAxNy44NSAxMS41IDI0LjE1IDguMSAzMi4zIDQuNSA0MC44IDQuNSA1MCA0LjUgNTkuMjUgOC4xIDY3Ljc1IDExLjU1IDc1LjkgMTcuODUgODIuMiAyNC4xNSA4OC41IDMyLjMgOTEuOTUgNDAuOCA5NS41NSA1MCA5NS41NSA1OS4yNSA5NS41NSA2Ny43NSA5MS45NSA3NS44NSA4OC41IDgyLjIgODIuMiA4OC41IDc1LjkgOTEuOTUgNjcuNzUgOTUuNTUgNTkuMjUgOTUuNTUgNTAgOTUuNTUgNDAuOCA5MS45NSAzMi4zIFoiLz4KCQk8L21hc2s+PGcgaWQ9Imdsb3NzLXRvcCI+CgkJCTxwYXRoIGZpbGw9InVybCgjR3JhZGllbnRfMikiIHN0cm9rZT0ibm9uZSIgZD0iIE0gOTkuNSA0Mi43NSBRIDk4LjE1IDMzLjggOTMuOCAyNS44NSA4OS41NSAxOC4xNSA4Mi44NSAxMi4zNSA3Ni4xNSA2LjUgNjcuODUgMy4zIDU5LjI1IDAgNTAgMCA0MC44IDAgMzIuMiAzLjMgMjMuOSA2LjUgMTcuMiAxMi4zNSAxMC41IDE4LjE1IDYuMiAyNS44NSAxLjg1IDMzLjggMC41NSA0Mi43NSAyLjM1IDQ1Ljc1IDQuNTUgNDguNSA0LjggMzkuNDUgOC41IDMxLjM1IDEyLjA1IDIzLjQgMTguMzUgMTcuMzUgMjQuNiAxMS4yNSAzMi42NSA3Ljk1IDQxIDQuNSA1MCA0LjUgNTkuMDUgNC41IDY3LjQgNy45NSA3NS40IDExLjI1IDgxLjY1IDE3LjM1IDg3Ljk1IDIzLjQgOTEuNSAzMS4zNSA5NS4yIDM5LjQ1IDk1LjUgNDguNSA5Ny42NSA0NS43NSA5OS41IDQyLjc1IFoiLz4KCQk8L2c+PGcgaWQ9Imdsb3NzLXJpZ2h0Ij4KCQkJPHBhdGggZmlsbD0idXJsKCNHcmFkaWVudF8zKSIgc3Ryb2tlPSJub25lIiBkPSIgTSA5NiAzMC42IFEgOTIuMiAyMS42IDg1LjI1IDE0LjcgNzguMyA3Ljc1IDY5LjQgMy45NSA2MC4xIDAgNDkuOSAwIDM3LjQ1IDAgMjYuNSA1Ljg1IDE1LjkgMTEuNSA5IDIxLjM1IEwgMTIuNSAyNC4yIFEgMTguOCAxNS4xIDI4LjUgOS45IDM4LjUgNC41IDQ5LjkgNC41IDU5LjIgNC41IDY3LjYgOC4xIDc1LjggMTEuNTUgODIuMSAxNy44NSA4OC40IDI0LjE1IDkxLjkgMzIuMyA5NS40NSA0MC44IDk1LjQ1IDUwIDk1LjQ1IDU4LjY1IDkyLjMgNjYuNjUgODkuMjUgNzQuNCA4My42NSA4MC41NSBMIDg3LjE1IDgzLjM1IFEgOTMuMjUgNzYuNTUgOTYuNSA2OC4xNSA5OS45IDU5LjQ1IDk5LjkgNTAgOTkuOSAzOS45IDk2IDMwLjYgWiIvPgoJCTwvZz48ZyBpZD0iZ2xvc3MtbGVmdCI+CgkJCTxwYXRoIGZpbGw9InVybCgjR3JhZGllbnRfNCkiIHN0cm9rZT0ibm9uZSIgZD0iIE0gODcuNDUgMjQuMiBMIDkxIDIxLjM1IFEgODQuMDUgMTEuNSA3My41IDUuODUgNjIuNSAwIDUwIDAgMzkuODUgMCAzMC41NSAzLjk1IDIxLjYgNy43NSAxNC43IDE0LjcgNy43NSAyMS42IDMuOTUgMzAuNiAwIDM5LjkgMCA1MCAwIDU5LjQ1IDMuNCA2OC4xNSA2LjcgNzYuNTUgMTIuNzUgODMuMzUgTCAxNi4zIDgwLjU1IFEgMTAuNjUgNzQuNCA3LjY1IDY2LjY1IDQuNSA1OC42NSA0LjUgNTAgNC41IDQwLjggOC4xIDMyLjMgMTEuNSAyNC4xNSAxNy44NSAxNy44NSAyNC4xNSAxMS41NSAzMi4zIDguMSA0MC44IDQuNSA1MCA0LjUgNjEuNDUgNC41IDcxLjQ1IDkuOSA4MS4xNSAxNS4xIDg3LjQ1IDI0LjIgWiIvPgoJCTwvZz4KCQkJCgk8bGluZWFyR3JhZGllbnQgaWQ9ImJhY2tncm91bmQtZ3JhZGllbnQiIHgxPSIwIiB5MT0iMCIgeTI9IjEiIHgyPSIwIiA+CgkJPHN0b3Agc3RvcC1jb2xvcj0iI2ZmZmZmZiIgb2Zmc2V0PSIwJSIvPgoJCTxzdG9wIHN0b3AtY29sb3I9IiNmZmZmZmYiIG9mZnNldD0iMTAwJSIvPgoJPC9saW5lYXJHcmFkaWVudD4KCgkJCQoJCQkKCQkJPGcgdHJhbnNmb3JtPSJzY2FsZSgwLjk5NjU1MTc3MjExNjAyOTUpIHRyYW5zbGF0ZSgtOTkuODI3MDAzNDc5MDAzOSAtOTkuODI3MDAzNDc5MDAzOSkiIGlkPSJwaWN0dXJlIj48cGF0aCBkPSJNMTI5LjkzIDEyMC41ODhoMTguNjg2di0xOS4wMzFjLTcuNjEzIDEuMDM4LTE0LjUzMyA4LjMwNS0xOC42ODUgMTkuMDMxem0xOC42ODYgMjcuNjgydi0yNC4yMjJoLTIwLjA3Yy0yLjQyMSA2LjkyLTMuODA2IDE1LjIyNS00LjE1MiAyNC4yMjJoMjQuMjIyem0yNy42ODIgMGMwLTguOTk3LTEuNzMtMTcuMzAxLTQuMTUzLTI0LjIyMmgtMjAuMDY5djI0LjIyMmgyNC4yMjJ6bS0yNC4yMjItNDYuNzEzdjE5LjAzMWgxOC42ODVjLTQuMTUyLTEwLjcyNi0xMS4wNzItMTcuOTkzLTE4LjY4NS0xOS4wMzF6bTI0LjU2OCA3MC45MzRoMTguMzM5YzMuMTE0LTYuMjI4IDUuMTktMTMuMTQ4IDUuMTktMjAuNzZoLTIwLjc2MWMwIDcuMjY1LTEuMDM4IDE0LjUzMi0yLjc2OCAyMC43NnptLTI4LjAyOC0yMC43NmgtMjQuMjIyYzAgNy42MTIgMS4wMzkgMTQuNTMyIDIuNzY5IDIwLjc2aDIxLjEwN3YtMjAuNzZoLjM0NnptLTI4LjAyOC0zLjQ2MWMwLTguNjUgMS43My0xNi45NTUgMy44MDYtMjQuMjIyaC0xNy4zYy00LjQ5OSA3LjI2Ny02LjkyMSAxNS4yMjUtNy4yNjcgMjQuMjIyaDIwLjc2MXptMCAzLjQ2SDk5LjgyN2MuMzQ2IDcuNjEzIDIuMDc2IDE0LjUzMyA1LjE5IDIwLjc2MWgxOC4zNGMtMS4zODUtNi4yMjgtMi40MjMtMTMuNDk1LTIuNzY5LTIwLjc2em00LjE1MiAyNC4yMjJoLTE3LjNjNy4yNjYgMTIuMTEgMTkuMzc3IDIwLjc2IDMzLjU2MyAyMy4xODMtNi45Mi0zLjgwNi0xMi44MDItMTIuMTEtMTYuMjYzLTIzLjE4M3ptMS4wMzktNTUuMzY0YzMuNDYtOS4zNDIgOC45OTYtMTYuMjYzIDE1LjIyNC0xOS43MjMtMTMuMTQ4IDIuMDc2LTI0LjIyMSA5LjY4OS0zMS40ODcgMTkuNzIzaDE2LjYwOS0uMzQ2em00OS44MjcgNTUuMzY0Yy0zLjQ2IDExLjA3Mi05LjM0MyAxOS4zNzctMTYuMjYzIDIzLjE4MyAxNC4xODYtMi43NjggMjYuMjk3LTExLjQxOSAzMy41NjQtMjMuMTgzaC0xNy4zMDF6bS0yNi45OSAyMi40OXYtMjIuNDloLTIwLjA3YzQuMTUzIDEyLjgwMiAxMS43NjUgMjEuMTA3IDIwLjA3IDIyLjQ5em0yNS45NTItNzcuODU0aDE2LjI2M2MtNy4yNjctMTAuMDM0LTE4LjY4Ni0xNy42NDctMzEuNDg4LTE5LjcyMyA2LjIyOCAzLjQ2IDExLjQxOCAxMC4zOCAxNS4yMjUgMTkuNzIzem0xLjAzOCAzLjQ2YzIuNDIyIDcuMjY3IDMuODA2IDE1LjU3MSAzLjgwNiAyNC4yMjJoMjAuNzYxYy0uMzQ2LTguOTk3LTIuNzY4LTE2Ljk1NS03LjI2Ni0yNC4yMjJoLTE3LjMwMXptLTMuNDYgNTEuOTA0aC0yMC4wN3YyMi40OWM4LjMwNS0xLjM4MyAxNS45MTctOS42ODggMjAuMDctMjIuNDl6bS0yMC4wNy0yNC4yMjJ2MjAuNzYxaDIxLjEwN2MxLjczLTYuMjI4IDIuNzY5LTEzLjE0OCAyLjc2OS0yMC43NmgtMjMuODc2eiIvPjwvZz4KCQkJCgk8bGluZWFyR3JhZGllbnQgaWQ9InBpY3R1cmUtZ3JhZGllbnQiIHgxPSIwIiB5MT0iMCIgeTI9IjEiIHgyPSIwIiA+CgkJPHN0b3Agc3RvcC1jb2xvcj0iI2ZmZmZmZiIgb2Zmc2V0PSIwJSIvPgoJCTxzdG9wIHN0b3AtY29sb3I9IiNmZmZmZmYiIG9mZnNldD0iMTAwJSIvPgoJPC9saW5lYXJHcmFkaWVudD4KCgkJPC9kZWZzPgoKCQkKCgkJCTx1c2UgeGxpbms6aHJlZj0iI2JhY2tncm91bmQiIGZpbGw9InVybCgjYmFja2dyb3VuZC1ncmFkaWVudCkiIC8+CgoJCQoKCQkJPGcgbWFzaz0idXJsKCNtYXNrKSI+CgkJCQk8ZyB0cmFuc2Zvcm09IgoJCQkJICAgICAgICB0cmFuc2xhdGUoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNTAgNTAKKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlKDAgMCkgIHNjYWxlKDAuNzUpICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtNTAgLTUwCikiPgoJCQkJCQk8dXNlIHhsaW5rOmhyZWY9IiNwaWN0dXJlIiBmaWxsPSJ1cmwoI3BpY3R1cmUtZ3JhZGllbnQpIiAgLz4KCQkJCTwvZz4KCQkJPC9nPgoKCQkKCgkJCTx1c2UgeGxpbms6aHJlZj0iI2dsb3NzLXRvcCIgb3BhY2l0eT0iMSIgLz4KCgoJPC9zdmc+Cg=="/></div>
<div>Be Thankful!</div>
<span flex></span>
<div>
<md-button class="md-button md-primary fa-icon ripple-light" aria-label="menu" md-no-ink ng-click="mCtrl.trending = !mCtrl.trending">
<i class="fa fa-fire fa-lg" aria-hidden="true"></i>
</md-button>
<div class="badge" ng-show="homeCtrl.getLocalData().newThankfuls > 0">{{homeCtrl.getLocalData().newThankfuls}}</div>
</div>
</div>
</md-toolbar>
<md-whiteframe class="md-padding md-whiteframe-z2 thankful-input-container">
<form ng-submit="homeCtrl.addThankful()" flex layout="row" layout-align="center center">
<md-input-container flex>
<label>I am thankful for...</label>
<input ng-model="homeCtrl.thankfulMessage" id="thanksfulYo" md-maxlength="120" />
</md-input-container>
<md-button class="md-raised md-primary fa-icon ripple-light" ng-click="homeCtrl.addThankful()" aria-label="add thankful item" md-no-ink>
<i class="fa fa-plus fa-lg" aria-hidden="true"></i>
</md-button>
</form>
</md-whiteframe>
<md-content class="thankful-container" layout="row" layout-wrap layout-align="start stretch">
<md-whiteframe ng-repeat="thankfulItem in homeCtrl.userThankfulList track by thankfulItem.id" flex-sm="100" flex-md="100"
flex-gt-sm="noshrink" class="ripple-dark thankful-item md-whiteframe-z2" layout="column" layout-align="center center" layout-margin style="background: {{::mCtrl.helperUtils.getThankfulColor(thankfulItem)}}">
<span class="thankful-item-content">{{thankfulItem.message}}</span>
<div class="author" layout-padding>
- {{thankfulItem.author}} ({{thankfulItem.created | date}})
</div>
<md-button class="ripple-dark delete-button" aria-label="remove thankful item" md-no-ink ng-click="homeCtrl.deleteThankful(thankfulItem, $event)">
<i class="fa fa-times fa" aria-hidden="true"></i>
</md-button>
</md-whiteframe>
</md-content>
</div>
<div class="app-state-container" ng-show="mCtrl.trending" md-theme="t1" md-theme-watch layout="column" ng-controller="TrendingCtrl as trendCtrl">
<md-toolbar>
<div class="md-toolbar-tools">
<span>What others are thankful for!</span>
<span flex></span>
<md-button class="md-button md-primary fa-icon ripple-light" aria-label="menu" md-no-ink ng-click="trendCtrl.moveToHome(mCtrl)">
<i class="fa fa-times fa-lg" aria-hidden="true" layout-align="center center" layout-fill></i>
</md-button>
</div>
</md-toolbar>
<md-whiteframe class="md-padding md-whiteframe-z2 thankful-input-container">
<div class="md-subhead">Tap on a thankful card to add it to your list or tap on the banner to like the card.</div>
<div layout-fill layout="row">
<md-input-container flex>
<md-select ng-model="trendCtrl.filter" aria-label="filter what others are grateful for">
<md-option ng-repeat="filter in ['Recent', 'Trending today', 'Trending this week', 'Trending this month', 'Trending all time']" value="{{filter}}">
{{filter}}
</md-option>
</md-select>
</md-input-container>
</div>
</md-whiteframe>
<md-content class="thankful-container" layout="row" layout-wrap layout-align="start stretch">
<md-whiteframe ng-repeat="thankfulItem in trendCtrl.list | limitTo:20 track by thankfulItem.id" flex-sm="100" flex-md="100" flex-gt-sm="noshrink" class="thankful-item md-whiteframe-z2 ripple-card" layout="column" layout-align="center center"
layout-margin ng-click="trendCtrl.addToUserThankfuls(thankfulItem)" style="background: {{::mCtrl.helperUtils.getThankfulColor(thankfulItem)}};">
<md-button class="like-button ripple-dark md-button md-raised md-accent {{ trendCtrl.likedThankfuls[thankfulItem.id] ? 'liked' : '' }}" md-no-ink ng-click="trendCtrl.likeThankful(thankfulItem)" aria-label="like thankful item">
<div class="like-p0">{{thankfulItem.likes}}</div>
<div class="like-p1">
<div class="animated like-p2">
<i class="fa fa-smile-o fa-lg like-micro-interaction animated" aria-hidden="true"></i>
</div>
</div>
</md-button>
<span class="thankful-item-content">"{{thankfulItem.message}}"</span>
<div class="author" layout-padding>
- {{thankfulItem.author}} ({{thankfulItem.created | date}})
</div>
</md-whiteframe>
</md-content>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-messages.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.11/ngStorage.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.js"></script>
<script src="https://cdn.rawgit.com/fians/Waves/master/dist/waves.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
</body>
body {
overflow-x: hidden;
}
div {
position: relative;
}
.waves-button {
font-size: inherit;
}
md-input-container .md-char-counter {
bottom: -12px;
}
.md-toolbar-tools {
color: white;
}
.fa-icon > .fa {
line-height: 2.35em;
vertical-align: 0;
}
.md-button.fa-icon {
min-width: 3em;
min-height: 3em;
max-height: 3em;
}
md-input-container {
margin-bottom: 8px !important;
}
.thankful-item {
transition: all linear 300ms;
font-size: 2em;
position: relative;
display: flex;
min-width: 200px;
min-height: 200px;
border-radius: 3px;
color: white;
background-color: rgba(0,0,0,.1);
width: 100%;
}
.thankful-item.ng-enter, {
animation: zoomOut 400ms;
}
.thankful-item.ng-enter.ng-enter-active {
animation: zoomIn 400ms;
}
.thankful-item.ng-leave {
animation: zoomIn 400ms;
}
.thankful-item.ng-leave.ng-leave-active {
animation: zoomOut 400ms;
}
.thankful-item:focus {
outline: none;
}
.thankful-item > .thankful-item-content {
margin: 1em;
text-align: center;
}
.thankful-item > .author {
font-size: 0.36em;
position: absolute;
right: 0;
bottom: 0;
}
.thankful-item > .like-button {
position: absolute;
margin: 0;
padding: 0;
transform: rotate(-45deg);
width: 8em;
top: .5em;
left: -2.5em;
min-height: 32px;
max-height: 32px;
}
.thankful-item > .delete-button {
color: white;
line-height: 1em;
font-size: 0.5em;
position: absolute;
top: 0;
right: 0;
min-height: 32px;
max-height: 32px;
min-width: 32px;
max-width: 32px;
}
.thankful-container {
margin-top: 8px;
padding-bottom: 8px;
justify-content: center;
width: 100%;
margin-left: auto;
margin-right: auto;
}
.home.ng-hide {
animation: slideOutLeft 1000ms;
}
.home {
animation: slideInLeft 600ms;
}
.app-state-container.ng-hide {
animation: slideOutRight 1000ms;
}
.app-state-container {
animation: slideInRight 600ms;
z-index: 15;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100vh;
background-color: white;
}
.badge {
position: absolute;
border-radius: 5px;
z-index: 12;
right: 0;
top: -4px;
height: 18px;
padding: 4px;
background: #FF4081;
text-align: center;
line-height: 10px;
font-size: 12px;
}
@media (min-width: 768px) {
.thankful-input-container {
width: 768px;
margin-left: auto;
margin-right: auto;
}
.thankful-item {
min-width: 400px;
max-width: 600px;
flex: 1;
}
}
.thankful-icon:hover {
animation: rubberBand 600ms;
}
.like-p0 {
transition: all linear 300ms;
transform: translateY(-0.5em);
}
.liked .like-p0 {
transform: translateY(-0.8em);
}
.like-p1 {
transition: all linear 350ms;
transform: translateY(-1.5em);
}
.liked .like-p1 {
transform: translateY(-2.25em);
}
.liked .like-p2 {
transition: all linear 300ms;
animation: rubberBand 800ms;
}
.liked .like-micro-interaction {
animation: pulse-micro-interaction 600ms both;
}
@keyframes pulse-micro-interaction {
from {
vertical-align: 0;
}
50% {
font-size: 200%;
}
to {
vertical-align: 0;
font-size: 100%;
}
}
angular.module('ThankfulApp', ['ngAnimate', 'ngMaterial', 'ngStorage'])
.constant('helperUtils', {
anonAnimalsList: 'alligator, anteater, armadillo, auroch, axolotl, badger, bat, beaver, buffalo, camel, chameleon, cheetah, chipmunk, chinchilla, chupacabra, cormorant, coyote, crow, dingo, dinosaur, dolphin, duck, elephant, ferret, fox, frog, giraffe, gopher, grizzly, hedgehog, hippo, hyena, jackal, ibex, ifrit, iguana, koala, kraken, lemur, leopard, liger, llama, manatee, mink, monkey, moose, narwhal, nyan cat, orangutan, otter, panda, penguin, platypus, python, pumpkin, quagga, rabbit, raccoon, rhino, sheep, shrew, skunk, slow loris, squirrel, tiger, turtle, walrus, wolf, wolverine, wombat'.split(','),
thankfulColorsList: ['#1abc9c','#2ecc71', '#2980b9', '#8e44ad', '#34495e', '#F9D627', '#e74c3c', '#7f8c8d', '#f39c12', '#774F38', '#8f575a'],
updateWaves: function ($timeout) {
$timeout(function(){
Waves.attach('.ripple-light', ['waves-light']);
Waves.attach('.ripple-card', ['waves-light']);
Waves.attach('.ripple-dark');
Waves.init();
});
},
getRandomAuthor: function() {
return this.anonAnimalsList[~~(Math.random()*this.anonAnimalsList.length)];
},
getThankfulColor: function(thankful) {
Math.seedrandom(thankful.message);
return this.thankfulColorsList[~~(Math.random()*this.thankfulColorsList.length)];
}
})
.controller('MainCtrl', function($scope, $timeout, thankfulService, helperUtils) {
var controller = this;
controller.trending = false;
controller.helperUtils = helperUtils;
helperUtils.updateWaves($timeout);
})
.controller('HomeCtrl', function($scope, $timeout, $mdDialog, thankfulService, helperUtils) {
var controller = this;
controller.userThankfulList = thankfulService.getUserThankfulList();
controller.addThankful = function() {
if (this.thankfulMessage === '' || this.thankfulMessage.length > 120) {
return;
}
thankfulService.createThankful(this.thankfulMessage);
controller.thankfulMessage = '';
document.activeElement.blur();
};
controller.deleteThankful = function(thankful, $event) {
$mdDialog.show(
$mdDialog.confirm()
.title('Remove Thankful Card')
.textContent('Are you sure you\'re no longer thankful for "'+ thankful.message +'" ?')
.ok('Remove')
.cancel('Keep')
.targetEvent($event)
).then(function () {
thankfulService.removeThankful(thankful);
});
};
controller.getLocalData = function() {
return thankfulService.localData;
};
$scope.$watch(function(scope) {
return controller.userThankfulList;
}, function(newVal, oldVal) {
helperUtils.updateWaves($timeout);
}, true);
})
.controller('TrendingCtrl', function($scope, $timeout, thankfulService, helperUtils) {
var controller = this,
recentLocalDataKey = 'recentList',
trendingLocalDataKey = 'trendingList',
filterTrendingMap = {
'Trending today': 0,
'Trending this week': 7,
'Trending this month': 30,
'Trending all time': 1565
},
updateList = function() {
controller.list.splice(0,controller.list.length);
thankfulService.localData[controller.localDataFilterKey].forEach(function(item){
controller.list.push(item);
});
},
onFilterChange = function(newVal, oldVal) {
if (newVal === oldVal) {
return;
}
controller.localDataFilterKey = recentLocalDataKey;
if (newVal === 'Recent') {
thankfulService.updateRecentThankfuls().then(updateList);
} else {
thankfulService.updateTrendingThankfuls(moment().subtract(filterTrendingMap[newVal], 'day').format('YYYY-MM-DD')).then(updateList);
controller.localDataFilterKey = trendingLocalDataKey;
}
};
var pollsUntilSleep = 20;
controller.pollCount = 0;
(function newThankfulPoll() {
$timeout(function() {
if (controller.pollCount < pollsUntilSleep) {
thankfulService.updateRecentThankfuls().then(updateList);
controller.pollCount++;
}
newThankfulPoll();
}, 5000);
})();
controller.list = [];
controller.localDataFilterKey = recentLocalDataKey;
controller.filter = 'Recent';
controller.likedThankfuls = thankfulService.getLikedThankfuls();
controller.likeThankful = function(thankful) {
thankfulService.likeThankful(thankful);
};
controller.addToUserThankfuls = function(thankful) {
thankfulService.addThankful(thankful);
};
controller.moveToHome = function(mCtrl) {
controller.pollCount = 0;
mCtrl.trending = !mCtrl.trending;
thankfulService.resetNewThankfulsCount();
};
thankfulService.updateRecentThankfuls().then(updateList).then(function() {
thankfulService.resetNewThankfulsCount();
});
$scope.$watch( function (scope) {
return controller.filter;
}, onFilterChange);
})
.factory('thankfulService', function($localStorage, $http, $rootScope, helperUtils, $timeout) {
// $localStorage.$reset();
var apiUrl = 'https://thankful-app-api.herokuapp.com/api/grateful';
var service = {};
var thankfulSortPredicate = function(a, b) {
if (a.created < b.created) {
return 1;
}
if (a.created > b.created) {
return -1;
}
return 0;
};
var getRecentRequestPromise = function() {
return $http.get(apiUrl + '/recent')
.then(function(response) {
response.data.forEach(function(thankful) {
if (!$localStorage.recentThankfulMap[thankful.id]) {
$localStorage.newThankfulsCount++;
}
$localStorage.recentThankfulMap[thankful.id] = thankful;
});
var recentThankfulList = [];
for (var key in $localStorage.recentThankfulMap) {
if ($localStorage.recentThankfulMap.hasOwnProperty(key)) {
recentThankfulList.push($localStorage.recentThankfulMap[key]);
}
}
helperUtils.updateWaves($timeout);
return recentThankfulList.sort(thankfulSortPredicate);
}, function(response) {
console.log(response);
return 0;
});
};
var getTrendingRequestPromise = function(dateQueryString) {
return $http.get(apiUrl + '/trending/' + dateQueryString)
.then(function(response) {
helperUtils.updateWaves($timeout);
return response.data;
}, function(response) {
console.log(response);
});
};
var getCreateThankfulRequestPromise = function(thankfulMessage, thankfulAuthor) {
return $http.post(apiUrl + '/create', {
message: thankfulMessage,
author: thankfulAuthor
})
.then(function(response) {
return response.data;
}, function(response) {
console.log(response);
});
}
$localStorage.newThankfulsCount = 0;
$localStorage.userThankfulList = $localStorage.userThankfulList || [
{
id: '57a266e6777367bd8be3c1a4',
message: "Being alive!",
author: "The Primogenitor",
likes: 31,
created: "2016-08-03T21:49:02.216Z"
}
];
$localStorage.likedThankfulMap = $localStorage.likedThankfulMap || {};
$localStorage.recentThankfulMap = $localStorage.recentThankfulMap || {};
service.localData = {
recentList: [],
trendingList: [],
newThankfuls: $localStorage.newThankfulsCount
};
service.guid = function() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
};
service.createThankful = function(thankfulMessage) {
var guid = service.guid();
service.addThankful({
message: thankfulMessage,
author: 'anonymous ' + helperUtils.getRandomAuthor(),
likes: 0,
created: moment().format(),
id: guid
});
getCreateThankfulRequestPromise(thankfulMessage, 'anonymous ' + helperUtils.getRandomAuthor())
.then(function(responseData) {
if (responseData) {
$localStorage.recentThankfulMap[responseData.record.id] = responseData.record;
$localStorage.userThankfulList.forEach(function(record) {
if (record.id === guid) {
record.id = responseData.record.id;
}
});
}
});
};
service.addThankful = function(thankful) {
if ($localStorage.userThankfulList.filter(function(item) {
return item.id === thankful.id;
}).length > 0) {
return;
}
$localStorage.userThankfulList.push({
message: thankful.message,
author: thankful.author,
id: thankful.id,
likes: thankful.likes,
created: moment().format()
});
$localStorage.userThankfulList.sort(thankfulSortPredicate);
};
service.removeThankful = function(thankful) {
var index = $localStorage.userThankfulList.indexOf(thankful);
if (index != -1) {
$localStorage.userThankfulList.splice(index, 1);
}
};
service.likeThankful = function(thankful) {
if (!$localStorage.likedThankfulMap[thankful.id]) {
$http.put(apiUrl + '/like/' + thankful.id).then(function(response) {
$localStorage.likedThankfulMap[thankful.id] = true;
thankful.likes++;
});
}
};
service.getLikedThankfuls = function() {
return $localStorage.likedThankfulMap;
};
service.getUserThankfulList = function() {
return $localStorage.userThankfulList.sort(thankfulSortPredicate);
};
service.updateRecentThankfuls = function() {
return getRecentRequestPromise().then(function (data) {
service.localData.recentList = data || [];
service.localData.newThankfuls = $localStorage.newThankfulsCount;
});
};
service.updateTrendingThankfuls = function(dateQueryString) {
return getTrendingRequestPromise(dateQueryString).then(function (data) {
service.localData.trendingList = data || [];
});
};
service.resetNewThankfulsCount = function() {
$localStorage.newThankfulsCount = 0;
service.localData.newThankfuls = $localStorage.newThankfulsCount;
};
return service;
})
.config(function($mdThemingProvider, $mdColorPalette) {
$mdThemingProvider.definePalette('mcgpalette1', {
'50': '#f0eef0',
'100': '#cdc5cb',
'200': '#b3a6af',
'300': '#92808d',
'400': '#84707e',
'500': '#73626e',
'600': '#62545e',
'700': '#52464e',
'800': '#41383f',
'900': '#312a2f',
'A100': '#f0eef0',
'A200': '#cdc5cb',
'A400': '#84707e',
'A700': '#52464e',
'contrastDefaultColor': 'light',
'contrastDarkColors': '50 100 200 300 A100 A200'
});
$mdThemingProvider.theme('t1').primaryPalette('mcgpalette1');
$mdThemingProvider.theme('t9').primaryPalette('blue-grey');
$mdThemingProvider.setDefaultTheme('t1');
// $mdThemingProvider.alwaysWatchTheme(true);
});
!function(a,b,c,d,e,f,g,h,i){function j(a){var b,c=a.length,e=this,f=0,g=e.i=e.j=0,h=e.S=[];for(c||(a=[c++]);d>f;)h[f]=f++;for(f=0;d>f;f++)h[f]=h[g=s&g+a[f%c]+(b=h[f])],h[g]=b;(e.g=function(a){for(var b,c=0,f=e.i,g=e.j,h=e.S;a--;)b=h[f=s&f+1],c=c*d+h[s&(h[f]=h[g=s&g+b])+(h[g]=b)];return e.i=f,e.j=g,c})(d)}function k(a,b){var c,d=[],e=typeof a;if(b&&"object"==e)for(c in a)try{d.push(k(a[c],b-1))}catch(f){}return d.length?d:"string"==e?a:a+"\0"}function l(a,b){for(var c,d=a+"",e=0;e<d.length;)b[s&e]=s&(c^=19*b[s&e])+d.charCodeAt(e++);return n(b)}function m(c){try{return o?n(o.randomBytes(d)):(a.crypto.getRandomValues(c=new Uint8Array(d)),n(c))}catch(e){return[+new Date,a,(c=a.navigator)&&c.plugins,a.screen,n(b)]}}function n(a){return String.fromCharCode.apply(0,a)}var o,p=c.pow(d,e),q=c.pow(2,f),r=2*q,s=d-1,t=c["seed"+i]=function(a,f,g){var h=[];f=1==f?{entropy:!0}:f||{};var o=l(k(f.entropy?[a,n(b)]:null==a?m():a,3),h),s=new j(h);return l(n(s.S),b),(f.pass||g||function(a,b,d){return d?(c[i]=a,b):a})(function(){for(var a=s.g(e),b=p,c=0;q>a;)a=(a+c)*d,b*=d,c=s.g(1);for(;a>=r;)a/=2,b/=2,c>>>=1;return(a+c)/b},o,"global"in f?f.global:this==c)};if(l(c[i](),b),g&&g.exports){g.exports=t;try{o=require("crypto")}catch(u){}}else h&&h.amd&&h(function(){return t})}(this,[],Math,256,6,52,"object"==typeof module&&module,"function"==typeof define&&define,"random");
This Pen doesn't use any external JavaScript resources.