diff --git a/js/h5p-data-view.js b/js/h5p-data-view.js new file mode 100644 index 0000000..e38ecd3 --- /dev/null +++ b/js/h5p-data-view.js @@ -0,0 +1,126 @@ +var H5PDataView = (function ($) { + + /** + * Initialize a new H5P data view. + * + * @param {Object} container + * @param {String} source URL for data + * @param {Array} headers for data + * @param {Object} l10n translations + */ + function H5PDataView(container, source, headers, l10n, classes) { + var self = this; + + self.$container = $(container).addClass('h5p-data-view').html(''); + H5PUtils.throbber(l10n.loading).appendTo(self.$container); + + self.source = source; + self.headers = headers; + self.l10n = l10n; + self.classes = (classes === undefined ? {} : classes); + self.limit = 20; + + self.loadData(); + } + + /** + * Load data for view. + * + * @param {Number} offset data collection offset + */ + H5PDataView.prototype.loadData = function (offset) { + var self = this; + + // Create URL + var url = self.source; + if (offset !== undefined) { + url += (url.indexOf('?') === -1 ? '?' : '&') + 'offset=' + offset + '&limit=' + self.limit; + } + + // Fire ajax request + $.ajax({ + dataType: 'json', + cache: true, + url: url + }).fail(function () { + // Error handling + self.setMessage(self.l10n.ajaxFailed); + }).done(function (data) { + if (!data.rows.length) { + self.setMessage(self.l10n.noData); + } + else { + // Update table data + self.updateTable(data.rows); + } + + // Update pagination widget + self.updatePagination(data.num); + }); + }; + + /** + * Display the given message to the user. + * + * @param {String} message + */ + H5PDataView.prototype.setMessage = function (message) { + var self = this; + + var $message = $('

', { + text: message + }); + if (self.table === undefined) { + self.$container.children().replaceWith($message); + } + else { + self.table.setBody($('

', {text: message})); + } + }; + + /** + * Update table data. + * + * @param {Array} rows + */ + H5PDataView.prototype.updateTable = function (rows) { + var self = this; + + if (self.table === undefined) { + // Create new table + self.table = new H5PUtils.Table(self.classes, self.headers); + self.table.appendTo(self.$container.html('')); + } + + // Add/update rows + self.table.setRows(rows); + }; + + /** + * Update pagination widget. + * + * @param {Number} num size of data collection + */ + H5PDataView.prototype.updatePagination = function (num) { + var self = this; + + if (self.pagination === undefined) { + // Create new widget + var $pagerContainer = $('

', {'class': 'h5p-pagination'}); + self.pagination = new H5PUtils.Pagination(num, self.limit, function (offset) { + // Handle page changes in pagination widget + self.table.setBody(H5PUtils.throbber(self.l10n.loading)); + self.loadData(offset); + }, self.l10n); + + self.pagination.appendTo($pagerContainer); + self.table.setFoot($pagerContainer); + } + else { + // Update existing widget + self.pagination.update(num, self.limit); + } + }; + + return H5PDataView; +})(H5P.jQuery); diff --git a/js/h5p-utils.js b/js/h5p-utils.js index 0db73a7..6ef61ad 100644 --- a/js/h5p-utils.js +++ b/js/h5p-utils.js @@ -64,7 +64,7 @@ var H5PUtils = H5PUtils || {}; return $field; }; - + /** * Replaces placeholder fields in translation strings * @@ -130,4 +130,224 @@ var H5PUtils = H5PUtils || {}; return $container; }; + /** + * Generic table class with useful helpers. + * + * @param {Object} classes to use for styling + * @param {Array} cols headers + */ + H5PUtils.Table = function (classes, cols) { + // Create basic table + var tableOptions = {}; + if (classes.table !== undefined) { + tableOptions['class'] = classes.table; + } + var $table = $('', tableOptions); + var $thead = $('').appendTo($table); + var $tfoot = $('').appendTo($table); + var $tbody = $('').appendTo($table); + + // Set cols - create header + var $tr = $('').appendTo($thead); + for (var i = 0; i < cols.length; i++) { + $(''); + + for (var i = 0; i < rows.length; i++) { + var $tr = $('').appendTo($newTbody); + + for (var j = 0; j < rows[i].length; j++) { + $(''); + var $tr = $('').appendTo($newTbody); + $(''); + var $tr = $('').appendTo($newTfoot); + $('
', { + html: cols[i] + }).appendTo($tr); + } + + /** + * Public. + * + * @param {Array} rows with cols + */ + this.setRows = function (rows) { + var $newTbody = $('
', { + html: rows[i][j] + }).appendTo($tr); + } + } + + $tbody.replaceWith($newTbody); + $tbody = $newTbody; + }; + + /** + * Public. + * + * @param {jQuery} $content custom + */ + this.setBody = function ($content) { + var $newTbody = $('
', { + colspan: cols.length + }).append($content).appendTo($tr); + $tbody.replaceWith($newTbody); + $tbody = $newTbody; + }; + + /** + * Public. + * + * @param {jQuery} $content custom + */ + this.setFoot = function ($content) { + var $newTfoot = $('
', { + colspan: cols.length + }).append($content).appendTo($tr); + $tfoot.replaceWith($newTfoot); + }; + + + /** + * Public. + * + * @param {jQuery} $container + */ + this.appendTo = function ($container) { + $table.appendTo($container); + }; + }; + + /** + * Generic pagination class. + * + * @param {Number} num total items + * @param {Number} limit items per page + * @param {Function} goneTo page callback + */ + H5PUtils.Pagination = function (num, limit, goneTo, l10n) { + var current = 0; + var pages = Math.ceil(num / limit); + + // Create components + + // Previous button + var $left = $('