AngularJS / Bootstrap 3 / jQuery "Growl" Directive v1.1
This version uses jQuery for the fadeOut and Bootstrap for the demo.
A Pen by Captain Anonymous on CodePen.
AngularJS / Bootstrap 3 / jQuery "Growl" Directive v1.1
This version uses jQuery for the fadeOut and Bootstrap for the demo.
A Pen by Captain Anonymous on CodePen.
| <head> | |
| <!-- jQuery --> | |
| <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> | |
| <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js'></script> | |
| <link rel='stylesheet prefetch' href='http://netdna.bootstrapcdn.com/bootstrap/3.0.1/css/bootstrap.min.css'> | |
| </head> | |
| <body ng-app="myApp" ng-controller="myController"> | |
| <div class="panel panel-default"> | |
| <div class="panel-heading"> | |
| <h3 class="panel-title">{{title}}</h3> | |
| </div> | |
| <div class="panel-body"> | |
| <p> | |
| These are the four types of "growls": | |
| </p> | |
| <p> | |
| <span ng-repeat="item in types"><button class="btn btn-{{item}}" ng-click="growlAdd(item)" data-test="test">{{item | capitalize}}</button></span> | |
| </p> | |
| <p> | |
| Timeout (ttl): <input ng-model="ttl" /><br/> | |
| </p> | |
| <p> | |
| Position: <input ng-model="position" /><br/> | |
| </p> | |
| <p> | |
| Text: <input ng-model="text" /><br/> | |
| </p> | |
| <p> | |
| <ul> | |
| <h4>Required for Release</h4> | |
| <li class="done">popup "growl" with id, type, title, text √</li> | |
| <li class="done">click-to-close: entire element or (x) √</li> | |
| <li class="done">ttl timeout √</li> | |
| <li class="done">settable text √</li> | |
| <h4>Extras</h4> | |
| <li class="done">four positions √</li> | |
| <li>fadeOut/fadeIn (switching to css animation)</li> | |
| <li>default bootstrap + custom styles</li> | |
| <li>http intercept to auto show server messages</li> | |
| </ul> | |
| </p> | |
| <h4>Growl Queue</h4> | |
| <pre> | |
| {{growls}} | |
| </pre> | |
| <span><button class="btn" ng-click="clear()">Clear Messages</button></span> | |
| <!-- growls container grows with content --> | |
| <div growls-container id="growls-container" class="{{position}}"></div> | |
| </div> | |
| </div> | |
| </body> |
| var lb = "• "; | |
| var myApp = angular.module("myApp", []); | |
| myApp.controller('myController', function($scope, $timeout) { | |
| $scope.title = 'AngularJS / Bootstrap 3 "Growl" Directive v1.1'; | |
| $scope.types = ["success", "info", "warning", "danger"]; | |
| $scope.growlsClear = function (){ | |
| $scope.growls = []; | |
| }; | |
| $scope.growlsClear(); | |
| // defaults | |
| $scope.ttl = 3000; | |
| $scope.position = "bottom-right"; | |
| $scope.text = "sample text"; | |
| // Add | |
| $scope.growlAdd = function(){ | |
| //console.log(this); | |
| var gid = $scope.growls.length + 1; | |
| var type = this.item; | |
| var title = this.item; | |
| var text = $scope.text; | |
| var item = {gid:gid, type:type, title:title, text:text}; | |
| $scope.growls.push(item); | |
| console.log(lb + "added " + type + " growl with gid " + gid) | |
| }; | |
| // Remove | |
| $scope.growlRemove = function(gid) { | |
| console.log(lb + 'growlRemove in controller removing gid ' + gid); | |
| for (var i=0; i < $scope.growls.length; i++){ | |
| if ($scope.growls[i].gid == gid) { | |
| $scope.growls.splice(i,1); | |
| break; | |
| } | |
| } | |
| }; | |
| }); | |
| myApp.directive('growlsContainer', function() { | |
| return { | |
| template: [ | |
| ' <div growl-item class="growl-item {{growl.type}}" ng-repeat="growl in growls" data-gid="{{growl.gid}}">', | |
| ' <div class="growl-content">', | |
| ' <h4>{{growl.title | capitalize}}</h4>', | |
| ' <p>{{growl.text}}</p>', | |
| ' </div>', | |
| ' <div class="growl-close" data-gid="{{growl.gid}}""></div>', | |
| ' </div>' | |
| ].join('\n'), | |
| }; | |
| }); | |
| myApp.directive("growlItem", function($timeout) { | |
| return function($scope, $element, $attrs) { | |
| var gid = $attrs.gid; | |
| function growlFadeOut(gid){ | |
| $($element).fadeOut(1000, function() { | |
| console.log(lb + "growlFadeOut completed in directive calling growlRemove gid " + gid); | |
| /* MUST wrap this in apply or digest will not happen */ | |
| $scope.$apply( function(){ | |
| $scope.growlRemove(gid); | |
| }); | |
| }); | |
| }; | |
| $element.bind("click", function() { | |
| console.log(lb + "click fading gid: "+ gid); | |
| growlFadeOut(gid); | |
| }); | |
| var promise = $timeout(function(){ | |
| console.log(lb + 'timeout fading gid ' + gid); | |
| growlFadeOut(gid); | |
| },$scope.ttl); | |
| $element.bind('$destroy', function() { | |
| if(promise){ | |
| console.log(lb + 'cancelling timeout for gid ' + gid) | |
| //console.log(promise); | |
| var cancelled = $timeout.cancel(promise) ? "timeout cancel success for gid " + gid : "timeout already expired for gid " + gid; | |
| console.log(lb + cancelled); | |
| }; | |
| }); | |
| }; | |
| }); | |
| myApp.filter('capitalize', function() { | |
| return function(input, scope) { | |
| if (input!=null){ | |
| return input.substring(0,1).toUpperCase()+input.substring(1); | |
| } | |
| } | |
| }); |
| .panel { | |
| width:80%; | |
| margin:2em auto; | |
| } | |
| p { | |
| padding:1em 1em 1em 1em ; | |
| } | |
| span { | |
| margin:4px; | |
| } | |
| input { | |
| float:right; | |
| width:50%; | |
| } | |
| .done{ | |
| font-weight:bold; | |
| } | |
| .growl-item p { | |
| padding:0; | |
| } | |
| .top-left { top: 10px; left: 15px; } | |
| .top-right { top: 10px; right: 15px; } | |
| .bottom-left { bottom: 10px; left: 15px; } | |
| .bottom-right { bottom: 10px; right: 15px; } | |
| #growls-container { | |
| width:300px; | |
| position:fixed; | |
| } | |
| .growl-item { | |
| background: #DDD; | |
| background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #F9F9F9), color-stop(1, #D5D5D5)); | |
| background: -moz-linear-gradient(top, #F9F9F9, #D5D5D5); | |
| background: -o-linear-gradient(#F9F9F9, #D5D5D5); | |
| filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F9F9F9', endColorstr='#D5D5D5'); | |
| width: 300px; | |
| font-size: 11px; | |
| color: #333; | |
| padding: 0; | |
| margin: 0 0 10px 0; | |
| border: 1px solid #A8A8A8; | |
| position: relative; | |
| -webkit-box-shadow: 0 0 7px rgba(0,0,0,.3); | |
| -moz-box-shadow: 0 0 7px rgba(0,0,0,.3); | |
| -o-box-shadow: 0 0 7px rgba(0,0,0,.3); | |
| box-shadow: 0 0 7px rgba(0,0,0,.3); | |
| -webkit-text-shadow: 0 0 1px #FFF; | |
| -moz-text-shadow: 0 0 1px #FFF; | |
| -o-text-shadow: 0 0 1px #FFF; | |
| text-shadow: 0 0 1px #FFF; | |
| -webkit-border-radius: 5px; | |
| -moz-border-radius: 5px; | |
| -o-border-radius: 5px; | |
| border-radius: 5px; | |
| } | |
| .growl-content h4 { | |
| font-weight:bold; | |
| font-size: 12px; | |
| color: #333; | |
| margin-bottom: .5em; | |
| -webkit-text-shadow: 0 0 1px #FFF; | |
| -moz-text-shadow: 0 0 1px #FFF; | |
| -o-text-shadow: 0 0 1px #FFF; | |
| text-shadow: 0 0 1px #FFF; | |
| } | |
| .growl-content { padding: 10px 20px 10px 10px; } | |
| .growl-close:hover { opacity: 1; cursor: pointer; } | |
| .growl-close { | |
| background: url(http://paulbhartzog.org/codepen/msgGrowl_close.png) no-repeat 50% 50%; | |
| width: 11px; | |
| height: 10px; | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| opacity: .4; | |
| border:1px solid gray; | |
| padding:5px; | |
| -webkit-border-radius: 2px; | |
| -moz-border-radius: 2px; | |
| -o-border-radius: 2px; | |
| border-radius: 2px; | |
| } | |
| .growl-item.success .growl-content { background: url(http://paulbhartzog.org/codepen/growl_success.png) no-repeat 10px 13px; } | |
| .growl-item.success .growl-content { padding-left: 50px; } | |
| .growl-item.success h4 { color: #5B7027; } | |
| .growl-item.danger .growl-content { background: url(http://paulbhartzog.org/codepen/growl_danger.png) no-repeat 10px 13px; } | |
| .growl-item.danger .growl-content { padding-left: 50px; } | |
| .growl-item.danger h4 { color: #AF4434; } | |
| .growl-item.info .growl-content { background: url(http://paulbhartzog.org/codepen/growl_info.png) no-repeat 10px 13px; } | |
| .growl-item.info .growl-content { padding-left: 50px; } | |
| .growl-item.info h4 { color: #316AB7; } | |
| .growl-item.warning .growl-content { background: url(http://paulbhartzog.org/codepen/growl_warning.png) no-repeat 10px 13px; } | |
| .growl-item.warning .growl-content { padding-left: 50px; } | |
| .growl-item.warning h4 { color: #B69201; } |