Browse Source

Cleaned up some Misago js

Rafał Pitoń 10 years ago
parent
commit
e86e4ac641

+ 6 - 4
misago/conf/defaults.py

@@ -57,16 +57,18 @@ PIPELINE_JS = {
             'misago/js/bootstrap.js',
             'misago/js/bootstrap.js',
             'misago/js/moment.min.js',
             'misago/js/moment.min.js',
             'misago/js/tinycon.min.js',
             'misago/js/tinycon.min.js',
+            'misago/js/knockout.js',
+            'misago/js/misago.js',
+            'misago/js/misago-alerts.js',
+            'misago/js/misago-ajax.js',
             'misago/js/misago-dom.js',
             'misago/js/misago-dom.js',
             'misago/js/misago-timestamps.js',
             'misago/js/misago-timestamps.js',
+            'misago/js/misago-uiserver.js',
+            'misago/js/misago-bindings.js',
             'misago/js/misago-tooltips.js',
             'misago/js/misago-tooltips.js',
             'misago/js/misago-yesnoswitch.js',
             'misago/js/misago-yesnoswitch.js',
-            'misago/js/misago-alerts.js',
-            'misago/js/misago-ajax.js',
             'misago/js/misago-modal.js',
             'misago/js/misago-modal.js',
             'misago/js/misago-scrolling.js',
             'misago/js/misago-scrolling.js',
-            'misago/js/misago-uiserver.js',
-            'misago/js/misago-user-nav.js',
             'misago/js/misago-notifications.js',
             'misago/js/misago-notifications.js',
             'misago/js/misago-threads-lists.js',
             'misago/js/misago-threads-lists.js',
         ),
         ),

+ 1 - 2
misago/core/uiviews.py

@@ -49,13 +49,12 @@ def uiserver(request):
         raise PermissionDenied()
         raise PermissionDenied()
 
 
     resolver_match = get_resolver_match(request)
     resolver_match = get_resolver_match(request)
-    response_dict = {'total_count': 0}
+    response_dict = {}
 
 
     for name, view in UI_VIEWS:
     for name, view in UI_VIEWS:
         try:
         try:
             view_response = view(request, resolver_match)
             view_response = view(request, resolver_match)
             if view_response:
             if view_response:
-                response_dict['total_count'] += view_response.get('count', 0)
                 response_dict[name] = view_response
                 response_dict[name] = view_response
         except PermissionDenied:
         except PermissionDenied:
             pass
             pass

+ 1 - 1
misago/notifications/views.py

@@ -111,7 +111,7 @@ def read_all(request):
     return redirect('misago:notifications')
     return redirect('misago:notifications')
 
 
 
 
-@uiview('misago_notifications')
+@uiview('notifications')
 @deny_guests
 @deny_guests
 def event_sender(request, resolver_match):
 def event_sender(request, resolver_match):
     if request.user.new_notifications:
     if request.user.new_notifications:

+ 1 - 1
misago/static/misago/js/misago-ajax.js

@@ -12,7 +12,7 @@ $(function() {
     }
     }
 
 
     if (thrownError != "") {
     if (thrownError != "") {
-      $.misago_alerts().error(error_message);
+      Misago.Alerts.error(error_message);
     }
     }
   }
   }
   $(document).ajaxError(handleAjaxError);
   $(document).ajaxError(handleAjaxError);

+ 73 - 91
misago/static/misago/js/misago-alerts.js

@@ -1,104 +1,86 @@
-// Misago alerts extension
-(function($) {
-
-  // Alerts handler class definition
-  // ===============================
-
-  var MisagoAlerts = function(options) {
-
-    this.options = $.extend({
-      alerts_container: ".misago-alerts",
-      generic_error: "Unspecified error occured",
-      error_template: "",
-      info_template: "",
-      success_template: ""
-    }, options);
-
-    // Get DOM elements
-    this.$alerts = $(this.options.alerts_container);
-    this.$alerts_list = this.$alerts.find('.alerts-list');
-
-    // Store and freeze alerts list height for affix
-    this.$height = this.$alerts.height();
-    this.$alerts.height(this.$height);
-
-    // Affix alerts
-    this.$alerts_list.affix({
-      offset: {
-        top: this.$alerts.offset().top
-      }
-    });
-
-    // Slide up alert
-    function bindCloseEvents(controller) {
-      controller.$alerts_list.on('click', '.alert-div .close', function() {
-        var $alert = $(this).parent().parent();
-        controller.$height -= $alert.height();
-        controller.$alerts.animate({height: controller.$height}, {queue: false});
-        $alert.slideUp(400, function() {
-          $(this).remove();
-        });
-      });
+// Misago alerts controller
+var MisagoAlerts = function(options) {
+
+  var _this = this;
+
+  this.options = $.extend({
+    alerts_container: ".misago-alerts",
+    generic_error: "Unspecified error occured",
+    error_template: "",
+    info_template: "",
+    success_template: ""
+  }, options);
+
+  // Get DOM elements
+  this.$alerts = $(this.options.alerts_container);
+  this.$alerts_list = this.$alerts.find('.alerts-list');
+
+  // Store and freeze alerts list height for affix
+  this.$height = this.$alerts.height();
+  this.$alerts.height(this.$height);
+
+  // Affix alerts
+  this.$alerts_list.affix({
+    offset: {
+      top: this.$alerts.offset().top
     }
     }
-    bindCloseEvents(this);
-
-    // Heartbeat alert
-    function heartbeat($element) {
-      $element.fadeTo(300, 0.8).fadeTo(1000, 1, function() {
-        heartbeat($element);
-      });
-    }
-
-    // Alerts functions
-    this.add_alert = function(template, message) {
-      if (message == undefined) {
-        message = this.options.generic_error;
-      }
-
-      var repeated_alert = false;
-      $alerts_list.find('.alert').each(function() {
-        if ($(this).text().indexOf(message) == 0 ) {
-          repeated_alert = true;
-          heartbeat($(this));
-        }
+  });
+
+  // Slide up alert
+  function bind_close_events() {
+    _this.$alerts_list.on('click', '.alert-div .close', function() {
+      var $alert = $(this).parent().parent();
+      _this.$height -= $alert.height();
+      _this.$alerts.animate({height: _this.$height}, {queue: false});
+      $alert.slideUp(400, function() {
+        $(this).remove();
       });
       });
+    });
+  }
+  bind_close_events();
 
 
-      if (!repeated_alert) {
-        var $alert = $(template.replace('%message%', message));
-        this.$alerts_list.append($alert);
+  // Heartbeat alert
+  function heartbeat($element) {
+    $element.fadeTo(300, 0.8).fadeTo(1000, 1, function() {
+      heartbeat($element);
+    });
+  }
 
 
-        this.$height += $alert.height();
-        $alert.hide();
-        this.$alerts.animate({height: this.$height}, {queue: false});
-        $alert.slideDown();
-      }
+  // Alerts functions
+  this.add_alert = function(template, message) {
+    if (message == undefined) {
+      message = this.options.generic_error;
     }
     }
 
 
-    this.error = function(message) {
-      this.add_alert(self.options.error_template, message);
-    }
+    var repeated_alert = false;
+    this.$alerts_list.find('.alert').each(function() {
+      if ($(this).text().indexOf(message) == 0 ) {
+        repeated_alert = true;
+        heartbeat($(this));
+      }
+    });
 
 
-    this.info = function(message) {
-      this.add_alert(self.options.info_template, message);
-    }
+    if (!repeated_alert) {
+      var $alert = $(template.replace('%message%', message));
+      this.$alerts_list.append($alert);
 
 
-    this.success = function(message) {
-      this.add_alert(self.options.success_template, message);
+      this.$height += $alert.height();
+      $alert.hide();
+      this.$alerts.animate({height: this.$height}, {queue: false});
+      $alert.slideDown();
     }
     }
+  }
 
 
-    // Return object
-    return this;
-
-  };
+  this.error = function(message) {
+    this.add_alert(this.options.error_template, message);
+  }
 
 
-  // Plugin definition
-  // ==========================
+  this.info = function(message) {
+    this.add_alert(this.options.info_template, message);
+  }
 
 
-  $.misago_alerts = function(options) {
-    if ($._misago_alerts == undefined) {
-      $._misago_alerts = MisagoAlerts(options);
-    }
-    return $._misago_alerts;
-  };
+  this.success = function(message) {
+    this.add_alert(this.options.success_template, message);
+  }
 
 
-}(jQuery));
+};

+ 53 - 0
misago/static/misago/js/misago-bindings.js

@@ -0,0 +1,53 @@
+// Extra data bindings
+$(function() {
+  // hide all pop-ins
+  $('[data-misago-pop-in]').hide();
+
+  // update bindings on new data from server
+  Misago.Server.on_data(function(data) {
+    // Update and fade in/out badges
+    $('[data-misago-badge]').each(function() {
+      var new_value = Misago.getattr(data, $(this).data('misago-badge'));
+      if (new_value != undefined) {
+        $(this).text(new_value);
+        if (new_value > 0) {
+          $(this).addClass("in");
+        } else {
+          $(this).removeClass("in");
+        }
+      }
+    });
+
+    // update text
+    $('[data-misago-text]').each(function() {
+      var new_value = Misago.getattr(data, $(this).data('misago-text'));
+      if (new_value != undefined) {
+        $(this).text(new_value);
+      }
+    });
+
+    // fade in/out depending on value
+    $('[data-misago-fade-in]').each(function() {
+      var new_value = Misago.getattr(data, $(this).data('misago-fade-in'));
+      if (new_value != undefined) {
+        if (new_value > 0) {
+          $(this).addClass("in");
+        } else {
+          $(this).removeClass("in");
+        }
+      }
+    });
+
+    // pop in/out depending on value
+    $('[data-misago-pop-in]').each(function() {
+      var new_value = Misago.getattr(data, $(this).data('misago-pop-in'));
+      if (new_value != undefined) {
+        if (new_value > 0) {
+          $(this).slideIn();
+        } else {
+          $(this).slideOut();
+        }
+      }
+    });
+  });
+});

+ 12 - 29
misago/static/misago/js/misago-dom.js

@@ -1,35 +1,18 @@
-// Misago DOM upades helper
-(function($) {
+// Event controller for DOM changes
+var MisagoDOM = function() {
 
 
-  // Events sender
-  // ===============================
-
-  var MisagoDOM = function() {
+  this.dom_listeners = [];
+  this.on_change = function(callback) {
+    this.dom_listeners.push(callback);
+    callback();
+  };
 
 
-    this.dom_listeners = [];
-    this.change = function(callback) {
-      this.dom_listeners.push(callback);
+  this.changed = function() {
+    $.each(this.dom_listeners, function(i, callback) {
       callback();
       callback();
-    };
-
-    this.changed = function() {
-      $.each(this.dom_listeners, function(i, callback) {
-        callback();
-      });
-    };
-
-    // Return object
-    return this;
+    });
   };
   };
 
 
-  // Plugin definition
-  // ==========================
-
-  $.misago_dom = function() {
-    if ($._misago_dom == undefined) {
-      $._misago_dom = MisagoDOM();
-    }
-    return $._misago_dom;
-  };
+};
 
 
-}(jQuery));
+Misago.DOM = new MisagoDOM();

+ 13 - 26
misago/static/misago/js/misago-modal.js

@@ -1,11 +1,10 @@
-// Misago modal extension
+// Misago modal controller
 (function($) {
 (function($) {
 
 
-  // Modal handler class definition
-  // ===============================
-
   var MisagoModal = function() {
   var MisagoModal = function() {
 
 
+    var _this = this;
+
     this.$modal = $('#ajax-modal');
     this.$modal = $('#ajax-modal');
     this.$content = $('#ajax-modal .modal-content');
     this.$content = $('#ajax-modal .modal-content');
 
 
@@ -13,38 +12,26 @@
       return $('body').hasClass('modal-open');
       return $('body').hasClass('modal-open');
     }
     }
 
 
-    this.show_modal = function(html) {
-      if (this.is_visible()) {
-        this.$content.fadeOut(200);
-        this.$content.html(html);
-        this.$content.fadeIn(200);
+    this.show = function(html) {
+      if (_this.is_visible()) {
+        _this.$content.fadeOut(200);
+        _this.$content.html(html);
+        _this.$content.fadeIn(200);
       } else {
       } else {
-        this.$content.html(html);
-        this.$modal.modal({show: true});
+        _this.$content.html(html);
+        _this.$modal.modal({show: true});
       }
       }
     }
     }
 
 
     this.post = function(url, data) {
     this.post = function(url, data) {
-      var _this = this;
       $.post(url, data, function(data) {
       $.post(url, data, function(data) {
-        _this.show_modal(data);
-        $.misago_dom().changed();
+        _this.show(data);
+        Misago.DOM.changed();
       });
       });
     }
     }
 
 
-    // Return object
-    return this;
-
   };
   };
 
 
-  // Plugin definition
-  // ==========================
-
-  $.misago_modal = function(options) {
-    if ($._misago_modal == undefined) {
-      $._misago_modal = MisagoModal();
-    }
-    return $._misago_modal;
-  };
+  Misago.Modal = new MisagoModal();
 
 
 }(jQuery));
 }(jQuery));

+ 16 - 17
misago/static/misago/js/misago-notifications.js

@@ -4,22 +4,21 @@ $(function() {
   var $container = $('.user-notifications-nav');
   var $container = $('.user-notifications-nav');
   var $link = $container.children('a');
   var $link = $container.children('a');
 
 
-  function notifications_handler(data) {
-    if (ajax_cache != null && data.count != ajax_cache.count) {
-      ajax_cache = null;
-      if ($container.hasClass('open')) {
-        $container.find('.btn-refresh').fadeIn();
-        if (data.count > 0) {
-          $container.find('.btn-read-all').fadeIn();
-        } else {
-          $container.find('.btn-read-all').fadeOut();
+  if (is_authenticated) {
+    Misago.Server.on_data("notifications", function(data) {
+      Tinycon.setBubble(data.count);
+      if (ajax_cache != null && data.count != ajax_cache.count) {
+        ajax_cache = null;
+        if ($container.hasClass('open')) {
+          $container.find('.btn-refresh').fadeIn();
+          if (data.count > 0) {
+            $container.find('.btn-read-all').fadeIn();
+          } else {
+            $container.find('.btn-read-all').fadeOut();
+          }
         }
         }
       }
       }
-    }
-  }
-
-  if (is_authenticated) {
-    $.misago_ui().observer("misago_notifications", notifications_handler);
+    });
   }
   }
 
 
   var $display = $container.find('.display');
   var $display = $container.find('.display');
@@ -30,7 +29,7 @@ $(function() {
     $loader.hide();
     $loader.hide();
     $display.html(data.html);
     $display.html(data.html);
     $display.show();
     $display.show();
-    $.misago_dom().changed();
+    Misago.DOM.changed();
     $link.tooltip('destroy');
     $link.tooltip('destroy');
   }
   }
 
 
@@ -54,7 +53,7 @@ $(function() {
     }
     }
   });
   });
   $container.on('hide.bs.dropdown', function() {
   $container.on('hide.bs.dropdown', function() {
-    misago_tooltip($link);
+    Misago.bind_tooltips();
     $container.find('.btn-refresh').hide();
     $container.find('.btn-refresh').hide();
   });
   });
   $container.on('submit', '.read-all-notifications', function() {
   $container.on('submit', '.read-all-notifications', function() {
@@ -62,7 +61,7 @@ $(function() {
     $loader.show();
     $loader.show();
     $.post($link.attr('href'), $(this).serialize(), function(data) {
     $.post($link.attr('href'), $(this).serialize(), function(data) {
       handle_list_response(data);
       handle_list_response(data);
-      $.misago_ui().query_server();
+      Misago.Server.update()
     });
     });
     return false;
     return false;
   });
   });

+ 2 - 1
misago/static/misago/js/misago-scrolling.js

@@ -1,3 +1,4 @@
+// Scrolling enhancement for overflow: scroll elements
 $(function() {
 $(function() {
   function handle_scroll($element, e) {
   function handle_scroll($element, e) {
     var scroll = $element.scrollTop();
     var scroll = $element.scrollTop();
@@ -24,5 +25,5 @@ $(function() {
     });
     });
   }
   }
 
 
-  $.misago_dom().change(add_scroll_handlers);
+  Misago.DOM.on_change(add_scroll_handlers);
 });
 });

+ 77 - 48
misago/static/misago/js/misago-timestamps.js

@@ -1,70 +1,99 @@
+// Misago dynamic timestamps via Moment.js
 $(function() {
 $(function() {
-  moment.lang($('html').attr('lang'))
 
 
-  if (lang_time_units === undefined) {
-    var units_formats = "smhd";
-  } else {
-    var units_formats = lang_time_units;
-  }
+  function MisagoTimestamps() {
 
 
-  var moment_now = moment();
-  var time_format = moment_now.lang()._longDateFormat.LT;
+    var _this = this;
 
 
-  var moments = {};
+    moment.lang($('html').attr('lang'))
 
 
-  // Initialize moment.js for dates
-  function discover_dates() {
-    $('.dynamic').each(function() {
-      var timestamp = $(this).data('timestamp');
-      var rel_moment = moment(timestamp);
+    if (lang_time_units === undefined) {
+      this.units_formats = "smhd";
+    } else {
+      this.units_formats = lang_time_units;
+    }
 
 
-      moments[timestamp] = {
-        rel_moment: rel_moment,
-        original: $(this).text()
-      }
-    });
-  }
-  discover_dates();
-
-  // Update function
-  function update_times() {
-    $('.time-ago').each(function() {
-      var timestamp = $(this).data('timestamp');
-
-      if (moment_now.diff(moments[timestamp].rel_moment, 'minutes') <= 6 && moment_now.diff(moments[timestamp].rel_moment, 'hours') >= -6) {
-        $(this).text(moments[timestamp].rel_moment.fromNow());
-      } else if (moment_now.diff(moments[timestamp].rel_moment, 'days') < 1 && moment_now.diff(moments[timestamp].rel_moment, 'days') > -1) {
-        $(this).text(moments[timestamp].rel_moment.calendar());
-      } else if (moment_now.diff(moments[timestamp].rel_moment, 'days') < 7 && moment_now.diff(moments[timestamp].rel_moment, 'days') > -7) {
-        $(this).text(moments[timestamp].rel_moment.format("dddd, " + time_format));
+    this.moment_now = moment();
+    this.time_format = this.moment_now.lang()._longDateFormat.LT;
+
+    this.moments = {};
+
+    this.time_ago = function(timestamp) {
+      var rel_moment = _this.moments[timestamp].rel_moment;
+
+      if (_this.moment_now.diff(rel_moment, 'minutes') <= 6 && _this.moment_now.diff(rel_moment, 'hours') >= -6) {
+        return _this.moments[timestamp].rel_moment.fromNow();
+      } else if (_this.moment_now.diff(rel_moment, 'days') < 1 && _this.moment_now.diff(rel_moment, 'days') > -1) {
+        return _this.moments[timestamp].rel_moment.calendar();
+      } else if (_this.moment_now.diff(rel_moment, 'days') < 7 && _this.moment_now.diff(rel_moment, 'days') > -7) {
+        return _this.moments[timestamp].rel_moment.format("dddd, " + _this.time_format);
       } else {
       } else {
-        $(this).text(moments[timestamp].original);
+        return _this.moments[timestamp].original;
       }
       }
-    });
+    }
 
 
-    $('.time-ago-compact').each(function() {
-      var timestamp = $(this).data('timestamp');
-      var diff_seconds = moment_now.diff(moments[timestamp].rel_moment, 'seconds');
+    this.time_ago_compact = function(timestamp) {
+      var rel_moment = _this.moments[timestamp].rel_moment;
+      var diff_seconds = _this.moment_now.diff(rel_moment, 'seconds');
 
 
       if (diff_seconds < 60) {
       if (diff_seconds < 60) {
-        $(this).text(diff_seconds + units_formats[0]);
+        return diff_seconds + _this.units_formats[0];
       } else if (diff_seconds < (60 * 56)) {
       } else if (diff_seconds < (60 * 56)) {
         var diff_minutes = Math.floor(diff_seconds / 60);
         var diff_minutes = Math.floor(diff_seconds / 60);
-        $(this).text(diff_minutes + units_formats[1]);
+        return diff_minutes + _this.units_formats[1];
       } else if (diff_seconds <= (3600 * 23)) {
       } else if (diff_seconds <= (3600 * 23)) {
         var diff_hours = Math.floor(diff_seconds / 3600);
         var diff_hours = Math.floor(diff_seconds / 3600);
-        $(this).text(diff_hours + units_formats[2]);
+        return diff_hours + _this.units_formats[2];
       } else if (true | diff_seconds < (3600 * 24 * 15)) {
       } else if (true | diff_seconds < (3600 * 24 * 15)) {
         var diff_days = Math.floor(diff_seconds / (3600 * 24));
         var diff_days = Math.floor(diff_seconds / (3600 * 24));
-        $(this).text(diff_days + units_formats[3]);
+        return diff_days + _this.units_formats[3];
       } else {
       } else {
-        $(this).text(moments[timestamp].original);
+        return _this.moments[timestamp].original;
       }
       }
-    });
+
+    }
+
+    this.discover = function() {
+      $('.dynamic').each(function() {
+        if ($(this).data('misago-timestamp') == undefined) {
+          $(this).data('misago-timestamp', true);
+
+          var timestamp = $(this).data('timestamp');
+          var rel_moment = moment(timestamp);
+
+          if (_this.moments[timestamp] == undefined) {
+            _this.moments[timestamp] = {
+              rel_moment: rel_moment,
+              original: $(this).text()
+            };
+          }
+        }
+      });
+    }
+
+    this.update = function() {
+      $('.time-ago').each(function() {
+        $(this).text(_this.time_ago($(this).data('timestamp')));
+      });
+
+      $('.time-ago-compact').each(function() {
+        $(this).text(_this.time_ago_compact($(this).data('timestamp')));
+      });
+    }
+
+    this.discover();
+    this.update();
+
   }
   }
 
 
-  // Run updates
-  $.misago_dom().change(discover_dates);
-  $.misago_dom().change(update_times);
-  window.setInterval(update_times, 5000);
+  // start timestamps controller
+  Misago.Timestamps = new MisagoTimestamps();
+  window.setInterval(Misago.Timestamps.update, 5000);
+
+  // keep document updated
+  Misago.DOM.on_change(function() {
+    Misago.Timestamps.discover();
+    Misago.Timestamps.update();
+  });
+
 });
 });

+ 17 - 22
misago/static/misago/js/misago-tooltips.js

@@ -1,30 +1,25 @@
-// Register tooltips
+// Fancy data-bound tooltips
 $(function() {
 $(function() {
-  $.misago_dom().change(function() {
+  function set_tooltips() {
     $('.tooltip-top').tooltip({container: 'body', placement: 'top'});
     $('.tooltip-top').tooltip({container: 'body', placement: 'top'});
     $('.tooltip-bottom').tooltip({container: 'body', placement: 'bottom'});
     $('.tooltip-bottom').tooltip({container: 'body', placement: 'bottom'});
     $('.tooltip-left').tooltip({container: 'body', placement: 'left'});
     $('.tooltip-left').tooltip({container: 'body', placement: 'left'});
     $('.tooltip-right').tooltip({container: 'body', placement: 'right'});
     $('.tooltip-right').tooltip({container: 'body', placement: 'right'});
-    $('.tooltip-top, .tooltip-bottom, .tooltip-left, .tooltip-right').each(function() {
-      $(this).tooltip('fixTitle');
-    });
-  });
-});
-
-// Helper for registering tooltips
-function misago_tooltip(element) {
-  placement = null;
-  if (element.hasClass('tooltip-top')) {
-    placement = 'top';
-  } else if (element.hasClass('tooltip-bottom')) {
-    placement = 'bottom';
-  } else if (element.hasClass('tooltip-left')) {
-    placement = 'left';
-  } else if (element.hasClass('tooltip-right')) {
-    placement = 'right';
   }
   }
 
 
-  if (placement) {
-    element.tooltip({container: 'body', placement: placement})
+  function bind_tooltips(data) {
+    $('[data-misago-tooltip]').each(function() {
+      var new_tooltip = Misago.getattr(data, $(this).data('misago-tooltip'));
+      if (new_tooltip != undefined) {
+        $(this).attr("title", new_tooltip);
+        $(this).tooltip('fixTitle');
+      }
+    });
   }
   }
-}
+
+  // Bind tooltips to DOM
+  bind_tooltips();
+  Misago.set_tooltips = set_tooltips;
+  Misago.DOM.on_change(set_tooltips);
+  Misago.Server.on_data(bind_tooltips);
+});

+ 34 - 50
misago/static/misago/js/misago-uiserver.js

@@ -1,65 +1,49 @@
 // Misago UI server
 // Misago UI server
-(function($) {
+var MisagoUIServer = function(frequency) {
 
 
-  // Class definition
-  // ===============================
+  if (frequency == undefined) {
+    frequency = 15000;
+  }
 
 
-  var MisagoUIServer = function(frequency) {
+  this.frequency = frequency;
+  var _this = this;
 
 
-    if (frequency == undefined) {
-      frequency = 15000;
+  this.listeners = [];
+  this.on_data = function(name, callback) {
+    if (callback == undefined) {
+      this.listeners.push({callback: name});
+    } else {
+      this.listeners.push({name: name, callback: callback});
     }
     }
+  };
 
 
-    this.ui_observers = [];
-    this.observer = function(name, callback) {
-      if (callback == undefined) {
-        this.ui_observers.push({callback: name});
-      } else {
-        this.ui_observers.push({name: name, callback: callback});
-      }
-    };
-
-    this.query_server = function(poll) {
-      if (poll === undefined) {
-        poll = 0;
-      }
-
-      ui_observers = this.ui_observers
-      $.get(uiserver_url, function(data) {
-        $.each(ui_observers, function(i, observer) {
-          if (observer.name == undefined) {
-            observer.callback(data);
-          } else if (typeof data[observer.name] !== "undefined") {
-            observer.callback(data[observer.name]);
-          }
-        });
-
-        $.misago_dom().changed();
+  this.update = function() {
+    $.get(uiserver_url, function(data) {
 
 
-        if (poll > 0) {
-          window.setTimeout(function() {
-            query_server(frequency);
-          }, poll);
+      $.each(_this.listeners, function(i, listener) {
+        if (listener.name == undefined) {
+          listener.callback(data);
+        } else if (typeof data[listener.name] !== "undefined") {
+          listener.callback(data[listener.name]);
         }
         }
       });
       });
-    };
 
 
-    window.setTimeout(function() {
-      query_server(frequency);
-    }, 2000); // First request after 2 seconds
+      Misago.DOM.changed();
 
 
-    // Return object
-    return this;
+      window.setTimeout(function() {
+        _this.update();
+      }, _this.frequency);
+
+    });
   };
   };
 
 
-  // Plugin definition
-  // ==========================
+}
 
 
-  $.misago_ui = function(frequency) {
-    if ($._misago_ui == undefined) {
-      $._misago_ui = MisagoUIServer(frequency);
-    }
-    return $._misago_ui;
-  };
 
 
-}(jQuery));
+// Create server and start it 2 seconds after dom ready
+Misago.Server = new MisagoUIServer();
+$(function() {
+  window.setTimeout(function() {
+    Misago.Server.update();
+  }, 2000);
+});

+ 0 - 31
misago/static/misago/js/misago-user-nav.js

@@ -1,31 +0,0 @@
-$(function() {
-  var $nav = $('#main-navbar');
-
-  if (is_authenticated) {
-    // badges updates
-    $.misago_ui().observer(function(data) {
-      $nav.find('.badge').each(function() {
-        var binding_name = $(this).data('badge-binding');
-        if (binding_name != undefined && data[binding_name].count != undefined) {
-          var count = data[binding_name].count;
-          $(this).text(count);
-          if (count > 0) {
-            $(this).addClass("in");
-          } else {
-            $(this).removeClass("in");
-          }
-        }
-      });
-    });
-
-    // tooltips updates
-    $.misago_ui().observer(function(data) {
-      $nav.find('.tooltip-bottom').each(function() {
-        var binding_name = $(this).data('tooltip-binding');
-        if (binding_name != undefined && data[binding_name].message != undefined) {
-          $(this).attr("title", data[binding_name].message);
-        }
-      });
-    });
-  }
-});

+ 14 - 0
misago/static/misago/js/misago.js

@@ -0,0 +1,14 @@
+// Just an container for Misago js
+// ===============================
+var Misago = {}
+
+Misago.getattr = function(obj, path) {
+  if (obj == undefined) {
+    return undefined;
+  }
+
+  $.each(path.split("."), function(i, bit) {
+    obj = obj[bit];
+  })
+  return obj;
+}

+ 1 - 1
misago/templates/misago/base.html

@@ -48,7 +48,7 @@
     {% compressed_js 'misago' %}
     {% compressed_js 'misago' %}
     <script lang="JavaScript">
     <script lang="JavaScript">
       $(function() {
       $(function() {
-        $.misago_alerts({
+        Misago.Alerts = new MisagoAlerts({
           generic_error: "{% trans "Unspecified error occured." %}",
           generic_error: "{% trans "Unspecified error occured." %}",
           error_template: "<div class=\"alert-div\"><p class=\"alert alert-danger\"><span class=\"alert-icon fa fa-times-circle\"></span>%message% <button type=\"button\" class=\"close\">{% trans "Ok!" %}</button></p></div>",
           error_template: "<div class=\"alert-div\"><p class=\"alert alert-danger\"><span class=\"alert-icon fa fa-times-circle\"></span>%message% <button type=\"button\" class=\"close\">{% trans "Ok!" %}</button></p></div>",
           info_template: "<div class=\"alert-div\"><p class=\"alert alert-info\"><span class=\"alert-icon fa fa-info-circle\"></span>%message% <button type=\"button\" class=\"close\">{% trans "Ok!" %}</button></p></div>",
           info_template: "<div class=\"alert-div\"><p class=\"alert alert-info\"><span class=\"alert-icon fa fa-info-circle\"></span>%message% <button type=\"button\" class=\"close\">{% trans "Ok!" %}</button></p></div>",

+ 1 - 1
misago/templates/misago/profile/base.html

@@ -50,7 +50,7 @@
       var $form = $(this);
       var $form = $(this);
       var $button = $form.find('button');
       var $button = $form.find('button');
       $.post($form.attr('action'), $form.serialize(), function(data) {
       $.post($form.attr('action'), $form.serialize(), function(data) {
-        $.misago_alerts().success(data.message);
+        Misago.Alerts.success(data.message);
         if (data.is_following) {
         if (data.is_following) {
           $button.addClass('active');
           $button.addClass('active');
         } else {
         } else {

+ 2 - 2
misago/templates/misago/threads/actions_js.html

@@ -7,13 +7,13 @@
 
 
     $('#threads-actions .action-move').click(function() {
     $('#threads-actions .action-move').click(function() {
       var action_data = $threads_actions.serialize($threads_actions) + '&action=move';
       var action_data = $threads_actions.serialize($threads_actions) + '&action=move';
-      $.misago_modal().post('', action_data);
+      Misago.Modal.post('', action_data);
       return false;
       return false;
     });
     });
 
 
     $('#threads-actions .action-merge').click(function() {
     $('#threads-actions .action-merge').click(function() {
       var action_data = $threads_actions.serialize($threads_actions) + '&action=merge';
       var action_data = $threads_actions.serialize($threads_actions) + '&action=merge';
-      $.misago_modal().post('', action_data);
+      Misago.Modal.post('', action_data);
       return false;
       return false;
     });
     });
   });
   });

+ 5 - 5
misago/templates/misago/user_nav.html

@@ -21,7 +21,7 @@
       </li>
       </li>
       <li>
       <li>
         <a href="{% url 'misago:notifications' %}">
         <a href="{% url 'misago:notifications' %}">
-          <span class="badge fade {{ "in"|iftrue:user.new_notifications }} pull-right" data-badge-binding="misago_notifications">{{ user.new_notifications }}</span>
+          <span class="badge fade {{ "in"|iftrue:user.new_notifications }} pull-right" data-misago-badge="notifications.count">{{ user.new_notifications }}</span>
           <span class="fa fa-bell-o"></span>
           <span class="fa fa-bell-o"></span>
           {% trans "See all notifications" %}
           {% trans "See all notifications" %}
         </a>
         </a>
@@ -29,14 +29,14 @@
       <li class="divider"></li>
       <li class="divider"></li>
       <li>
       <li>
         <a href="{% url 'misago:new_threads' %}">
         <a href="{% url 'misago:new_threads' %}">
-          <span class="badge fade {{ "in"|iftrue:user.new_threads }} pull-right" data-badge-binding="misago_new_threads">{{ user.new_threads }}</span>
+          <span class="badge fade {{ "in"|iftrue:user.new_threads }} pull-right" data-misago-badge="new_threads">{{ user.new_threads }}</span>
           <span class="fa fa-plus-circle"></span>
           <span class="fa fa-plus-circle"></span>
           {% trans "New threads" %}
           {% trans "New threads" %}
         </a>
         </a>
       </li>
       </li>
       <li>
       <li>
         <a href="{% url 'misago:unread_threads' %}">
         <a href="{% url 'misago:unread_threads' %}">
-          <span class="badge fade {{ "in"|iftrue:user.unread_threads }} pull-right" data-badge-binding="misago_unread_threads">{{ user.unread_threads }}</span>
+          <span class="badge fade {{ "in"|iftrue:user.unread_threads }} pull-right" data-misago-badge="unread_threads">{{ user.unread_threads }}</span>
           <span class="fa fa-signal"></span>
           <span class="fa fa-signal"></span>
           {% trans "Unread threads" %}
           {% trans "Unread threads" %}
         </a>
         </a>
@@ -75,7 +75,7 @@
     </a>
     </a>
   </li>
   </li>
   <li class="user-notifications-nav dropdown">
   <li class="user-notifications-nav dropdown">
-    <a href="{% url 'misago:notifications' %}" class="dropdown-toggle tooltip-bottom" data-tooltip-binding="misago_notifications"
+    <a href="{% url 'misago:notifications' %}" class="dropdown-toggle tooltip-bottom" data-misago-tooltip="notifications.message"
         {% if user.new_notifications %}
         {% if user.new_notifications %}
         title="{% blocktrans with notifications=user.new_notifications count counter=user.new_notifications %}{{ notifications }} new notification{% plural %}{{ notifications }} new notifications{% endblocktrans %}"
         title="{% blocktrans with notifications=user.new_notifications count counter=user.new_notifications %}{{ notifications }} new notification{% plural %}{{ notifications }} new notifications{% endblocktrans %}"
         {% else %}
         {% else %}
@@ -83,7 +83,7 @@
         {% endif %}
         {% endif %}
         data-toggle="dropdown">
         data-toggle="dropdown">
       <span class="fa fa-bell-o fa-fw"></span>
       <span class="fa fa-bell-o fa-fw"></span>
-      <span class="badge fade {{ "in"|iftrue:user.new_notifications }}" data-badge-binding="misago_notifications">{{ user.new_notifications }}</span>
+      <span class="badge fade {{ "in"|iftrue:user.new_notifications }}" data-misago-badge="notifications.count">{{ user.new_notifications }}</span>
     </a>
     </a>
     <div class="dropdown-menu">
     <div class="dropdown-menu">
       <div class="display"></div>
       <div class="display"></div>

+ 3 - 3
misago/templates/misago/usercp/upload_avatar.html

@@ -82,12 +82,12 @@
       error: function(avatar, message, xhr) {
       error: function(avatar, message, xhr) {
         if (xhr != undefined) {
         if (xhr != undefined) {
           if (message.message != undefined) {
           if (message.message != undefined) {
-            $.misago_alerts().error(message.message);
+            Misago.Alerts.error(message.message);
           } else {
           } else {
-            $.misago_alerts().error("{% trans "Error occured when sending file to server." %}");
+            Misago.Alerts.error("{% trans "Error occured when sending file to server." %}");
           }
           }
         } else {
         } else {
-          $.misago_alerts().error(message);
+          Misago.Alerts.error(message);
         }
         }
       },
       },
       addedfile: function(file) {
       addedfile: function(file) {

+ 2 - 4
misago/threads/views/newthreads.py

@@ -51,9 +51,7 @@ class NewThreadsView(ThreadsView):
                 request, *args, **kwargs)
                 request, *args, **kwargs)
 
 
 
 
-@uiview("misago_new_threads")
+@uiview("new_threads")
 @deny_guests
 @deny_guests
 def event_sender(request, resolver_match):
 def event_sender(request, resolver_match):
-    return {
-        'count': int(request.user.new_threads)
-    }
+    return int(request.user.new_threads)

+ 2 - 4
misago/threads/views/unreadthreads.py

@@ -53,9 +53,7 @@ class UnreadThreadsView(ThreadsView):
                 request, *args, **kwargs)
                 request, *args, **kwargs)
 
 
 
 
-@uiview("misago_unread_threads")
+@uiview("unread_threads")
 @deny_guests
 @deny_guests
 def event_sender(request, resolver_match):
 def event_sender(request, resolver_match):
-    return {
-        'count': int(request.user.unread_threads)
-    }
+    return int(request.user.unread_threads)