diff --git a/modoboa/extensions/sievefilters/templates/sievefilters/filter.html b/modoboa/extensions/sievefilters/templates/sievefilters/filter.html
index bd51ecdbb..e0476c0b4 100644
--- a/modoboa/extensions/sievefilters/templates/sievefilters/filter.html
+++ b/modoboa/extensions/sievefilters/templates/sievefilters/filter.html
@@ -1,5 +1,8 @@
{% extends "common/generic_modal_form.html" %}
{% load i18n form_tags sfilters_tags %}
+
+{% block modal_css_classes %}modal-lg{% endblock %}
+
{% block formbody %}
{% if oldname %}{% endif %}
{% render_field form.name %}
diff --git a/modoboa/extensions/webmail/lib/__init__.py b/modoboa/extensions/webmail/lib/__init__.py
index bf1f4b89f..0f0b166b3 100644
--- a/modoboa/extensions/webmail/lib/__init__.py
+++ b/modoboa/extensions/webmail/lib/__init__.py
@@ -6,7 +6,6 @@ from .imapemail import ImapEmail, ReplyModifier, ForwardModifier
from .imaputils import (
BodyStructure, IMAPconnector, get_imapconnector, separate_mailbox
)
-from .listing import ImapListing
from .signature import EmailSignature
from .utils import decode_payload, WebmailNavigationParameters
from .sendmail import send_mail
@@ -20,7 +19,6 @@ __all__ = [
'ForwardModifier',
'IMAPconnector',
'ImapEmail',
- 'ImapListing',
'ReplyModifier',
'WebmailNavigationParameters',
'clean_attachments',
diff --git a/modoboa/extensions/webmail/lib/imaputils.py b/modoboa/extensions/webmail/lib/imaputils.py
index 5b4447f8c..d087306f4 100644
--- a/modoboa/extensions/webmail/lib/imaputils.py
+++ b/modoboa/extensions/webmail/lib/imaputils.py
@@ -141,6 +141,9 @@ class BodyStructure(object):
class IMAPconnector(object):
+
+ """The IMAPv4 connector."""
+
__metaclass__ = ConnectionsManager
list_base_pattern = r'\((?P.*?)\) "(?P.*)" "?(?P[^"]*)"?'
@@ -300,6 +303,32 @@ class IMAPconnector(object):
del self.m
self.m = None
+ def parse_search_parameters(self, criterion, pattern):
+ """Parse search information and apply them."""
+
+ def or_criterion(old, c):
+ if old == "":
+ return c
+ return "OR (%s) (%s)" % (old, c)
+
+ if criterion == u"both":
+ criterion = u"from_addr, subject"
+ criterions = ""
+ if type(pattern) is unicode:
+ pattern = pattern.encode("utf-8")
+ if type(criterion) is unicode:
+ criterion = criterion.encode("utf-8")
+ for c in criterion.split(','):
+ if c == "from_addr":
+ key = "FROM"
+ elif c == "subject":
+ key = "SUBJECT"
+ else:
+ continue
+ criterions = \
+ or_criterion(criterions, '(%s "%s")' % (key, pattern))
+ self.criterions = [criterions]
+
def messages_count(self, **kwargs):
"""An enhanced version of messages_count
@@ -456,7 +485,9 @@ class IMAPconnector(object):
from operator import itemgetter
mailboxes += sorted(newmboxes, key=itemgetter("name"))
- def getmboxes(self, user, topmailbox='', until_mailbox=None, unseen_messages=True):
+ def getmboxes(
+ self, user, topmailbox='', until_mailbox=None,
+ unseen_messages=True):
"""Returns a list of mailboxes for a particular user
By default, only the first level of mailboxes under
@@ -588,23 +619,33 @@ class IMAPconnector(object):
return True
def getquota(self, mailbox):
+ """Retrieve quota information from the server.
+
+ We also compute the current usage.
+ """
if not "QUOTA" in self.capabilities:
- self.quota_limit = self.quota_actual = None
+ self.quota_limit = self.quota_current = None
return
data = self._cmd("GETQUOTAROOT", self._encode_mbox_name(mailbox),
responses=["QUOTAROOT", "QUOTA"])
if data is None:
- self.quota_limit = self.quota_actual = None
+ self.quota_limit = self.quota_current = None
return
quotadef = data[1][0]
- m = re.search("\(STORAGE (\d+) (\d+)\)", quotadef)
+ m = re.search(r"\(STORAGE (\d+) (\d+)\)", quotadef)
if not m:
print "Problem while parsing quota def"
return
self.quota_limit = int(m.group(2))
- self.quota_actual = int(m.group(1))
+ self.quota_current = int(m.group(1))
+ try:
+ self.quota_usage = (
+ int(float(self.quota_current) / float(self.quota_limit) * 100)
+ )
+ except TypeError:
+ self.quota_usage = -1
def fetchpart(self, uid, mbox, partnum):
"""Retrieve a specific message part
diff --git a/modoboa/extensions/webmail/lib/listing.py b/modoboa/extensions/webmail/lib/listing.py
deleted file mode 100644
index 80d0927d4..000000000
--- a/modoboa/extensions/webmail/lib/listing.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from django.conf import settings
-from django.utils.translation import ugettext_lazy
-
-from modoboa.lib import parameters, tables
-from modoboa.lib.email_listing import EmailListing
-from . import IMAPconnector, imapheader
-
-
-class WMtable(tables.Table):
-
- """Webmail listing table."""
-
- tableid = "emails"
- styles = "table-hover"
- idkey = "imapid"
- drag = tables.ImgColumn(
- "drag", cssclass="draggable left",
- defvalue="%spics/grippy.png" % settings.STATIC_URL,
- header=""
- )
- selection = tables.SelectionColumn(
- "selection", safe=True, header=None, sortable=False
- )
- flags = tables.ImgColumn("flags")
- withatts = tables.ImgColumn("withatts")
- subject = tables.Column(
- "subject", label=ugettext_lazy("Subject"), limit=60,
- cssclass="openable"
- )
- from_ = tables.Column(
- "from", label=ugettext_lazy("From"), limit=30,
- cssclass="openable"
- )
- date = tables.Column(
- "date", label=ugettext_lazy("Date"), cssclass="openable"
- )
-
- cols_order = [
- "drag", "selection", "flags", "from_", "subject", "withatts", "date"
- ]
-
- def parse(self, header, value):
- if value is None:
- return ""
- try:
- value = getattr(imapheader, "parse_%s" % header)(value)
- except AttributeError:
- pass
- return value
-
-
-class ImapListing(EmailListing):
- tpl = "webmail/index.html"
- tbltype = WMtable
- deflocation = "INBOX/"
- defcallback = "wm_updatelisting"
- reset_wm_url = False
-
- def __init__(self, user, password, **kwargs):
- self.user = user
- self.mbc = IMAPconnector(user=user.username, password=password)
- if "pattern" in kwargs and kwargs["pattern"]:
- self.parse_search_parameters(
- kwargs["criteria"], kwargs["pattern"]
- )
- else:
- self.mbc.criterions = []
-
- super(ImapListing, self).__init__(**kwargs)
- self.extravars["refreshrate"] = \
- int(parameters.get_user(user, "REFRESH_INTERVAL")) * 1000
-
- def parse_search_parameters(self, criterion, pattern):
-
- def or_criterion(old, c):
- if old == "":
- return c
- return "OR (%s) (%s)" % (old, c)
-
- if criterion == u"both":
- criterion = u"from_addr, subject"
- criterions = ""
- if type(pattern) is unicode:
- pattern = pattern.encode("utf-8")
- if type(criterion) is unicode:
- criterion = criterion.encode("utf-8")
- for c in criterion.split(','):
- if c == "from_addr":
- key = "FROM"
- elif c == "subject":
- key = "SUBJECT"
- else:
- continue
- criterions = \
- or_criterion(criterions, '(%s "%s")' % (key, pattern))
- self.mbc.criterions = [criterions]
-
- @staticmethod
- def computequota(mbc):
- try:
- return int(float(mbc.quota_actual) \
- / float(mbc.quota_limit) * 100)
- except (AttributeError, TypeError):
- return -1
-
- def getquota(self):
- return ImapListing.computequota(self.mbc)
diff --git a/modoboa/extensions/webmail/static/webmail/css/webmail.css b/modoboa/extensions/webmail/static/webmail/css/webmail.css
index dd85f5f6b..6add291a7 100644
--- a/modoboa/extensions/webmail/static/webmail/css/webmail.css
+++ b/modoboa/extensions/webmail/static/webmail/css/webmail.css
@@ -46,9 +46,6 @@
}
/* GENERAL */
-body, html {
- /*overflow: hidden;*/
-}
#rightcol {
position: fixed;
@@ -90,10 +87,6 @@ body, html {
width: 8px;
}
-#mboxes_container {
- /*overflow: auto;*/
-}
-
.nav-sidebar li > a {
padding-top: 7px;
padding-bottom: 7px;
@@ -273,8 +266,9 @@ list {
}
/*
- * Folder form
+ * Folders form
*/
+
.modal-body {
max-height: 300px;
overflow-y: auto;
@@ -284,6 +278,22 @@ list {
position: relative;
}
+#folders2 div.clickbox {
+ left: 0;
+ top: 0px;
+}
+
+#folders2 li li {
+ margin-left: 10px;
+}
+
+#folders2 .active > a,
+#folders2 .active > a:hover,
+#folders2 .active > a:focus {
+ color: #fff;
+ background-color: #428bca;
+}
+
/*
* Table
*/
diff --git a/modoboa/extensions/webmail/static/webmail/js/webmail.js b/modoboa/extensions/webmail/static/webmail/js/webmail.js
index d49de0ba8..6a356f39f 100644
--- a/modoboa/extensions/webmail/static/webmail/js/webmail.js
+++ b/modoboa/extensions/webmail/static/webmail/js/webmail.js
@@ -186,7 +186,7 @@ Webmail.prototype = {
return $("#emails").height() - $element.height();
},
get_args: function() {
- var args = that.navparams;
+ var args = $.extend({}, that.navparams);
args.scroll = true;
return args;
},
@@ -281,6 +281,8 @@ Webmail.prototype = {
/**
* Simple helper to retrieve the currently selected mailbox.
+ *
+ * @this Webmail
*/
get_current_mailbox: function() {
return this.navobject.getparam("mbox", "INBOX");
@@ -289,9 +291,11 @@ Webmail.prototype = {
/**
* Keep track of interesting navigation parameters in order to
* restore them later.
+ *
+ * @this Webmail
*/
store_nav_params: function() {
- var params = new Array("page", "order", "pattern", "criteria");
+ var params = new Array("order", "pattern", "criteria");
this.navparams = {};
for (var idx in params) {
@@ -299,9 +303,11 @@ Webmail.prototype = {
}
},
- /*
+ /**
* Restore navigation parameters previously stored via
* store_nav_params.
+ *
+ * @this Webmail
*/
restore_nav_params: function() {
if (this.navparams === undefined) {
@@ -360,12 +366,13 @@ Webmail.prototype = {
}
if (response.menu !== undefined) {
$("#menubar").html(response.menu);
- $("#searchfield").searchbar({navobj: this.navobject});
+ $("#searchfield").searchbar({
+ navobj: this.navobject,
+ pattern_changed: function(navobj) {
+ navobj.setparam("reset_page", "true");
+ }
+ });
}
- /*if (response.navbar) {
- $("#pagination").html(response.navbar);
- $("#pagination-responsive").html(response.navbar);
- }*/
$("#listing").html(response.listing);
@@ -525,7 +532,12 @@ Webmail.prototype = {
* @param {Object} parent - parent node where mailboxes will be appended
* @param {boolean} async - if true, the ajax call will be asynchronous
*/
- get_mailboxes: function(parent, async) {
+ get_mailboxes: function(parent, async, with_unseen) {
+ var args = "topmailbox=" + parent.attr("name");
+
+ if (with_unseen) {
+ args += "&unseen=true";
+ }
if (async === undefined) {
async = true;
}
@@ -533,7 +545,7 @@ Webmail.prototype = {
url: this.options.submboxes_url,
dataType: 'json',
async: async,
- data: "topmailbox=" + parent.attr("name")
+ data: args
}).done($.proxy(function(data) {
this.inject_mailboxes(parent, data);
}, this));
@@ -575,7 +587,9 @@ Webmail.prototype = {
var $ul = $parent.find('ul[name="' + $parent.attr("name") + '"]');
if (!$ul.length) {
- this.get_mailboxes($parent);
+ var $link = $div.next();
+ var with_unseen = ($link.attr("name") == "loadfolder") ? true : false;
+ this.get_mailboxes($parent, true, with_unseen);
return;
}
this.toggle_mbox_state($div, $ul);
@@ -642,6 +656,12 @@ Webmail.prototype = {
$('li[name="' + mailbox + '"]').addClass("active");
},
+ /**
+ * Click handler : select the parent mailbox of the mailbox being
+ * created/modified.
+ *
+ * @param {Object} e - event object
+ */
select_parent_mailbox: function(e) {
e.preventDefault();
var $this = $(this);
@@ -808,6 +828,12 @@ Webmail.prototype = {
}, this));
},
+ /**
+ * Click event: empty Trash folder.
+ *
+ * @this Webmail
+ * @param {Object} e - event object
+ */
empty: function(e) {
e.preventDefault();
var $link = $(e.target);
@@ -894,7 +920,7 @@ Webmail.prototype = {
}
this.navobject.reset().setparams({
action: "listmailbox",
- mbox: obj.attr("href"),
+ mbox: obj.attr("href")
});
if (reset_page) {
this.navobject.setparam("reset_page", reset_page);
@@ -1061,16 +1087,19 @@ Webmail.prototype = {
this.resize_compose_body();
},
- /*
+ /**
* Callback of the 'viewmail' action
+ *
+ * @this Webmail
+ * @param {Object} resp - AJAX call response (JSON)
*/
viewmail_callback: function(resp) {
this.page_update(resp);
$("#listing").css("overflow", "hidden");
- // $("a[name=back]").click($.proxy(function(e) {
- // e.preventDefault();
- // this.go_back_to_listing();
- // }, this));
+ $("a[name=back]").click($.proxy(function(e) {
+ e.preventDefault();
+ this.go_back_to_listing();
+ }, this));
},
mark_callback: function(data) {
diff --git a/modoboa/extensions/webmail/views.py b/modoboa/extensions/webmail/views.py
index 1de405f76..c99d84334 100644
--- a/modoboa/extensions/webmail/views.py
+++ b/modoboa/extensions/webmail/views.py
@@ -19,6 +19,7 @@ from django.views.decorators.gzip import gzip_page
from modoboa.lib import parameters
from modoboa.lib.exceptions import ModoboaException, BadRequest
+from modoboa.lib.paginator import Paginator
from modoboa.lib.webutils import (
_render_to_string, ajax_response, render_to_json_response
)
@@ -29,7 +30,7 @@ from .forms import (
)
from .lib import (
decode_payload, AttachmentUploadHandler,
- save_attachment, ImapListing, EmailSignature,
+ save_attachment, EmailSignature,
clean_attachments, set_compose_session, send_mail,
ImapEmail, WebmailNavigationParameters, ReplyModifier, ForwardModifier,
get_imapconnector, IMAPconnector, separate_mailbox
@@ -337,7 +338,8 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
parameter. (user preferences)
:param request: a ``Request`` object
- :param defmailbox: the default mailbox (when not present inside request arguments)
+ :param defmailbox: the default mailbox (when not present inside
+ request arguments)
:return: a dictionnary
"""
navparams = WebmailNavigationParameters(request, defmailbox)
@@ -345,30 +347,34 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
if update_session:
navparams.store()
mbox = navparams.get('mbox')
- lst = ImapListing(
- request.user, request.session["password"],
- baseurl="?action=listmailbox&mbox=%s&" % mbox,
- folder=mbox,
- elems_per_page=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE")),
- **request.session["webmail_navparams"]
- )
page_id = int(navparams["page"])
- page = lst.paginator.getpage(page_id)
+ mbc = get_imapconnector(request)
+ mbc.parse_search_parameters(
+ navparams.get("criteria"), navparams.get("pattern"))
+
+ paginator = Paginator(
+ mbc.messages_count(folder=mbox, order=navparams.get("order")),
+ int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
+ )
+ page = paginator.getpage(page_id)
+
if page is not None:
- email_list = lst.mbc.fetch(
- page.id_start, page.id_stop, mbox,
- nbelems=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
+ email_list = mbc.fetch(
+ page.id_start, page.id_stop, mbox, nbelems=page.items
)
content = _render_to_string(request, "webmail/email_list.html", {
"email_list": email_list,
"page": page_id,
"with_top_div": request.GET.get("scroll", "false") == "false"
})
+ length = len(content)
else:
- content = ""
+ content = "{}
".format(
+ _("Empty mailbox")
+ )
+ length = 0
navparams["page"] = previous_page_id
- return {"listing": content, "length": len(content), "page": page_id}
- #return lst.render(request, navparams.get('page'))
+ return {"listing": content, "length": length, "page": page_id}
def render_compose(request, form, posturl, email=None, insert_signature=False):
@@ -513,8 +519,11 @@ def viewmail(request):
@login_required
@needs_mailbox()
def submailboxes(request):
+ """Retrieve the sub mailboxes of a mailbox."""
topmailbox = request.GET.get('topmailbox', '')
- mboxes = get_imapconnector(request).getmboxes(request.user, topmailbox)
+ with_unseen = request.GET.get('unseen', None)
+ mboxes = get_imapconnector(request).getmboxes(
+ request.user, topmailbox, unseen_messages=with_unseen == 'true')
return render_to_json_response(mboxes)
@@ -575,7 +584,7 @@ def index(request):
imapc.getquota(curmbox)
response["refreshrate"] = \
int(parameters.get_user(request.user, "REFRESH_INTERVAL"))
- response["quota"] = ImapListing.computequota(imapc)
+ response["quota"] = imapc.quota_usage
trash = parameters.get_user(request.user, "TRASH_FOLDER")
response["trash"] = trash
response["ro_mboxes"] = [
diff --git a/modoboa/lib/email_listing.py b/modoboa/lib/email_listing.py
index 8d4c6e904..a576129df 100644
--- a/modoboa/lib/email_listing.py
+++ b/modoboa/lib/email_listing.py
@@ -4,72 +4,7 @@ from django.template.loader import render_to_string
from django.template import Template, Context
from django.utils.translation import ugettext as _
-attached_map = {}
-
-
-class Page(object):
- def __init__(self, pageid, id_start, id_stop, items,
- items_per_page, has_previous, has_next,
- baseurl=None):
- self.number = pageid
- self.id_start = id_start
- self.id_stop = id_stop
- self.items = items
- self.items_per_page = items_per_page
- self.has_previous = has_previous
- self.has_next = has_next
- self.baseurl = baseurl
-
- def previous_page_number(self):
- if not self.has_previous:
- return False
- return self.number - 1
-
- def next_page_number(self):
- if not self.has_next:
- return False
- return self.number + 1
-
- def last_page(self):
- lid = self.items / self.items_per_page
- if not lid:
- return 1
- if self.items % self.items_per_page:
- lid += 1
- return lid
-
-
-class Paginator(object):
- def __init__(self, total, elems_per_page):
- self.total = total
- self.elems_per_page = elems_per_page
- self.num_pages = total / elems_per_page
- if total % elems_per_page:
- self.num_pages += 1
-
- def _indexes(self, page):
- id_start = self.elems_per_page * page + 1
- id_stop = id_start + self.elems_per_page - 1
- return (id_start, id_stop)
-
- def getpage(self, page):
- if page < 1:
- return None
- id_start, id_stop = self._indexes(page - 1)
- has_previous = has_next = False
- if id_start <= self.total:
- if page > 1:
- has_previous = True
- if id_stop < self.total:
- has_next = True
- else:
- id_stop = self.total
- else:
- return None
- p = Page(page, id_start, id_stop, self.total,
- self.elems_per_page, has_previous, has_next)
- p.paginator = self
- return p
+from modoboa.lib.paginator import Paginator
class EmailListing(object):
diff --git a/modoboa/lib/paginator.py b/modoboa/lib/paginator.py
new file mode 100644
index 000000000..6ba5dab20
--- /dev/null
+++ b/modoboa/lib/paginator.py
@@ -0,0 +1,99 @@
+"""
+Custom pagination tools.
+"""
+
+
+class Page(object):
+
+ """Class to represent a page."""
+
+ def __init__(self, paginator, pageid, id_start, id_stop, baseurl=None):
+ """Constructor."""
+ self.paginator = paginator
+ self.number = pageid
+ self.id_start = id_start
+ self.id_stop = id_stop
+ self.baseurl = baseurl
+
+ self._has_previous = None
+ self._has_next = None
+
+ @property
+ def items_per_page(self):
+ """The number of items in a page. (shortcut)"""
+ return self.paginator.elems_per_page
+
+ @property
+ def items(self):
+ """The total number of items. (shortcut)"""
+ return self.paginator.total
+
+ @property
+ def has_previous(self):
+ """Tell if a previous page is available or not."""
+ if self._has_previous is None:
+ self._has_previous = True if self.number > 1 else False
+ return self._has_previous
+
+ @property
+ def previous_page_number(self):
+ """Return the index of the previous page."""
+ if not self.has_previous:
+ return False
+ return self.number - 1
+
+ @property
+ def has_next(self):
+ """Tell if a next page is available or not."""
+ if self._has_next is None:
+ self._has_next = (
+ True if self.id_stop < self.paginator.total else False
+ )
+ return self._has_next
+
+ @property
+ def next_page_number(self):
+ """Return the index of the next page."""
+ if not self.has_next:
+ return False
+ return self.number + 1
+
+ @property
+ def last_page(self):
+ """Retrieve the id of the last page."""
+ lid = self.items / self.items_per_page
+ if not lid:
+ return 1
+ if self.items % self.items_per_page:
+ lid += 1
+ return lid
+
+
+class Paginator(object):
+
+ """Pagination class."""
+
+ def __init__(self, total, elems_per_page):
+ self.total = total
+ self.elems_per_page = elems_per_page
+ self.num_pages = total / elems_per_page
+ if total % elems_per_page:
+ self.num_pages += 1
+
+ def _indexes(self, page):
+ """Compute start and stop indexes."""
+ id_start = self.elems_per_page * page + 1
+ id_stop = id_start + self.elems_per_page - 1
+ return (id_start, id_stop)
+
+ def getpage(self, page_id):
+ """Retrieve a specific page."""
+ if page_id < 1:
+ return None
+ id_start, id_stop = self._indexes(page_id - 1)
+ if id_start <= self.total:
+ if id_stop >= self.total:
+ id_stop = self.total
+ else:
+ return None
+ return Page(self, page_id, id_start, id_stop)
diff --git a/modoboa/static/js/global.js b/modoboa/static/js/global.js
index 30a49dba9..f13dc6343 100644
--- a/modoboa/static/js/global.js
+++ b/modoboa/static/js/global.js
@@ -20,6 +20,11 @@ function get_static_url(value) {
return static_url + value;
}
+/**
+ * Open a modal box and load its content using an AJAX request.
+ *
+ * @param {Object} e - event object
+ */
function modalbox(e, css, defhref, defcb, defclosecb) {
e.preventDefault();
var $this = $(this);
@@ -39,7 +44,8 @@ function modalbox(e, css, defhref, defcb, defclosecb) {
url: href
}).done(function(data) {
var $div = $('', {
- id: "modalbox", 'class': "modal fade", html: data
+ id: "modalbox", 'class': "modal fade", role: "modal",
+ html: data, 'aria-hidden': true
});
$div.modal({show: false});
diff --git a/modoboa/static/js/jquery.infinitescroll.js b/modoboa/static/js/jquery.infinitescroll.js
index e577b09b2..80f0fc43a 100644
--- a/modoboa/static/js/jquery.infinitescroll.js
+++ b/modoboa/static/js/jquery.infinitescroll.js
@@ -10,7 +10,7 @@
* Creates an instance of InfiniteScroll.
*
* @constructor
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
* @param {object} element
* @param {dictionary} options - instance options
*/
@@ -33,7 +33,7 @@
/**
* Scroll event handler.
*
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
*/
on_scroll: function() {
var bottom = this.$options.calculate_bottom(this.$element);
@@ -49,7 +49,7 @@
* Load the previous page from the server.
*
* @private
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
*/
load_previous_page: function() {
var $this = this;
@@ -74,7 +74,7 @@
/**
* Load the next page from the server.
*
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
*/
load_next_page: function() {
var $this = this;
@@ -95,7 +95,7 @@
* Load a page's content.
*
* @private
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
* @param {string} direction - direction of the scroll (up or down)
*/
load_page: function(direction) {
@@ -117,7 +117,6 @@
}
$this.executing = false;
$this.loaded_pages.push($this.current_page);
- console.log("page", $this.current_page, "loaded successfuly");
}
});
},
@@ -125,18 +124,19 @@
/**
* Reset the loaded pages cache.
*
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
* @param {Array} current_page - the new current_page
*/
reset_loaded_pages: function(current_page) {
this.current_page = current_page;
this.loaded_pages = [this.current_page];
+ this.end_of_results = false;
},
/**
* Suspend the "infinite scroll" mode.
*
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
*/
pause: function() {
this.$element.unbind("scroll");
@@ -145,7 +145,7 @@
/**
* Resume the "infinite scroll" mode.
*
- * @this {InfiniteScroll}
+ * @this InfiniteScroll
*/
resume: function() {
this.$element.scroll($.proxy(this.on_scroll, this));
diff --git a/modoboa/static/js/searchbar.js b/modoboa/static/js/searchbar.js
index d4734523f..10d163337 100644
--- a/modoboa/static/js/searchbar.js
+++ b/modoboa/static/js/searchbar.js
@@ -1,4 +1,12 @@
(function($) {
+
+ /**
+ * Return an instance of SearchBar.
+ *
+ * @constructor
+ * @param {Object} element -
+ * @param {Object} options - instance options
+ */
var SearchBar = function(element, options) {
this.initialize(element, options);
};
@@ -16,24 +24,30 @@
});
this.$element.blur(function(e) {
var $this = $(this);
- if ($this.val() == "") {
+ if ($this.val() === "") {
$this.val(gettext("Search..."));
}
});
- if (this.options.navobj.params.pattern != undefined) {
+ if (this.options.navobj.params.pattern !== undefined) {
this.$element.val(this.options.navobj.getparam("pattern"));
}
- if (this.options.navobj.params.criteria != undefined) {
+ if (this.options.navobj.params.criteria !== undefined) {
$("#crit_" + this.options.navobj.params.criteria).attr("checked", "checked");
}
},
+ /**
+ * Change event: apply search criterion.
+ *
+ * @this SearchBar
+ * @param {Object} e - event object
+ */
pattern_change: function(e) {
var $input = $(e.target);
var criteria = $("input[name=scriteria]:checked").val();
var pattern = $input.val();
- if (pattern != "") {
+ if (pattern !== "") {
this.options.navobj.setparams({
pattern: pattern,
criteria: criteria
@@ -43,6 +57,9 @@
this.options.navobj.delparam("criteria");
this.options.navobj.delparam("page");
}
+ if (this.options.pattern_changed) {
+ this.options.pattern_changed(this.options.navobj);
+ }
this.options.navobj.update();
}
};
@@ -63,6 +80,7 @@
};
$.fn.searchbar.defaults = {
- navobj: null
+ navobj: null,
+ pattern_changed: null
};
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/modoboa/templates/common/generic_modal.html b/modoboa/templates/common/generic_modal.html
index 23a890ca7..b0a389b0a 100644
--- a/modoboa/templates/common/generic_modal.html
+++ b/modoboa/templates/common/generic_modal.html
@@ -1,6 +1,6 @@
{% load i18n %}
-