mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-01 00:19:33 +00:00
560 lines
No EOL
20 KiB
JavaScript
560 lines
No EOL
20 KiB
JavaScript
/**
|
|
* @depends /core/jquery-1.7.2.js
|
|
* @depends /bootstrap/bootstrap.js
|
|
* @depends /bootstrap/html5.js
|
|
*/
|
|
(function($) {
|
|
|
|
$.fn.ajaxPager = function(options) {
|
|
|
|
if($.ajaxPager.methods[options]){
|
|
return $.ajaxPager.methods[options].apply( this, Array.prototype.slice.call( arguments, 1 ));
|
|
} else if ( typeof options === 'object' || ! options ) {
|
|
return $.ajaxPager.methods.init.apply( this, arguments );
|
|
} else {
|
|
$.error( 'Method ' + options + ' does not exist on jQuery.ajaxPager' );
|
|
}
|
|
|
|
var settings = {};
|
|
var privatevars = {};
|
|
var handlers = {};
|
|
var getAccessor = null;
|
|
var makeRequest = null;
|
|
var changePage = null;
|
|
var mask = null;
|
|
var unmask = null;
|
|
};
|
|
|
|
// publicly accessible defaults
|
|
$.fn.ajaxPager.defaults = {
|
|
position : 'top', // top|bottom|both
|
|
classes : '', // for additional classes
|
|
stripedrows : false,
|
|
loadtext : 'Loading...',
|
|
page : 1,
|
|
limit : 25, // number of records
|
|
limitdd : true,
|
|
limitoptions : [25,50,75,100],
|
|
sortcolumn : null,
|
|
sortdir : 'asc',
|
|
sortby : {},
|
|
searchtext : null,
|
|
ajaxoptions : {
|
|
url : '',
|
|
type : 'POST',
|
|
data : {},
|
|
dataType : 'json'
|
|
},
|
|
reader : {
|
|
success : 'success',
|
|
message : 'message',
|
|
totalpages : 'totalpages',
|
|
totalrecords : 'totalrecords',
|
|
root : ''
|
|
},
|
|
params : {
|
|
start : 'start',
|
|
limit : 'limit',
|
|
page : 'page',
|
|
sort : 'sort',
|
|
dir : 'dir',
|
|
search : 'search'
|
|
},
|
|
renderoutput : null,
|
|
listeners: {
|
|
init : null,
|
|
render : null,
|
|
preprocess : null,
|
|
beforeload : null,
|
|
load : null,
|
|
destroy : null
|
|
}
|
|
};
|
|
|
|
$.fn.ajaxPager.privatevars = {
|
|
dataloaded : false,
|
|
rendered : false,
|
|
totalpages : 12,
|
|
totalrecords: 293,
|
|
firstrecord : 0,
|
|
lastrecord : 0,
|
|
pagers: null
|
|
};
|
|
|
|
// These are the methods of the plugin
|
|
$.ajaxPager = {
|
|
methods: {
|
|
init: function(options){
|
|
var options = options||{};
|
|
settings = $.extend(true, {}, $.fn.ajaxPager.defaults, options);
|
|
handlers = $.ajaxPager.handlers;
|
|
getAccessor = $.ajaxPager._getAccessor;
|
|
makeRequest = $.ajaxPager._makeRequest;
|
|
changePage = $.ajaxPager._changePage;
|
|
mask = $.ajaxPager._maskContent;
|
|
unmask = $.ajaxPager._unmaskContent;
|
|
|
|
return this.each(function(){
|
|
var $self = $(this),
|
|
data = $self.data('ajaxPager');
|
|
|
|
// setup bindings
|
|
$self.bind('optionchange.ajaxPager', handlers.optionChangeHandler);
|
|
$self.bind('pagechange.ajaxPager', handlers.pageChangeHandler);
|
|
$self.bind('firstpage.ajaxPager', handlers.firstPageHandler);
|
|
$self.bind('previouspage.ajaxPager', handlers.previousPageHandler);
|
|
$self.bind('nextpage.ajaxPager', handlers.nextPageHandler);
|
|
$self.bind('lastpage.ajaxPager', handlers.lastPageHandler);
|
|
$self.bind('init.ajaxPager', handlers.initHandler);
|
|
$self.bind('render.ajaxPager', handlers.renderHandler);
|
|
$self.bind('beforeload.ajaxPager', handlers.beforeLoadHandler);
|
|
$self.bind('load.ajaxPager', handlers.loadHandler);
|
|
$self.bind('destroy.ajaxPager', handlers.destroyHandler);
|
|
|
|
// Create some UI
|
|
var barUI = $.ajaxPager._buildPagerBar(settings);
|
|
$self.wrap('<div class="ajaxPagerContainer" />').addClass('pagingContent');
|
|
switch (settings.position) {
|
|
case "both":
|
|
$self.before(barUI).after(barUI);
|
|
break;
|
|
case "top":
|
|
$self.before(barUI);
|
|
break;
|
|
case "bottom":
|
|
$self.after(barUI);
|
|
break;
|
|
}
|
|
|
|
if(!data){
|
|
$self.data('ajaxPager',$.extend({}, $.fn.ajaxPager.privatevars, {
|
|
target: $self,
|
|
pagers: $('.pagingbar', $self.parent()),
|
|
origcontent: $(this).html()
|
|
}));
|
|
}
|
|
//console.log('data init ', $self.data('ajaxPager'));
|
|
|
|
$self.trigger('init').trigger('render');
|
|
});
|
|
},
|
|
destroy: function(){
|
|
|
|
return this.each(function(){
|
|
var $self = $(this),
|
|
data = $self.data('ajaxPager');
|
|
if (settings.listeners.destroy && typeof settings.listeners.destroy === 'function'){
|
|
settings.listeners.destroy.call($self, 'destroy');
|
|
}
|
|
$self.unbind('.ajaxPager');
|
|
$('a.paging-nav', data.pagers).unbind('click');
|
|
if (!$.isEmptyObject(settings.sortby)) {
|
|
$('a.paging-filter', data.pagers).unbind('click');
|
|
}
|
|
if (settings.limitdd) {
|
|
$('a.paging-limit', data.pagers).unbind('click');
|
|
}
|
|
$('.navbar-form', data.pagers).unbind('submit');
|
|
$('.navbar-form input', data.pagers).unbind('keypress');
|
|
$self.html(data.origcontent);
|
|
data.pagers.remove();
|
|
$self.unwrap().removeClass('pagingContent');
|
|
$self.removeData('ajaxPager');
|
|
});
|
|
},
|
|
option: function(options){
|
|
var orig = $.extend({}, settings);
|
|
var $self = $(this);
|
|
if (typeof options === 'object'){
|
|
settings = $.extend(true, settings, options);
|
|
} else if (arguments.length === 2) {
|
|
settings[arguments[0]] = arguments[1];
|
|
} else {
|
|
return settings[arguments[0]];
|
|
}
|
|
$.each(orig, function(ind,el){
|
|
if(settings[ind]!==el){
|
|
$self.trigger('optionchange', [ind, el, settings[ind]]);
|
|
}
|
|
})
|
|
return;
|
|
},
|
|
reload: function() {
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
$.ajaxPager._makeRequest.call($self, settings.page);
|
|
}
|
|
},
|
|
handlers: {
|
|
optionChangeHandler: function(event, option, oldvalue, newvalue){
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
switch (option) {
|
|
case "page":
|
|
if (newvalue > data.totalpages && (data.rendered && data.dataloaded)) {
|
|
settings.page = oldvalue;
|
|
$('form[name="jump"] input[name="page"]', data.pagers).val(oldvalue);
|
|
$.error( 'You have tried to set a \"page\" beyond the number of available pages' );
|
|
} else {
|
|
$self.trigger('pagechange', newvalue);
|
|
}
|
|
break;
|
|
case "classes":
|
|
var pagers = data.pagers;
|
|
if (!pagers.hasClass(newvalue)) {
|
|
pagers.addClass(newvalue);
|
|
}
|
|
break;
|
|
case "searchtext":
|
|
$self.trigger('pagechange', 1);
|
|
break;
|
|
}
|
|
},
|
|
jumpFormHandler: function(event){
|
|
event.preventDefault();
|
|
var $pager = $('.pagingContent', $(this).closest('.pagingbar').parent());
|
|
var val = $('input[name="page"]', $(this)).val();
|
|
$pager.ajaxPager('option', 'page', val);
|
|
return false;
|
|
},
|
|
pageChangeHandler: function(event, page){
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
|
|
var newpage = page;
|
|
switch(page){
|
|
case 1:
|
|
newpage = 1;
|
|
break;
|
|
case data.totalpages:
|
|
newpage = data.totalpages;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//console.log('in page change to page ', page)
|
|
$.ajaxPager._makeRequest.call($(this), newpage);
|
|
},
|
|
filterLinkHandler: function(event){
|
|
event.preventDefault();
|
|
var $pager = event.data.el,
|
|
action = $(this).attr('rel'),
|
|
icon = $('i', $('a[rel="' + action + '"]')),
|
|
diricon = icon.attr('class'),
|
|
data = $pager.data('ajaxPager'),
|
|
sortby = $('.paging-filter', data.pagers),
|
|
newicon = 'icon-arrow-down';
|
|
$('i',sortby).removeClass('icon-arrow-up').removeClass('icon-arrow-down').removeClass('icon-').addClass('icon-');
|
|
|
|
settings.sortcolumn = action;
|
|
if (diricon === 'icon-arrow-up') {
|
|
settings.sortdir = 'desc';
|
|
newicon = 'icon-arrow-down';
|
|
} else if (diricon === 'icon-arrow-down') {
|
|
settings.sortdir = 'asc';
|
|
newicon = 'icon-arrow-up';
|
|
} else {
|
|
settings.sortdir = 'desc';
|
|
}
|
|
icon.removeClass('icon-').addClass(newicon);
|
|
$('li.dropdown.open').removeClass('open');
|
|
//console.log(settings.sortcolumn, settings.sortdir);
|
|
$.ajaxPager._makeRequest.call($pager, settings.page);
|
|
return false;
|
|
},
|
|
limitLinkHandler: function(event) {
|
|
event.preventDefault();
|
|
var $pager = event.data.el,
|
|
action = $(this).attr('rel'),
|
|
newlimit = $(this).text(),
|
|
icon = $('i', $('a[rel="' + action + '"]')),
|
|
diricon = icon.attr('class'),
|
|
data = $pager.data('ajaxPager'),
|
|
limitby = $('.paging-limit', data.pagers);
|
|
settings.limit = newlimit;
|
|
$('i',limitby).removeClass('icon-chevron-right').removeClass('icon-').addClass('icon-');
|
|
icon.removeClass('icon-').addClass('icon-chevron-right');
|
|
$('li.dropdown.open').removeClass('open');
|
|
//console.log(settings.sortcolumn, settings.sortdir);
|
|
$.ajaxPager._makeRequest.call($pager, settings.page);
|
|
return false;
|
|
},
|
|
navLinkHandler: function(event) {
|
|
event.preventDefault();
|
|
var $pager = event.data.el,
|
|
action = $(this).attr('rel');
|
|
if (!$(this).hasClass('disabled')){
|
|
$pager.trigger(action + 'page');
|
|
}
|
|
return false;
|
|
},
|
|
firstPageHandler: function(event){
|
|
$(this).trigger('optionchange',['page', settings.page, 1]);
|
|
},
|
|
previousPageHandler: function(event){
|
|
$(this).trigger('optionchange',['page', settings.page, settings.page-1]);
|
|
},
|
|
lastPageHandler: function(event){
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
$(this).trigger('optionchange',['page', settings.page, data.totalpages]);
|
|
},
|
|
nextPageHandler: function(event){
|
|
$(this).trigger('optionchange',['page', settings.page, settings.page+1]);
|
|
},
|
|
initHandler: function () {
|
|
var $self = $(this);
|
|
if (settings.listeners.init && typeof settings.listeners.init === 'function'){
|
|
settings.listeners.init.call($self, 'init');
|
|
}
|
|
},
|
|
renderHandler: function(event){
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
if (settings.listeners.render && typeof settings.listeners.render === 'function'){
|
|
settings.listeners.render.call($self, 'render');
|
|
}
|
|
// setup UI bindings
|
|
$('a.paging-nav', data.pagers).bind('click', {el: $self}, handlers.navLinkHandler);
|
|
$('.navbar-form', data.pagers).bind('submit', handlers.jumpFormHandler);
|
|
$('.navbar-form input', data.pagers).bind('keypress',function(e){
|
|
c = e.which ? e.which : e.keyCode;
|
|
if(c === 13) {
|
|
e.preventDefault();
|
|
var form = $(this).parent();
|
|
form.trigger('submit');
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
// if there are sortby, we setup bindings
|
|
if (!$.isEmptyObject(settings.sortby)) {
|
|
$('a.paging-filter', data.pagers).bind('click', {el: $self}, handlers.filterLinkHandler);
|
|
}
|
|
if (settings.limitdd) {
|
|
$('a.paging-limit', data.pagers).bind('click', {el: $self}, handlers.limitLinkHandler);
|
|
}
|
|
$self.data('ajaxPager', $.extend(data,{rendered: true}));
|
|
//console.log('in render ', $self.data('ajaxPager'));
|
|
$self.trigger('pagechange', settings.page);
|
|
},
|
|
beforeLoadHandler: function(event) {
|
|
var $self = $(this);
|
|
if (settings.listeners.beforeload && typeof settings.listeners.beforeload === 'function'){
|
|
settings.listeners.beforeload.call($self, 'beforeload');
|
|
}
|
|
},
|
|
loadHandler: function(event) {
|
|
var $self = $(this);
|
|
if (settings.listeners.load && typeof settings.listeners.load === 'function'){
|
|
settings.listeners.load.call($self, 'load');
|
|
}
|
|
}
|
|
},
|
|
_buildPagerBar: function(settings){
|
|
var ui = '<div class="pagingbar ajaxPager' + ((settings.classes.length > 0) ? (' ' + settings.classes) : '') + '">'
|
|
+ '<div class="pagingbar-inner">'
|
|
+ '<div class="container">'
|
|
+ '<div class="nav-collapse">'
|
|
+ '<ul class="nav nav-pills">'
|
|
+ '<li><a href="#first" class="paging-nav" rel="first">|«</a></li>'
|
|
+ '<li class="divider-vertical"></li>'
|
|
+ '<li><a href="#previous" class="paging-nav" rel="previous">«</a></li>'
|
|
+ '<li class="divider-vertical"></li>'
|
|
+ '</ul>'
|
|
+ '<form name="jump" class="navbar-form pull-left">'
|
|
+ '<strong>Page</strong> <input type="text" name="page" value="0" style="width:25px;" /> <strong>of <span class="total-pages">0</span></strong>'
|
|
+ '</form>'
|
|
+ '<ul class="nav nav-pills">'
|
|
+ '<li class="divider-vertical"></li>'
|
|
+ '<li><a href="#next" class="paging-nav" rel="next">»</a></li>'
|
|
+ '<li class="divider-vertical"></li>'
|
|
+ '<li><a href="#last" class="paging-nav" rel="last">»|</a></li>'
|
|
+ '<li class="divider-vertical"></li>';
|
|
if (settings.limitdd) {
|
|
ui += '<li class="dropdown">'
|
|
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#">Limit<b class="caret"></b></a>'
|
|
+ '<ul class="dropdown-menu">';
|
|
for (var i = 0; i < settings.limitoptions.length; i++) {
|
|
ui += '<li><a href="#limit-' + settings.limitoptions[i] + '" class="paging-limit" rel="' + settings.limitoptions[i] + '"><i class="icon-' + ((settings.limitoptions[i] === settings.limit) ? 'chevron-right' : '') + '"></i>' + settings.limitoptions[i] + '</a></li>';
|
|
}
|
|
ui += '</ul>'
|
|
+ '</li>'
|
|
+ '<li class="divider-vertical"></li>';
|
|
}
|
|
if (!$.isEmptyObject(settings.sortby)) {
|
|
ui += '<li class="dropdown">'
|
|
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#">Sort By<b class="caret"></b></a>'
|
|
+ '<ul class="dropdown-menu">';
|
|
for (var i in settings.sortby){
|
|
ui += '<li><a href="#filter-' + i + '" class="paging-filter" rel="' + i + '">';
|
|
if (settings.sortcolumn && i === settings.sortcolumn) {
|
|
if (settings.sortdir === 'asc') {
|
|
ui += '<i class="icon-arrow-up"></i> ';
|
|
} else if (settings.sortcolumn && settings.sortdir === 'desc') {
|
|
ui += '<i class="icon-arrow-down"></i> ';
|
|
}
|
|
} else {
|
|
ui += '<i class="icon-"></i> ';
|
|
}
|
|
ui += settings.sortby[i] + '</a>';
|
|
}
|
|
ui += '</ul>'
|
|
+ '</li>'
|
|
+ '<li class="divider-vertical"></li>';
|
|
}
|
|
ui += '</ul>'
|
|
+'<span class="pull-right navbar-text pagingbar-counts" style="margin-right:20px;">'
|
|
+ '<strong>View <span class="first-record">0</span> - <span class="last-record">0</span> of <span class="record-count">0</span></strong>'
|
|
+ '</span>'
|
|
+ '</div>'
|
|
+ '</div>'
|
|
+ '</div>'
|
|
+ '</div>';
|
|
return ui;
|
|
},
|
|
_maskContent: function (label) {
|
|
var $self = $(this);
|
|
$self.append('<div class="component-backdrop fade in" />').addClass('masked');
|
|
if(label !== undefined) {
|
|
var maskMsgDiv = $('<div class="mask-msg alert alert-info" style="display:none;"></div>');
|
|
maskMsgDiv.append('<div>' + label + '</div>');
|
|
$self.append(maskMsgDiv);
|
|
|
|
//calculate center position
|
|
maskMsgDiv.css("top", Math.round($self.height() / 2 - (maskMsgDiv.height() - parseInt(maskMsgDiv.css("padding-top")) - parseInt(maskMsgDiv.css("padding-bottom"))) / 2)+"px");
|
|
maskMsgDiv.css("left", Math.round($self.width() / 2 - (maskMsgDiv.width() - parseInt(maskMsgDiv.css("padding-left")) - parseInt(maskMsgDiv.css("padding-right"))) / 2)+"px");
|
|
|
|
maskMsgDiv.show();
|
|
}
|
|
},
|
|
_unmaskContent: function () {
|
|
var $self = $(this);
|
|
$('div.component-backdrop,div.mask-msg', $self).remove();
|
|
$self.removeClass('masked');
|
|
//console.log('let\'s unmask this thing',$('div.component-backdrop', $self));
|
|
},
|
|
_changePage: function (page, totalpages, totalrecords) {
|
|
var $self = $(this),
|
|
data = $(this).data('ajaxPager');
|
|
data = $.extend(data, {totalpages: totalpages, totalrecords: totalrecords});
|
|
switch(page){
|
|
case 1:
|
|
$('a.paging-nav[rel="first"], a.paging-nav[rel="previous"]', data.pagers).addClass('disabled');
|
|
if (data.totalpages !== 1){
|
|
$('a.paging-nav[rel="next"], a.paging-nav[rel="last"]', data.pagers).removeClass('disabled');
|
|
} else {
|
|
$('a.paging-nav[rel="next"], a.paging-nav[rel="last"]', data.pagers).addClass('disabled');
|
|
}
|
|
break;
|
|
case data.totalpages:
|
|
$('a.paging-nav[rel="first"], a.paging-nav[rel="previous"]', data.pagers).removeClass('disabled');
|
|
$('a.paging-nav[rel="next"], a.paging-nav[rel="last"]', data.pagers).addClass('disabled');
|
|
break;
|
|
default:
|
|
$('a.paging-nav[rel="first"], a.paging-nav[rel="previous"]', data.pagers).removeClass('disabled');
|
|
$('a.paging-nav[rel="next"], a.paging-nav[rel="last"]', data.pagers).removeClass('disabled');
|
|
break;
|
|
}
|
|
settings.page = page;
|
|
|
|
var count = (page*settings.limit);
|
|
data = $.extend(data, {
|
|
firstrecord: ((settings.limit*(page-1))+1),
|
|
lastrecord: (count > data.totalrecords) ? data.totalrecords : count
|
|
});
|
|
$self.data('ajaxPager', data);
|
|
//console.log('after some sets ', $self.data('ajaxPager'));
|
|
$('.pagingbar-counts .first-record', data.pagers).html(data.firstrecord);
|
|
$('.pagingbar-counts .last-record', data.pagers).html(data.lastrecord);
|
|
$('.pagingbar-counts .record-count', data.pagers).html(data.totalrecords);
|
|
$('.navbar-form .total-pages', data.pagers).html(data.totalpages);
|
|
|
|
$('form[name="jump"] input[name="page"]', data.pagers).val(page);
|
|
},
|
|
_makeRequest: function (page) {
|
|
var $self = $(this),
|
|
req = $.extend({}, settings.ajaxoptions),
|
|
tmp = {},
|
|
opts = settings,
|
|
acc = getAccessor
|
|
cp = changePage,
|
|
u = unmask,
|
|
data = $self.data('ajaxPager'),
|
|
target = data.target;
|
|
|
|
tmp[settings.params.start] = (page-1) * settings.limit;
|
|
tmp[settings.params.page] = page;
|
|
tmp[settings.params.limit] = settings.limit;
|
|
if (settings.sortcolumn) {
|
|
tmp[settings.params.sort] = settings.sortcolumn;
|
|
tmp[settings.params.dir] = settings.sortdir;
|
|
}
|
|
if (settings.searchtext) {
|
|
tmp[settings.params.search] = settings.searchtext;
|
|
}
|
|
for(var i in req){
|
|
if (req[i] === null) {
|
|
delete req[i];
|
|
}
|
|
}
|
|
req.data = $.extend({}, req.data, tmp);
|
|
mask.call($self, opts.loadtext);
|
|
$.ajax($.extend(req,{
|
|
success: function (d, s, o) {
|
|
var output = null,
|
|
dataset = null,
|
|
totalpages = null,
|
|
totalrecords = null;
|
|
// Preprocess the return, if necessary
|
|
d = (opts.listeners.preprocess && typeof opts.listeners.preprocess === 'function') ? opts.listeners.preprocess.call($self, d) : d;
|
|
// Adjust our internal data to reflect values returned from the server
|
|
// Valuable to change the display if a search is conducted
|
|
dataset = acc(d, opts.reader.root);
|
|
totalpages = parseInt(acc(d, opts.reader.totalpages));
|
|
totalpages = parseInt((totalpages !== 'undefined') ? totalpages : 1);
|
|
totalrecords = parseInt(acc(d,opts.reader.totalrecords));
|
|
totalrecords = parseInt((totalrecords !== undefined) ? totalrecords : dataset.length);
|
|
cp.call($self, page, totalpages, totalrecords);
|
|
output = (opts.renderoutput && typeof opts.renderoutput === 'function') ? opts.renderoutput.call($self, d) : d;
|
|
$self.trigger('beforeload');
|
|
u.call($self,[]);
|
|
target.html(output);
|
|
|
|
if (opts.stripedrows) {
|
|
$self.children(':even').addClass('striped-row')
|
|
}
|
|
data = $.extend(data, {dataloaded: true});
|
|
$self.data('ajaxPager', data);
|
|
$self.trigger('load');
|
|
},
|
|
error: function (o, s, err){
|
|
u.call($self,[]);
|
|
$.error('There was an error in making your request. Please notify your developer.');
|
|
}
|
|
}));
|
|
},
|
|
_getAccessor : function(obj, expr) {
|
|
var ret,p,prm = [], i;
|
|
if( typeof expr === 'function') { return expr(obj); }
|
|
ret = obj[expr];
|
|
if(ret===undefined) {
|
|
try {
|
|
if ( typeof expr === 'string' ) {
|
|
prm = expr.split('.');
|
|
}
|
|
i = prm.length;
|
|
if( i ) {
|
|
ret = obj;
|
|
while (ret && i--) {
|
|
p = prm.shift();
|
|
ret = ret[p];
|
|
}
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
})(jQuery); |