diff --git a/bower.json b/bower.json
index a37d0cd..e2be03e 100755
--- a/bower.json
+++ b/bower.json
@@ -42,8 +42,7 @@
"ngInfiniteScroll": "1.2.1",
"angular-socket-io": "^0.7.0",
"socket.io-client": "^1.4.6",
- "angular-toastr": "^1.7.0",
- "jquery.gritter": "^1.7.4"
+ "angular-toastr": "^1.7.0"
},
"devDependencies": {
"angular-mocks": ">=1.2.*",
diff --git a/client/assets/gritter/css/jquery.gritter.css b/client/assets/gritter/css/jquery.gritter.css
new file mode 100755
index 0000000..26fd5b0
--- /dev/null
+++ b/client/assets/gritter/css/jquery.gritter.css
@@ -0,0 +1,102 @@
+/* the norm */
+#gritter-notice-wrapper {
+ position:fixed;
+ top:20px;
+ right:20px;
+ width:301px;
+ z-index:9999;
+}
+#gritter-notice-wrapper.top-left {
+ left: 20px;
+ right: auto;
+}
+#gritter-notice-wrapper.bottom-right {
+ top: auto;
+ left: auto;
+ bottom: 20px;
+ right: 20px;
+}
+#gritter-notice-wrapper.bottom-left {
+ top: auto;
+ right: auto;
+ bottom: 20px;
+ left: 20px;
+}
+.gritter-item-wrapper {
+ position:relative;
+ margin:0 0 10px 0;
+ background:url('../images/ie-spacer.gif'); /* ie7/8 fix */
+}
+.gritter-top {
+ background:url(../images/gritter.png) no-repeat left -30px;
+ height:10px;
+}
+.hover .gritter-top {
+ background-position:right -30px;
+}
+.gritter-bottom {
+ background:url(../images/gritter.png) no-repeat left bottom;
+ height:8px;
+ margin:0;
+}
+.hover .gritter-bottom {
+ background-position: bottom right;
+}
+.gritter-item {
+ display:block;
+ background:url(../images/gritter.png) no-repeat left -40px;
+ color:#eee;
+ padding:2px 11px 8px 11px;
+ font-size: 11px;
+ font-family:verdana;
+}
+.hover .gritter-item {
+ background-position:right -40px;
+}
+.gritter-item p {
+ padding:0;
+ margin:0;
+ word-wrap:break-word;
+}
+.gritter-close {
+ display:none;
+ position:absolute;
+ top:5px;
+ left:3px;
+ background:url(../images/gritter.png) no-repeat left top;
+ cursor:pointer;
+ width:30px;
+ height:30px;
+ text-indent:-9999em;
+}
+.gritter-title {
+ font-size:14px;
+ font-weight:bold;
+ padding:0 0 7px 0;
+ display:block;
+ text-shadow:1px 1px 0 #000; /* Not supported by IE :( */
+}
+.gritter-image {
+ width:48px;
+ height:48px;
+ float:left;
+}
+.gritter-with-image,
+.gritter-without-image {
+ padding:0;
+}
+.gritter-with-image {
+ width:220px;
+ float:right;
+}
+/* for the light (white) version of the gritter notice */
+.gritter-light .gritter-item,
+.gritter-light .gritter-bottom,
+.gritter-light .gritter-top,
+.gritter-light .gritter-close {
+ background-image: url(../images/gritter-light.png);
+ color: #222;
+}
+.gritter-light .gritter-title {
+ text-shadow: none;
+}
diff --git a/client/assets/images/gritter-light.png b/client/assets/gritter/images/gritter-light.png
similarity index 100%
rename from client/assets/images/gritter-light.png
rename to client/assets/gritter/images/gritter-light.png
diff --git a/client/assets/images/gritter-long.png b/client/assets/gritter/images/gritter-long.png
similarity index 100%
rename from client/assets/images/gritter-long.png
rename to client/assets/gritter/images/gritter-long.png
diff --git a/client/assets/images/gritter.png b/client/assets/gritter/images/gritter.png
similarity index 100%
rename from client/assets/images/gritter.png
rename to client/assets/gritter/images/gritter.png
diff --git a/client/assets/images/ie-spacer.gif b/client/assets/gritter/images/ie-spacer.gif
similarity index 100%
rename from client/assets/images/ie-spacer.gif
rename to client/assets/gritter/images/ie-spacer.gif
diff --git a/client/assets/images/trees.jpg b/client/assets/gritter/images/trees.jpg
similarity index 100%
rename from client/assets/images/trees.jpg
rename to client/assets/gritter/images/trees.jpg
diff --git a/client/assets/gritter/js/jquery.gritter.js b/client/assets/gritter/js/jquery.gritter.js
new file mode 100755
index 0000000..3587ac5
--- /dev/null
+++ b/client/assets/gritter/js/jquery.gritter.js
@@ -0,0 +1,419 @@
+/*
+ * Gritter for jQuery
+ * http://www.boedesign.com/
+ *
+ * Copyright (c) 2012 Jordan Boesch
+ * Dual licensed under the MIT and GPL licenses.
+ *
+ * Date: February 24, 2012
+ * Version: 1.7.4
+ */
+
+(function($){
+
+ /**
+ * Set it up as an object under the jQuery namespace
+ */
+ $.gritter = {};
+
+ /**
+ * Set up global options that the user can over-ride
+ */
+ $.gritter.options = {
+ position: '',
+ class_name: '', // could be set to 'gritter-light' to use white notifications
+ fade_in_speed: 'medium', // how fast notifications fade in
+ fade_out_speed: 1000, // how fast the notices fade out
+ time: 6000 // hang on the screen for...
+ }
+
+ /**
+ * Add a gritter notification to the screen
+ * @see Gritter#add();
+ */
+ $.gritter.add = function(params){
+
+ try {
+ return Gritter.add(params || {});
+ } catch(e) {
+
+ var err = 'Gritter Error: ' + e;
+ (typeof(console) != 'undefined' && console.error) ?
+ console.error(err, params) :
+ alert(err);
+
+ }
+
+ }
+
+ /**
+ * Remove a gritter notification from the screen
+ * @see Gritter#removeSpecific();
+ */
+ $.gritter.remove = function(id, params){
+ Gritter.removeSpecific(id, params || {});
+ }
+
+ /**
+ * Remove all notifications
+ * @see Gritter#stop();
+ */
+ $.gritter.removeAll = function(params){
+ Gritter.stop(params || {});
+ }
+
+ /**
+ * Big fat Gritter object
+ * @constructor (not really since its object literal)
+ */
+ var Gritter = {
+
+ // Public - options to over-ride with $.gritter.options in "add"
+ position: '',
+ fade_in_speed: '',
+ fade_out_speed: '',
+ time: '',
+
+ // Private - no touchy the private parts
+ _custom_timer: 0,
+ _item_count: 0,
+ _is_setup: 0,
+ _tpl_close: 'Close Notification',
+ _tpl_title: '[[title]]',
+ _tpl_item: '
[[close]][[image]]
[[title]]
[[text]]
',
+ _tpl_wrap: '',
+
+ /**
+ * Add a gritter notification to the screen
+ * @param {Object} params The object that contains all the options for drawing the notification
+ * @return {Integer} The specific numeric id to that gritter notification
+ */
+ add: function(params){
+ // Handle straight text
+ if(typeof(params) == 'string'){
+ params = {text:params};
+ }
+
+ // We might have some issues if we don't have a title or text!
+ if(params.text === null){
+ throw 'You must supply "text" parameter.';
+ }
+
+ // Check the options and set them once
+ if(!this._is_setup){
+ this._runSetup();
+ }
+
+ // Basics
+ var title = params.title,
+ text = params.text,
+ image = params.image || '',
+ sticky = params.sticky || false,
+ item_class = params.class_name || $.gritter.options.class_name,
+ position = $.gritter.options.position,
+ time_alive = params.time || '';
+
+ this._verifyWrapper();
+
+ this._item_count++;
+ var number = this._item_count,
+ tmp = this._tpl_item;
+
+ // Assign callbacks
+ $(['before_open', 'after_open', 'before_close', 'after_close']).each(function(i, val){
+ Gritter['_' + val + '_' + number] = ($.isFunction(params[val])) ? params[val] : function(){}
+ });
+
+ // Reset
+ this._custom_timer = 0;
+
+ // A custom fade time set
+ if(time_alive){
+ this._custom_timer = time_alive;
+ }
+
+ var image_str = (image != '') ? '' : '',
+ class_name = (image != '') ? 'gritter-with-image' : 'gritter-without-image';
+
+ // String replacements on the template
+ if(title){
+ title = this._str_replace('[[title]]',title,this._tpl_title);
+ }else{
+ title = '';
+ }
+
+ tmp = this._str_replace(
+ ['[[title]]', '[[text]]', '[[close]]', '[[image]]', '[[number]]', '[[class_name]]', '[[item_class]]'],
+ [title, text, this._tpl_close, image_str, this._item_count, class_name, item_class], tmp
+ );
+
+ // If it's false, don't show another gritter message
+ if(this['_before_open_' + number]() === false){
+ return false;
+ }
+
+ $('#gritter-notice-wrapper').addClass(position).append(tmp);
+
+ var item = $('#gritter-item-' + this._item_count);
+
+ item.fadeIn(this.fade_in_speed, function(){
+ Gritter['_after_open_' + number]($(this));
+ });
+
+ if(!sticky){
+ this._setFadeTimer(item, number);
+ }
+
+ // Bind the hover/unhover states
+ $(item).bind('mouseenter mouseleave', function(event){
+ if(event.type == 'mouseenter'){
+ if(!sticky){
+ Gritter._restoreItemIfFading($(this), number);
+ }
+ }
+ else {
+ if(!sticky){
+ Gritter._setFadeTimer($(this), number);
+ }
+ }
+ Gritter._hoverState($(this), event.type);
+ });
+
+ // Clicking (X) makes the perdy thing close
+ $(item).find('.gritter-close').click(function(){
+ Gritter.removeSpecific(number, {}, null, true);
+ return false;
+ });
+
+ return number;
+
+ },
+
+ /**
+ * If we don't have any more gritter notifications, get rid of the wrapper using this check
+ * @private
+ * @param {Integer} unique_id The ID of the element that was just deleted, use it for a callback
+ * @param {Object} e The jQuery element that we're going to perform the remove() action on
+ * @param {Boolean} manual_close Did we close the gritter dialog with the (X) button
+ */
+ _countRemoveWrapper: function(unique_id, e, manual_close){
+
+ // Remove it then run the callback function
+ e.remove();
+ this['_after_close_' + unique_id](e, manual_close);
+
+ // Check if the wrapper is empty, if it is.. remove the wrapper
+ if($('.gritter-item-wrapper').length == 0){
+ $('#gritter-notice-wrapper').remove();
+ }
+
+ },
+
+ /**
+ * Fade out an element after it's been on the screen for x amount of time
+ * @private
+ * @param {Object} e The jQuery element to get rid of
+ * @param {Integer} unique_id The id of the element to remove
+ * @param {Object} params An optional list of params to set fade speeds etc.
+ * @param {Boolean} unbind_events Unbind the mouseenter/mouseleave events if they click (X)
+ */
+ _fade: function(e, unique_id, params, unbind_events){
+
+ var params = params || {},
+ fade = (typeof(params.fade) != 'undefined') ? params.fade : true,
+ fade_out_speed = params.speed || this.fade_out_speed,
+ manual_close = unbind_events;
+
+ this['_before_close_' + unique_id](e, manual_close);
+
+ // If this is true, then we are coming from clicking the (X)
+ if(unbind_events){
+ e.unbind('mouseenter mouseleave');
+ }
+
+ // Fade it out or remove it
+ if(fade){
+
+ e.animate({
+ opacity: 0
+ }, fade_out_speed, function(){
+ e.animate({ height: 0 }, 300, function(){
+ Gritter._countRemoveWrapper(unique_id, e, manual_close);
+ })
+ })
+
+ }
+ else {
+
+ this._countRemoveWrapper(unique_id, e);
+
+ }
+
+ },
+
+ /**
+ * Perform actions based on the type of bind (mouseenter, mouseleave)
+ * @private
+ * @param {Object} e The jQuery element
+ * @param {String} type The type of action we're performing: mouseenter or mouseleave
+ */
+ _hoverState: function(e, type){
+
+ // Change the border styles and add the (X) close button when you hover
+ if(type == 'mouseenter'){
+
+ e.addClass('hover');
+
+ // Show close button
+ e.find('.gritter-close').show();
+
+ }
+ // Remove the border styles and hide (X) close button when you mouse out
+ else {
+
+ e.removeClass('hover');
+
+ // Hide close button
+ e.find('.gritter-close').hide();
+
+ }
+
+ },
+
+ /**
+ * Remove a specific notification based on an ID
+ * @param {Integer} unique_id The ID used to delete a specific notification
+ * @param {Object} params A set of options passed in to determine how to get rid of it
+ * @param {Object} e The jQuery element that we're "fading" then removing
+ * @param {Boolean} unbind_events If we clicked on the (X) we set this to true to unbind mouseenter/mouseleave
+ */
+ removeSpecific: function(unique_id, params, e, unbind_events){
+
+ if(!e){
+ var e = $('#gritter-item-' + unique_id);
+ }
+
+ // We set the fourth param to let the _fade function know to
+ // unbind the "mouseleave" event. Once you click (X) there's no going back!
+ this._fade(e, unique_id, params || {}, unbind_events);
+
+ },
+
+ /**
+ * If the item is fading out and we hover over it, restore it!
+ * @private
+ * @param {Object} e The HTML element to remove
+ * @param {Integer} unique_id The ID of the element
+ */
+ _restoreItemIfFading: function(e, unique_id){
+
+ clearTimeout(this['_int_id_' + unique_id]);
+ e.stop().css({ opacity: '', height: '' });
+
+ },
+
+ /**
+ * Setup the global options - only once
+ * @private
+ */
+ _runSetup: function(){
+
+ for(opt in $.gritter.options){
+ this[opt] = $.gritter.options[opt];
+ }
+ this._is_setup = 1;
+
+ },
+
+ /**
+ * Set the notification to fade out after a certain amount of time
+ * @private
+ * @param {Object} item The HTML element we're dealing with
+ * @param {Integer} unique_id The ID of the element
+ */
+ _setFadeTimer: function(e, unique_id){
+
+ var timer_str = (this._custom_timer) ? this._custom_timer : this.time;
+ this['_int_id_' + unique_id] = setTimeout(function(){
+ Gritter._fade(e, unique_id);
+ }, timer_str);
+
+ },
+
+ /**
+ * Bring everything to a halt
+ * @param {Object} params A list of callback functions to pass when all notifications are removed
+ */
+ stop: function(params){
+
+ // callbacks (if passed)
+ var before_close = ($.isFunction(params.before_close)) ? params.before_close : function(){};
+ var after_close = ($.isFunction(params.after_close)) ? params.after_close : function(){};
+
+ var wrap = $('#gritter-notice-wrapper');
+ before_close(wrap);
+ wrap.fadeOut(function(){
+ $(this).remove();
+ after_close();
+ });
+
+ },
+
+ /**
+ * An extremely handy PHP function ported to JS, works well for templating
+ * @private
+ * @param {String/Array} search A list of things to search for
+ * @param {String/Array} replace A list of things to replace the searches with
+ * @return {String} sa The output
+ */
+ _str_replace: function(search, replace, subject, count){
+
+ var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
+ f = [].concat(search),
+ r = [].concat(replace),
+ s = subject,
+ ra = r instanceof Array, sa = s instanceof Array;
+ s = [].concat(s);
+
+ if(count){
+ this.window[count] = 0;
+ }
+
+ for(i = 0, sl = s.length; i < sl; i++){
+
+ if(s[i] === ''){
+ continue;
+ }
+
+ for (j = 0, fl = f.length; j < fl; j++){
+
+ temp = s[i] + '';
+ repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
+ s[i] = (temp).split(f[j]).join(repl);
+
+ if(count && s[i] !== temp){
+ this.window[count] += (temp.length-s[i].length) / f[j].length;
+ }
+
+ }
+ }
+
+ return sa ? s : s[0];
+
+ },
+
+ /**
+ * A check to make sure we have something to wrap our notices with
+ * @private
+ */
+ _verifyWrapper: function(){
+
+ if($('#gritter-notice-wrapper').length == 0){
+ $('body').append(this._tpl_wrap);
+ }
+
+ }
+
+ }
+
+})(jQuery);
diff --git a/client/index.html b/client/index.html
index d7e2683..4e1e2c4 100644
--- a/client/index.html
+++ b/client/index.html
@@ -28,7 +28,6 @@
-
@@ -38,6 +37,7 @@
+
@@ -132,7 +132,6 @@
-
@@ -148,6 +147,7 @@
+