From 7188c3a328b8d1aafd9d09d0be56bfb5c030fa6c Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Thu, 11 Dec 2014 19:53:08 +0000 Subject: [PATCH] Factored out Pagination into its own Container view. --- cms/static/js/views/library_container.js | 180 +---------------------- cms/static/js/views/paged_container.js | 158 ++++++++++++++++++++ cms/static/js/views/paging.js | 40 +---- cms/static/js/views/paging_mixin.js | 37 +++++ 4 files changed, 202 insertions(+), 213 deletions(-) create mode 100644 cms/static/js/views/paged_container.js create mode 100644 cms/static/js/views/paging_mixin.js diff --git a/cms/static/js/views/library_container.js b/cms/static/js/views/library_container.js index a8c15999ab..7c48e83cee 100644 --- a/cms/static/js/views/library_container.js +++ b/cms/static/js/views/library_container.js @@ -1,179 +1,7 @@ -define(["jquery", "underscore", "js/views/container", "js/utils/module", "gettext", "js/views/feedback_notification", +define(["jquery", "underscore", "js/views/paged_container", "js/utils/module", "gettext", "js/views/feedback_notification", "js/views/paging_header", "js/views/paging_footer"], - function ($, _, ContainerView, ModuleUtils, gettext, NotificationView, PagingHeader, PagingFooter) { - var LibraryContainerView = ContainerView.extend({ - // Store the request token of the first xblock on the page (which we know was rendered by Studio when - // the page was generated). Use that request token to filter out user-defined HTML in any - // child xblocks within the page. - - initialize: function(options){ - var self = this; - ContainerView.prototype.initialize.call(this); - this.page_size = this.options.page_size || 10; - this.page_reload_callback = options.page_reload_callback || function () {}; - // emulating Backbone.paginator interface - this.collection = { - currentPage: 0, - totalPages: 0, - totalCount: 0, - sortDirection: "desc", - start: 0, - _size: 0, - - bind: function() {}, // no-op - size: function() { return self.collection._size; } - }; - }, - - render: function(options) { - var eff_options = options || {}; - eff_options.page_number = typeof eff_options.page_number !== "undefined" - ? eff_options.page_number - : this.collection.currentPage; - return this.renderPage(eff_options); - }, - - renderPage: function(options){ - var self = this, - view = this.view, - xblockInfo = this.model, - xblockUrl = xblockInfo.url(); - return $.ajax({ - url: decodeURIComponent(xblockUrl) + "/" + view, - type: 'GET', - cache: false, - data: this.getRenderParameters(options.page_number), - headers: { Accept: 'application/json' }, - success: function(fragment) { - self.handleXBlockFragment(fragment, options); - self.processPaging({ requested_page: options.page_number }); - // This is expected to render the add xblock components menu. - self.page_reload_callback(self.$el) - } - }); - }, - - getRenderParameters: function(page_number) { - return { - enable_paging: true, - page_size: this.page_size, - page_number: page_number - }; - }, - - getPageCount: function(total_count){ - if (total_count===0) return 1; - return Math.ceil(total_count / this.page_size); - }, - - setPage: function(page_number) { - this.render({ page_number: page_number}); - }, - - nextPage: function() { - var collection = this.collection, - currentPage = collection.currentPage, - lastPage = collection.totalPages - 1; - if (currentPage < lastPage) { - this.setPage(currentPage + 1); - } - }, - - previousPage: function() { - var collection = this.collection, - currentPage = collection.currentPage; - if (currentPage > 0) { - this.setPage(currentPage - 1); - } - }, - - processPaging: function(options){ - var $element = this.$el.find('.xblock-container-paging-parameters'), - total = $element.data('total'), - displayed = $element.data('displayed'), - start = $element.data('start'); - - this.collection.currentPage = options.requested_page; - this.collection.totalCount = total; - this.collection.totalPages = this.getPageCount(total); - this.collection.start = start; - this.collection._size = displayed; - - this.processPagingHeaderAndFooter(); - }, - - processPagingHeaderAndFooter: function(){ - if (this.pagingHeader) - this.pagingHeader.undelegateEvents(); - if (this.pagingFooter) - this.pagingFooter.undelegateEvents(); - - this.pagingHeader = new PagingHeader({ - view: this, - el: this.$el.find('.container-paging-header') - }); - this.pagingFooter = new PagingFooter({ - view: this, - el: this.$el.find('.container-paging-footer') - }); - - this.pagingHeader.render(); - this.pagingFooter.render(); - }, - - xblockReady: function () { - ContainerView.prototype.xblockReady.call(this); - - this.requestToken = this.$('div.xblock').first().data('request-token'); - }, - - refresh: function(block_added) { - if (block_added) { - this.collection.totalCount += 1; - this.collection._size +=1; - if (this.collection.totalCount == 1) { - this.render(); - return - } - this.collection.totalPages = this.getPageCount(this.collection.totalCount); - var new_page = this.collection.totalPages - 1; - // If we're on a new page due to overflow, or this is the first item, set the page. - if (((this.collection.currentPage) != new_page) || this.collection.totalCount == 1) { - this.setPage(new_page); - } else { - this.pagingHeader.render(); - this.pagingFooter.render(); - } - } - }, - - acknowledgeXBlockDeletion: function (locator){ - this.notifyRuntime('deleted-child', locator); - this.collection._size -= 1; - this.collection.totalCount -= 1; - var current_page = this.collection.currentPage; - var total_pages = this.getPageCount(this.collection.totalCount); - this.collection.totalPages = total_pages; - // Starts counting from 0 - if ((current_page + 1) > total_pages) { - // The number of total pages has changed. Move down. - // Also, be mindful of the off-by-one. - this.setPage(total_pages - 1) - } else if ((current_page + 1) != total_pages) { - // Refresh page to get any blocks shifted from the next page. - this.setPage(current_page) - } else { - // We're on the last page, just need to update the numbers in the - // pagination interface. - this.pagingHeader.render(); - this.pagingFooter.render(); - } - }, - - sortDisplayName: function() { - return "Date added"; // TODO add support for sorting - } - }); - + function ($, _, PagedContainerView) { + // To be extended with Library-specific features later. + var LibraryContainerView = PagedContainerView; return LibraryContainerView; }); // end define(); diff --git a/cms/static/js/views/paged_container.js b/cms/static/js/views/paged_container.js new file mode 100644 index 0000000000..cd7590156a --- /dev/null +++ b/cms/static/js/views/paged_container.js @@ -0,0 +1,158 @@ +define(["jquery", "underscore", "js/views/container", "js/utils/module", "gettext", + "js/views/feedback_notification", "js/views/paging_header", "js/views/paging_footer", "js/views/paging_mixin"], + function ($, _, ContainerView, ModuleUtils, gettext, NotificationView, PagingHeader, PagingFooter, PagingMixin) { + var PagedContainerView = ContainerView.extend(PagingMixin).extend({ + initialize: function(options){ + var self = this; + ContainerView.prototype.initialize.call(this); + this.page_size = this.options.page_size || 10; + this.page_reload_callback = options.page_reload_callback || function () {}; + // emulating Backbone.paginator interface + this.collection = { + currentPage: 0, + totalPages: 0, + totalCount: 0, + sortDirection: "desc", + start: 0, + _size: 0, + + bind: function() {}, // no-op + size: function() { return self.collection._size; } + }; + }, + + render: function(options) { + var eff_options = options || {}; + eff_options.page_number = typeof eff_options.page_number !== "undefined" + ? eff_options.page_number + : this.collection.currentPage; + return this.renderPage(eff_options); + }, + + renderPage: function(options){ + var self = this, + view = this.view, + xblockInfo = this.model, + xblockUrl = xblockInfo.url(); + return $.ajax({ + url: decodeURIComponent(xblockUrl) + "/" + view, + type: 'GET', + cache: false, + data: this.getRenderParameters(options.page_number), + headers: { Accept: 'application/json' }, + success: function(fragment) { + self.handleXBlockFragment(fragment, options); + self.processPaging({ requested_page: options.page_number }); + // This is expected to render the add xblock components menu. + self.page_reload_callback(self.$el) + } + }); + }, + + getRenderParameters: function(page_number) { + return { + enable_paging: true, + page_size: this.page_size, + page_number: page_number + }; + }, + + getPageCount: function(total_count){ + if (total_count===0) return 1; + return Math.ceil(total_count / this.page_size); + }, + + setPage: function(page_number) { + this.render({ page_number: page_number}); + }, + + processPaging: function(options){ + var $element = this.$el.find('.xblock-container-paging-parameters'), + total = $element.data('total'), + displayed = $element.data('displayed'), + start = $element.data('start'); + + this.collection.currentPage = options.requested_page; + this.collection.totalCount = total; + this.collection.totalPages = this.getPageCount(total); + this.collection.start = start; + this.collection._size = displayed; + + this.processPagingHeaderAndFooter(); + }, + + processPagingHeaderAndFooter: function(){ + if (this.pagingHeader) + this.pagingHeader.undelegateEvents(); + if (this.pagingFooter) + this.pagingFooter.undelegateEvents(); + + this.pagingHeader = new PagingHeader({ + view: this, + el: this.$el.find('.container-paging-header') + }); + this.pagingFooter = new PagingFooter({ + view: this, + el: this.$el.find('.container-paging-footer') + }); + + this.pagingHeader.render(); + this.pagingFooter.render(); + }, + + xblockReady: function () { + ContainerView.prototype.xblockReady.call(this); + + this.requestToken = this.$('div.xblock').first().data('request-token'); + }, + + refresh: function(block_added) { + if (block_added) { + this.collection.totalCount += 1; + this.collection._size +=1; + if (this.collection.totalCount == 1) { + this.render(); + return + } + this.collection.totalPages = this.getPageCount(this.collection.totalCount); + var new_page = this.collection.totalPages - 1; + // If we're on a new page due to overflow, or this is the first item, set the page. + if (((this.collection.currentPage) != new_page) || this.collection.totalCount == 1) { + this.setPage(new_page); + } else { + this.pagingHeader.render(); + this.pagingFooter.render(); + } + } + }, + + acknowledgeXBlockDeletion: function (locator){ + this.notifyRuntime('deleted-child', locator); + this.collection._size -= 1; + this.collection.totalCount -= 1; + var current_page = this.collection.currentPage; + var total_pages = this.getPageCount(this.collection.totalCount); + this.collection.totalPages = total_pages; + // Starts counting from 0 + if ((current_page + 1) > total_pages) { + // The number of total pages has changed. Move down. + // Also, be mindful of the off-by-one. + this.setPage(total_pages - 1) + } else if ((current_page + 1) != total_pages) { + // Refresh page to get any blocks shifted from the next page. + this.setPage(current_page) + } else { + // We're on the last page, just need to update the numbers in the + // pagination interface. + this.pagingHeader.render(); + this.pagingFooter.render(); + } + }, + + sortDisplayName: function() { + return "Date added"; // TODO add support for sorting + } + }); + + return PagedContainerView; + }); // end define(); diff --git a/cms/static/js/views/paging.js b/cms/static/js/views/paging.js index c6c3a491ca..c4d9b1b602 100644 --- a/cms/static/js/views/paging.js +++ b/cms/static/js/views/paging.js @@ -1,7 +1,7 @@ -define(["underscore", "js/views/baseview", "js/views/feedback_alert", "gettext"], - function(_, BaseView, AlertView, gettext) { +define(["underscore", "js/views/baseview", "js/views/feedback_alert", "gettext", "js/views/paging_mixin"], + function(_, BaseView, AlertView, gettext, PagingMixin) { - var PagingView = BaseView.extend({ + var PagingView = BaseView.extend(PagingMixin).extend({ // takes a Backbone Paginator as a model sortableColumns: {}, @@ -21,43 +21,10 @@ define(["underscore", "js/views/baseview", "js/views/feedback_alert", "gettext"] this.$('#' + sortColumn).addClass('current-sort'); }, - setPage: function(page) { - var self = this, - collection = self.collection, - oldPage = collection.currentPage; - collection.goTo(page, { - reset: true, - success: function() { - window.scrollTo(0, 0); - }, - error: function(collection) { - collection.currentPage = oldPage; - self.onError(); - } - }); - }, - onError: function() { // Do nothing by default }, - nextPage: function() { - var collection = this.collection, - currentPage = collection.currentPage, - lastPage = collection.totalPages - 1; - if (currentPage < lastPage) { - this.setPage(currentPage + 1); - } - }, - - previousPage: function() { - var collection = this.collection, - currentPage = collection.currentPage; - if (currentPage > 0) { - this.setPage(currentPage - 1); - } - }, - /** * Registers information about a column that can be sorted. * @param columnName The element name of the column. @@ -110,6 +77,5 @@ define(["underscore", "js/views/baseview", "js/views/feedback_alert", "gettext"] this.setPage(0); } }); - return PagingView; }); // end define(); diff --git a/cms/static/js/views/paging_mixin.js b/cms/static/js/views/paging_mixin.js new file mode 100644 index 0000000000..d2c1700e5d --- /dev/null +++ b/cms/static/js/views/paging_mixin.js @@ -0,0 +1,37 @@ +define(["jquery", "underscore"], + function ($, _) { + var PagedMixin = { + setPage: function (page) { + var self = this, + collection = self.collection, + oldPage = collection.currentPage; + collection.goTo(page, { + reset: true, + success: function () { + window.scrollTo(0, 0); + }, + error: function (collection) { + collection.currentPage = oldPage; + self.onError(); + } + }); + }, + nextPage: function() { + var collection = this.collection, + currentPage = collection.currentPage, + lastPage = collection.totalPages - 1; + if (currentPage < lastPage) { + this.setPage(currentPage + 1); + } + }, + + previousPage: function() { + var collection = this.collection, + currentPage = collection.currentPage; + if (currentPage > 0) { + this.setPage(currentPage - 1); + } + } + }; + return PagedMixin; + });