412 lines
11 KiB
JavaScript
412 lines
11 KiB
JavaScript
/**
|
|
* @file js/controllers/grid/CategoryGridHandler.js
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2000-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class CategoryGridHandler
|
|
* @ingroup js_controllers_grid
|
|
*
|
|
* @brief Category grid handler.
|
|
*/
|
|
(function($) {
|
|
|
|
|
|
/**
|
|
* @constructor
|
|
*
|
|
* @extends $.pkp.controllers.grid.GridHandler
|
|
*
|
|
* @param {jQueryObject} $grid The grid this handler is
|
|
* attached to.
|
|
* @param {Object} options Grid handler configuration.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler = function($grid, options) {
|
|
this.parent($grid, options);
|
|
};
|
|
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.CategoryGridHandler,
|
|
$.pkp.controllers.grid.GridHandler);
|
|
|
|
|
|
//
|
|
// Public methods.
|
|
//
|
|
/**
|
|
* Get category id prefix.
|
|
* @return {string} Category id prefix.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategoryIdPrefix =
|
|
function() {
|
|
return this.getGridIdPrefix() + '-category-';
|
|
};
|
|
|
|
|
|
/**
|
|
* Get categories tbody element.
|
|
* @return {jQueryObject} Categories tbody elements.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategories =
|
|
function() {
|
|
return $('.category_grid_body:not(.empty)',
|
|
this.getHtmlElement());
|
|
};
|
|
|
|
|
|
/**
|
|
* Get a category tbody element by category data id.
|
|
* @param {string} categoryDataId The category data id.
|
|
* @return {jQueryObject} Category tbody element.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategoryByDataId =
|
|
function(categoryDataId) {
|
|
return $('#' + this.getCategoryIdPrefix() + categoryDataId);
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the category row inside a tbody category element. If none element
|
|
* is passed, get all grid category rows.
|
|
* @param {jQueryObject} $opt_category Category tbody element.
|
|
* @return {jQueryObject} Category rows.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategoryRow =
|
|
function($opt_category) {
|
|
var $context = this.getHtmlElement();
|
|
if ($opt_category !== undefined) {
|
|
$context = $opt_category;
|
|
}
|
|
|
|
return $('tr.category', $context);
|
|
};
|
|
|
|
|
|
/**
|
|
* Get rows inside a tbody category element, excluding the category row.
|
|
* @param {jQueryObject} $category Category tbody element.
|
|
* @return {jQueryObject} Category rows.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getRowsInCategory =
|
|
function($category) {
|
|
return $('tr.gridRow', $category).not('.category');
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the category empty placeholder.
|
|
* @param {jQueryObject} $category A grid category element.
|
|
* @return {jQueryObject} The category empty placeholder.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.
|
|
getCategoryEmptyPlaceholder = function($category) {
|
|
var selector = '#' + $category.attr('id') + '-emptyPlaceholder';
|
|
return $(selector, this.getHtmlElement());
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the category data id by the passed category element.
|
|
* @param {jQueryObject} $category Category element.
|
|
* @return {string} Category data id.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategoryDataId =
|
|
function($category) {
|
|
var categoryId = $category.attr('id'),
|
|
startExtractPosition = this.getCategoryIdPrefix().length;
|
|
|
|
return /** @type {string} */ (categoryId.slice(startExtractPosition));
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the category data id by the passed row element id.
|
|
* @param {string} gridRowId Category row element id.
|
|
* @return {string} Category data id.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getCategoryDataIdByRowId =
|
|
function(gridRowId) {
|
|
// Remove the category id prefix to avoid getting wrong data.
|
|
gridRowId = gridRowId.replace(this.getCategoryIdPrefix(), ' ');
|
|
|
|
// Get the category data id.
|
|
var categoryDataId = gridRowId.match('(.*)-row');
|
|
return $.trim(categoryDataId[1]);
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the id prefix of the grid row inside a category.
|
|
* @return {string}
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getRowIdPrefix =
|
|
function() {
|
|
return this.getGridIdPrefix() + '-category-';
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the grid row by the passed data element id.
|
|
* @param {number} rowDataId
|
|
* @return {jQueryObject}
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getRowByDataId =
|
|
function(rowDataId) {
|
|
this.parent('getRowByDataId', rowDataId);
|
|
return $('#' + this.getRowIdPrefix() + this.currentCategoryId_ +
|
|
'-row-' + rowDataId, this.getHtmlElement());
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the data element id of the passed grid row.
|
|
* @param {jQueryObject} $gridRow The grid row JQuery object.
|
|
* @return {string} The data element id of the passed grid row.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getRowDataId =
|
|
function($gridRow) {
|
|
var rowDataId;
|
|
rowDataId = $gridRow.attr('id').
|
|
slice(this.getRowIdPrefix().length);
|
|
rowDataId = rowDataId.match('-row-(.*)');
|
|
return /** @type {string} */ ($.trim(rowDataId[1]));
|
|
};
|
|
|
|
|
|
/**
|
|
* Append a category to the end of the list.
|
|
* @param {jQueryObject} $category Category to append.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.appendCategory =
|
|
function($category) {
|
|
var $gridBody = this.getHtmlElement().find(this.bodySelector);
|
|
$gridBody.append($category);
|
|
};
|
|
|
|
|
|
/**
|
|
* Re-sequence all category elements based on the passed sequence map.
|
|
* @param {Array} sequenceMap A sequence array with the category
|
|
* element id as value.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.resequenceCategories =
|
|
function(sequenceMap) {
|
|
var categoryId, index, $category;
|
|
for (index in sequenceMap) {
|
|
categoryId = sequenceMap[index];
|
|
$category = $('#' + categoryId);
|
|
this.appendCategory($category);
|
|
}
|
|
|
|
this.updateEmptyPlaceholderPosition();
|
|
};
|
|
|
|
|
|
/**
|
|
* Move all empty category placeholders to their correct position,
|
|
* below of each correspondent category element.
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.
|
|
updateEmptyPlaceholderPosition = function() {
|
|
var $categories = this.getCategories(),
|
|
index, limit,
|
|
$category, $emptyPlaceholder;
|
|
for (index = 0, limit = $categories.length; index < limit; index++) {
|
|
$category = $($categories[index]);
|
|
$emptyPlaceholder = this.getCategoryEmptyPlaceholder($category);
|
|
if ($emptyPlaceholder.length > 0) {
|
|
$emptyPlaceholder.insertAfter($category);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
//
|
|
// Extended methods from GridHandler
|
|
//
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.initialize =
|
|
function(options) {
|
|
// Save the URL to fetch a whole category.
|
|
this.fetchCategoryUrl_ = options.fetchCategoryUrl;
|
|
|
|
this.parent('initialize', options);
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getElementsByType =
|
|
function($element) {
|
|
if ($element.hasClass('category_grid_body')) {
|
|
return this.getCategories();
|
|
} else {
|
|
return /** @type {jQueryObject} */ (
|
|
this.parent('getElementsByType', $element));
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.getEmptyElement =
|
|
function($element) {
|
|
if ($element.hasClass('category_grid_body')) {
|
|
// Return the grid empty element placeholder.
|
|
return this.getHtmlElement().find('.empty').not('.category_placeholder');
|
|
} else {
|
|
return /** @type {jQueryObject} */ (
|
|
this.parent('getEmptyElement', $element));
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.refreshGridHandler =
|
|
function(sourceElement, event, opt_elementId) {
|
|
|
|
var fetchedAlready = false, elementIds,
|
|
// Hack to avoid closure compiler warnings on type difference
|
|
castElementId = /** @type {{parentElementId: number}} */ (opt_elementId);
|
|
|
|
if (opt_elementId !== undefined) {
|
|
// Check if we want to refresh a row inside a category.
|
|
if (castElementId.parentElementId !== undefined) {
|
|
elementIds = {rowId: opt_elementId[0],
|
|
rowCategoryId: castElementId.parentElementId};
|
|
|
|
// Store the category id.
|
|
this.currentCategoryId_ = castElementId.parentElementId;
|
|
|
|
// Retrieve a single row from the server.
|
|
$.get(this.fetchRowUrl, elementIds,
|
|
this.callbackWrapper(
|
|
this.replaceElementResponseHandler), 'json');
|
|
} else {
|
|
// Retrieve the entire category from the server.
|
|
$.get(this.fetchCategoryUrl_, {rowId: opt_elementId},
|
|
this.callbackWrapper(
|
|
this.replaceElementResponseHandler), 'json');
|
|
}
|
|
fetchedAlready = true;
|
|
}
|
|
|
|
this.parent('refreshGridHandler', sourceElement,
|
|
event, opt_elementId, fetchedAlready);
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.deleteElement =
|
|
function($element) {
|
|
|
|
var $gridBody, index, limit, $parent, $emptyPlaceholder;
|
|
|
|
if ($element.length > 1) {
|
|
// Category and category row have the same element data id,
|
|
// handle this case.
|
|
if ($element.length == 2 &&
|
|
$element.hasClass('category_grid_body') &&
|
|
$element.hasClass('category')) {
|
|
// Always delete the entire category.
|
|
$element = $element.filter('.category_grid_body');
|
|
}
|
|
|
|
// Sometimes grid rows inside different categories may have
|
|
// the same id. Try to find the correct one to delete.
|
|
if (this.currentCategoryId_) {
|
|
$gridBody = this.getCategoryByDataId(this.currentCategoryId_);
|
|
for (index = 0, limit = $element.length; index < limit; index++) {
|
|
$parent = $($element[index]).
|
|
parents('#' + $gridBody.attr('id'));
|
|
if ($parent.length === 1) {
|
|
$element = $($element[index]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($element.hasClass('category_grid_body')) {
|
|
// Need to delete the category empty placeholder.
|
|
$emptyPlaceholder = this.getCategoryEmptyPlaceholder($element);
|
|
this.unbindPartial($emptyPlaceholder);
|
|
$emptyPlaceholder.remove();
|
|
}
|
|
|
|
this.parent('deleteElement', $element);
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.addElement =
|
|
function($element) {
|
|
var $gridBody = null, categoryDataId, $emptyPlaceholder;
|
|
|
|
if ($element.hasClass('gridRow')) {
|
|
// New row must be inside a category.
|
|
categoryDataId = /** @type {string} */ (
|
|
this.getCategoryDataIdByRowId(
|
|
/** @type {string} */ ($element.attr('id'))));
|
|
$gridBody = /** @type {jQueryObject} */ (
|
|
this.getCategoryByDataId(categoryDataId));
|
|
}
|
|
|
|
// Add the element.
|
|
this.parent('addElement', $element, $gridBody);
|
|
|
|
// Make sure the placeholder is the last grid element.
|
|
if ($element.hasClass('category_grid_body')) {
|
|
$emptyPlaceholder = this.getEmptyElement($element);
|
|
this.getHtmlElement().find(this.bodySelector).append($emptyPlaceholder);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.replaceElement =
|
|
function($existingElement, $newElement) {
|
|
|
|
if ($newElement.hasClass('category_grid_body')) {
|
|
// Need to delete the category empty placeholder.
|
|
var $emptyPlaceholder = this.getCategoryEmptyPlaceholder($existingElement);
|
|
this.unbindPartial($emptyPlaceholder);
|
|
$emptyPlaceholder.remove();
|
|
}
|
|
|
|
this.parent('replaceElement', $existingElement, $newElement);
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
$.pkp.controllers.grid.CategoryGridHandler.prototype.hasSameNumOfColumns =
|
|
function($row) {
|
|
var $element = $row,
|
|
checkColSpan = false;
|
|
|
|
if ($row.hasClass('category_grid_body')) {
|
|
$element = $row.find('tr');
|
|
checkColSpan = true;
|
|
}
|
|
|
|
return /** @type {boolean} */ (
|
|
this.parent('hasSameNumOfColumns', $element, checkColSpan));
|
|
};
|
|
|
|
|
|
}(jQuery));
|