
Originally Posted by
SimonFlack
This plugin was just what I needed. Although I needed it for paging.
Here is my modified version.
Plugin:
Code:
mobile.plugins.ListPullPager = ...
That great! but had some bugs,i modify and extend it!
Usage:
Code:
plugins: ["listpager"]
Code:
plugins: ["listpullpager"]
Code:
plugins: [{ptype:"listpullpager",isAutoButtons:false}]
Plugin:
Code:
Ext.plugins.ListPaging = Ext.extend(Ext.util.Observable, {
isAutoButtons:true,
init:function (list) {
this.store = list.store;
list.load = this.load;
if (this.isAutoButtons) {
list.prevBtn = this.prevBtn = new Ext.Button({text:"1", handler:this.onPrevTap, ui:"back", scope:this});
list.nextBtn = this.nextBtn = new Ext.Button({text:"1", handler:this.onNextTap, ui:"forward", scope:this});
list.reloadBtn = this.reloadBtn = new Ext.Button({iconMask:true,ui:'plain',iconCls:'refresh',handler:this.onRefreshAction, scope:this});
}
this.store.on("load", this.handleStoreLoad, this);
},
onPrevTap:function () {
this.loadPage(-1);
},
onNextTap:function () {
this.loadPage(1);
},
onRefreshAction:function() {
this.loadPage(0);
},
handlePrevPage:function () {
this.loadPage(-1);
},
handleNextPage:function () {
this.loadPage(1);
},
reload:function () {
this.loadPage(0);
},
load:function() {
var store = this.store;
store.currentPage = 1;
store.baseParams["start"] = 0;
store.baseParams["limit"] = this.store.pageSize;
store.load({params:this.store.baseParams});
},
loadPage:function (cpage) {
var store = this.store;
var totalNum = this.getTotalRecs();
var numPages = Math.ceil(totalNum / store.pageSize);
var page = this.store.currentPage + cpage;
if (page < 1) {
page = 1;
}
if (page > numPages) {
page = numPages;
}
store.currentPage = page;
store.baseParams["start"] = (page - 1) * this.store.pageSize;
store.baseParams["limit"] = this.store.pageSize;
store.load({params:this.store.baseParams});
},
getTotalPage:function () {
var store = this.store;
var totalNum = this.getTotalRecs();
return Math.ceil(totalNum / store.pageSize);
},
getTotalRecs:function () {
var store = this.store;
var proxy = store.getProxy();
var reader = proxy.getReader();
return reader.getTotal(reader.rawData);
},
handleStoreLoadBtn:function (store, pageMatch) {
var currentPage = store.currentPage;
if (currentPage > 1) {
this.prevBtn.setText((currentPage - 1) + "/" + pageMatch);
this.prevBtn.enable();
} else {
this.prevBtn.setText(pageMatch == 0 ? 0 : 1);
this.prevBtn.disable();
}
if (currentPage < pageMatch - 1) {
this.nextBtn.setText((currentPage + 1) + "/" + pageMatch);
this.nextBtn.enable();
} else {
this.nextBtn.setText(pageMatch);
this.nextBtn.disable();
}
},
handleStoreLoad:function (store, recs, success) {
if (success) {
var totalNum = this.getTotalRecs();
var numPages = Math.ceil(totalNum / store.pageSize);
if (store.currentPage > numPages) store.currentPage = numPages;
if (store.currentPage < 1) store.currentPage = 1;
if (this.isAutoButtons) {
this.handleStoreLoadBtn(store, numPages);
}
}
}
});
Ext.preg('listpager', Ext.plugins.ListPaging);
Code:
Ext.apply(Ext.anims, {
rotate: new Ext.Anim({
autoClear: false,
out: false,
before: function(el) {
var d = '';
if (this.dir == 'ccw') {
d = '-';
}
this.from = {
'-webkit-transform': 'rotate(' + d + '' + this.fromAngle + 'deg)'
};
this.to = {
'-webkit-transform': 'rotate(' + d + '' + this.toAngle + 'deg)'
};
}
})
});
Code:
Ext.plugins.ListPullPager = Ext.extend(Ext.plugins.ListPaging, {
langPullPrevious: 'Pull down to load {0} of {1},total {2}',
pullPreviousText: 'Pull down to load previous...',
langReleasePrevious: 'Release to load previous...',
langPullNext: 'Pull up to load page {0} of {1} ,total {2}',
pullNextText: 'Pull up to load next...',
langReleaseNext: 'Release to load next...',
langLoading: 'Loading...',
loading: false,
// private
init: function(list) {
this.list = list;
this.lastUpdated = new Date();
list.loadingText = undefined;
list.on('render', this.initPullHandler, this);
Ext.plugins.ListPullPager.superclass.init.apply(this, arguments);
},
// private
initPullHandler: function() {
//Previous
this.previousTpl = new Ext.XTemplate(
'<div class="x-list-pullprevpage">',
'<div class="x-list-pullprevpage-arrow"></div>',
'<div class="x-list-pullrefresh-wrap">',
'<h3 class="x-list-pullrefresh-message">{m}</h3>',
'<div class="x-list-pullrefresh-updated">Last Updated: <span>{l:date("m/d/Y h:iA")}</span></div>',
'</div>',
'</div>'
);
this.previousEl = this.previousTpl.insertBefore(this.list.scroller.el,
{m:this.pullPreviousText,l:this.lastUpdated}, true);
this.previousEl.hide();
Ext.Element.cssTranslate(this.previousEl, {x:0, y:-75});
//Next
this.nextTpl = new Ext.XTemplate(
'<div class="x-list-pullnextpage">',
'<div class="x-list-pullnextpage-arrow"></div>',
'<div class="x-list-pullrefresh-wrap">',
'<h3 class="x-list-pullrefresh-message">{m}</h3>',
'<div class="x-list-pullrefresh-updated">Last Updated: <span>{l:date("m/d/Y h:iA")}</span></div>',
'</div>',
'</div>'
);
this.nextEl = this.nextTpl.insertAfter(this.list.scroller.el,
{m:this.pullNextText,l:this.lastUpdated}, true);
this.nextEl.hide();
Ext.Element.cssTranslate(this.nextEl, {x:0, y:-90});
this.list.scroller.on('offsetchange', this.handleOffsettChange, this);
},
handleOffsettChange: function(scroller, offset) {
if (scroller.direction === 'vertical' && !this.loading) {
var heightOfList = scroller.size.height - scroller.containerBox.height;
if (offset.y > 0) {
//console.log('up:'+offset);
this.handlePrevious(scroller, offset, heightOfList);
}
if (offset.y < (heightOfList * -1)) {
//console.log('down:'+offset);
this.handleNext(scroller, offset, heightOfList);
}
}
},
//private
handlePrevious: function(scroller, offset, heightOfList) {
if (scroller.direction === 'vertical' && !this.loading) {
if (offset) {
Ext.Element.cssTranslate(this.previousEl, {x:0, y:offset.y - 76});
if (offset.y > 90) {
// state 1
if (this.state !== 1) {
this.prevState = this.state;
this.state = 1;
this.previousTpl.overwrite(this.previousEl, {m:this.langReleasePrevious,l:this.lastUpdated});
Ext.Anim.run(this.previousEl.select('.x-list-pullprevpage-arrow').first(), 'rotate', {dir:'ccw',fromAngle:0,toAngle:180});
}
} else if (!scroller.isDragging()) {
// state 3
if (this.state !== 3) {
this.prevState = this.state;
this.state = 3;
this.previousEl.hide();
if (this.prevState == 1) {
this.loading = true;
this.lastUpdated = new Date();
this.loadPage(-1);
this.callback = this.previousComplete();
}
}
} else {
// state 2
if (this.state !== 2) {
this.prevState = this.state;
this.state = 2;
this.previousTpl.overwrite(this.previousEl, {m:this.pullPreviousText,l:this.lastUpdated});
this.previousEl.show();
if (this.prevState == 1) {
Ext.Anim.run(this.previousEl.select('.x-list-pullprevpage-arrow').first(), 'rotate', {dir:'cw',fromAngle:180,toAngle:0});
}
}
}
}
}
},
handleNext: function(scroller, offset, heightOfList) {
if (scroller.direction === 'vertical' && !this.loading) {
if (offset) {
Ext.Element.cssTranslate(this.nextEl, {x:0, y:offset.y});
if (offset.y < ((heightOfList + 90) * -1)) {
// state 1
if (this.state !== 1) {
this.nextState = this.state;
this.state = 1;
this.nextTpl.overwrite(this.nextEl, {m:this.langReleaseNext,l:this.lastUpdated});
Ext.Anim.run(this.nextEl.select('.x-list-pullnextpage-arrow').first(), 'rotate', {dir:'ccw',fromAngle:180,toAngle:0});
}
} else if (!scroller.isDragging()) {
// state 3
if (this.state !== 3) {
this.nextState = this.state;
this.state = 3;
this.nextEl.hide();
if (this.nextState == 1) {
this.loading = true;
this.lastUpdated = new Date();
this.loadPage(1);
this.callback = this.nextComplete();
}
}
} else {
// state 2
if (this.state !== 2) {
this.nextState = this.state;
this.state = 2;
this.nextTpl.overwrite(this.nextEl, {m:this.pullNextText,l:this.lastUpdated});
this.nextEl.show();
if (this.nextState == 1) {
Ext.Anim.run(this.nextEl.select('.x-list-pullnextpage-arrow').first(), 'rotate', {dir:'cw',fromAngle:0,toAngle:180});
}
}
}
}
}
},
//private
previousComplete: function() {
this.loading = false;
this.lastUpdated = new Date();
this.previousTpl.overwrite(this.previousEl, {m:this.pullPreviousText,l:this.lastUpdated});
},
nextComplete: function() {
this.loading = false;
this.lastUpdated = new Date();
this.nextTpl.overwrite(this.nextEl, {m:this.pullNextText,l:this.lastUpdated});
},
handleStoreLoad:function (store, recs, success) {
Ext.plugins.ListPullPager.superclass.handleStoreLoad.apply(this, arguments);
var totalNum = this.getTotalRecs();
var numPages = Math.ceil(totalNum / store.pageSize);
if (store.currentPage > numPages) store.currentPage = numPages;
if (store.currentPage < 1) store.currentPage = 1;
var c = store.currentPage;
this.pullPreviousText = Ext.util.Format.format(this.langPullPrevious, c > 1 ? c - 1 : 1, numPages, totalNum);
this.pullNextText = Ext.util.Format.format(this.langPullNext, c < numPages ? c + 1 : numPages, numPages, totalNum);
if (this.callback) {
this.callback();
}
}
});
Ext.preg('listpullpager', Ext.plugins.ListPullPager);
CSS
Code:
.x-list-pullprevpage {
display: -webkit-box;
display: box;
-webkit-box-orient: horizontal;
box-orient: horizontal;
-webkit-box-align: center;
box-align: center;
-webkit-box-pack: center;
box-pack: center;
left: 0;
width: 100%;
height: 0
}
.x-list-pullnextpage {
display: -webkit-box;
display: box;
-webkit-box-orient: horizontal;
box-orient: horizontal;
-webkit-box-align: center;
box-align: center;
-webkit-box-pack: center;
box-pack: center;
position: absolute;
left: 0;
width: 100%;
height: 0
}
.x-list-pullrefresh-message {
font-weight: bold;
font-size: 1.0em;
margin-bottom: 0.1em;
text-align: center
}
.x-list-pullprevpage-arrow {
width: 2.5em;
height: 3.0em;
-webkit-mask: center center url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wBHwEEFZRBU1UAAAI7SURBVGje7dq/a5NRFMbxz6ttHSym4CK4+A8UtZPugpOrqKNiETqIq2tB3EQoIgjiIhZdCoIguLu1SkGFLi6Cmz+KQ432OvQGXjRN75vcN4ltDpwpL9xvnvecc885SRFCMMy2z5DbGBRFkfr8/kzn/k55KISwBZhoRUbATYRkBasqnsGadRyYU8GiLgXHB5IkFb71WEYF7UkFx0cKtiuGw2ohhP/kqku0CRzPdO5b/KwjSSaGOUmGHlBGwNrq4IF+KzgqM/18xQdxPtO5T/FjV8TgrgOcGGXxbs7iKdzMdO4tfN2TzcLAsvgEGgmFOhfgqYRC/Q1vWoAbuKJ/y6RLCauR22UF32MJF4ckeZ/g3d8xuIRpzAwYbjmybAVrCKG8fmvgHg4PCO4LrsX4E0L4B1BU8Y7+Lzc3cQOr5ZukXZlZxaP4Tfpp98tw273ist3F6T7Bvcb1dndxJ8AGFnGkZrjPuNCKuyqAYkY/rHEn08TlmLlddTPLWIiAdfjCdnApMVi2BziTWb1XuLpTP5gKOIWXOJoJ7hPO7tRyVQGEk3ieIR6bOIeV3B31Cubj9diLz6fAVY3Bsj2OCnRjL2JJSZ5JugE8FAvrsYpwH2Ph/15poOtyqpvBeuwjU3y9my6pF0CYw69En+t27Ox1Ll609ZNWJ3/Wy1zcK2ADax3g1hJmnVoBWwPXRhu4jfiZQQPCbBvA2Ryrj5y7mXI8LubazeQEnMSH6JPDCNiaZ6ZzbreK0d9SRoAjwM72B0xIAaqN33EkAAAAAElFTkSuQmCC') no-repeat;
-webkit-mask-size: 2em 3em;
-webkit-transform: rotate(0deg);
background-color: #111
}
.x-list-pullnextpage-arrow {
width: 2.5em;
height: 3.0em;
-webkit-mask: center center url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wBHwEEFZRBU1UAAAI7SURBVGje7dq/a5NRFMbxz6ttHSym4CK4+A8UtZPugpOrqKNiETqIq2tB3EQoIgjiIhZdCoIguLu1SkGFLi6Cmz+KQ432OvQGXjRN75vcN4ltDpwpL9xvnvecc885SRFCMMy2z5DbGBRFkfr8/kzn/k55KISwBZhoRUbATYRkBasqnsGadRyYU8GiLgXHB5IkFb71WEYF7UkFx0cKtiuGw2ohhP/kqku0CRzPdO5b/KwjSSaGOUmGHlBGwNrq4IF+KzgqM/18xQdxPtO5T/FjV8TgrgOcGGXxbs7iKdzMdO4tfN2TzcLAsvgEGgmFOhfgqYRC/Q1vWoAbuKJ/y6RLCauR22UF32MJF4ckeZ/g3d8xuIRpzAwYbjmybAVrCKG8fmvgHg4PCO4LrsX4E0L4B1BU8Y7+Lzc3cQOr5ZukXZlZxaP4Tfpp98tw273ist3F6T7Bvcb1dndxJ8AGFnGkZrjPuNCKuyqAYkY/rHEn08TlmLlddTPLWIiAdfjCdnApMVi2BziTWb1XuLpTP5gKOIWXOJoJ7hPO7tRyVQGEk3ieIR6bOIeV3B31Cubj9diLz6fAVY3Bsj2OCnRjL2JJSZ5JugE8FAvrsYpwH2Ph/15poOtyqpvBeuwjU3y9my6pF0CYw69En+t27Ox1Ll609ZNWJ3/Wy1zcK2ADax3g1hJmnVoBWwPXRhu4jfiZQQPCbBvA2Ryrj5y7mXI8LubazeQEnMSH6JPDCNiaZ6ZzbreK0d9SRoAjwM72B0xIAaqN33EkAAAAAElFTkSuQmCC') no-repeat;
-webkit-mask-size: 2em 3em;
-webkit-transform: rotate(180deg);
background-color: #111
}