* @author Alexander Ebert
* @copyright 2001-2015 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ *
+ * @deprecated 2.2 - please use `WoltLab/WCF/Ui/Like/Handler` instead
*/
WCF.Like = Class.extend({
/**
/**
* Provides the 'jump to page' overlay.
+ *
+ * @deprecated 2.2 - use `WoltLab/WCF/Ui/Page/JumpTo` instead
*/
WCF.System.PageNavigation = {
- /**
- * submit button
- * @var jQuery
- */
- _button: null,
-
- /**
- * page No description
- * @var jQuery
- */
- _description: null,
-
- /**
- * dialog overlay
- * @var jQuery
- */
- _dialog: null,
-
- /**
- * active element id
- * @var string
- */
- _elementID: '',
-
- /**
- * list of tracked navigation bars
- * @var object
- */
- _elements: { },
-
- /**
- * page No input
- * @var jQuery
- */
- _pageNo: null,
-
- /**
- * Initializes the 'jump to page' overlay for given selector.
- *
- * @param string selector
- * @param object callback
- */
init: function(selector, callback) {
- var $elements = $(selector);
- if (!$elements.length) {
- return;
- }
-
- callback = callback || null;
- if (callback !== null && !$.isFunction(callback)) {
- console.debug("[WCF.System.PageNavigation] Callback for selector '" + selector + "' is invalid, aborting.");
- return;
- }
-
- this._initElements($elements, callback);
- },
-
- /**
- * Initializes the 'jump to page' overlay for given elements.
- *
- * @param jQuery elements
- * @param object callback
- */
- _initElements: function(elements, callback) {
- var self = this;
- elements.each(function(index, element) {
- var $element = $(element);
- var $elementID = $element.wcfIdentify();
-
- if (self._elements[$elementID] === undefined) {
- self._elements[$elementID] = $element;
- $element.find('li.jumpTo').data('elementID', $elementID).click($.proxy(self._click, self));
+ require(['WoltLab/WCF/Ui/Page/JumpTo'], function(UiPageJumpTo) {
+ var elements = elBySelAll(selector);
+ for (var i = 0, length = elements.length; i < length; i++) {
+ UiPageJumpTo.init(elements[i], callback);
}
- }).data('callback', callback);
- },
-
- /**
- * Shows the 'jump to page' overlay.
- *
- * @param object event
- */
- _click: function(event) {
- this._elementID = $(event.currentTarget).data('elementID');
-
- if (this._dialog === null) {
- this._dialog = $('<div id="pageNavigationOverlay" />').hide().appendTo(document.body);
-
- var $fieldset = $('<fieldset><legend>' + WCF.Language.get('wcf.global.page.jumpTo') + '</legend></fieldset>').appendTo(this._dialog);
- $('<dl><dt><label for="jsPageNavigationPageNo">' + WCF.Language.get('wcf.global.page.jumpTo') + '</label></dt><dd></dd></dl>').appendTo($fieldset);
- this._pageNo = $('<input type="number" id="jsPageNavigationPageNo" value="1" min="1" max="1" class="tiny" />').keyup($.proxy(this._keyUp, this)).appendTo($fieldset.find('dd'));
- this._description = $('<small></small>').insertAfter(this._pageNo);
- var $formSubmit = $('<div class="formSubmit" />').appendTo(this._dialog);
- this._button = $('<button class="buttonPrimary">' + WCF.Language.get('wcf.global.button.submit') + '</button>').click($.proxy(this._submit, this)).appendTo($formSubmit);
- }
-
- this._button.enable();
- this._description.html(WCF.Language.get('wcf.global.page.jumpTo.description').replace(/#pages#/, this._elements[this._elementID].data('pages')));
- this._pageNo.val(this._elements[this._elementID].data('pages')).attr('max', this._elements[this._elementID].data('pages'));
-
- this._dialog.wcfDialog({
- 'title': WCF.Language.get('wcf.global.page.pageNavigation')
});
- },
-
- /**
- * Validates the page No input.
- *
- * @param Event event
- */
- _keyUp: function(event) {
- if (event.which == $.ui.keyCode.ENTER && !this._button.prop('disabled')) {
- this._submit();
- return;
- }
-
- var $pageNo = parseInt(this._pageNo.val()) || 0;
- if ($pageNo < 1 || $pageNo > this._pageNo.attr('max')) {
- this._button.disable();
- }
- else {
- this._button.enable();
- }
- },
-
- /**
- * Redirects to given page No.
- */
- _submit: function() {
- var $pageNavigation = this._elements[this._elementID];
- if ($pageNavigation.data('callback') === null) {
- var $redirectURL = $pageNavigation.data('link').replace(/pageNo=%d/, 'pageNo=' + this._pageNo.val());
- window.location = $redirectURL;
- }
- else {
- $pageNavigation.data('callback')(this._pageNo.val());
- this._dialog.wcfDialog('close');
- }
}
};
/**
* jQuery widget implementation of the wcf pagination.
+ *
+ * @deprecated 2.2 - use `WoltLab/WCF/Ui/Pagination` instead
*/
$.widget('ui.wcfPages', {
+ _api: null,
+
SHOW_LINKS: 11,
SHOW_SUB_LINKS: 20,
options: {
// vars
activePage: 1,
- maxPage: 1,
-
- // language
- // we use options here instead of language variables, because the paginator is not only usable with pages
- nextPage: null,
- previousPage: null
+ maxPage: 1
},
/**
* Creates the pages widget.
*/
_create: function() {
- if (this.options.nextPage === null) this.options.nextPage = WCF.Language.get('wcf.global.page.next');
- if (this.options.previousPage === null) this.options.previousPage = WCF.Language.get('wcf.global.page.previous');
-
- this.element.addClass('pageNavigation');
-
- this._render();
+ require(['WoltLab/WCF/Ui/Pagination'], (function(UiPagination) {
+ this._api = new UiPagination(this.element, {
+ activePage: this.options.activePage,
+ maxPage: this.options.maxPage,
+
+ callbackShouldSwitch: (function(pageNo) {
+ var result = this._trigger('shouldSwitch', undefined, {
+ nextPage: pageNo
+ });
+
+ return (result !== false);
+ }).bind(this),
+ callbackSwitch: (function(pageNo) {
+ this._trigger('switched', undefined, {
+ activePage: pageNo
+ });
+ }).bind(this)
+ });
+ }).bind(this));
},
/**
destroy: function() {
$.Widget.prototype.destroy.apply(this, arguments);
- this.element.children().remove();
- },
-
- /**
- * Renders the pages widget.
- */
- _render: function() {
- // only render if we have more than 1 page
- if (!this.options.disabled && this.options.maxPage > 1) {
- var $hasHiddenPages = false;
-
- // make sure pagination is visible
- if (this.element.hasClass('hidden')) {
- this.element.removeClass('hidden');
- }
- this.element.show();
-
- this.element.children().remove();
-
- var $pageList = $('<ul />');
- this.element.append($pageList);
-
- var $previousElement = $('<li class="button skip" />');
- $pageList.append($previousElement);
-
- if (this.options.activePage > 1) {
- var $previousLink = $('<a' + ((this.options.previousPage != null) ? (' title="' + this.options.previousPage + '"') : ('')) + '></a>');
- $previousElement.append($previousLink);
- this._bindSwitchPage($previousLink, this.options.activePage - 1);
-
- var $previousImage = $('<span class="icon icon16 icon-double-angle-left" />');
- $previousLink.append($previousImage);
- }
- else {
- var $previousImage = $('<span class="icon icon16 icon-double-angle-left" />');
- $previousElement.append($previousImage);
- $previousElement.addClass('disabled').removeClass('button');
- $previousImage.addClass('disabled');
- }
-
- // add first page
- $pageList.append(this._renderLink(1));
-
- // calculate page links
- var $maxLinks = this.SHOW_LINKS - 4;
- var $linksBefore = this.options.activePage - 2;
- if ($linksBefore < 0) $linksBefore = 0;
- var $linksAfter = this.options.maxPage - (this.options.activePage + 1);
- if ($linksAfter < 0) $linksAfter = 0;
- if (this.options.activePage > 1 && this.options.activePage < this.options.maxPage) $maxLinks--;
-
- var $half = $maxLinks / 2;
- var $left = this.options.activePage;
- var $right = this.options.activePage;
- if ($left < 1) $left = 1;
- if ($right < 1) $right = 1;
- if ($right > this.options.maxPage - 1) $right = this.options.maxPage - 1;
-
- if ($linksBefore >= $half) {
- $left -= $half;
- }
- else {
- $left -= $linksBefore;
- $right += $half - $linksBefore;
- }
-
- if ($linksAfter >= $half) {
- $right += $half;
- }
- else {
- $right += $linksAfter;
- $left -= $half - $linksAfter;
- }
-
- $right = Math.ceil($right);
- $left = Math.ceil($left);
- if ($left < 1) $left = 1;
- if ($right > this.options.maxPage) $right = this.options.maxPage;
-
- // left ... links
- if ($left > 1) {
- if ($left - 1 < 2) {
- $pageList.append(this._renderLink(2));
- }
- else {
- $('<li class="button jumpTo"><a title="' + WCF.Language.get('wcf.global.page.jumpTo') + '" class="jsTooltip">...</a></li>').appendTo($pageList);
- $hasHiddenPages = true;
- }
- }
-
- // visible links
- for (var $i = $left + 1; $i < $right; $i++) {
- $pageList.append(this._renderLink($i));
- }
-
- // right ... links
- if ($right < this.options.maxPage) {
- if (this.options.maxPage - $right < 2) {
- $pageList.append(this._renderLink(this.options.maxPage - 1));
- }
- else {
- $('<li class="button jumpTo"><a title="' + WCF.Language.get('wcf.global.page.jumpTo') + '" class="jsTooltip">...</a></li>').appendTo($pageList);
- $hasHiddenPages = true;
- }
- }
-
- // add last page
- $pageList.append(this._renderLink(this.options.maxPage));
-
- // add next button
- var $nextElement = $('<li class="button skip" />');
- $pageList.append($nextElement);
-
- if (this.options.activePage < this.options.maxPage) {
- var $nextLink = $('<a' + ((this.options.nextPage != null) ? (' title="' + this.options.nextPage + '"') : ('')) + '></a>');
- $nextElement.append($nextLink);
- this._bindSwitchPage($nextLink, this.options.activePage + 1);
-
- var $nextImage = $('<span class="icon icon16 icon-double-angle-right" />');
- $nextLink.append($nextImage);
- }
- else {
- var $nextImage = $('<span class="icon icon16 icon-double-angle-right" />');
- $nextElement.append($nextImage);
- $nextElement.addClass('disabled').removeClass('button');
- $nextImage.addClass('disabled');
- }
-
- if ($hasHiddenPages) {
- $pageList.data('pages', this.options.maxPage);
- WCF.System.PageNavigation.init('#' + $pageList.wcfIdentify(), $.proxy(function(pageNo) {
- this.switchPage(pageNo);
- }, this));
- }
- }
- else {
- // otherwise hide the paginator if not already hidden
- this.element.hide();
- }
- },
-
- /**
- * Renders a page link.
- *
- * @parameter integer page
- * @return jQuery
- */
- _renderLink: function(page, lineBreak) {
- var $pageElement = $('<li class="button"></li>');
- if (lineBreak != undefined && lineBreak) {
- $pageElement.addClass('break');
- }
- if (page != this.options.activePage) {
- var $pageLink = $('<a>' + WCF.String.addThousandsSeparator(page) + '</a>');
- $pageElement.append($pageLink);
- this._bindSwitchPage($pageLink, page);
- }
- else {
- $pageElement.addClass('active');
- var $pageSubElement = $('<span>' + WCF.String.addThousandsSeparator(page) + '</span><span class="invisible">' + WCF.Language.get('wcf.page.pagePosition', { pageNo: page, pages: this.options.maxPage }) + '</span>');
- $pageElement.append($pageSubElement);
- }
-
- return $pageElement;
- },
-
- /**
- * Binds the 'click'-event for the page switching to the given element.
- *
- * @parameter $(element) element
- * @paremeter integer page
- */
- _bindSwitchPage: function(element, page) {
- var $self = this;
- element.click(function() {
- $self.switchPage(page);
- });
- },
-
- /**
- * Switches to the given page
- *
- * @parameter Event event
- * @parameter integer page
- */
- switchPage: function(page) {
- this._setOption('activePage', page);
+ this._api = null;
+ this.element[0].innerHTML = '';
},
/**
});
if ($result || $result !== undefined) {
- this.options[key] = value;
- this._render();
- this._trigger('switched', undefined, {
- activePage: value
- });
+ this._api.switchPage(value);
+
}
else {
this._trigger('notSwitched', undefined, {
}
}
}
- else {
- this.options[key] = value;
-
- if (key == 'disabled') {
- if (value) {
- this.element.children().remove();
- }
- else {
- this._render();
- }
- }
- else if (key == 'maxPage') {
- this._render();
- }
- }
return this;
- },
-
- /**
- * Start input of pagenumber
- *
- * @parameter Event event
- */
- _startInput: function(event) {
- // hide a-tag
- var $childLink = $(event.currentTarget);
- if (!$childLink.is('a')) $childLink = $childLink.parent('a');
-
- $childLink.hide();
-
- // show input-tag
- var $childInput = $childLink.parent('li').children('input')
- .css('display', 'block')
- .val('');
-
- $childInput.focus();
- },
-
- /**
- * Stops input of pagenumber
- *
- * @parameter Event event
- */
- _stopInput: function(event) {
- // hide input-tag
- var $childInput = $(event.currentTarget);
- $childInput.css('display', 'none');
-
- // show a-tag
- var $childContainer = $childInput.parent('li');
- if ($childContainer != undefined && $childContainer != null) {
- $childContainer.children('a').show();
- }
- },
-
- /**
- * Handles input of pagenumber
- *
- * @parameter Event event
- */
- _handleInput: function(event) {
- var $ie7 = ($.browser.msie && $.browser.version == '7.0');
- if (event.type != 'keyup' || $ie7) {
- if (!$ie7 || ((event.which == 13 || event.which == 27) && event.type == 'keyup')) {
- if (event.which == 13) {
- this.switchPage(parseInt($(event.currentTarget).val()));
- }
-
- if (event.which == 13 || event.which == 27) {
- this._stopInput(event);
- event.stopPropagation();
- }
- }
- }
}
});
DomUtil.prepend(dialog, _container);
+ if (typeof options.onSetup === 'function') {
+ options.onSetup(content);
+ }
+
if (createOnly !== true) {
this._updateDialog(id, null);
}
-define(['Ajax', 'Core', 'Dictionary', 'Language', 'ObjectMap', 'StringUtil', 'Dom/ChangeListener', 'Dom/Util', 'Ui/Dialog'], function(Ajax, Core, Dictionary, Language, ObjectMap, StringUtil, DomChangeListener, DomUtil, UiDialog) {
+/**
+ * Provides interface elements to display and review likes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLab/WCF/Ui/Like/Handler
+ */
+define(
+ [
+ 'Ajax', 'Core', 'Dictionary', 'Language',
+ 'ObjectMap', 'StringUtil', 'Dom/ChangeListener', 'Dom/Util',
+ 'Ui/Dialog', 'WoltLab/WCF/Ui/User/List'
+ ],
+ function(
+ Ajax, Core, Dictionary, Language,
+ ObjectMap, StringUtil, DomChangeListener, DomUtil,
+ UiDialog, UiUserList
+ )
+{
"use strict";
var _isBusy = false;
+ /**
+ * @constructor
+ */
function UiLikeHandler(objectType, options) { this.init(objectType, options); };
UiLikeHandler.prototype = {
+ /**
+ * Initializes the like handler.
+ *
+ * @param {string} objectType object type
+ * @param {object} options initilization options
+ */
init: function(objectType, options) {
if (options.containerSelector === '') {
throw new Error("[WoltLab/WCF/Ui/Like/Handler] Expected a non-emtpy string for option 'containerSelector'.");
this.initContainers(options, objectType);
},
+ /**
+ * Initializes all applicable containers.
+ */
initContainers: function() {
var element, elements = elBySelAll(this._options.containerSelector), elementData, triggerChange = false;
for (var i = 0, length = elements.length; i < length; i++) {
}
},
+ /**
+ * Creates the interface elements.
+ *
+ * @param {Element} element container element
+ * @param {object} elementData like data
+ */
_buildWidget: function(element, elementData) {
// build summary
if (this._options.canViewSummary) {
}
},
+ /**
+ * Creates a like or dislike button.
+ *
+ * @param {Element} element container element
+ * @param {Element} insertBefore insert button before given element
+ * @param {boolean} isLike false if this is a dislike button
+ * @return {Element} button element
+ */
_createButton: function(element, insertBefore, isLike) {
var title = Language.get('wcf.like.button.' + (isLike ? 'like' : 'dislike'));
return button;
},
+ /**
+ * Shows the summary of likes/dislikes.
+ *
+ * @param {Element} element container element
+ * @param {object} event event object
+ */
_showSummary: function(element, event) {
event.preventDefault();
if (!this._details.has(element)) {
- // @TODO
- this._details.set(element, new WCF.User.List('wcf\\data\\like\\LikeAction', Language.get('wcf.like.details'), {
- data: {
- containerID: DomUtil.identify(element),
- objectID: this._containers.get(element).objectId,
- objectType: this._objectType
+ this._details.set(element, new UiUserList({
+ className: 'wcf\\data\\like\\LikeAction',
+ dialogTitle: Language.get('wcf.like.details'),
+ parameters: {
+ data: {
+ containerID: DomUtil.identify(element),
+ objectID: this._containers.get(element).objectId,
+ objectType: this._objectType
+ }
}
}));
}
this._details.get(element).open();
},
+ /**
+ * Updates the display of cumulative likes.
+ *
+ * @param {Element} element container element
+ */
_updateBadge: function(element) {
var data = this._containers.get(element);
}
},
+ /**
+ * Updates the like summary.
+ *
+ * @param {Element} element container element
+ */
_updateSummary: function(element) {
var data = this._containers.get(element);
}
},
+ /**
+ * Updates the active like/dislike button state.
+ *
+ * @param {Element} element container element
+ */
_updateActiveState: function(element) {
var data = this._containers.get(element);
}
},
+ /**
+ * Likes or dislikes an element.
+ *
+ * @param {Element} element container element
+ * @param {object} event event object
+ */
_like: function(element, event) {
event.preventDefault();
--- /dev/null
+/**
+ * Utility class to provide a 'Jump To' overlay.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLab/WCF/Ui/Page/JumpTo
+ */
+define(['Language', 'ObjectMap', 'Ui/Dialog'], function(Language, ObjectMap, UiDialog) {
+ "use strict";
+
+ var _activeElement = null;
+ var _buttonSubmit = null;
+ var _description = null;
+ var _elements = new ObjectMap();
+ var _input = null;
+
+ /**
+ * @exports WoltLab/WCF/Ui/Page/JumpTo
+ */
+ var UiPageJumpTo = {
+ /**
+ * Initializes a 'Jump To' element.
+ *
+ * @param {Element} element trigger element
+ * @param {function} callback callback function, receives the page number as first argument
+ */
+ init: function(element, callback) {
+ callback = callback || null;
+ if (callback === null) {
+ var redirectUrl = elAttr(element, 'data-link');
+ if (redirectUrl) {
+ callback = function(pageNo) {
+ window.location = redirectUrl.replace(/pageNo=%d/, 'pageNo=' + pageNo);
+ };
+ }
+ else {
+ callback = function() {};
+ }
+
+ }
+ else if (typeof callback !== 'function') {
+ throw new TypeError("Expected a valid function for parameter 'callback'.");
+ }
+
+ if (!_elements.has(element)) {
+ var jumpTo = elBySel('.jumpTo', element);
+ if (jumpTo !== null) {
+ jumpTo.addEventListener('click', this._click.bind(this, element));
+
+ _elements.set(element, { callback: callback });
+ }
+ }
+ },
+
+ /**
+ * Handles clicks on the trigger element.
+ *
+ * @param {Element} element trigger element
+ * @param {object} event event object
+ */
+ _click: function(element, event) {
+ _activeElement = element;
+
+ if (typeof event === 'object') {
+ event.preventDefault();
+ }
+
+ UiDialog.open(this);
+
+ var pages = elAttr(element, 'data-pages');
+ _input.value = pages;
+ _input.setAttribute('max', pages);
+
+ _description.textContent = Language.get('wcf.global.page.jumpTo.description').replace(/#pages#/, pages);
+ },
+
+ /**
+ * Handles changes to the page number input field.
+ *
+ * @param {object} event event object
+ */
+ _keyUp: function(event) {
+ if (event.which === 13 && _buttonSubmit.disabled === false) {
+ this._submit();
+ return;
+ }
+
+ var pageNo = ~~_input.value;
+ if (pageNo < 1 || pageNo > ~~elAttr(_input, 'max')) {
+ _buttonSubmit.disabled = true;
+ }
+ else {
+ _buttonSubmit.disabled = false;
+ }
+ },
+
+ /**
+ * Invokes the callback with the chosen page number as first argument.
+ *
+ * @param {object} event event object
+ */
+ _submit: function(event) {
+ _elements.get(_activeElement).callback(~~_input.value);
+
+ UiDialog.close(this);
+ },
+
+ _dialogSetup: function() {
+ var source = '<dl>'
+ + '<dt><label for="jsPageNavigationPageNo">' + Language.get('wcf.global.page.jumpTo') + '</label></dt>'
+ + '<dd>'
+ + '<input type="number" id="jsPageNavigationPageNo" value="1" min="1" max="1" class="tiny">'
+ + '<small></small>'
+ + '</dd>'
+ + '</dl>'
+ + '<div class="formSubmit">'
+ + '<button class="buttonPrimary">' + Language.get('wcf.global.button.submit') + '</button>'
+ + '</div>';
+
+ return {
+ id: 'pageNavigationOverlay',
+ options: {
+ onSetup: (function(content) {
+ _input = elByTag('input', content)[0];
+ _input.addEventListener('keyup', this._keyUp.bind(this));
+
+ _description = elByTag('small', content)[0];
+
+ _buttonSubmit = elByTag('button', content)[0];
+ _buttonSubmit.addEventListener('click', this._submit.bind(this));
+ }).bind(this),
+ title: Language.get('wcf.global.page.pageNavigation')
+ },
+ source: source
+ };
+ }
+ };
+
+ return UiPageJumpTo;
+});
\ No newline at end of file
--- /dev/null
+/**
+ * Callback-based pagination.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLab/WCF/Ui/Pagination
+ */
+define(['Core', 'Language', 'ObjectMap', 'StringUtil', 'WoltLab/WCF/Ui/Page/JumpTo'], function(Core, Language, ObjectMap, StringUtil, UiPageJumpTo) {
+ "use strict";
+
+ /**
+ * @constructor
+ */
+ function UiPagination(element, options) { this.init(element, options); };
+ UiPagination.prototype = {
+ /**
+ * maximum number of displayed page links, should match the PHP implementation
+ * @var {integer}
+ */
+ SHOW_LINKS: 11,
+
+ /**
+ * Initializes the pagination.
+ *
+ * @param {Element} element container element
+ * @param {object} options list of initilization options
+ */
+ init: function(element, options) {
+ this._element = element;
+ this._options = Core.extend({
+ activePage: 1,
+ maxPage: 1,
+
+ callbackShouldSwitch: null,
+ callbackSwitch: null
+ }, options);
+
+ if (typeof this._options.callbackShouldSwitch !== 'function') this._options.callbackShouldSwitch = null;
+ if (typeof this._options.callbackSwitch !== 'function') this._options.callbackSwitch = null;
+
+ this._element.classList.add('pageNavigation');
+ this._element.classList.add('small');
+
+ this._rebuild(this._element);
+ },
+
+ /**
+ * Rebuilds the entire pagination UI.
+ */
+ _rebuild: function() {
+ var hasHiddenPages = false;
+
+ // clear content
+ this._element.innerHTML = '';
+
+ var list = elCreate('ul'), link;
+
+ var listItem = elCreate('li');
+ listItem.className = 'skip';
+ list.appendChild(listItem);
+
+ var iconClassNames = 'icon icon16 fa-angle-double-left';
+ if (this._options.activePage > 1) {
+ link = elCreate('a');
+ link.className = iconClassNames + ' jsTooltip';
+ link.href = '#';
+ link.title = Language.get('wcf.global.page.previous');
+ listItem.appendChild(link);
+
+ link.addEventListener('click', this.switchPage.bind(this, this._options.activePage - 1));
+ }
+ else {
+ listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+ listItem.classList.add('disabled');
+ }
+
+ // add first page
+ list.appendChild(this._createLink(1, this._options));
+
+ // calculate page links
+ var maxLinks = this.SHOW_LINKS - 4;
+ var linksBefore = this._options.activePage - 2;
+ if (linksBefore < 0) linksBefore = 0;
+ var linksAfter = this._options.maxPage - (this._options.activePage + 1);
+ if (linksAfter < 0) linksAfter = 0;
+ if (this._options.activePage > 1 && this._options.activePage < this._options.maxPage) maxLinks--;
+
+ var half = maxLinks / 2;
+ var left = this._options.activePage;
+ var right = this._options.activePage;
+ if (left < 1) left = 1;
+ if (right < 1) right = 1;
+ if (right > this._options.maxPage - 1) right = this._options.maxPage - 1;
+
+ if (linksBefore >= half) {
+ left -= half;
+ }
+ else {
+ left -= linksBefore;
+ right += half - linksBefore;
+ }
+
+ if (linksAfter >= half) {
+ right += half;
+ }
+ else {
+ right += linksAfter;
+ left -= half - linksAfter;
+ }
+
+ right = Math.ceil(right);
+ left = Math.ceil(left);
+ if (left < 1) left = 1;
+ if (right > this._options.maxPage) right = this._options.maxPage;
+
+ // left ... links
+ var jumpToHtml = '<a class="jsTooltip" title="' + Language.get('wcf.global.page.jumpTo') + '">…</a>';
+ if (left > 1) {
+ if (left - 1 < 2) {
+ list.appendChild(this._createLink(2, this._options));
+ }
+ else {
+ var listItem = elCreate('li');
+ listItem.className = 'jumpTo';
+ listItem.innerHTML = jumpToHtml;
+ list.appendChild(listItem);
+
+ hasHiddenPages = true;
+ }
+ }
+
+ // visible links
+ for (var i = left + 1; i < right; i++) {
+ list.appendChild(this._createLink(i, this._options));
+ }
+
+ // right ... links
+ if (right < this._options.maxPage) {
+ if (this._options.maxPage - right < 2) {
+ list.appendChild(this._createLink(this._options.maxPage - 1, this._options));
+ }
+ else {
+ var listItem = elCreate('li');
+ listItem.className = 'jumpTo';
+ listItem.innerHTML = jumpToHtml;
+ list.appendChild(listItem);
+
+ hasHiddenPages = true;
+ }
+ }
+
+ // add last page
+ list.appendChild(this._createLink(this._options.maxPage, this._options));
+
+ // add next button
+ listItem = elCreate('li');
+ listItem.className = 'skip';
+ list.appendChild(listItem);
+
+ iconClassNames = 'icon icon16 fa-angle-double-right';
+ if (this._options.activePage < this._options.maxPage) {
+ link = elCreate('a');
+ link.className = iconClassNames + ' jsTooltip';
+ link.href = '#';
+ link.title = Language.get('wcf.global.page.next');
+ listItem.appendChild(link);
+
+ link.addEventListener('click', this.switchPage.bind(this, this._options.activePage + 1));
+ }
+ else {
+ listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+ listItem.classList.add('disabled');
+ }
+
+ if (hasHiddenPages) {
+ list.setAttribute('data-pages', this._options.maxPage);
+
+ UiPageJumpTo.init(list, this.switchPage.bind(this));
+ }
+
+ this._element.appendChild(list);
+ },
+
+ /**
+ * Creates a link to a specific page.
+ *
+ * @param {integer} pageNo page number
+ * @return {Element} link element
+ */
+ _createLink: function(pageNo) {
+ var listItem = elCreate('li');
+ if (pageNo !== this._options.activePage) {
+ var link = elCreate('a');
+ link.textContent = StringUtil.addThousandsSeparator(pageNo);
+ link.addEventListener('click', this.switchPage.bind(this, pageNo));
+ listItem.appendChild(link);
+ }
+ else {
+ listItem.classList.add('active');
+ listItem.innerHTML = '<span>' + StringUtil.addThousandsSeparator(pageNo) + '</span><span class="invisible">' + Language.get('wcf.page.pagePosition', { pageNo: pageNo, pages: this._options.maxPage }) + '</span>';
+ }
+
+ return listItem;
+ },
+
+ /**
+ * Switches to given page number.
+ *
+ * @param {integer} pageNo page number
+ * @param {object} event event object
+ */
+ switchPage: function(pageNo, event) {
+ if (typeof event === 'object') {
+ event.preventDefault();
+ }
+
+ pageNo = ~~pageNo;
+
+ if (pageNo > 0 && this._options.activePage !== pageNo && pageNo <= this._options.maxPage) {
+ if (this._options.callbackShouldSwitch !== null) {
+ if (this._options.callbackShouldSwitch(pageNo) !== true) {
+ return;
+ }
+ }
+
+ this._options.activePage = pageNo;
+ this._rebuild();
+
+ if (this._options.callbackSwitch !== null) {
+ this._options.callbackSwitch(pageNo);
+ }
+ }
+ }
+ };
+
+ return UiPagination;
+});
--- /dev/null
+/**
+ * Object-based user list.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLab/WCF/Ui/User/List
+ */
+define(['Ajax', 'Core', 'Dictionary', 'Dom/Util', 'Ui/Dialog', 'WoltLab/WCF/Ui/Pagination'], function(Ajax, Core, Dictionary, DomUtil, UiDialog, UiPagination) {
+ "use strict";
+
+ /**
+ * @constructor
+ */
+ function UiUserList(options) { this.init(options); };
+ UiUserList.prototype = {
+ /**
+ * Initializes the user list.
+ *
+ * @param {object} options list of initialization options
+ */
+ init: function(options) {
+ this._cache = new Dictionary();
+ this._pageCount = 0;
+ this._pageNo = 1;
+
+ this._options = Core.extend({
+ className: '',
+ dialogTitle: '',
+ parameters: {}
+ }, options);
+ },
+
+ /**
+ * Opens the user list.
+ */
+ open: function() {
+ this._pageNo = 1;
+ this._showPage();
+ },
+
+ /**
+ * Shows the current or given page.
+ *
+ * @param {integer=} pageNo page number
+ */
+ _showPage: function(pageNo) {
+ if (typeof pageNo === 'number') {
+ this._pageNo = ~~pageNo;
+ }
+
+ if (this._pageCount !== 0 && (this._pageNo < 1 || this._pageNo > this._pageCount)) {
+ throw new RangeError("pageNo must be between 1 and " + this._pageCount + " (" + this._pageNo + " given).");
+ }
+
+ if (this._cache.has(this._pageNo)) {
+ var dialog = UiDialog.open(this, this._cache.get(this._pageNo));
+
+ if (this._pageCount > 1) {
+ var element = elBySel('.jsPagination', dialog.content);
+ if (element !== null) {
+ new UiPagination(element, {
+ activePage: this._pageNo,
+ maxPage: this._pageCount,
+
+ callbackSwitch: this._showPage.bind(this)
+ });
+ }
+ }
+ }
+ else {
+ this._options.parameters.pageNo = this._pageNo;
+
+ Ajax.api(this, {
+ parameters: this._options.parameters
+ });
+ }
+ },
+
+ _ajaxSuccess: function(data) {
+ if (data.returnValues.pageCount !== undefined) {
+ this._pageCount = ~~data.returnValues.pageCount;
+ }
+
+ this._cache.set(this._pageNo, data.returnValues.template);
+ this._showPage();
+ },
+
+ _ajaxSetup: function() {
+ return {
+ data: {
+ actionName: 'getGroupedUserList',
+ className: this._options.className,
+ interfaceName: 'wcf\\data\\IGroupedUserListAction'
+ }
+ };
+ },
+
+ _dialogSetup: function() {
+ return {
+ id: DomUtil.getUniqueId(),
+ options: {
+ title: this._options.dialogTitle
+ },
+ source: null
+ };
+ }
+ };
+
+ return UiUserList;
+});