diff --git a/modoboa/extensions/admin/static/admin/js/admin.js b/modoboa/extensions/admin/static/admin/js/admin.js
index 5200fc4c6..1c18507a5 100644
--- a/modoboa/extensions/admin/static/admin/js/admin.js
+++ b/modoboa/extensions/admin/static/admin/js/admin.js
@@ -23,12 +23,16 @@ Admin.prototype = {
this.listen();
},
+ /**
+ * Callback used when the initial content of the listing is
+ * received.
+ *
+ * @this Admin
+ * @param {Object} data - response of the ajax call (JSON)
+ */
list_cb: function(data) {
- $("#objects_table tbody").html(function(pos, oldhtml) {
- return oldhtml + data.rows;
- });
+ $("#objects_table tbody").html(data.rows);
this.update_listing(data);
- $("a.filter").click($.proxy(this.filter_by_tag, this));
},
/**
@@ -47,6 +51,7 @@ Admin.prototype = {
* Children must override this method.
*/
listen: function() {
+ $(document).on("click", "a.filter", $.proxy(this.filter_by_tag, this));
},
importform_cb: function() {
@@ -106,7 +111,8 @@ var Domains = function(options) {
Domains.prototype = {
initialize: function(options) {
Admin.prototype.initialize.call(this, options);
- this.register_tag_handler("dom", this.generic_tag_handler);
+ this.options.navigation_params.push("domfilter", "srvfilter");
+ this.register_tag_handler("dom");
},
end_of_list_reached: function(element) {
@@ -239,8 +245,9 @@ var Identities = function(options) {
Identities.prototype = {
initialize: function(options) {
Admin.prototype.initialize.call(this, options);
+ this.options.navigation_params.push("idtfilter", "grpfilter");
this.domain_list = [];
- this.register_tag_handler("idt", this.generic_tag_handler);
+ this.register_tag_handler("idt");
this.register_tag_handler("grp", this.grp_tag_handler);
},
@@ -289,16 +296,17 @@ Identities.prototype = {
},
grp_tag_handler: function(tag, $link) {
- if (this.navobj.getparam(tag + "filter") === undefined && $link.hasClass(tag)) {
+ if (this.navobj.getparam(tag + "filter") === undefined &&
+ $link.hasClass(tag)) {
var text = $link.attr("name");
this.navobj
.setparam("idtfilter", "account")
.setparam(tag + "filter", text)
.update();
if ($("a[name=idt]").length === 0) {
- $("#searchform").parent().after(this.make_tag("account", "idt"));
+ $("#taglist").append(this.make_tag("account", "idt"));
}
- $("#searchform").parent().after(this.make_tag(text, tag));
+ $("#taglist").append(this.make_tag(text, tag));
return true;
}
return false;
diff --git a/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js b/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
index 3b6a36386..dddc99e8d 100644
--- a/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
+++ b/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
@@ -90,9 +90,9 @@ RelayDomains.prototype = {
.setparam(tag + "filter", text)
.update();
if ($("a[name=dom]").length === 0) {
- $("#searchform").parent().after(this.make_tag("relaydomain", "dom"));
+ $("#taglist").append(this.make_tag("relaydomain", "dom"));
}
- $("#searchform").parent().after(this.make_tag(text, tag));
+ $("#taglist").append(this.make_tag(text, tag));
return true;
}
return false;
diff --git a/modoboa/static/js/listing.js b/modoboa/static/js/listing.js
index a8317eba9..b1c745d7c 100644
--- a/modoboa/static/js/listing.js
+++ b/modoboa/static/js/listing.js
@@ -17,7 +17,8 @@ Listing.prototype = {
pbar_id: '#pagination_bar',
sortable_selector: '.sortable',
with_searchform: true,
- load_page_url: null
+ load_page_url: null,
+ navigation_params: ["sort_order", "searchquery"]
},
initialize: function(options) {
@@ -76,6 +77,23 @@ Listing.prototype = {
this.navobj.updateparams($link.attr("href")).update();
},
+ /**
+ * Return extra arguments used to fetch a page.
+ *
+ * @this Listing
+ */
+ get_load_page_args: function() {
+ var $this = this;
+ var args = {};
+
+ $.each(this.options.navigation_params, function(pos, param) {
+ if ($this.navobj.hasparam(param)) {
+ args[param] = $this.navobj.getparam(param);
+ }
+ });
+ return args;
+ },
+
/**
* Update the listing with the received data.
*
@@ -83,16 +101,20 @@ Listing.prototype = {
* @param {Object} data - new content
*/
update_listing: function(data) {
- $(window).infinite_scroll({
- url: this.options.load_page_url,
- calculate_bottom: function($element) {
- var $last_row = $("#objects_table").find("tr").last();
-
- return $last_row.offset().top - $element.height();
- },
- process_results: this.add_new_page,
- end_of_list_reached: this.end_of_list_reached
- });
+ if ($(window).data("infinite-scroll") !== undefined) {
+ $(window).infinite_scroll("reset_loaded_pages", data.page);
+ } else {
+ $(window).infinite_scroll({
+ url: this.options.load_page_url,
+ get_args: $.proxy(this.get_load_page_args, this),
+ calculate_bottom: function($element) {
+ var $last_row = $("#objects_table").find("tr").last();
+ return $last_row.offset().top - $element.height();
+ },
+ process_results: this.add_new_page,
+ end_of_list_reached: this.end_of_list_reached
+ });
+ }
var $sortables = $(this.options.sortable_selector);
if ($sortables.length) {
@@ -136,7 +158,17 @@ Listing.prototype = {
this.navobj.setparam("sort_order", sort_order).update();
},
+ /**
+ * Register a new tag handler.
+ *
+ * @this Listing
+ * @param {string} name - name of the tag
+ * @param {function} handler - reference to a function (optional)
+ */
register_tag_handler: function(name, handler) {
+ if (handler === undefined) {
+ handler = this.generic_tag_handler;
+ }
this.tag_handlers[name] = handler;
if (this.navobj.getparam(name + "filter") !== undefined) {
var text = this.navobj.getparam(name + "filter");
@@ -144,6 +176,14 @@ Listing.prototype = {
}
},
+ /**
+ * Default tag handler.
+ *
+ * @this Listing
+ * @param {string} tag - name of the tag
+ * @param {Object} $link - tag that was clicked
+ * @return {boolean} - return true if handler has been executed
+ */
generic_tag_handler: function(tag, $link) {
if (this.navobj.getparam(tag + "filter") === undefined && $link.hasClass(tag)) {
var text = $link.attr("name");
@@ -154,10 +194,18 @@ Listing.prototype = {
return false;
},
+ /**
+ * Build a button to remove a specific filter.
+ *
+ * @this Listing
+ * @param {string} text - text of the button
+ * @param {string} type - tag type
+ * @return {Object} - new button object
+ */
make_tag: function(text, type) {
var $tag = $("", {
"name": type, "class" : "btn btn-default btn-xs",
- "html": text
+ "html": " " + text
});
$("", {"class" : "fa fa-remove"}).prependTo($tag);
@@ -165,6 +213,12 @@ Listing.prototype = {
return $tag;
},
+ /**
+ * Click event : remove a tag button.
+ *
+ * @this Listing
+ * @param {Object} e - event object
+ */
remove_tag: function(e) {
var $tag = $(e.target);
@@ -176,6 +230,12 @@ Listing.prototype = {
$tag.remove();
},
+ /**
+ * Click event: filter the listing when a tag is clicked.
+ *
+ * @this Listing
+ * @param {Object} e - event object
+ */
filter_by_tag: function(e) {
var $link = $(e.target);
e.preventDefault();