Pager.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // wrapped by build app
  2. define("dojox/widget/Pager", ["dijit","dojo","dojox","dojo/require!dijit/_Widget,dijit/_Templated,dojo/fx"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.widget.Pager");
  4. dojo.experimental("dojox.widget.Pager");
  5. dojo.require("dijit._Widget");
  6. dojo.require("dijit._Templated");
  7. dojo.require("dojo.fx");
  8. dojo.declare("dojox.widget.Pager",
  9. [dijit._Widget, dijit._Templated],
  10. {
  11. // summary: A Pager, displaying a list of sized nodes
  12. templateString: dojo.cache("dojox.widget", "Pager/Pager.html", "<div dojoAttachPoint=\"pagerContainer\" tabIndex=\"0\" dojoAttachEvent=\"onkeypress: _handleKey, onfocus: _a11yStyle, onblur:_a11yStyle\" class=\"${orientation}PagerContainer\">\n <div class=\"pagerContainer\">\n\t\t<div dojoAttachPoint=\"pagerContainerStatus\" class=\"${orientation}PagerStatus\"></div>\n\t\t<div dojoAttachPoint=\"pagerContainerView\" class=\"${orientation}PagerView\">\n\t\t <div dojoAttachPoint=\"pagerItemContainer\"><ul dojoAttachPoint=\"pagerItems\" class=\"pagerItems\"></ul></div>\n\t\t</div>\n\t\t<div dojoAttachPoint=\"pagerContainerPager\" class=\"${orientation}PagerPager\">\n\t\t\t<div tabIndex=\"0\" dojoAttachPoint=\"pagerNext\" class=\"pagerIconContainer\" dojoAttachEvent=\"onclick: _pagerNext\"><img dojoAttachPoint=\"pagerIconNext\" src=\"${iconNext}\" alt=\"Next\" /></div>\n\t\t\t<div tabIndex=\"0\" dojoAttachPoint=\"pagerPrevious\" class=\"pagerIconContainer\" dojoAttachEvent=\"onclick: _pagerPrevious\"><img dojoAttachPoint=\"pagerIconPrevious\" src=\"${iconPrevious}\" alt=\"Previous\" /></div>\n\t\t</div>\n </div>\n\t<div dojoAttachPoint=\"containerNode\" style=\"display:none\"></div>\n</div>"),
  13. /*=====
  14. // iconPrevious: String?
  15. // The url of the previous page icon
  16. iconPrevious: "",
  17. // iconNext: String?
  18. // The url of the next page icon
  19. iconNext: "",
  20. =====*/
  21. iconPage: dojo.moduleUrl("dojox.widget", "Pager/images/pageInactive.png"),
  22. iconPageActive: dojo.moduleUrl("dojox.widget", "Pager/images/pageActive.png"),
  23. // store: Object
  24. // A dojo.data Data store
  25. store: null, // data store for items
  26. // orientation: String
  27. // Either "horizontal or "vertical" to define the direction the pages will slide
  28. orientation: "horizontal", // or vertical
  29. // statusPos: String
  30. // A string describing where to put the Pager "current page" indicator. Options are
  31. // "leading" or "trailing". In the case of horiztonal orientation, "leading" indicates
  32. // positioned above the PageItems. In the case of vertical, "leading" indicates "before".
  33. statusPos: "leading",
  34. // pagerPos: String
  35. // TODOC
  36. pagerPos: "center",
  37. // duration: Integer
  38. // Time in milliseconds to transition the pages
  39. duration: 500,
  40. // itemSpace: Integer
  41. // Spacing between items? TODOC
  42. itemSpace: 2,
  43. // resizeChildren: Boolean
  44. // TODOC
  45. resizeChildren: true,
  46. // itemClass: String
  47. // The full dotted named of a Class to use for the internal Pager Items.
  48. itemClass: "dojox.widget._PagerItem",
  49. // itemsPage: Integer
  50. // The numbers of items to display in each "Page"
  51. itemsPage: 3,
  52. postMixInProperties: function(){
  53. var h = (this.orientation == "horizontal");
  54. dojo.mixin(this,{
  55. _totalPages:0,
  56. _currentPage:1,
  57. dirClass: "pager" + (h ? "Horizontal" : "Vertical"),
  58. iconNext: dojo.moduleUrl("dojox.widget", "Pager/images/" + (h ? "h" : "v") + "Next.png"),
  59. iconPrevious: dojo.moduleUrl("dojox.widget", "Pager/images/" + (h ? "h" : "v") + "Previous.png")
  60. });
  61. },
  62. postCreate: function(){
  63. this.inherited(arguments);
  64. //this.connect(this.domNode,"onkeypress","_handleKey");
  65. this.store.fetch({
  66. onComplete: dojo.hitch(this, "_init")
  67. });
  68. },
  69. _a11yStyle: function(e){
  70. // summary: top level onfocus/onblur listen to set a class "pagerFocus" on some node
  71. // and remove it onblur
  72. dojo[(e.type == "focus" ? "addClass" : "removeClass")](e.target,"pagerFocus");
  73. },
  74. _handleKey: function(e){
  75. // summary: Handle keyboard navigation internally
  76. var dk = dojo.keys;
  77. var key = (e.charCode == dk.SPACE ? dk.SPACE : e.keyCode);
  78. switch(key){
  79. case dk.UP_ARROW:
  80. case dk.RIGHT_ARROW:
  81. case 110:
  82. case 78: // key "n"
  83. e.preventDefault();
  84. this._pagerNext();
  85. break;
  86. case dk.DOWN_ARROW:
  87. case dk.LEFT_ARROW:
  88. case 112:
  89. case 80: // key "p"
  90. e.preventDefault();
  91. this._pagerPrevious();
  92. break;
  93. case dk.ENTER:
  94. switch(e.target){
  95. case this.pagerNext : this._pagerNext(); break;
  96. case this.pagerPrevious : this._pagerPrevious(); break;
  97. }
  98. break;
  99. }
  100. },
  101. _init: function(items) {
  102. this.items = items;
  103. this._renderPages();
  104. this._renderStatus();
  105. this._renderPager();
  106. },
  107. _renderPages: function(){
  108. var pcv = this.pagerContainerView;
  109. var _h = (this.orientation == "horizontal");
  110. var style = dojo.style;
  111. if(_h){
  112. var pagerH = dojo.marginBox(this.pagerContainerPager).h;
  113. var statusH = dojo.marginBox(this.pagerContainerStatus).h;
  114. if (this.pagerPos != 'center'){
  115. var addonHeight = pagerH+statusH;
  116. }else{
  117. var addonHeight = statusH;
  118. var widthSub = this.pagerIconNext.width;
  119. var containerWidth = style(pcv, 'width');
  120. var newWidth = containerWidth-(2*widthSub);
  121. style(pcv, {
  122. width: newWidth+'px',
  123. marginLeft: this.pagerIconNext.width+'px',
  124. marginRight: this.pagerIconNext.width+'px'
  125. });
  126. }
  127. var totalH = style(this.pagerContainer, 'height') - addonHeight;
  128. style(this.pagerContainerView, 'height', totalH+'px');
  129. var itemSpace = Math.floor(style(pcv, 'width') / this.itemsPage);
  130. if(this.statusPos == 'trailing'){
  131. if(this.pagerPos != 'center'){
  132. style(pcv, 'marginTop', pagerH+'px');
  133. }
  134. style(pcv, 'marginBottom', statusH+'px');
  135. }else{
  136. style(pcv, 'marginTop', statusH+'px');
  137. if (this.pagerPos != 'center'){
  138. style(pcv, 'marginTop', pagerH+'px');
  139. }
  140. }
  141. }else{
  142. var pagerW = dojo.marginBox(this.pagerContainerPager).w;
  143. var statusW = dojo.marginBox(this.pagerContainerStatus).w;
  144. var containerW = style(this.pagerContainer, 'width');
  145. if(this.pagerPos != 'center'){
  146. var addonWidth = pagerW + statusW;
  147. }else{
  148. var addonWidth = statusW;
  149. var heightSub = this.pagerIconNext.height;
  150. var containerHeight = style(pcv, 'height');
  151. var newHeight = containerHeight - (2 * heightSub);
  152. style(pcv,{
  153. height: newHeight+'px',
  154. marginTop: this.pagerIconNext.height+'px',
  155. marginBottom: this.pagerIconNext.height+'px'
  156. });
  157. }
  158. var totalW = style(this.pagerContainer, 'width') - addonWidth;
  159. style(pcv, 'width', totalW+'px');
  160. var itemSpace = Math.floor(style(pcv, 'height') / this.itemsPage);
  161. if(this.statusPos == 'trailing'){
  162. if (this.pagerPos != 'center'){
  163. style(pcv, 'marginLeft', pagerW + 'px');
  164. }
  165. style(pcv, 'marginRight', statusW + 'px');
  166. }else{
  167. style(pcv, 'marginLeft', statusW + 'px');
  168. if(this.pagerPos != 'center'){
  169. style(pcv, 'marginRight', pagerW+'px');
  170. }
  171. }
  172. }
  173. var _PagerItem = dojo.getObject(this.itemClass);
  174. var paddingLead = "padding" + (_h ? "Left" : "Top");
  175. var paddingTrail = "padding" + (_h ? "Right" : "Bottom");
  176. dojo.forEach(this.items, function(item, cnt){
  177. var contentContainer = dojo.create('div', {
  178. innerHTML: item.content
  179. });
  180. var pagerItem = new _PagerItem({
  181. id: this.id + '-item-' + (cnt + 1)
  182. }, contentContainer);
  183. this.pagerItems.appendChild(pagerItem.domNode);
  184. var containerProps = {};
  185. containerProps[(_h ? "width" : "height")] = (itemSpace - this.itemSpace) + "px";
  186. var p = (_h ? "height" : "width");
  187. containerProps[p] = style(pcv, p) + "px";
  188. style(pagerItem.containerNode, containerProps);
  189. if(this.resizeChildren){
  190. pagerItem.resizeChildren();
  191. }
  192. pagerItem.parseChildren();
  193. // only display amount of items as defined in itemsPage
  194. style(pagerItem.domNode, "position", "absolute");
  195. if (cnt < this.itemsPage){
  196. var pos = (cnt) * itemSpace;
  197. var trailingDir = (_h ? "left" : "top");
  198. var dir = (_h ? "top" : "left");
  199. style(pagerItem.domNode, dir, "0px");
  200. style(pagerItem.domNode, trailingDir, pos+"px");
  201. }else{
  202. style(pagerItem.domNode, "top", "-1000px");
  203. style(pagerItem.domNode, "left", "-1000px");
  204. }
  205. style(pagerItem.domNode, paddingTrail, (this.itemSpace/2)+"px");
  206. style(pagerItem.domNode, paddingLead, (this.itemSpace/2)+"px");
  207. }, this);
  208. },
  209. _renderPager: function() {
  210. var tcp = this.pagerContainerPager;
  211. var zero = "0px";
  212. var _h = (this.orientation == "horizontal");
  213. if(_h){
  214. if(this.statusPos == 'center'){
  215. }else if (this.statusPos == 'trailing'){
  216. dojo.style(tcp, 'top', zero);
  217. }else{
  218. dojo.style(tcp, 'bottom', zero);
  219. }
  220. dojo.style(this.pagerNext, 'right', zero);
  221. dojo.style(this.pagerPrevious, 'left', zero);
  222. }else{
  223. if (this.statusPos == 'trailing'){
  224. dojo.style(tcp, 'left', zero);
  225. }else{
  226. dojo.style(tcp, 'right', zero);
  227. }
  228. dojo.style(this.pagerNext, 'bottom', zero);
  229. dojo.style(this.pagerPrevious, 'top', zero);
  230. }
  231. },
  232. _renderStatus: function() {
  233. this._totalPages = Math.ceil(this.items.length / this.itemsPage);
  234. // FIXME!!
  235. this.iconWidth = 0;
  236. this.iconHeight = 0;
  237. this.iconsLoaded = 0;
  238. this._iconConnects = [];
  239. for (var i = 1; i <= this._totalPages; i++){
  240. var icon = new Image();
  241. var pointer = i;
  242. dojo.connect(icon, 'onclick', dojo.hitch(this, function(pointer) {
  243. this._pagerSkip(pointer);
  244. }, pointer));
  245. this._iconConnects[pointer] = dojo.connect(icon, 'onload', dojo.hitch(this,function(pointer){
  246. this.iconWidth += icon.width;
  247. this.iconHeight += icon.height;
  248. this.iconsLoaded++;
  249. if (this._totalPages == this.iconsLoaded){
  250. if (this.orientation == "horizontal"){
  251. if (this.statusPos == 'trailing'){
  252. if (this.pagerPos == 'center'){
  253. var containerHeight = dojo.style(this.pagerContainer, 'height');
  254. var statusHeight = dojo.style(this.pagerContainerStatus, 'height');
  255. dojo.style(this.pagerContainerPager, 'top', ((containerHeight/2)-(statusHeight/2))+'px');
  256. }
  257. dojo.style(this.pagerContainerStatus, 'bottom', '0px');
  258. }else{
  259. if (this.pagerPos == 'center'){
  260. var containerHeight = dojo.style(this.pagerContainer, 'height');
  261. var statusHeight = dojo.style(this.pagerContainerStatus, 'height');
  262. dojo.style(this.pagerContainerPager, 'bottom', ((containerHeight/2)-(statusHeight/2))+'px');
  263. }
  264. dojo.style(this.pagerContainerStatus, 'top', '0px');
  265. }
  266. var position = (dojo.style(this.pagerContainer, 'width')/2)-(this.iconWidth/2);
  267. dojo.style(this.pagerContainerStatus, 'paddingLeft', position+'px');
  268. }else{
  269. if (this.statusPos == 'trailing'){
  270. if (this.pagerPos == 'center'){
  271. var containerWidth = dojo.style(this.pagerContainer, 'width');
  272. var statusWidth = dojo.style(this.pagerContainerStatus, 'width');
  273. dojo.style(this.pagerContainerPager, 'left', ((containerWidth/2)-(statusWidth/2))+'px');
  274. }
  275. dojo.style(this.pagerContainerStatus, 'right', '0px');
  276. }else{
  277. if (this.pagerPos == 'center'){
  278. var containerWidth = dojo.style(this.pagerContainer, 'width');
  279. var statusWidth = dojo.style(this.pagerContainerStatus, 'width');
  280. dojo.style(this.pagerContainerPager, 'right', ((containerWidth/2)-(statusWidth/2))+'px');
  281. }
  282. dojo.style(this.pagerContainerStatus, 'left', '0px');
  283. }
  284. var position = (dojo.style(this.pagerContainer, 'height')/2)-(this.iconHeight/2);
  285. dojo.style(this.pagerContainerStatus, 'paddingTop', position+'px');
  286. }
  287. }
  288. dojo.disconnect(this._iconConnects[pointer]);
  289. }, pointer));
  290. if (i==this._currentPage){
  291. icon.src=this.iconPageActive;
  292. }else{
  293. icon.src=this.iconPage;
  294. }
  295. var pointer = i;
  296. dojo.addClass(icon, this.orientation+'PagerIcon');
  297. dojo.attr(icon, 'id', this.id+'-status-'+i);
  298. this.pagerContainerStatus.appendChild(icon);
  299. if (this.orientation == "vertical"){
  300. dojo.style(icon, 'display', 'block');
  301. }
  302. }
  303. },
  304. _pagerSkip: function(page){
  305. if (this._currentPage == page){
  306. return;
  307. }else{
  308. // calculate whether to go left or right, take shortest way
  309. var distanceP; var distanceN;
  310. if (page < this._currentPage){
  311. distanceP = this._currentPage - page;
  312. distanceN = (this._totalPages + page) - this._currentPage;
  313. }else{
  314. distanceP = (this._totalPages + this._currentPage) - page;
  315. distanceN = page - this._currentPage;
  316. }
  317. var b = (distanceN > distanceP);
  318. this._toScroll = (b ? distanceP : distanceN);
  319. var cmd = (b ? "_pagerPrevious" : "_pagerNext");
  320. var connect = this.connect(this, "onScrollEnd", function(){
  321. this._toScroll--;
  322. if(this._toScroll < 1){
  323. this.disconnect(connect);
  324. }else{
  325. this[cmd]();
  326. }
  327. });
  328. this[cmd]();
  329. }
  330. },
  331. _pagerNext: function(){
  332. if(this._anim) return;
  333. /**
  334. * fade slide out current items
  335. * make sure that next items are ligned up nicely before sliding them in
  336. */
  337. var _anims = [];
  338. for (var i = this._currentPage * this.itemsPage; i > (this._currentPage - 1) * this.itemsPage; i--){
  339. if (!dojo.byId(this.id+'-item-'+i)) continue;
  340. var currentItem = dojo.byId(this.id+'-item-'+i);
  341. var marginBox = dojo.marginBox(currentItem);
  342. if (this.orientation == "horizontal") {
  343. var move = marginBox.l - (this.itemsPage * marginBox.w);
  344. _anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
  345. }else{
  346. var move = marginBox.t - (this.itemsPage * marginBox.h);
  347. _anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
  348. }
  349. }
  350. var previousPage = this._currentPage;
  351. if (this._currentPage == this._totalPages){
  352. this._currentPage = 1;
  353. }else{
  354. this._currentPage++;
  355. }
  356. var cnt = this.itemsPage;
  357. for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
  358. if (dojo.byId(this.id+'-item-'+i)){
  359. var currentItem = dojo.byId(this.id+'-item-'+i);
  360. var marginBox = dojo.marginBox(currentItem);
  361. if (this.orientation == "horizontal") {
  362. var newPos = (dojo.style(this.pagerContainerView, 'width')+((cnt-1)*marginBox.w))-1;
  363. dojo.style(currentItem, 'left', newPos+'px');
  364. dojo.style(currentItem, 'top', '0px');
  365. var move = newPos-(this.itemsPage*marginBox.w);
  366. _anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
  367. }else{
  368. newPos = (dojo.style(this.pagerContainerView, 'height')+((cnt-1)*marginBox.h))-1;
  369. dojo.style(currentItem, 'top', newPos+'px');
  370. dojo.style(currentItem, 'left', '0px');
  371. var move = newPos-(this.itemsPage*marginBox.h);
  372. _anims.push(dojo.fx.slideTo({ node: currentItem, top: move, duration: this.duration}));
  373. }
  374. }
  375. cnt--;
  376. }
  377. this._anim = dojo.fx.combine(_anims);
  378. var animConnect = this.connect(this._anim, "onEnd", function(){
  379. delete this._anim;
  380. this.onScrollEnd();
  381. this.disconnect(animConnect);
  382. });
  383. this._anim.play();
  384. // set pager icons
  385. dojo.byId(this.id+'-status-'+previousPage).src = this.iconPage;
  386. dojo.byId(this.id+'-status-'+this._currentPage).src = this.iconPageActive;
  387. },
  388. _pagerPrevious: function(){
  389. if(this._anim) return;
  390. var _anims = [];
  391. for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
  392. if (!dojo.byId(this.id+'-item-'+i)) continue;
  393. var currentItem = dojo.byId(this.id+'-item-'+i);
  394. var marginBox = dojo.marginBox(currentItem);
  395. if (this.orientation == "horizontal") {
  396. var move = dojo.style(currentItem, 'left')+(this.itemsPage*marginBox.w);
  397. _anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
  398. }else{
  399. var move = dojo.style(currentItem, 'top')+(this.itemsPage*marginBox.h);
  400. _anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
  401. }
  402. }
  403. var previousPage = this._currentPage;
  404. if (this._currentPage == 1){
  405. this._currentPage = this._totalPages;
  406. }else{
  407. this._currentPage--;
  408. }
  409. var cnt = this.itemsPage;
  410. var j=1;
  411. for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
  412. if(dojo.byId(this.id+'-item-'+i)){
  413. var currentItem = dojo.byId(this.id+'-item-'+i);
  414. var marginBox = dojo.marginBox(currentItem);
  415. if (this.orientation == "horizontal") {
  416. var newPos = -(j * marginBox.w) + 1;
  417. dojo.style(currentItem, 'left', newPos+'px');
  418. dojo.style(currentItem, 'top', '0px');
  419. var move = ((cnt - 1) * marginBox.w);
  420. _anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
  421. var move = newPos+(this.itemsPage * marginBox.w);
  422. _anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
  423. }else{
  424. newPos = -((j * marginBox.h) + 1);
  425. dojo.style(currentItem, 'top', newPos+'px');
  426. dojo.style(currentItem, 'left', '0px');
  427. var move = ((cnt - 1) * marginBox.h);
  428. _anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
  429. }
  430. }
  431. cnt--;
  432. j++;
  433. }
  434. this._anim = dojo.fx.combine(_anims);
  435. var animConnect = dojo.connect(this._anim, "onEnd", dojo.hitch(this, function(){
  436. delete this._anim;
  437. this.onScrollEnd();
  438. dojo.disconnect(animConnect);
  439. }));
  440. this._anim.play();
  441. // set pager icons
  442. dojo.byId(this.id + '-status-' + previousPage).src = this.iconPage;
  443. dojo.byId(this.id + '-status-' + this._currentPage).src = this.iconPageActive;
  444. },
  445. onScrollEnd: function(){
  446. // summary: Stub Function. Fired after the slide is complete. Override or connect.
  447. }
  448. });
  449. dojo.declare("dojox.widget._PagerItem",
  450. [dijit._Widget, dijit._Templated],
  451. {
  452. templateString: '<li class="pagerItem" dojoAttachPoint="containerNode"></li>',
  453. resizeChildren: function(){
  454. var box = dojo.marginBox(this.containerNode);
  455. dojo.style(this.containerNode.firstChild, {
  456. width: box.w +'px',
  457. height: box.h + 'px'
  458. });
  459. },
  460. parseChildren: function(){
  461. dojo.parser.parse(this.containerNode);
  462. }
  463. });
  464. });