From a8ca01ba6240579419866604cf3406b287a5b648 Mon Sep 17 00:00:00 2001 From: TheHollidayInn Date: Sat, 30 May 2015 22:00:29 -0500 Subject: [PATCH 1/4] Added markdown filter to endCast notification --- website/public/js/controllers/rootCtrl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/public/js/controllers/rootCtrl.js b/website/public/js/controllers/rootCtrl.js index 8f1f4255fa..6ac31b9585 100644 --- a/website/public/js/controllers/rootCtrl.js +++ b/website/public/js/controllers/rootCtrl.js @@ -3,8 +3,8 @@ /* Make user and settings available for everyone through root scope. */ -habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrl', 'Payments','$sce','$window', - function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrl, Payments, $sce, $window) { +habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrl', 'Payments','$sce','$window', '$filter', + function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrl, Payments, $sce, $window, $filter) { var user = User.user; var initSticky = _.once(function(){ @@ -278,7 +278,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break; } - Notification.text(msg); + Notification.text($filter("markdown")(msg)); User.sync(); }); From 39f363ec29aeef513d1e975cc9dc42a26db1e9bf Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 1 Jun 2015 17:38:18 -0500 Subject: [PATCH 2/4] Add tests for castEnd on root controller --- test/spec/rootCtrlSpec.js | 116 ++++++++++++++++++---- website/public/js/controllers/rootCtrl.js | 23 ++--- 2 files changed, 106 insertions(+), 33 deletions(-) diff --git a/test/spec/rootCtrlSpec.js b/test/spec/rootCtrlSpec.js index 5f4b61b1d2..8a68896a7b 100644 --- a/test/spec/rootCtrlSpec.js +++ b/test/spec/rootCtrlSpec.js @@ -1,38 +1,112 @@ 'use strict'; -// @TODO: Something here is calling a full page reload describe('Root Controller', function() { - var scope, user, ctrl; + var scope, rootscope, user, User, notification, ctrl, $httpBackend; beforeEach(function () { module(function($provide) { $provide.value('User', {}); }); - inject(function($rootScope, $controller) { + inject(function($rootScope, $controller, _$httpBackend_, Notification) { scope = $rootScope.$new(); - scope.loginUsername = 'user' - scope.loginPassword = 'pass' - user = specHelper.newUser(); + scope.loginUsername = 'user'; + scope.loginPassword = 'pass'; - ctrl = $controller('RootCtrl', {$scope: scope, User: {user: user}}); + rootscope = $rootScope; + + $httpBackend = _$httpBackend_; + + notification = Notification; + sinon.stub(notification, 'text') + + user = specHelper.newUser(); + User = {user: user}; + User.save = sinon.spy(); + User.sync = sinon.spy(); + + ctrl = $controller('RootCtrl', {$scope: scope, User: User}); }); }); - it('shows contributor level text', function(){ - expect(scope.contribText()).to.eql(undefined); - expect(scope.contribText(null, {npc: 'NPC'})).to.eql('NPC'); - expect(scope.contribText({level: 0, text: 'Blacksmith'})).to.eql(undefined); - expect(scope.contribText({level: 1, text: 'Blacksmith'})).to.eql('Friend Blacksmith'); - expect(scope.contribText({level: 2, text: 'Blacksmith'})).to.eql('Friend Blacksmith'); - expect(scope.contribText({level: 3, text: 'Blacksmith'})).to.eql('Elite Blacksmith'); - expect(scope.contribText({level: 4, text: 'Blacksmith'})).to.eql('Elite Blacksmith'); - expect(scope.contribText({level: 5, text: 'Blacksmith'})).to.eql('Champion Blacksmith'); - expect(scope.contribText({level: 6, text: 'Blacksmith'})).to.eql('Champion Blacksmith'); - expect(scope.contribText({level: 7, text: 'Blacksmith'})).to.eql('Legendary Blacksmith'); - expect(scope.contribText({level: 8, text: 'Blacksmith'})).to.eql('Guardian Blacksmith'); - expect(scope.contribText({level: 9, text: 'Blacksmith'})).to.eql('Heroic Blacksmith'); - expect(scope.contribText({level: 9, text: 'Blacksmith'}, {npc: 'NPC'})).to.eql('NPC'); + afterEach(function() { + notification.text.reset(); + User.save.reset(); + User.sync.reset(); }); + describe('contribText', function(){ + it('shows contributor level text', function(){ + expect(scope.contribText()).to.eql(undefined); + expect(scope.contribText(null, {npc: 'NPC'})).to.eql('NPC'); + expect(scope.contribText({level: 0, text: 'Blacksmith'})).to.eql(undefined); + expect(scope.contribText({level: 1, text: 'Blacksmith'})).to.eql('Friend Blacksmith'); + expect(scope.contribText({level: 2, text: 'Blacksmith'})).to.eql('Friend Blacksmith'); + expect(scope.contribText({level: 3, text: 'Blacksmith'})).to.eql('Elite Blacksmith'); + expect(scope.contribText({level: 4, text: 'Blacksmith'})).to.eql('Elite Blacksmith'); + expect(scope.contribText({level: 5, text: 'Blacksmith'})).to.eql('Champion Blacksmith'); + expect(scope.contribText({level: 6, text: 'Blacksmith'})).to.eql('Champion Blacksmith'); + expect(scope.contribText({level: 7, text: 'Blacksmith'})).to.eql('Legendary Blacksmith'); + expect(scope.contribText({level: 8, text: 'Blacksmith'})).to.eql('Guardian Blacksmith'); + expect(scope.contribText({level: 9, text: 'Blacksmith'})).to.eql('Heroic Blacksmith'); + expect(scope.contribText({level: 9, text: 'Blacksmith'}, {npc: 'NPC'})).to.eql('NPC'); + }); + }); + + describe('castEnd', function(){ + var task_target, type; + + beforeEach(function(){ + task_target = { id: 'task-id' }; + type = 'task'; + scope.spell = { + target: 'task', + key: 'fireball', + mana: 10, + text: env.t('spellWizardFireballText'), + cast: function(){} + }; + rootscope.applyingAction = true; + }); + + context('fails', function(){ + it('exits early if there is no applying action', function(){ + rootscope.applyingAction = null; + expect(scope.castEnd(task_target, type)).to.be.eql('No applying action'); + }); + + it('sends notification if target is invalid', function(){ + scope.spell.target = 'not_the_same_target'; + + scope.castEnd(task_target, type) + + notification.text.should.have.been.calledWith(window.env.t('invalidTarget')); + }); + }); + + context('succeeds', function(){ + it('sets scope.spell and rootScope.applyingAction to falsy values', function(){ + + scope.castEnd(task_target, type) + + expect(rootscope.applyingAction).to.eql(false); + expect(scope.spell).to.eql(null); + }); + + it('calls $scope.spell.cast', function(){ + // Kind of a hack, would prefer to use sinon.spy, + // but scope.spell gets turned to null in scope.castEnd + var spellWasCast = false; + scope.spell.cast = function(){ spellWasCast = true }; + + scope.castEnd(task_target, type) + + expect(spellWasCast).to.eql(true); + }); + + it('calls cast endpoint'); + + it('sends notification that spell was cast'); + }); + }); }); diff --git a/website/public/js/controllers/rootCtrl.js b/website/public/js/controllers/rootCtrl.js index 6ac31b9585..a8eb87641d 100644 --- a/website/public/js/controllers/rootCtrl.js +++ b/website/public/js/controllers/rootCtrl.js @@ -259,7 +259,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ } $scope.castEnd = function(target, type, $event){ - if (!$rootScope.applyingAction) return; + if (!$rootScope.applyingAction) return 'No applying action'; $event && ($event.stopPropagation(),$event.preventDefault()); if ($scope.spell.target != type) return Notification.text(window.env.t('invalidTarget')); $scope.spell.cast(User.user, target); @@ -271,17 +271,16 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $rootScope.applyingAction = false; $http.post(ApiUrl.get() + '/api/v2/user/class/cast/'+spell.key+'?targetType='+type+'&targetId='+targetId) - .success(function(){ - var msg = window.env.t('youCast', {spell: spell.text()}); - switch (type) { - case 'task': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.text});break; - case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; - case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break; - } - Notification.text($filter("markdown")(msg)); - User.sync(); - }); - + .success(function(){ + var msg = window.env.t('youCast', {spell: spell.text()}); + switch (type) { + case 'task': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.text});break; + case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; + case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break; + } + Notification.text($filter("markdown")(msg)); + User.sync(); + }); } $rootScope.castCancel = function(){ From 3291062b31e2d5ad6e3836f55fe5614cca1df58f Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 1 Jun 2015 17:49:27 -0500 Subject: [PATCH 3/4] Move markdown parsing to notification service --- website/public/js/controllers/rootCtrl.js | 6 +++--- website/public/js/services/notificationServices.js | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/website/public/js/controllers/rootCtrl.js b/website/public/js/controllers/rootCtrl.js index a8eb87641d..53e802a0b7 100644 --- a/website/public/js/controllers/rootCtrl.js +++ b/website/public/js/controllers/rootCtrl.js @@ -3,8 +3,8 @@ /* Make user and settings available for everyone through root scope. */ -habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrl', 'Payments','$sce','$window', '$filter', - function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrl, Payments, $sce, $window, $filter) { +habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrl', 'Payments','$sce','$window', + function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrl, Payments, $sce, $window) { var user = User.user; var initSticky = _.once(function(){ @@ -278,7 +278,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break; } - Notification.text($filter("markdown")(msg)); + Notification.markdown(msg); User.sync(); }); } diff --git a/website/public/js/services/notificationServices.js b/website/public/js/services/notificationServices.js index 481f3222e0..f6f586293c 100644 --- a/website/public/js/services/notificationServices.js +++ b/website/public/js/services/notificationServices.js @@ -2,7 +2,7 @@ Set up "+1 Exp", "Level Up", etc notifications */ angular.module("habitrpg").factory("Notification", -[function() { +['$filter', function($filter) { var stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60}; function notify(html, type, icon) { var notice = $.pnotify({ @@ -62,6 +62,12 @@ angular.module("habitrpg").factory("Notification", notify(val, 'info'); } }, + markdown: function(val){ + if (val) { + var parsed_markdown = $filter("markdown")(val); + notify(parsed_markdown, 'info'); + } + }, lvl: function(){ notify(window.env.t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up'); }, From b375c068deed7853084f812b5a0d5b975ae4bfb7 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 2 Jun 2015 07:51:54 -0500 Subject: [PATCH 4/4] Refactor notification service and add tests --- karma.conf.js | 1 + test/spec/notificationServicesSpec.js | 185 +++++++++++++++++- .../js/services/notificationServices.js | 184 ++++++++++------- 3 files changed, 293 insertions(+), 77 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index 53a7e4999b..a6d310f33b 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -12,6 +12,7 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ 'website/public/bower_components/jquery/dist/jquery.js', + 'website/public/bower_components/pnotify/jquery.pnotify.js', 'website/public/bower_components/angular/angular.js', 'website/public/bower_components/angular-loading-bar/build/loading-bar.min.js', 'website/public/bower_components/angular-resource/angular-resource.min.js', diff --git a/test/spec/notificationServicesSpec.js b/test/spec/notificationServicesSpec.js index fbaae22aa0..85570c8372 100644 --- a/test/spec/notificationServicesSpec.js +++ b/test/spec/notificationServicesSpec.js @@ -1,9 +1,14 @@ 'use strict'; -//TODO mock bootstrapGrowl, add remaining tests describe('notificationServices', function() { var notification; + before(function(){ + sinon.stub($, 'pnotify', function(){ + return { click: function(){}} + }); + }); + beforeEach(function() { module(function($provide){ $provide.value('User', {}); @@ -14,12 +19,190 @@ describe('notificationServices', function() { }); }); + afterEach(function() { + $.pnotify.reset(); + }); + it('notifies coins amount', function() { var SILVER_COIN = ""; var GOLD_COIN = ""; + + expect(notification.coins(0)).to.not.exist; expect(notification.coins(0.01)).to.eql("1 " + SILVER_COIN); expect(notification.coins(0.1)).to.eql("10 " + SILVER_COIN); expect(notification.coins(1)).to.eql("1 " + GOLD_COIN); expect(notification.coins(12.34)).to.eql("12 " + GOLD_COIN +" 33 " + SILVER_COIN); }); + + it('sends crit notification', function() { + notification.crit(5); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('crit'); + expect(arg.text).to.eql('Critical Hit! Bonus: 5%'); + expect(arg.icon).to.eql('glyphicon glyphicon-certificate'); + }); + + it('sends drop notification for unspecified item', function() { + notification.drop('msg'); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('drop'); + expect(arg.text).to.eql('msg'); + expect(arg.icon).to.eql(false); + }); + + it('sends drop notification for Egg', function() { + var item = { type: 'Egg', key: 'wolf' }; + notification.drop('msg', item); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('drop'); + expect(arg.text).to.eql('msg'); + expect(arg.icon).to.eql('Pet_Egg_wolf'); + }); + + it('sends drop notification for Hatching Potion', function() { + var item = { type: 'HatchingPotion', key: 'red' }; + notification.drop('msg', item); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('drop'); + expect(arg.text).to.eql('msg'); + expect(arg.icon).to.eql('Pet_HatchingPotion_red'); + }); + + it('sends drop notification for Food', function() { + var item = { type: 'Food', key: 'meat' }; + notification.drop('msg', item); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('drop'); + expect(arg.text).to.eql('msg'); + expect(arg.icon).to.eql('Pet_Food_meat'); + }); + + it('does not send exp notification if val < -50', function() { + notification.exp(-51); + expect($.pnotify).to.not.have.been.called; + }); + + it('send exp notification if val >= -50', function() { + notification.exp(50); + notification.exp(0); + notification.exp(-50); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledThrice; + expect(arg.type).to.eql('xp'); + expect(arg.text).to.eql('+ 50 XP'); + expect(arg.icon).to.eql('glyphicon glyphicon-star'); + }); + + it('send exp notification with rounded value', function() { + notification.exp(50.23333); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('xp'); + expect(arg.text).to.eql('+ 50.2 XP'); + expect(arg.icon).to.eql('glyphicon glyphicon-star'); + }); + + it('send error notification', function() { + notification.error('there was an error'); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('danger'); + expect(arg.text).to.eql('there was an error'); + expect(arg.icon).to.eql('glyphicon glyphicon-exclamation-sign'); + }); + + it('send gp gained notification', function() { + notification.gp(50, 4); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('gp'); + expect(arg.text).to.eql('+ 46 '); + expect(arg.icon).to.eql(false); + }); + + it('send hp notification', function() { + notification.hp(10); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('hp'); + expect(arg.text).to.eql('+ 10 HP'); + expect(arg.icon).to.eql('glyphicon glyphicon-heart'); + }); + + it('send level up notification', function() { + notification.lvl(10); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('lvl'); + expect(arg.text).to.eql('Level Up!'); + expect(arg.icon).to.eql('glyphicon glyphicon-chevron-up'); + }); + + it('send markdown parsed notification', function() { + notification.markdown(":smile: - task name"); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('info'); + expect(arg.text).to.eql('

:smile: - task name

\n'); + expect(arg.icon).to.eql(false); + }); + + it('does not send markdown notification if no text is given', function() { + notification.markdown(); + + expect($.pnotify).to.not.have.been.called; + }); + + it('send mp notification', function() { + notification.mp(10); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('mp'); + expect(arg.text).to.eql('+ 10 MP'); + expect(arg.icon).to.eql('glyphicon glyphicon-fire'); + }); + + it('send streak notification', function() { + notification.streak(10); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('streak'); + expect(arg.text).to.eql('Streak Achievements: 10'); + expect(arg.icon).to.eql('glyphicon glyphicon-repeat'); + }); + + it('send text notification', function() { + notification.text('task name'); + var arg = $.pnotify.args[0][0] + + expect($.pnotify).to.have.been.calledOnce; + expect(arg.type).to.eql('info'); + expect(arg.text).to.eql('task name'); + expect(arg.icon).to.eql(false); + }); + + it('does not send text notification if no text is given', function() { + notification.text(); + + expect($.pnotify).to.not.have.been.called; + }); }); diff --git a/website/public/js/services/notificationServices.js b/website/public/js/services/notificationServices.js index f6f586293c..f53894b65e 100644 --- a/website/public/js/services/notificationServices.js +++ b/website/public/js/services/notificationServices.js @@ -1,24 +1,27 @@ +'use strict' /** Set up "+1 Exp", "Level Up", etc notifications */ angular.module("habitrpg").factory("Notification", ['$filter', function($filter) { - var stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60}; - function notify(html, type, icon) { - var notice = $.pnotify({ - type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit') - text: html, - opacity: 1, - addclass: 'alert-' + type, - delay: 7000, - hide: (type == 'error') ? false : true, - mouse_reset: false, - width: "250px", - stack: stack_topright, - icon: icon || false - }).click(function() { notice.pnotify_remove() }); + + var notificationService = { + coins: coins, + crit: crit, + drop: drop, + exp: exp, + error: error, + gp: gp, + hp: hp, + lvl: lvl, + markdown: markdown, + mp: mp, + streak: streak, + text: text }; + return notificationService; + /** Show "+ 5 {gold_coin} 3 {silver_coin}" */ @@ -34,73 +37,102 @@ angular.module("habitrpg").factory("Notification", } else if (silver > 0) { return "" + silver + " "; } - }; + } - var sign = function(number){ + function crit(val) { + _notify(window.env.t('critBonus') + Math.round(val) + "%", 'crit', 'glyphicon glyphicon-certificate'); + } + + function drop(val, item) { + var dropClass = ""; + if ( item !== undefined ) { + switch ( item.type ) { + case "Egg": + dropClass = 'Pet_Egg_' + item.key; + break; + case "HatchingPotion": + dropClass = 'Pet_HatchingPotion_' + item.key; + break; + case "Food": + dropClass = 'Pet_Food_' + item.key; + break; + default: + dropClass = 'glyphicon glyphicon-gift'; + } + } + _notify(val, 'drop', dropClass); + } + + function exp(val) { + if (val < -50) return; // don't show when they level up (resetting their exp) + _notify(_sign(val) + " " + _round(val) + " " + window.env.t('xp'), 'xp', 'glyphicon glyphicon-star'); + } + + function error(error){ + _notify(error, "danger", 'glyphicon glyphicon-exclamation-sign'); + } + + function gp(val, bonus) { + _notify(_sign(val) + " " + coins(val - bonus), 'gp'); + } + + function hp(val) { + // don't show notifications if user dead + _notify(_sign(val) + " " + _round(val) + " " + window.env.t('hp'), 'hp', 'glyphicon glyphicon-heart'); + } + + function lvl(){ + _notify(window.env.t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up'); + } + + function markdown(val){ + if (val) { + var parsed_markdown = $filter("markdown")(val); + _notify(parsed_markdown, 'info'); + } + } + + function mp(val) { + _notify(_sign(val) + " " + _round(val) + " " + window.env.t('mp'), 'mp', 'glyphicon glyphicon-fire'); + } + + function streak(val) { + _notify(window.env.t('streakName') + ': ' + val, 'streak', 'glyphicon glyphicon-repeat'); + } + + function text(val){ + if (val) { + _notify(val, 'info'); + } + } + + //-------------------------------------------------- + // Private Methods + //-------------------------------------------------- + + function _sign(number){ return number?number<0?'-':'+':'+'; } - var round = function(number){ + function _round(number){ return Math.abs(number.toFixed(1)); } - return { - coins: coins, - hp: function(val) { - // don't show notifications if user dead - notify(sign(val) + " " + round(val) + " " + window.env.t('hp'), 'hp', 'glyphicon glyphicon-heart'); - }, - exp: function(val) { - if (val < -50) return; // don't show when they level up (resetting their exp) - notify(sign(val) + " " + round(val) + " " + window.env.t('xp'), 'xp', 'glyphicon glyphicon-star'); - }, - gp: function(val, bonus) { - notify(sign(val) + " " + coins(val - bonus), 'gp'); - }, - text: function(val){ - if (val) { - notify(val, 'info'); - } - }, - markdown: function(val){ - if (val) { - var parsed_markdown = $filter("markdown")(val); - notify(parsed_markdown, 'info'); - } - }, - lvl: function(){ - notify(window.env.t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up'); - }, - error: function(error){ - notify(error, "danger", 'glyphicon glyphicon-exclamation-sign'); - }, - mp: function(val) { - notify(sign(val) + " " + round(val) + " " + window.env.t('mp'), 'mp', 'glyphicon glyphicon-fire'); - }, - crit: function(val) { - notify(window.env.t('critBonus') + Math.round(val) + "%", 'crit', 'glyphicon glyphicon-certificate'); - }, - streak: function(val) { - notify(window.env.t('streakName') + ': ' + val, 'streak', 'glyphicon glyphicon-repeat'); - }, - drop: function(val, item) { - var dropClass = ""; - if ( item !== undefined ) { - switch ( item.type ) { - case "Egg": - dropClass = 'Pet_Egg_' + item.key; - break; - case "HatchingPotion": - dropClass = 'Pet_HatchingPotion_' + item.key; - break; - case "Food": - dropClass = 'Pet_Food_' + item.key; - break; - default: - dropClass = 'glyphicon glyphicon-gift'; - } - } - notify(val, 'drop', dropClass); - } - }; + // Used to stack notifications, must be outside of _notify + var stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60}; + + function _notify(html, type, icon) { + var notice = $.pnotify({ + type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit') + text: html, + opacity: 1, + addclass: 'alert-' + type, + delay: 7000, + hide: (type == 'error') ? false : true, + mouse_reset: false, + width: "250px", + stack: stack_topright, + icon: icon || false + }).click(function() { notice.pnotify_remove() }); + } }]);