mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
@@ -33,3 +33,12 @@ class WebmailNavigationParameters(NavigationParameters):
|
||||
)
|
||||
if defmailbox is not None:
|
||||
self.parameters += [('mbox', defmailbox, False)]
|
||||
|
||||
def _store_page(self):
|
||||
"""Specific method to store the current page."""
|
||||
if self.request.GET.get("reset_page", None) or "page" not in self:
|
||||
self["page"] = 1
|
||||
else:
|
||||
page = self.request.GET.get("page", None)
|
||||
if page is not None:
|
||||
self["page"] = int(page)
|
||||
|
||||
@@ -26,7 +26,7 @@ Webmail.prototype = {
|
||||
this.editorid = "id_body";
|
||||
|
||||
this.navobject = new History({
|
||||
deflocation: "?action=listmailbox",
|
||||
deflocation: "?action=listmailbox&reset_page=true",
|
||||
defcallback: $.proxy(this.listmailbox_callback, this)
|
||||
});
|
||||
this.poller = new Poller(this.options.poller_url, {
|
||||
@@ -158,21 +158,42 @@ Webmail.prototype = {
|
||||
/**
|
||||
* Setup an "infinite scroll" behaviour for the email list.
|
||||
*/
|
||||
setup_infinite_scroll: function() {
|
||||
setup_infinite_scroll: function(data) {
|
||||
var $container = $("#listing");
|
||||
var that = this;
|
||||
|
||||
$("#listing").infinite_scroll({
|
||||
if ($container.data("infinite-scroll") !== undefined) {
|
||||
$container.scrollTop(10);
|
||||
$container.infinite_scroll(
|
||||
"reset_loaded_pages", parseInt(data.page));
|
||||
$container.infinite_scroll("resume");
|
||||
return;
|
||||
}
|
||||
|
||||
$container.infinite_scroll({
|
||||
initial_page: parseInt(data.page),
|
||||
url: this.options.listing_url,
|
||||
calculate_bottom: function($element) {
|
||||
return $("#emails").height() - $element.height();
|
||||
},
|
||||
get_args: function() {
|
||||
return that.navparams;
|
||||
var args = that.navparams;
|
||||
args.scroll = true;
|
||||
return args;
|
||||
},
|
||||
process_results: function(data) {
|
||||
var content = $("#emails").html() + data.listing;
|
||||
process_results: function(data, direction) {
|
||||
var $emails = $("#emails");
|
||||
|
||||
$("#emails").html(content);
|
||||
if (direction === "down") {
|
||||
$emails.html($emails.html() + data.listing);
|
||||
} else {
|
||||
var row_id = $emails.children(".email").first().attr("id");
|
||||
|
||||
$emails.html(data.listing + $emails.html());
|
||||
|
||||
var $row = $("#" + row_id);
|
||||
$("#listing").scrollTop($row.offset().top);
|
||||
}
|
||||
},
|
||||
end_of_list_reached: function($element) {
|
||||
$element.append(
|
||||
@@ -184,6 +205,17 @@ Webmail.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the infinite scroll mode.
|
||||
*/
|
||||
disable_infinite_scroll: function() {
|
||||
var $container = $("#listing");
|
||||
|
||||
if ($container.data("infinite-scroll") !== undefined) {
|
||||
$container.infinite_scroll("pause");
|
||||
}
|
||||
},
|
||||
|
||||
record_unseen_messages: function() {
|
||||
var unseen_counters = {};
|
||||
|
||||
@@ -319,7 +351,14 @@ Webmail.prototype = {
|
||||
$("#pagination").html(response.navbar);
|
||||
$("#pagination-responsive").html(response.navbar);
|
||||
}*/
|
||||
|
||||
$("#listing").html(response.listing);
|
||||
|
||||
if (this.navobject.getparam("action") == "listmailbox") {
|
||||
this.setup_infinite_scroll(response);
|
||||
} else {
|
||||
this.disable_infinite_scroll();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -871,7 +910,7 @@ Webmail.prototype = {
|
||||
$("body").notify("success", gettext("Message sent"), 2000);
|
||||
}, this)).fail($.proxy(function(jqxhr) {
|
||||
var data = $.parseJSON(jqxhr.responseText);
|
||||
if (data != undefined) {
|
||||
if (data !== undefined) {
|
||||
this.compose_callback(data);
|
||||
}
|
||||
$("a[name=sendmail]").attr("disabled", null);
|
||||
@@ -917,7 +956,9 @@ Webmail.prototype = {
|
||||
this.htmltable = $("#emails").data("htmltable");
|
||||
this.init_draggables();
|
||||
$("#listing").css("overflow", "auto");
|
||||
this.setup_infinite_scroll();
|
||||
if (this.navobject.hasparam("reset_page")) {
|
||||
this.navobject.delparam("reset_page").update(false, true);
|
||||
}
|
||||
},
|
||||
|
||||
add_field: function(e, name) {
|
||||
@@ -965,10 +1006,10 @@ Webmail.prototype = {
|
||||
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) {
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
{% if with_top_div %}<div id="emails">{% endif %}
|
||||
{% for email in email_list %}
|
||||
<div id="{{ email.imapid }}" class="row email{% if email.style %} {{ email.style }}{% endif %}">
|
||||
<div id="{{ email.imapid }}" class="row email{% if email.style %} {{ email.style }}{% endif %}" data-page="{{ page }}">
|
||||
<div class="hidden-xs col-sm-1">
|
||||
<img name="drag" src="{{ STATIC_URL }}pics/grippy.png" class="draggable" />
|
||||
|
||||
<input type="checkbox" />
|
||||
</div>
|
||||
<div class="col-xs-9 col-sm-9 openable">
|
||||
{{ email.from|parse_imap_header:"from" }}
|
||||
{{ email.subject|parse_imap_header:"subject" }}
|
||||
<p class="text-muted">
|
||||
{{ email.subject|parse_imap_header:"subject" }}
|
||||
{{ email.from|parse_imap_header:"from" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-3 col-sm-2 text-right">
|
||||
|
||||
@@ -18,7 +18,9 @@ register = template.Library()
|
||||
def viewmail_menu(selection, folder, user, mail_id=None):
|
||||
entries = [
|
||||
{"name": "back",
|
||||
"url": "javascript:history.go(-1);",
|
||||
# "url": reverse("modoboa.extensions.webmail.views.index")
|
||||
# + "#?action=listmailbox&mbox=%s" % folder,
|
||||
"url": "javascript:history.go(-1)",
|
||||
"img": "fa fa-arrow-left",
|
||||
"class": "btn-default sm-margin-left-back",
|
||||
"label": _("Back")},
|
||||
|
||||
@@ -335,6 +335,7 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
|
||||
:return: a dictionnary
|
||||
"""
|
||||
navparams = WebmailNavigationParameters(request, defmailbox)
|
||||
previous_page_id = int(navparams["page"])
|
||||
if update_session:
|
||||
navparams.store()
|
||||
mbox = navparams.get('mbox')
|
||||
@@ -345,7 +346,7 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
|
||||
elems_per_page=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE")),
|
||||
**request.session["webmail_navparams"]
|
||||
)
|
||||
page_id = int(navparams.get('page'))
|
||||
page_id = int(navparams["page"])
|
||||
page = lst.paginator.getpage(page_id)
|
||||
if page is not None:
|
||||
email_list = lst.mbc.fetch(
|
||||
@@ -353,11 +354,14 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
|
||||
nbelems=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
|
||||
)
|
||||
content = _render_to_string(request, "webmail/email_list.html", {
|
||||
"email_list": email_list, "with_top_div": page_id == 1
|
||||
"email_list": email_list,
|
||||
"page": page_id,
|
||||
"with_top_div": request.GET.get("scroll", "false") == "false"
|
||||
})
|
||||
else:
|
||||
content = ""
|
||||
return {"listing": content, "length": len(content)}
|
||||
navparams["page"] = previous_page_id
|
||||
return {"listing": content, "length": len(content), "page": page_id}
|
||||
#return lst.render(request, navparams.get('page'))
|
||||
|
||||
|
||||
|
||||
+10
-3
@@ -181,18 +181,25 @@ class NavigationParameters(object):
|
||||
return self.request.session[self.sessionkey][key]
|
||||
|
||||
def __contains__(self, key):
|
||||
"""
|
||||
"""
|
||||
"""Check if key is present."""
|
||||
return key in self.request.session[self.sessionkey]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Set a new item."""
|
||||
self.request.session[self.sessionkey][key] = value
|
||||
|
||||
def _store_page(self):
|
||||
"""Specific method to store the current page."""
|
||||
self["page"] = int(self.request.GET.get("page", 1))
|
||||
|
||||
def store(self):
|
||||
"""Store navigation parameters into session.
|
||||
"""
|
||||
if not self.sessionkey in self.request.session:
|
||||
self.request.session[self.sessionkey] = {}
|
||||
self._store_page()
|
||||
navparams = self.request.session[self.sessionkey]
|
||||
navparams["order"] = self.request.GET.get("sort_order", "-date")
|
||||
navparams["page"] = int(self.request.GET.get("page", 1))
|
||||
for param, defvalue, escape in self.parameters:
|
||||
value = self.request.GET.get(param, defvalue)
|
||||
if value is None:
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
/**
|
||||
* Creates an instance of History.
|
||||
*
|
||||
* @constructor
|
||||
* @this {History}
|
||||
* @param {dictionary} options - instance options
|
||||
*/
|
||||
var History = function(options) {
|
||||
this.initialize(options);
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.callbacks = {};
|
||||
this.base = '';
|
||||
this.serialized = null;
|
||||
this.updatenext = true;
|
||||
this.load_params();
|
||||
if (this.options.defcallback) {
|
||||
this.register_callback("default", this.options.defcallback);
|
||||
this.check_id =
|
||||
setInterval($.proxy(this.check, this), this.options.checkinterval);
|
||||
}
|
||||
};
|
||||
|
||||
History.prototype = {
|
||||
@@ -11,21 +28,7 @@ History.prototype = {
|
||||
defcallback: null
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.callbacks = {};
|
||||
this.base = '';
|
||||
this.serialized = null;
|
||||
this.updatenext = true;
|
||||
this.load_params();
|
||||
if (this.options.defcallback) {
|
||||
this.register_callback("default", this.options.defcallback);
|
||||
this.check_id =
|
||||
setInterval($.proxy(this.check, this), this.options.checkinterval);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
/**
|
||||
* Return the encoded hash part of the URL (some browsers like FF
|
||||
* automatically decode the location.hash variable).
|
||||
*/
|
||||
@@ -61,10 +64,10 @@ History.prototype = {
|
||||
},
|
||||
|
||||
parse_string: function(value, reset) {
|
||||
var splits = (value.charAt(0) == '#')
|
||||
? value.substring(1).split('?') : value.split('?');
|
||||
var splits = (value.charAt(0) == '#') ?
|
||||
value.substring(1).split('?') : value.split('?');
|
||||
|
||||
if (splits.length == 0) {
|
||||
if (splits.length === 0) {
|
||||
this.base = this.options.deflocation;
|
||||
return this;
|
||||
}
|
||||
@@ -75,7 +78,7 @@ History.prototype = {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
if ((this.base = splits[0]) != "") {
|
||||
if ((this.base = splits[0]) !== "") {
|
||||
var re = new RegExp("/$");
|
||||
if (!this.base.match(re)) {
|
||||
this.base += '/';
|
||||
@@ -101,7 +104,7 @@ History.prototype = {
|
||||
var res = this.base;
|
||||
var args = "";
|
||||
|
||||
if (this.paramslength() != 0) {
|
||||
if (this.paramslength() !== 0) {
|
||||
args += "?";
|
||||
$.each(this.params, function(key, value) {
|
||||
if (args != "?") {
|
||||
@@ -113,6 +116,12 @@ History.prototype = {
|
||||
return res + args;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the current location.
|
||||
*
|
||||
* @param {boolean} force - force the update
|
||||
* @param {boolean} noupdate - disable the next update
|
||||
*/
|
||||
update: function(force, noupdate) {
|
||||
location.hash = this.serialize();
|
||||
|
||||
@@ -128,20 +137,39 @@ History.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
updateparams: function(str) {
|
||||
if (str.charAt(0) == '?') {
|
||||
str = str.substring(1);
|
||||
}
|
||||
var elems = str.split('&');
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
var pdef = elems[i].split('=');
|
||||
this.setparam(pdef[0], pdef[1]);
|
||||
}
|
||||
return this;
|
||||
/**
|
||||
* Check if a parameter is present.
|
||||
*
|
||||
* @param {string} name - name of the parameter
|
||||
* @return {boolean} true if parameter is present, false otherwise
|
||||
*/
|
||||
hasparam: function(name) {
|
||||
return this.params[name] !== undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a parameter.
|
||||
*
|
||||
* @param {string} name - name of the parameter
|
||||
* @return {string} the parameter's value (URI decoded)
|
||||
*/
|
||||
getparam: function(name, defvalue) {
|
||||
if (this.params[name] === undefined) {
|
||||
return (defvalue !== undefined) ? defvalue : undefined;
|
||||
}
|
||||
return decodeURIComponent(this.params[name]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set a parameter.
|
||||
*
|
||||
* @param {string} name - name of the parameter
|
||||
* @param {string} value - parameter's value
|
||||
* @param {boolean} encode - URI encode the parameter if true
|
||||
* @return {History}
|
||||
*/
|
||||
setparam: function(name, value, encode) {
|
||||
if (encode == undefined || encode) {
|
||||
if (encode === undefined || encode) {
|
||||
this.params[name] = encodeURIComponent(value);
|
||||
} else {
|
||||
this.params[name] = value;
|
||||
@@ -154,15 +182,34 @@ History.prototype = {
|
||||
return this;
|
||||
},
|
||||
|
||||
getparam: function(name, defvalue) {
|
||||
if (this.params[name] === undefined) {
|
||||
return (defvalue != undefined) ? defvalue : undefined;
|
||||
updateparams: function(str) {
|
||||
if (str.charAt(0) == '?') {
|
||||
str = str.substring(1);
|
||||
}
|
||||
return decodeURIComponent(this.params[name]);
|
||||
var elems = str.split('&');
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
var pdef = elems[i].split('=');
|
||||
this.setparam(pdef[0], pdef[1]);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a parameter.
|
||||
*
|
||||
* @param {string} name - name of the parameter
|
||||
* @return {History}
|
||||
*/
|
||||
delparam: function(name) {
|
||||
if (this.params[name] === undefined) {
|
||||
return this;
|
||||
}
|
||||
delete(this.params[name]);
|
||||
return this;
|
||||
},
|
||||
|
||||
baseurl: function(value, noreset) {
|
||||
if (noreset === undefined || noreset == 0) {
|
||||
if (noreset === undefined || noreset === 0) {
|
||||
this.reset();
|
||||
}
|
||||
this.base = value;
|
||||
@@ -182,14 +229,6 @@ History.prototype = {
|
||||
return decodeURIComponent(this.base.substr(0, this.base.length - 1));
|
||||
},
|
||||
|
||||
delparam: function(name) {
|
||||
if (this.params[name] == undefined) {
|
||||
return this;
|
||||
}
|
||||
delete(this.params[name]);
|
||||
return this;
|
||||
},
|
||||
|
||||
register_callback: function(name, callback) {
|
||||
this.callbacks[name] = callback;
|
||||
},
|
||||
@@ -229,7 +268,7 @@ History.prototype = {
|
||||
cache: false,
|
||||
dataType: 'json'
|
||||
}).done($.proxy(function(resp) {
|
||||
var callback = (resp.callback != undefined) ? resp.callback : "default";
|
||||
var callback = (resp.callback !== undefined) ? resp.callback : "default";
|
||||
|
||||
this.callbacks[callback](resp);
|
||||
if (resp.respmsg) {
|
||||
@@ -237,4 +276,4 @@ History.prototype = {
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,77 +1,185 @@
|
||||
/**
|
||||
* Infinite scroll plugin for jQuery.
|
||||
*
|
||||
* @author {Antoine Nguyen}
|
||||
*/
|
||||
!function($) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Creates an instance of InfiniteScroll.
|
||||
*
|
||||
* @constructor
|
||||
* @this {InfiniteScroll}
|
||||
* @param {object} element
|
||||
* @param {dictionary} options - instance options
|
||||
*/
|
||||
var InfiniteScroll = function(element, options) {
|
||||
this.$element = $(element);
|
||||
this.$data = $(element).data();
|
||||
this.$options = options;
|
||||
this.executing = false;
|
||||
this.end_of_results = false;
|
||||
this.current_page = 1;
|
||||
var that = this;
|
||||
this.current_page = (isNaN(this.$options.initial_page)) ?
|
||||
1 : this.$options.initial_page;
|
||||
this.loaded_pages = [this.current_page];
|
||||
|
||||
this.$element.scroll(function() {
|
||||
if (that.$element.scrollTop() >= that.$options.calculate_bottom(that.$element)) {
|
||||
that.load_more();
|
||||
}
|
||||
});
|
||||
this.resume();
|
||||
};
|
||||
|
||||
InfiniteScroll.prototype = {
|
||||
constructor: InfiniteScroll,
|
||||
|
||||
load_more: function() {
|
||||
/**
|
||||
* Scroll event handler.
|
||||
*
|
||||
* @this {InfiniteScroll}
|
||||
*/
|
||||
on_scroll: function() {
|
||||
var bottom = this.$options.calculate_bottom(this.$element);
|
||||
|
||||
if (this.$element.scrollTop() >= bottom) {
|
||||
this.load_next_page();
|
||||
} else if (this.$element.scrollTop() === 0) {
|
||||
this.load_previous_page();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the previous page from the server.
|
||||
*
|
||||
* @private
|
||||
* @this {InfiniteScroll}
|
||||
*/
|
||||
load_previous_page: function() {
|
||||
var $this = this;
|
||||
|
||||
if ($this.executing || $.inArray(1, $this.loaded_pages) != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ($this.current_page > 0) {
|
||||
$this.current_page -= 1;
|
||||
if ($.inArray($this.current_page, $this.loaded_pages) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this.current_page === 0) {
|
||||
$this.current_page = 1;
|
||||
return;
|
||||
}
|
||||
this.load_page("up");
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the next page from the server.
|
||||
*
|
||||
* @this {InfiniteScroll}
|
||||
*/
|
||||
load_next_page: function() {
|
||||
var $this = this;
|
||||
|
||||
if ($this.executing || $this.end_of_results) {
|
||||
return;
|
||||
}
|
||||
/*$this.$element.find('.spinner').removeClass('hide');*/
|
||||
$this.executing = true;
|
||||
$this.current_page += 1;
|
||||
var args = $this.$options.get_args();
|
||||
args.page = $this.current_page;
|
||||
while (true) {
|
||||
$this.current_page += 1;
|
||||
if ($.inArray($this.current_page, $this.loaded_pages) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.load_page("down");
|
||||
},
|
||||
|
||||
/**
|
||||
* Load a page's content.
|
||||
*
|
||||
* @private
|
||||
* @this {InfiniteScroll}
|
||||
* @param {string} direction - direction of the scroll (up or down)
|
||||
*/
|
||||
load_page: function(direction) {
|
||||
var args = this.$options.get_args();
|
||||
var $this = this;
|
||||
|
||||
this.executing = true;
|
||||
args.page = this.current_page;
|
||||
$.ajax({
|
||||
contentType: 'application/json; charset=UTF-8',
|
||||
data: args,
|
||||
url: $this.$options.url,
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
$this.$options.process_results(data);
|
||||
$this.$options.process_results(data, direction);
|
||||
if (data.length === 0) {
|
||||
$this.end_of_results = true;
|
||||
$this.$options.end_of_list_reached($this.$element);
|
||||
}
|
||||
//$this.$element.find('.spinner').addClass('hide');
|
||||
$this.executing = false;
|
||||
$this.loaded_pages.push($this.current_page);
|
||||
console.log("page", $this.current_page, "loaded successfuly");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the loaded pages cache.
|
||||
*
|
||||
* @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];
|
||||
},
|
||||
|
||||
/**
|
||||
* Suspend the "infinite scroll" mode.
|
||||
*
|
||||
* @this {InfiniteScroll}
|
||||
*/
|
||||
pause: function() {
|
||||
this.$element.unbind("scroll");
|
||||
},
|
||||
|
||||
/**
|
||||
* Resume the "infinite scroll" mode.
|
||||
*
|
||||
* @this {InfiniteScroll}
|
||||
*/
|
||||
resume: function() {
|
||||
this.$element.scroll($.proxy(this.on_scroll, this));
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.infinite_scroll = function (option) {
|
||||
var args = arguments;
|
||||
|
||||
return this.each(function () {
|
||||
var $this = $(this),
|
||||
data = $this.data('infinite-scroll'),
|
||||
options = $.extend({}, $.fn.infinite_scroll.defaults, typeof option == 'object' && option);
|
||||
options = $.extend(
|
||||
{}, $.fn.infinite_scroll.defaults,
|
||||
typeof option == 'object' && option
|
||||
);
|
||||
|
||||
if (!data) {
|
||||
$this.data('infinite-scroll', (data = new InfiniteScroll(this, options)));
|
||||
$this.data('infinite-scroll', (
|
||||
data = new InfiniteScroll(this, options))
|
||||
);
|
||||
}
|
||||
if (typeof options == 'string') {
|
||||
data[options]();
|
||||
if (typeof option == 'string') {
|
||||
data[option].apply(data, Array.prototype.slice.call(args, 1));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.infinite_scroll.defaults = {
|
||||
initial_page: 1,
|
||||
calculate_bottom: null,
|
||||
get_data: null,
|
||||
process_results: null,
|
||||
end_of_list_reached: null,
|
||||
url: ''
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user