first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,411 @@
/**
* @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));
+983
View File
@@ -0,0 +1,983 @@
/**
* @defgroup js_controllers_grid
*/
/**
* @file js/controllers/grid/GridHandler.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 GridHandler
* @ingroup js_controllers_grid
*
* @brief Grid row handler.
*/
(function($) {
// Define the namespace.
$.pkp.controllers.grid = $.pkp.controllers.grid || {};
/**
* @constructor
*
* @extends $.pkp.classes.Handler
*
* @param {jQueryObject} $grid The grid this handler is
* attached to.
* @param {{features}} options Grid handler configuration.
*/
$.pkp.controllers.grid.GridHandler = function($grid, options) {
this.parent($grid, options);
// We give a chance for this handler to initialize
// before we initialize its features.
this.initialize(options);
this.initFeatures_(options.features);
};
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.GridHandler,
$.pkp.classes.Handler);
//
// Constants.
//
/**
* Flag to be used to fetch all curent page grid rows.
* @public
* @type {Object}
*/
$.pkp.controllers.grid.GridHandler.FETCH_ALL_ROWS_ID = {};
//
// Protected properties
//
/**
* The selector for the grid body.
* @protected
* @type {?string}
*/
$.pkp.controllers.grid.GridHandler.prototype.bodySelector = null;
/**
* The URL to fetch a grid row.
* @protected
* @type {?string}
*/
$.pkp.controllers.grid.GridHandler.prototype.fetchRowUrl = null;
/**
* The URL to fetch all loaded grid rows.
* @protected
* @type {?string}
*/
$.pkp.controllers.grid.GridHandler.prototype.fetchRowsUrl = null;
//
// Private properties
//
/**
* The id of the grid.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.GridHandler.prototype.gridId_ = null;
/**
* The URL to fetch the entire grid.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.GridHandler.prototype.fetchGridUrl_ = null;
/**
* This grid features.
* @private
* @type {Object}
*/
$.pkp.controllers.grid.GridHandler.prototype.features_ = null;
/**
* Fetch elements extra request parameters.
* @private
* @type {Object}
*/
$.pkp.controllers.grid.GridHandler.prototype.fetchExtraParams_ = null;
//
// Public methods
//
/**
* Get fetch element extra request parameters.
* @return {Object} Extra request parameters.
*/
$.pkp.controllers.grid.GridHandler.prototype.getFetchExtraParams =
function() {
return this.fetchExtraParams_;
};
/**
* Set fetch element extra request parameters.
* @param {Object} extraParams Extra request parameters.
*/
$.pkp.controllers.grid.GridHandler.prototype.setFetchExtraParams =
function(extraParams) {
this.fetchExtraParams_ = extraParams;
};
/**
* Get the fetch row URL.
* @return {?string} URL to the "fetch row" operation handler.
*/
$.pkp.controllers.grid.GridHandler.prototype.getFetchRowUrl =
function() {
return this.fetchRowUrl;
};
/**
* Get the fetch rows URL.
* @return {?string} URL to the "fetch rows" operation handler.
*/
$.pkp.controllers.grid.GridHandler.prototype.getFetchRowsUrl =
function() {
return this.fetchRowsUrl;
};
/**
* Get all grid rows.
*
* @return {jQueryObject} The rows as a JQuery object.
*/
$.pkp.controllers.grid.GridHandler.prototype.getRows =
function() {
return $('.gridRow', this.getHtmlElement()).not('.gridRowDeleted');
};
/**
* Get the id prefix of this grid.
* @return {string} The ID prefix of this grid.
*/
$.pkp.controllers.grid.GridHandler.prototype.getGridIdPrefix =
function() {
return 'component-' + this.gridId_;
};
/**
* Get the id prefix of this grid row.
* @return {string} The id prefix of this grid row.
*/
$.pkp.controllers.grid.GridHandler.prototype.getRowIdPrefix =
function() {
return this.getGridIdPrefix() + '-row-';
};
/**
* Get the grid row by the passed data element id.
* @param {number} rowDataId
* @param {number=} opt_parentElementId
* @return {jQueryObject}
*/
$.pkp.controllers.grid.GridHandler.prototype.getRowByDataId =
function(rowDataId, opt_parentElementId) {
return $('#' +
this.getRowIdPrefix() +
$.pkp.classes.Helper.escapeJQuerySelector(String(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.GridHandler.prototype.getRowDataId =
function($gridRow) {
var rowDataId;
rowDataId = /** @type {string} */ ($gridRow.attr('id').
slice(this.getRowIdPrefix().length));
return rowDataId;
};
/**
* Get the parent grid row of the passed element, if any.
* @param {jQueryObject} $element The element that is inside the row.
* @return {jQueryObject} The element parent grid row.
*/
$.pkp.controllers.grid.GridHandler.prototype.getParentRow =
function($element) {
return $element.parents('.gridRow:first');
};
/**
* Get the same type elements of the passed element.
* @param {jQueryObject} $element The element to get the type from.
* @return {jQueryObject} The grid elements with the same type
* of the passed element.
*/
$.pkp.controllers.grid.GridHandler.prototype.getElementsByType =
function($element) {
if ($element.hasClass('gridRow')) {
var $container = $element.parents('tbody:first');
return $('.gridRow', $container);
} else {
return null;
}
};
/**
* Get the empty element based on the type of the passed element.
* @param {jQueryObject} $element The element to get the type from.
* @return {jQueryObject} The empty element.
*/
$.pkp.controllers.grid.GridHandler.prototype.getEmptyElement =
function($element) {
if ($element.hasClass('gridRow')) {
// Return the rows empty element placeholder.
var $container = $element.parents('tbody:first');
return $container.next('.empty');
} else {
return null;
}
};
/**
* Show/hide row actions.
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
*/
$.pkp.controllers.grid.GridHandler.prototype.toggleRowActions =
function(sourceElement, event) {
// Don't follow the link
event.preventDefault();
// Toggle the extras link class.
$(sourceElement).toggleClass('show_extras');
$(sourceElement).toggleClass('hide_extras');
// Toggle the row actions.
var $controlRow = $(sourceElement).parents('tr').next('.row_controls');
this.applyToggleRowActionEffect_($controlRow);
};
/**
* Hide all visible row controls.
*/
$.pkp.controllers.grid.GridHandler.prototype.hideAllVisibleRowActions =
function() {
this.getHtmlElement().find('a.hide_extras').click();
};
/**
* Hide row actions div container.
*/
$.pkp.controllers.grid.GridHandler.prototype.hideRowActionsDiv =
function() {
var $rowActionDivs, index, limit, $div;
$rowActionDivs = $('.gridRow div.row_actions', this.getHtmlElement());
$rowActionDivs.hide();
// FIXME: Hack to correctly align the first column cell content after
// hiding the row actions div.
for (index = 0, limit = $rowActionDivs.length; index < limit; index++) {
$div = $($rowActionDivs[index]);
}
};
/**
* Show row actions div container.
*/
$.pkp.controllers.grid.GridHandler.prototype.showRowActionsDiv =
function() {
var $rowActionDivs, index, limit, $div;
$rowActionDivs = $('.gridRow div.row_actions', this.getHtmlElement());
$rowActionDivs.show();
};
/**
* Enable/disable all link actions inside this grid.
* @param {boolean} enable Enable/disable flag.
* @param {jQueryObject} $linkElements Link elements JQuery object.
*/
$.pkp.controllers.grid.GridHandler.prototype.changeLinkActionsState =
function(enable, $linkElements) {
if ($linkElements === undefined) {
$linkElements = $('.pkp_controllers_linkAction', this.getHtmlElement());
}
$linkElements.each(function() {
/** {$.pkp.controllers.LinkActionHandler} */
var linkHandler;
linkHandler = $.pkp.classes.Handler.getHandler($(this));
if (enable) {
linkHandler.enableLink();
} else {
linkHandler.disableLink();
}
});
};
/**
* Re-sequence all grid rows based on the passed sequence map.
* @param {Array} sequenceMap A sequence array with the row id or
* row data id as value.
*/
$.pkp.controllers.grid.GridHandler.prototype.resequenceRows =
function(sequenceMap) {
var id, index, $row;
if (!sequenceMap) {
return;
}
for (index in sequenceMap) {
id = sequenceMap[index];
$row = $('#' + $.pkp.classes.Helper.escapeJQuerySelector(String(id)));
if ($row.length == 0) {
$row = this.getRowByDataId(id);
}
if ($row.length == 0) {
throw new Error('Row with id ' + id + ' not found!');
}
this.addElement($row);
}
this.updateControlRowsPosition();
this.callFeaturesHook('resequenceRows', sequenceMap);
};
/**
* Move all grid control rows to their correct position,
* below of each correspondent data grid row.
*/
$.pkp.controllers.grid.GridHandler.prototype.updateControlRowsPosition =
function() {
var $rows, index, limit, $row, $controlRow;
$rows = this.getRows();
for (index = 0, limit = $rows.length; index < limit; index++) {
$row = $($rows[index]);
$controlRow = this.getControlRowByGridRow($row);
if ($controlRow.length > 0) {
$controlRow.insertAfter($row);
}
}
};
/**
* Inserts or replaces a grid element.
* @param {string|jQueryObject} elementContent The new mark-up of the element.
* @param {boolean=} opt_prepend Prepend the new row instead of append it?
*/
$.pkp.controllers.grid.GridHandler.prototype.insertOrReplaceElement =
function(elementContent, opt_prepend) {
var $newElement, newElementId, $grid, $existingElement;
// Parse the HTML returned from the server.
$newElement = $(elementContent);
newElementId = $newElement.attr('id');
// Does the element exist already?
$grid = this.getHtmlElement();
$existingElement = newElementId ?
$grid.find('#' +
$.pkp.classes.Helper.escapeJQuerySelector(
/** @type {string} */ (newElementId))
) :
null;
if ($existingElement !== null && $existingElement.length > 1) {
throw new Error('There were ' + $existingElement.length +
' rather than 0 or 1 elements to be replaced!');
}
if (!this.hasSameNumOfColumns($newElement)) {
// Redraw the whole grid so new columns
// get added/removed to match element.
$.get(this.fetchGridUrl_, null,
this.callbackWrapper(this.replaceGridResponseHandler_), 'json');
} else {
if ($existingElement !== null && $existingElement.length === 1) {
// Update element.
this.replaceElement($existingElement, $newElement);
} else {
// Insert row.
this.addElement($newElement, null, opt_prepend);
}
// Refresh row action event binding.
this.activateRowActions_();
}
};
/**
* Delete a grid element.
* @param {jQueryObject} $element The element to be deleted.
* @param {boolean=} opt_noFadeOut Whether the item deletion
* will use the fade out effect or not.
*/
$.pkp.controllers.grid.GridHandler.prototype.deleteElement =
function($element, opt_noFadeOut) {
var lastElement, $emptyElement, deleteFunction, self;
// Check whether we really only match one element.
if ($element.length !== 1) {
throw new Error('There were ' + $element.length +
' rather than 1 element to delete!');
}
// Flag this element as deleted, so getRows()
// will return only existing rows from now on.
$element.addClass('gridRowDeleted');
// Check whether this is the last row.
lastElement = false;
if (this.getElementsByType($element).length == 1) {
lastElement = true;
}
// Remove the controls row, if any.
if ($element.hasClass('gridRow')) {
this.deleteControlsRow_($element);
}
$emptyElement = this.getEmptyElement($element);
self = this;
deleteFunction = function() {
self.unbindPartial($element);
$element.remove();
if (lastElement) {
$emptyElement.fadeIn(100);
}
};
if (opt_noFadeOut != undefined && opt_noFadeOut) {
deleteFunction();
} else {
$element.fadeOut(500, deleteFunction);
}
};
//
// Protected methods
//
/**
* Set data and execute operations to initialize.
*
* @protected
*
* @param {Object} options Grid options.
*/
$.pkp.controllers.grid.GridHandler.prototype.initialize =
function(options) {
var $searchLink;
// Bind the handler for the "elements changed" event.
this.bind('dataChanged', this.refreshGridHandler);
// Bind the handler for the "add new row" event.
this.bind('addRow', this.addRowHandler_);
// Handle grid filter events.
this.bind('formSubmitted', this.refreshGridWithFilterHandler_);
// Save the ID of this grid.
this.gridId_ = options.gridId;
// Save the URL to fetch a row.
this.fetchRowUrl = options.fetchRowUrl;
// Save the URL to fetch all rows.
this.fetchRowsUrl = options.fetchRowsUrl;
// Save the URL to fetch the entire grid
this.fetchGridUrl_ = options.fetchGridUrl;
// Save the selector for the grid body.
if ($('div.scrollable', this.getHtmlElement()).length > 0) {
this.bodySelector = 'div.scrollable table';
} else {
this.bodySelector = options.bodySelector;
}
// Show/hide row action feature.
this.activateRowActions_();
this.setFetchExtraParams({});
// Search control.
this.getHtmlElement().find('.pkp_form').hide();
$searchLink = this.getHtmlElement().
find('.pkp_linkaction_search');
if ($searchLink.length !== 0) {
$searchLink.click(
this.callbackWrapper(function() {
this.getHtmlElement().find('.pkp_form').toggle();
$searchLink.toggleClass('is_open');
}));
} else {
// This grid doesn't have an expand/collapse control. If there is
// a form, expand it.
this.getHtmlElement().find('.pkp_form').toggle();
}
this.trigger('gridInitialized');
};
/**
* Call features hooks.
*
* @protected
*
* @param {string} hookName The name of the hook.
* @param {Array|jQueryObject|Object|number|boolean=} opt_args
* The arguments array.
*/
$.pkp.controllers.grid.GridHandler.prototype.callFeaturesHook =
function(hookName, opt_args) {
var featureName;
if (!$.isArray(opt_args)) {
opt_args = [opt_args];
}
for (featureName in this.features_) {
this.features_[featureName][hookName].
apply(this.features_[featureName], opt_args);
}
};
/**
* Refresh either a single row of the grid or the whole grid.
*
* @protected
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @param {number|Object=} opt_elementId The id of a data element that was
* updated, added or deleted. If not given then the whole grid
* will be refreshed.
* @param {Boolean=} opt_fetchedAlready Flag that subclasses can send
* telling that a fetch operation was already handled there.
*/
$.pkp.controllers.grid.GridHandler.prototype.refreshGridHandler =
function(sourceElement, event, opt_elementId, opt_fetchedAlready) {
var params;
this.callFeaturesHook('refreshGrid', opt_elementId);
params = this.getFetchExtraParams();
// Check if subclasses already handled the fetch of new elements.
if (!opt_fetchedAlready) {
if (opt_elementId) {
if (opt_elementId ==
$.pkp.controllers.grid.GridHandler.FETCH_ALL_ROWS_ID) {
$.get(this.fetchRowsUrl, params,
this.callbackWrapper(this.replaceElementResponseHandler), 'json');
} else {
params.rowId = opt_elementId;
// Retrieve a single row from the server.
$.get(this.fetchRowUrl, params,
this.callbackWrapper(this.replaceElementResponseHandler), 'json');
}
} else {
// Retrieve the whole grid from the server.
$.get(this.fetchGridUrl_, params,
this.callbackWrapper(this.replaceGridResponseHandler_), 'json');
}
}
// Let the calling context (page?) know that the grids are being redrawn.
this.trigger('gridRefreshRequested');
this.publishChangeEvents();
};
/**
* Add a new row to the grid.
*
* @protected
*
* @param {jQueryObject} $newRow The new row to append.
* @param {jQueryObject=} opt_$gridBody The tbody container element.
* @param {boolean=} opt_prepend Prepend the element instead of append it?
*/
$.pkp.controllers.grid.GridHandler.prototype.addElement =
function($newRow, opt_$gridBody, opt_prepend) {
if (opt_$gridBody === undefined || opt_$gridBody === null) {
opt_$gridBody = this.getHtmlElement().find(this.bodySelector);
}
// Add the new element.
if (opt_prepend != undefined && opt_prepend) {
opt_$gridBody.prepend($newRow);
} else {
opt_$gridBody.append($newRow);
}
// Hide the empty placeholder.
var $emptyElement = this.getEmptyElement($newRow);
if ($emptyElement) {
$emptyElement.hide();
}
this.callFeaturesHook('addElement', $newRow);
};
/**
* Update an existing element using the passed new element content.
*
* @protected
*
* @param {jQueryObject} $existingElement The element that is already
* in grid.
* @param {jQueryObject} $newElement The element with new content.
*/
$.pkp.controllers.grid.GridHandler.prototype.replaceElement =
function($existingElement, $newElement) {
if ($newElement.hasClass('gridRow')) {
this.deleteControlsRow_($existingElement);
}
this.replacePartialWith($newElement, $existingElement);
this.callFeaturesHook('replaceElement', $newElement);
};
/**
* Does the passed row have a different number of columns than the
* existing grid?
*
* @protected
*
* @param {jQueryObject} $row The row to be checked against grid columns.
* @param {Boolean=} opt_checkColSpan Will get the number of row columns
* by column span.
* @return {boolean} Whether it has the same number of grid columns
* or not.
*/
$.pkp.controllers.grid.GridHandler.prototype.hasSameNumOfColumns =
function($row, opt_checkColSpan) {
var $grid, numColumns, $tdElements, numCellsInNewRow;
$grid = this.getHtmlElement();
numColumns = $grid.find('th').length;
$tdElements = $row.first().find('td');
if (opt_checkColSpan) {
numCellsInNewRow = $tdElements.attr('colspan');
} else {
numCellsInNewRow = $tdElements.length;
}
return (numColumns == numCellsInNewRow);
};
/**
* Callback to insert, remove or replace a row after an
* element has been inserted, update or deleted.
*
* @protected
*
* @param {Object} ajaxContext The AJAX request context.
* @param {Object} jsonData A parsed JSON response object.
* @return {boolean|undefined} Return false when no replace action is taken.
*/
$.pkp.controllers.grid.GridHandler.prototype.replaceElementResponseHandler =
function(ajaxContext, jsonData) {
var elementId, $element, handledJsonData, castJsonData, $responseElement,
$responseRow, $responseControlRow, $responseRows, $responseRowsControls,
index, limit;
handledJsonData = this.handleJson(jsonData);
if (handledJsonData !== false) {
if (handledJsonData.elementNotFound) {
// The server reported that this element no
// longer exists in the database so let's
// delete it.
elementId = handledJsonData.elementNotFound;
$element = this.getRowByDataId(elementId);
// Sometimes we get a delete event before the
// element has actually been inserted (e.g. when deleting
// elements due to a cancel action or similar).
if ($element.length > 0) {
this.deleteElement($element);
}
} else {
// The server returned mark-up to replace
// or insert the row.
$responseElement = $(handledJsonData.content);
if ($responseElement.filter("tr:not('.row_controls')").length > 1) {
$responseRows = $responseElement.filter('tr.gridRow');
$responseRowsControls = $responseElement.filter('tr.row_controls');
for (index = 0, limit = $responseRows.length; index < limit; index++) {
$responseRow = $($responseRows[index]);
$responseControlRow = this.getControlRowByGridRow($responseRow,
$responseRowsControls);
this.insertOrReplaceElement($responseRow.add($responseControlRow));
}
} else {
this.insertOrReplaceElement(handledJsonData.content);
}
castJsonData = /** @type {{sequenceMap: Array}} */ (handledJsonData);
this.resequenceRows(castJsonData.sequenceMap);
}
}
this.callFeaturesHook('replaceElementResponseHandler', handledJsonData);
};
//
// Private methods
//
/**
* Refresh the grid after its filter has changed.
*
* @private
*
* @param {$.pkp.controllers.form.ClientFormHandler} filterForm
* The filter form.
* @param {Event} event A "formSubmitted" event.
* @param {string} filterData Serialized filter data.
*/
$.pkp.controllers.grid.GridHandler.prototype.refreshGridWithFilterHandler_ =
function(filterForm, event, filterData) {
// Retrieve the grid from the server and add the
// filter data as form data.
$.post(this.fetchGridUrl_, filterData,
this.callbackWrapper(this.replaceGridResponseHandler_), 'json');
};
/**
* Add a new row to the grid.
*
* @private
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @param {Object} params The request parameters to use to generate
* the new row.
*/
$.pkp.controllers.grid.GridHandler.prototype.addRowHandler_ =
function(sourceElement, event, params) {
// Retrieve a single new row from the server.
$.get(this.fetchRowUrl, params,
this.callbackWrapper(this.replaceElementResponseHandler), 'json');
};
/**
* Callback to replace a grid's content.
*
* @private
*
* @param {Object} ajaxContext The AJAX request context.
* @param {Object} jsonData A parsed JSON response object.
*/
$.pkp.controllers.grid.GridHandler.prototype.replaceGridResponseHandler_ =
function(ajaxContext, jsonData) {
var handledJsonData, $grid, $gridParent, $newGrid,
isFilterVisible;
handledJsonData = this.handleJson(jsonData);
if (handledJsonData !== false) {
// Get the grid that we're updating
$grid = this.getHtmlElement();
$gridParent = $grid.parent();
isFilterVisible = $grid.find('.filter').is(':visible');
// Replace the grid content
this.replaceWith(handledJsonData.content);
// Update the html element of this handler.
$newGrid = $('div[id^="' + this.getGridIdPrefix() + '"]', $gridParent);
this.setHtmlElement($newGrid);
// Refresh row action event binding.
this.activateRowActions_();
if (isFilterVisible) {
// Open search control again.
$newGrid.find('.pkp_linkaction_search').click();
}
}
};
/**
* Helper that deletes the row of controls (if present).
*
* @private
*
* @param {jQueryObject} $row The row whose matching control row should be
* deleted.
*/
$.pkp.controllers.grid.GridHandler.prototype.deleteControlsRow_ =
function($row) {
var $controlRow = $('#' + $.pkp.classes.Helper.escapeJQuerySelector(
/** @type {string} */ ($row.attr('id'))) + '-control-row',
this.getHtmlElement());
if ($controlRow.is('tr') && $controlRow.hasClass('row_controls')) {
this.unbindPartial($controlRow);
$controlRow.remove();
}
};
/**
* Get the control row for the passed the grid row.
*
* @param {jQueryObject} $gridRow The grid row JQuery object.
* @param {jQueryObject=} opt_$context Optional context to get
* the control row from.
* @return {jQueryObject} The control row JQuery object.
*/
$.pkp.controllers.grid.GridHandler.prototype.getControlRowByGridRow =
function($gridRow, opt_$context) {
var rowId, controlRowId, $context;
if (opt_$context === undefined || opt_$context === null) {
$context = this.getHtmlElement().find('tr');
} else {
$context = opt_$context;
}
rowId = $gridRow.attr('id');
controlRowId = rowId + '-control-row';
return $context.filter('#' +
$.pkp.classes.Helper.escapeJQuerySelector(controlRowId));
};
/**
* Helper that attaches any action handlers related to rows.
*
* @private
*/
$.pkp.controllers.grid.GridHandler.prototype.activateRowActions_ =
function() {
var $grid = this.getHtmlElement(),
$gridRows = this.getHtmlElement().find('tr.gridRow').not('.category');
$grid.find('a.show_extras').unbind('click').bind('click',
this.callbackWrapper(this.toggleRowActions));
};
/**
* Apply the effect for hide/show row actions.
*
* @private
*
* @param {jQueryObject} $controlRow The control row JQuery object.
*/
$.pkp.controllers.grid.GridHandler.prototype.applyToggleRowActionEffect_ =
function($controlRow) {
var $row;
$row = $controlRow.prev().find('td:not(.indent_row)');
$row = $row.add($controlRow.prev());
$controlRow.toggle();
};
/**
* Add a grid feature.
*
* @private
*
* @param {string} id Feature id.
* @param {$.pkp.classes.features.Feature} $feature The grid
* feature to be added.
*/
$.pkp.controllers.grid.GridHandler.prototype.addFeature_ =
function(id, $feature) {
if (!this.features_) {
this.features_ = [];
}
this.features_[id] = $feature;
};
/**
* Add grid features.
*
* @private
*
* @param {Array.<{JSClass, options}>} features The features options array.
*/
$.pkp.controllers.grid.GridHandler.prototype.initFeatures_ =
function(features) {
var id, $feature, jsClass;
for (id in features) {
// Only initiate features that have a js handler.
jsClass = features[id].JSClass;
if (jsClass === null) {
continue;
}
$feature =
/** @type {$.pkp.classes.features.Feature} */
($.pkp.classes.Helper.objectFactory(
jsClass, [this, features[id].options]));
this.addFeature_(id, $feature);
this.features_[id].init();
}
};
}(jQuery));
@@ -0,0 +1,43 @@
/**
* @file js/controllers/grid/files/review/AuthorReviewRevisionsGridHandler.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 AuthorReviewRevisionsGridHandler
* @ingroup js_controllers_grid
*
* @brief Author revisions grid handler.
*/
(function($) {
/**
* Define the namespace
*/
$.pkp.controllers.grid.files = $.pkp.controllers.grid.files ||
{ review: {} };
/**
* @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.files.review.AuthorReviewRevisionsGridHandler = function(
$grid, options) {
this.parent($grid, options);
this.bindGlobal('refreshRevisionsGrid', function() {
this.refreshGridHandler();
});
};
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.files.review.
AuthorReviewRevisionsGridHandler, $.pkp.controllers.grid.GridHandler);
}(jQuery));
@@ -0,0 +1,269 @@
/**
* @file js/controllers/grid/navigationMenus/form/NavigationMenuFormHandler.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 NavigationMenuFormHandler
* @ingroup js_controllers_grid_navigationMenus_form
*
* @brief NavigationMenuItems form handler.
*/
(function($) {
/**
* Define the namespace
*/
$.pkp.controllers.grid.navigationMenus =
$.pkp.controllers.grid.navigationMenus ||
{ form: {} };
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $formElement The form element
* @param {Object} options Modal options.
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler =
function($formElement, options) {
this.okButton_ = options.okButton;
this.warningModalTitle_ = options.warningModalTitle;
this.submenuWarning_ = options.submenuWarning;
this.itemTypeConditionalWarnings_ = options.itemTypeConditionalWarnings;
$formElement.on('click', '.btnConditionalDisplay',
this.callbackWrapper(this.showConditionalDisplayWarning));
$formElement.on('click', '.btnSubmenuWarning',
this.callbackWrapper(this.showSubmenuWarning));
this.parent($formElement, options);
this.initSorting();
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private properties
//
/**
* The label for the ok button on the modals displaying submenuWarning and
* conditionalWarnings.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler
.prototype.okButton_ = null;
/**
* The title of the modals displaying submenuWarning and conditionalWarnings.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler
.prototype.warningModalTitle_ = null;
/**
* The warning message to display about submenus
* @private
* @type {string|undefined}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler
.prototype.submenuWarning_ = undefined;
/**
* Warnings about the conditions of display for each item type.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler
.prototype.itemTypeConditionalWarnings_ = null;
/**
* Initialize the .sortable() lists, limit nesting to one level deep and
* ensure lists are formatted properly the CSS styles
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler.
prototype.initSorting = function() {
var self = this;
// Remove any submenu warning buttons
$('.btnSubmenuWarning', this.getHtmlElement()).remove();
// Limit nesting to one level deep and ensure nested lists are formatted
// properly for appropriate styles
$('#pkpNavAssigned > li').each(
function() {
var $childList = $(this).children('ul'),
$children = $childList.children(),
$grandchildren = $children.find('li');
if (!$childList.length) {
$(this).append('<ul></ul>');
return;
}
if (!$children.length) {
// Ensure it's just an empty ul (with no spaces) so the CSS
// :empty psuedo class can be used
$childList.replaceWith('<ul></ul>');
} else {
// Prevent nesting two levels deep by moving any items
// nested at that level up one level.
if ($grandchildren.length) {
$grandchildren.each(function() {
$(this).appendTo($childList);
});
}
// Add a submenu warning button
if (!$(this).find(
'> .item > .item_buttons .btnSubmenuWarning').length) {
$(this).find('> .item > .item_buttons').prepend(
$('<button></button>')
.addClass('btnSubmenuWarning')
.append(
$('<span></span>')
.addClass('fa fa-exclamation-triangle')
)
.append(
$('<span></span>')
.addClass('-screenReader')
.text(self.submenuWarning_)
)
);
}
}
}
);
// Reset any nesting that's been carried over from the assigned list
$('#pkpNavUnassigned > li').each(
function() {
var $childList = $(this).children('ul');
if ($childList.length) {
$childList.find('li').each(function() {
$(this).appendTo($('#pkpNavUnassigned'));
});
}
$childList.remove();
}
);
// Initialize the sortable controls
$('#pkpNavManagement ul').sortable({
placeholder: 'pkp_nav_item_placeholder',
delay: 250,
connectWith: '#pkpNavManagement ul',
update: this.callbackWrapper(this.updateSorting),
start: function() {
$('#pkpNavAssigned').addClass('pkp_is_sorting');
},
stop: function() {
$('#pkpNavAssigned').removeClass('pkp_is_sorting');
}
});
};
/**
* Re-initialize the .sortable() components and generate the form fields
* whenever the list is re-sorted.
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler.
prototype.updateSorting = function() {
var $navManagement = $('#pkpNavManagement'),
seq = 0,
parent = null,
currentName = '';
// Re-intialize the sortable component after adjusting sort order
this.initSorting();
// Remove existing hidden fields
$('input', $navManagement).remove();
// Generate new hidden form fields
$('#pkpNavAssigned > li').each(function() {
currentName = 'menuTree[' + $(this).data('id') + ']';
$navManagement.append('<input type="hidden" name="' +
currentName + '[seq]" value="' +
seq + '">');
seq++;
var parentId = $(this).data('id');
$(this).find('li').each(function() {
currentName = 'menuTree[' + $(this).data('id') + ']';
$navManagement.append('<input type="hidden" name="' +
currentName + '[seq]" value="' +
seq + '">');
$navManagement.append('<input type="hidden" name="' +
currentName + '[parentId]" value="' +
parentId + '">');
seq++;
});
});
};
/**
* Show the conditional display warning message
* @param {jQueryObject} htmlElement The html element
* @return {boolean}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler.
prototype.showConditionalDisplayWarning = function(htmlElement) {
var itemType = $(htmlElement).closest('li').data('type'),
opts = {
title: this.warningModalTitle_,
okButton: this.okButton_,
cancelButton: false,
dialogText: this.itemTypeConditionalWarnings_[itemType]
};
if (this.itemTypeConditionalWarnings_[itemType] !== null) {
$('<div id="' + $.pkp.classes.Helper.uuid() + '" ' +
'class="pkp_modal pkpModalWrapper" tabindex="-1"></div>')
.pkpHandler('$.pkp.controllers.modal.ConfirmationModalHandler', opts);
}
return false;
};
/**
* Show the submenu link warning message
* @return {boolean}
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuFormHandler.
prototype.showSubmenuWarning = function() {
var opts = {
title: this.warningModalTitle_,
okButton: this.okButton_,
cancelButton: false,
dialogText: this.submenuWarning_
};
$('<div id="' + $.pkp.classes.Helper.uuid() + '" ' +
'class="pkp_modal pkpModalWrapper" tabindex="-1"></div>')
.pkpHandler('$.pkp.controllers.modal.ConfirmationModalHandler', opts);
return false;
};
}(jQuery));
@@ -0,0 +1,125 @@
/**
* @file js/controllers/grid/navigationMenus/form/NavigationMenuItemsFormHandler.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 NavigationMenuItemsFormHandler
* @ingroup js_controllers_grid_navigationMenus_form
*
* @brief NavigationMenuItems form handler.
*/
(function($) {
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $formElement A wrapped HTML element that
* represents the form interface element.
* @param {Object} options javascript form options.
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuItemsFormHandler =
function($formElement, options) {
this.parent($formElement, options);
this.previewUrl_ = options.previewUrl;
this.itemTypeDescriptions_ = options.itemTypeDescriptions;
this.itemTypeConditionalWarnings_ = options.itemTypeConditionalWarnings;
$('#previewButton', $formElement).click(this.callbackWrapper(
this.showPreview_));
$('#menuItemType', $formElement).change(this.callbackWrapper(this.setType));
$('#menuItemType', $formElement).trigger('change');
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuItemsFormHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private properties
//
/**
* The preview url.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.navigationMenus.form.
NavigationMenuItemsFormHandler.prototype.previewUrl_ = null;
/**
* Descriptions for each item type.
* @private
* @type {?Object}
*/
$.pkp.controllers.grid.navigationMenus.form.
NavigationMenuItemsFormHandler.prototype.itemTypeDescriptions_ = null;
/**
* Warnings about the conditions of display for each item type.
* @private
* @type {?Object}
*/
$.pkp.controllers.grid.navigationMenus.form.
NavigationMenuItemsFormHandler.prototype
.itemTypeConditionalWarnings_ = null;
/**
* Callback triggered on clicking the "preview"
* button to open a preview window.
*
* @param {HTMLElement} submitButton The submit button.
* @param {Event} event The event that triggered the
* submit button.
* @return {boolean} true.
* @private
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuItemsFormHandler.
prototype.showPreview_ = function(submitButton, event) {
var $formElement = this.getHtmlElement();
$.post(this.previewUrl_,
$formElement.serialize(),
function(data) {
var win = window.open('about:blank');
win.document.open();
win.document.write(data);
win.document.close();
}
);
return true;
};
/**
* Callback triggered when the type is set
*/
$.pkp.controllers.grid.navigationMenus.form.NavigationMenuItemsFormHandler.
prototype.setType = function() {
var itemType = $('#menuItemType', this.getHtmlElement()).val(),
$descriptionEl = $('#menuItemTypeSection [for="menuItemType"]');
$('.NMI_TYPE_CUSTOM_EDIT', this.getHtmlElement()).hide();
$('#' + itemType).fadeIn();
if (typeof this.itemTypeDescriptions_[itemType] !== 'undefined') {
$descriptionEl.text(this.itemTypeDescriptions_[itemType]);
}
};
}(jQuery));
@@ -0,0 +1,207 @@
/**
* @file js/controllers/grid/notifications/NotificationsGridHandler.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 NotificationsGridHandler
* @ingroup js_controllers_grid
*
* @brief Category grid handler.
*/
(function($) {
// Define the namespace.
$.pkp.controllers.grid.notifications =
$.pkp.controllers.grid.notifications || {};
/**
* @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.notifications.NotificationsGridHandler =
function($grid, options) {
$grid.find('a[id*="markNew"]').click(
this.callbackWrapper(this.markNewHandler_));
$grid.find('a[id*="markRead"]').click(
this.callbackWrapper(this.markReadHandler_));
$grid.find('a[id*="deleteNotification"]').click(
this.callbackWrapper(this.deleteHandler_));
this.parent($grid, options);
};
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.notifications
.NotificationsGridHandler, $.pkp.controllers.grid.GridHandler);
//
// Private properties
//
/**
* The CSRF token for POST requests.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler
.prototype.csrfToken_ = null;
/**
* The "mark notifications as new" URL
* @private
* @type {?string}
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler
.prototype.markNewUrl_ = null;
/**
* The "mark notifications as read" URL
* @private
* @type {?string}
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler
.prototype.markReadUrl_ = null;
/**
* The "delete notifications" URL
* @private
* @type {?string}
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler
.prototype.deleteUrl_ = null;
//
// Extended methods from GridHandler
//
/**
* @inheritDoc
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.
prototype.initialize = function(options) {
// Save the URLs to interact with selected sets of notifications
this.markNewUrl_ = options.markNewUrl;
this.markReadUrl_ = options.markReadUrl;
this.deleteUrl_ = options.deleteUrl;
this.csrfToken_ = options.csrfToken;
this.parent('initialize', options);
};
//
// Private methods.
//
/**
* Get the array of selected notifications
* @private
* @return {Array} List of selected notification IDs.
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.prototype.
getSelectedNotifications_ = function() {
var selectedElements = [];
this.getHtmlElement().find('input:checkbox:checked').each(function() {
selectedElements.push($(this).val());
});
return selectedElements;
};
/**
* Callback that will be activated when the "mark new" icon is clicked
*
* @private
*
* @param {Object} callingContext The calling element or object.
* @param {Event=} opt_event The triggering event (e.g. a click on
* a button.
* @return {boolean} Should return false to stop event processing.
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.prototype.
markNewHandler_ = function(callingContext, opt_event) {
$.post(this.markNewUrl_, {selectedElements: this.getSelectedNotifications_(),
csrfToken: this.csrfToken_},
this.callbackWrapper(this.responseHandler_, null), 'json');
return false;
};
/**
* Callback that will be activated when the "mark read" icon is clicked
*
* @private
*
* @param {Object} callingContext The calling element or object.
* @param {Event=} opt_event The triggering event (e.g. a click on
* a button.
* @return {boolean} Should return false to stop event processing.
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.prototype.
markReadHandler_ = function(callingContext, opt_event) {
$.post(this.markReadUrl_,
{selectedElements: this.getSelectedNotifications_(),
csrfToken: this.csrfToken_},
this.callbackWrapper(this.responseHandler_, null), 'json');
return false;
};
/**
* Callback that will be activated when the "delete" icon is clicked
*
* @private
*
* @param {Object} callingContext The calling element or object.
* @param {Event=} opt_event The triggering event (e.g. a click on
* a button.
* @return {boolean} Should return false to stop event processing.
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.prototype.
deleteHandler_ = function(callingContext, opt_event) {
$.post(this.deleteUrl_, {selectedElements: this.getSelectedNotifications_(),
csrfToken: this.csrfToken_},
this.callbackWrapper(this.responseHandler_, null), 'json');
return false;
};
/**
* Callback after a response returns from the server.
*
* @private
*
* @param {Object} ajaxContext The AJAX request context.
* @param {Object} jsonData A parsed JSON response object.
*/
$.pkp.controllers.grid.notifications.NotificationsGridHandler.prototype.
responseHandler_ = function(ajaxContext, jsonData) {
// Bounce the selected notification IDs back to the server
// so that selections can be maintained
var params = this.getFetchExtraParams();
params.selectedNotificationIds = jsonData.content;
this.setFetchExtraParams(params);
// Pass through the JSON handler to cause the grid to be
// refreshed.
this.handleJson(jsonData);
};
}(jQuery));
@@ -0,0 +1,120 @@
/**
* @defgroup js_controllers_grid_queries
*/
/**
* @file js/controllers/grid/queries/QueryFormHandler.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 ReadQueryHandler
* @ingroup js_controllers_grid_queries
*
* @brief Handler for a query form modal
*
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.queries =
$.pkp.controllers.grid.queries || {};
/**
* @constructor
*
* @extends $.pkp.controllers.form.CancelActionAjaxFormHandler
*
* @param {jQueryObject} $form The query form element
* @param {Object} options non-default Dialog options
* to be passed into the dialog widget.
*
* Options are:
* - all options documented for the CancelActionAjaxFormHandler.
* - templateUrl: The URL to retrieve templates from.
*/
$.pkp.controllers.grid.queries.QueryFormHandler =
function($form, options) {
this.parent($form, options);
// Set the URL to retrieve templates from.
if (options.templateUrl) {
this.templateUrl_ = options.templateUrl;
}
// Attach form elements events.
$form.find('#template').change(
this.callbackWrapper(this.selectTemplateHandler_));
};
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.queries.
QueryFormHandler, $.pkp.controllers.form.CancelActionAjaxFormHandler);
//
// Private properties
//
/**
* The URL to use to retrieve template bodies
* @private
* @type {string?}
*/
$.pkp.controllers.grid.queries.
QueryFormHandler.prototype.templateUrl_ = null;
//
// Private methods
//
/**
* Respond to an "item selected" call by triggering a published event.
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @private
*/
$.pkp.controllers.grid.queries.
QueryFormHandler.prototype.selectTemplateHandler_ =
function(sourceElement, event) {
var $form = this.getHtmlElement(),
template = $form.find('[name="template"]');
$.post(this.templateUrl_, template.serialize(),
this.callbackWrapper(this.updateTemplate), 'json');
};
//
// Private methods
//
/**
* Internal callback to replace the textarea with the contents of the
* template body.
*
* @param {HTMLElement} formElement The wrapped HTML form.
* @param {Object} jsonData The data returned from the server.
* @return {boolean} The response status.
*/
$.pkp.controllers.grid.queries.
QueryFormHandler.prototype.updateTemplate =
function(formElement, jsonData) {
var $form = this.getHtmlElement(),
processedJsonData = this.handleJson(jsonData),
jsonDataContent =
/** @type {{variables: Object, body: string}} */ (jsonData.content),
$textarea = $form.find('textarea[name="comment"]'),
editor =
tinyMCE.EditorManager.get(/** @type {string} */ ($textarea.attr('id')));
if (jsonDataContent.variables) {
$textarea.attr('data-variables', JSON.stringify(jsonDataContent.variables));
}
editor.setContent(jsonDataContent.body);
$form.find('[name="subject"]').val(jsonDataContent.subject);
return processedJsonData.status;
};
}(jQuery));
@@ -0,0 +1,167 @@
/**
* @defgroup js_controllers_grid_queries
*/
/**
* @file js/controllers/grid/queries/ReadQueryHandler.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 ReadQueryHandler
* @ingroup js_controllers_grid_queries
*
* @brief Handler for a "read query" modal
*
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.queries =
$.pkp.controllers.grid.queries || { };
/**
* @constructor
*
* @extends $.pkp.classes.Handler
*
* @param {jQueryObject} $containerElement The HTML element encapsulating
* the carousel container.
* @param {Object} options Handler options.
*/
$.pkp.controllers.grid.queries.ReadQueryHandler =
function($containerElement, options) {
this.fetchNoteFormUrl_ = options.fetchNoteFormUrl;
this.fetchParticipantsListUrl_ = options.fetchParticipantsListUrl;
$containerElement.find('.openNoteForm a').click(
this.callbackWrapper(this.showNoteFormHandler_));
$containerElement.bind('dataChanged',
this.callbackWrapper(this.reloadParticipantsList_));
$containerElement.bind('user-left-discussion', function() {
$containerElement.parent().trigger('modalFinished');
});
this.loadParticipantsList();
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.queries.ReadQueryHandler,
$.pkp.classes.Handler);
//
// Private properties
//
/**
* The URL to be called to fetch a new note form for a query.
* @private
* @type {string?}
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.
prototype.fetchNoteFormUrl_ = null;
/**
* The URL to be called to fetch a list of participants.
* @private
* @type {string?}
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.
prototype.fetchParticipantsListUrl_ = null;
//
// Public methods
//
/**
* Load the participants list.
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.prototype.
loadParticipantsList = function() {
$.get(this.fetchParticipantsListUrl_,
this.callbackWrapper(this.showFetchedParticipantsList_), 'json');
};
//
// Private methods
//
/**
* Event handler that is called when the "new note" button is clicked.
* @param {HTMLElement} element The checkbox input element.
* @private
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.prototype.
showNoteFormHandler_ = function(element) {
$(element).parents('.queryEditButtons').addClass('is_loading');
$.get(this.fetchNoteFormUrl_,
this.callbackWrapper(this.showFetchedNoteForm_), 'json');
};
/**
* Event handler that is called when the new note form is ready.
* @param {Object} ajaxContext The AJAX request context.
* @param {Object} jsonData A parsed JSON response object.
* @private
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.prototype.
showFetchedNoteForm_ = function(ajaxContext, jsonData) {
var processedJsonData = this.handleJson(jsonData),
$noteFormContainer = $('#newNotePlaceholder', this.getHtmlElement()),
$queryEditButtons = $('.queryEditButtons.is_loading',
this.getHtmlElement());
this.unbindPartial($queryEditButtons);
$queryEditButtons.remove();
this.unbindPartial($noteFormContainer);
$noteFormContainer.html(processedJsonData.content);
};
/**
* Event handler that is called when the participants list fetch is complete.
* @param {Object} ajaxContext The AJAX request context.
* @param {Object} jsonData A parsed JSON response object.
* @private
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.prototype.
showFetchedParticipantsList_ = function(ajaxContext, jsonData) {
var processedJsonData = this.handleJson(jsonData),
$participantsListContainer = $('#participantsListPlaceholder',
this.getHtmlElement()),
$leaveQueryButton = $('.leaveQueryForm', this.getHtmlElement());
if (processedJsonData.showLeaveQueryButton) {
$leaveQueryButton.show();
} else {
$leaveQueryButton.hide();
}
this.unbindPartial($participantsListContainer);
$participantsListContainer.children().remove();
$participantsListContainer.append(processedJsonData.content);
};
/**
* Handler to update the participants list on change.
* @param {HTMLElement} sourceElement The element that issued the
* "dataChanged" event.
* @param {Event} event The "dataChanged" event.
* @param {HTMLElement} triggerElement The element that triggered
* the "dataChanged" event.
* @private
*/
$.pkp.controllers.grid.queries.ReadQueryHandler.prototype.
reloadParticipantsList_ = function(sourceElement, event, triggerElement) {
this.loadParticipantsList();
};
}(jQuery));
@@ -0,0 +1,84 @@
/**
* @defgroup js_controllers_grid_representations_form
*/
/**
* @file js/controllers/grid/representations/form/RepresentationFormHandler.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 RepresentationFormHandler
* @ingroup js_controllers_grid_representations_form
*
* @brief Handle the representations forms.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.representations =
$.pkp.controllers.grid.representations ||
{ form: { } };
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $form the wrapped page element.
* @param {Object} options handler options.
*/
$.pkp.controllers.grid.representations.form.RepresentationFormHandler =
function($form, options) {
this.parent($form, options);
this.remoteRepresentation_ = options.remoteRepresentation;
if (this.remoteRepresentation_) {
$('#remotelyHostedContent').prop('checked', true);
$('#remote').show(20);
$('#urlPathSection').hide();
} else {
$('#remotelyHostedContent').prop('checked', false);
$('#remote').hide();
$('#urlPathSection').show(20);
}
$('#remotelyHostedContent').change(this.callbackWrapper(this.toggleRemote_));
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.representations.form.RepresentationFormHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private methods.
//
/**
* Internal callback called on checkbox change to show or hide
* remote URL input field.
* @private
* @param {HTMLElement} element The remotely hosted content checkbox.
* @param {Event} event The event that triggered the checkbox.
* @return {boolean} true.
*/
$.pkp.controllers.grid.representations.form.RepresentationFormHandler.
prototype.toggleRemote_ = function(element, event) {
if ($('#remotelyHostedContent').prop('checked')) {
// show the remote URL input field
$('#remote').show(20);
$('#urlPathSection').hide();
$('input[id^="urlPath"]').val('');
} else {
// hide and clear the remote URL input field
$('#remote').hide(20);
$('input[id^="urlRemote"]').val('');
$('#urlPathSection').show(20);
}
return true;
};
}(jQuery));
@@ -0,0 +1,278 @@
/**
* @defgroup js_controllers_grid_roles_form Role form javascript
*/
/**
* @file js/controllers/grid/settings/roles/form/UserGroupFormHandler.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 UserGroupFormHandler
* @ingroup js_controllers_grid_settings_roles_form
*
* @brief Handle the role create/edit form.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.settings.roles =
$.pkp.controllers.grid.settings.roles || { form: { }};
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {{
* selfRegistrationRoleIds: Array,
* roleForbiddenStagesJSON: Object.<string, *>,
* stagesSelector: string
* }} options form options.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler =
function($form, options) {
var $roleId = $('[id^="roleId"]', $form);
this.parent($form, options);
// Set the role IDs for which the self-registration checkbox
// is relevant.
if (options.selfRegistrationRoleIds) {
this.selfRegistrationRoleIds_ = options.selfRegistrationRoleIds;
}
// Set the role IDs for which the recommendOnly checkbox
// is relevant.
if (options.recommendOnlyRoleIds) {
this.recommendOnlyRoleIds_ = options.recommendOnlyRoleIds;
}
// Set the roles that are not able to change
// submission metadata edit perissions
if (options.notChangeMetadataEditPermissionRoles) {
this.notChangeMetadataEditPermissionRoles_ =
options.notChangeMetadataEditPermissionRoles;
}
this.roleForbiddenStages_ = options.roleForbiddenStagesJSON.content;
this.stagesSelector_ = options.stagesSelector;
// Initialize the "permit self register" checkbox disabled
// state based on the form's current selection
this.updatePermitSelfRegistration(
/** @type {string} */ ($roleId.val()));
// Initialize the "permit metadata edit" checkbox disabled
// state based on the form's current selection
this.updatePermitMetadataEdit(
/** @type {string} */ ($roleId.val()), false);
// ...also initialize the stage options, disabling the ones
// that are forbidden for the current role.
this.updateStageOptions(
/** @type {string} */ ($roleId.val()));
// ...also initialize the recommendOnly option, disabling it
// if it is forbidden for the current role.
this.updateRecommendOnly(
/** @type {string} */ ($roleId.val()));
// ...and make sure both it's updated when changing roles.
$roleId.change(this.callbackWrapper(this.changeRoleId));
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private properties
//
/**
* The list of self-registration role IDs
* @private
* @type {Object?}
*/
$.pkp.controllers.grid.settings.roles.form.
UserGroupFormHandler.prototype.selfRegistrationRoleIds_ = null;
/**
* A list of role forbidden stages.
* @private
* @type {Object}
*/
$.pkp.controllers.grid.settings.roles.form.
UserGroupFormHandler.prototype.roleForbiddenStages_ = null;
/**
* The stage options selector.
* @private
* @type {?string}
*/
$.pkp.controllers.grid.settings.roles.form.
UserGroupFormHandler.prototype.stagesSelector_ = null;
/**
* The list of not allowed to change submission metadata edit permissions roles
* @private
* @type {Object?}
*/
$.pkp.controllers.grid.settings.roles.form.
UserGroupFormHandler.prototype.notChangeMetadataEditPermissionRoles_ = null;
//
// Private methods.
//
/**
* Event handler that is called when the role ID dropdown is changed.
* @param {string} dropdown The dropdown input element.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler.prototype.
changeRoleId = function(dropdown) {
var dropDownValue = /** @type {string} */ ($(dropdown).val());
this.updatePermitSelfRegistration((dropDownValue));
this.updatePermitMetadataEdit(/** @type {string} */ (dropDownValue), true);
// Also update the stages options.
this.updateStageOptions(/** @type {string} */ (dropDownValue));
this.updateRecommendOnly(/** @type {string} */ (dropDownValue));
};
/**
* Update the enabled/disabled state of the permitSelfRegistration
* checkbox.
* @param {number|string} roleId The role ID to select.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler.prototype.
updatePermitSelfRegistration = function(roleId) {
// JQuerify the element
var $checkbox = $('[id^="permitSelfRegistration"]'),
$form = this.getHtmlElement(),
i,
found = false;
for (i = 0; i < this.selfRegistrationRoleIds_.length; i++) {
if (this.selfRegistrationRoleIds_[i] == roleId) {
found = true;
}
}
if (found) {
$checkbox.removeAttr('disabled');
} else {
$checkbox.attr('disabled', 'disabled');
$checkbox.removeAttr('checked');
}
};
/**
* Update the enabled/disabled state of the PermitMetadataEdit
* checkbox.
* @param {number|string} roleId The role ID to select.
* @param {boolean} roleIdChanged True iff the role ID changed.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler.prototype.
updatePermitMetadataEdit = function(roleId, roleIdChanged) {
var i, $checkbox = $('[id^="permitMetadataEdit"]'),
found = false;
for (i = 0; i < this.notChangeMetadataEditPermissionRoles_.length; i++) {
if (this.notChangeMetadataEditPermissionRoles_[i] == roleId) {
found = true;
}
}
// If found then the check box should be disabled and checked
if (found) {
$checkbox.attr('disabled', 'disabled');
$checkbox.attr('checked', 'checked');
$checkbox.prop('checked', 'checked');
} else {
$checkbox.removeAttr('disabled');
if (roleIdChanged) {
$checkbox.removeAttr('checked');
}
}
};
/**
* Update the stage options.
* @param {number|string} roleId The role ID to select.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler.prototype.
updateStageOptions = function(roleId) {
// JQuerify the element
var $htmlElement = this.getHtmlElement(),
$stageContainer = $htmlElement.find('#userGroupStageContainer'),
$stageOptions = $(this.stagesSelector_, $htmlElement).filter('input'),
i,
stageId = null;
$stageOptions.removeAttr('disabled');
if (this.roleForbiddenStages_[roleId] != undefined) {
for (i = 0; i < this.roleForbiddenStages_[roleId].length; i++) {
stageId = this.roleForbiddenStages_[roleId][i];
$stageOptions.filter('input[value="' + stageId + '"]').
attr('disabled', 'disabled');
}
}
if ($htmlElement.find(
'input[id^=\'assignedStages-\']:enabled').length == 0) {
$stageContainer.hide('slow');
$('#showTitle').attr('disabled', 'disabled');
} else {
$stageContainer.show('slow');
$('#showTitle').removeAttr('disabled');
}
};
/**
* Update the enabled/disabled state of the recommendOnly checkbox.
* @param {number|string} roleId The role ID to select.
*/
$.pkp.controllers.grid.settings.roles.form.UserGroupFormHandler.prototype.
updateRecommendOnly = function(roleId) {
// JQuerify the element
var $checkbox = $('[id^=\'recommendOnly\']', this.getHtmlElement()),
i,
found = false;
for (i = 0; i < this.recommendOnlyRoleIds_.length; i++) {
if (this.recommendOnlyRoleIds_[i] == roleId) {
found = true;
}
}
if (found) {
$checkbox.removeAttr('disabled');
} else {
$checkbox.attr('disabled', 'disabled');
$checkbox.removeAttr('checked');
}
};
}(jQuery));
@@ -0,0 +1,97 @@
/**
* @defgroup js_controllers_grid_users_user_form User form javascript
*/
/**
* @file js/controllers/grid/settings/user/form/UserDetailsFormHandler.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 UserDetailsFormHandler
* @ingroup js_controllers_grid_settings_user_form
*
* @brief Handle the user settings form.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.settings =
$.pkp.controllers.grid.settings || { user: { form: { } }};
/**
* @constructor
*
* @extends $.pkp.controllers.form.UserFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {Object} options form options.
*/
$.pkp.controllers.grid.settings.user.form.UserDetailsFormHandler =
function($form, options) {
this.parent($form, options);
// Attach form elements events.
$('[id^="generatePassword"]', $form).click(
this.callbackWrapper(this.setGenerateRandom));
// Check the generate password check box.
if ($('[id^="generatePassword"]', $form).attr('checked')) {
this.setGenerateRandom('[id^="generatePassword"]');
}
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.settings.user.form.UserDetailsFormHandler,
$.pkp.controllers.form.UserFormHandler);
//
// Public methods.
//
/**
* @see AjaxFormHandler::submitForm
* @param {Object} validator The validator plug-in.
* @param {HTMLElement} formElement The wrapped HTML form.
*/
$.pkp.controllers.grid.settings.user.form.UserDetailsFormHandler.prototype.
submitForm = function(validator, formElement) {
var $form = this.getHtmlElement();
$(':password', $form).removeAttr('disabled');
this.parent('submitForm', validator, formElement);
};
/**
* Event handler that is called when generate password checkbox is
* clicked.
* @param {string} checkbox The checkbox input element.
*/
$.pkp.controllers.grid.settings.user.form.UserDetailsFormHandler.prototype.
setGenerateRandom = function(checkbox) {
// JQuerify the element
var $checkbox = $(checkbox),
$form = this.getHtmlElement(),
passwordValue = '',
activeAndCheck = 0;
if ($checkbox.prop('checked')) {
passwordValue = '********';
activeAndCheck = 'disabled';
} else {
passwordValue = '';
activeAndCheck = '';
}
$(':password', $form).
prop('disabled', activeAndCheck).val(passwordValue);
$('[id^="sendNotify"]', $form).attr('disabled', activeAndCheck).
prop('checked', activeAndCheck);
};
}(jQuery));
@@ -0,0 +1,51 @@
/**
* @file js/controllers/grid/users/UserGridHandler.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 UserGridHandler
* @ingroup js_controllers_grid
*
* @brief User grid handler. Used to keep user grids in sync, such as when
* merging users.
*/
(function($) {
// Define the namespace.
$.pkp.controllers.grid.users = $.pkp.controllers.grid.users || {};
/**
* @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.users.UserGridHandler =
function($grid, options) {
this.parent($grid, options);
this.bindGlobal('userMerged', function() {
// Signal to any parent modals that they can close now
this.trigger('modalFinished');
this.refreshGridHandler();
});
// Refresh the grid when a user group has been added/edited
this.bindGlobal('userGroupUpdated', function() {
this.refreshGridHandler();
});
};
$.pkp.classes.Helper.inherits($.pkp.controllers.grid.users.UserGridHandler,
$.pkp.controllers.grid.GridHandler);
}(jQuery));
@@ -0,0 +1,105 @@
/**
* @defgroup js_controllers_grid_users_stageParticipant_form
*/
/**
* @file js/controllers/AdvancedReviewerSearchHandler.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 AdvancedReviewerSearchHandler
* @ingroup js_controllers
*
* @brief Handle the advanced reviewer search tab in the add reviewer modal.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.users.reviewer =
$.pkp.controllers.grid.users.reviewer || {};
/**
* @constructor
*
* @extends $.pkp.classes.Handler
*
* @param {jQueryObject} $container the wrapped page element.
* @param {Object} options handler options.
*/
$.pkp.controllers.grid.users.reviewer.AdvancedReviewerSearchHandler =
function($container, options) {
this.parent($container, options);
$container.find('.button').button();
pkp.eventBus.$on('selected:reviewer', function(reviewer) {
$('#reviewerId').val(reviewer.id);
$('[id^="selectedReviewerName"]').text(reviewer.fullName);
$('#searchGridAndButton').hide();
$('#regularReviewerForm').show();
// Set the email message for reviewers depending
// on previous completed assignments
var $textarea = $('#reviewerFormFooter [name="personalMessage"]'),
$templateInput,
$templateOption,
editor,
templateKey;
if ($textarea.val()) {
return; // The message is already set; shouldn't happen
}
// Only 1 template available
$templateInput = $('#reviewerFormFooter input[name="template"]');
// Multiple available templates
$templateOption = $('#reviewerFormFooter select[name="template"]');
editor = tinyMCE.EditorManager.get($textarea.attr('id'));
templateKey = '';
if (options.lastRoundReviewerIds.includes(reviewer.id)) {
templateKey = 'REVIEW_REQUEST_SUBSEQUENT';
editor.setContent(options.reviewerMessages[templateKey]);
$templateInput.val(templateKey);
$templateOption.find('[value="REVIEW_REQUEST"]').remove();
} else {
templateKey = 'REVIEW_REQUEST';
editor.setContent(options.reviewerMessages[templateKey]);
$templateInput.val(templateKey);
$templateOption.find('[value="REVIEW_REQUEST_SUBSEQUENT"]').remove();
}
// Select the right template option to correspond
// the one, which is set in TinyMCE
$templateOption.find('[value="' + templateKey + '"]')
.prop('selected', true);
});
$('#regularReviewerForm').hide();
this.bind('refreshForm', this.handleRefresh_);
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.reviewer.AdvancedReviewerSearchHandler,
$.pkp.classes.Handler);
//
// Private helper methods.
//
/**
* Handle the form refresh event.
* @private
* @param {HTMLElement} sourceElement The element that issued the event.
* @param {Event} event The triggering event.
* @param {string} content HTML contents to replace element contents.
*/
$.pkp.controllers.grid.users.reviewer.AdvancedReviewerSearchHandler.prototype.
handleRefresh_ = function(sourceElement, event, content) {
if (content) {
this.replaceWith(content);
}
};
}(jQuery));
@@ -0,0 +1,99 @@
/**
* @defgroup js_controllers_grid_users_reviewer
*/
/**
* @file js/controllers/grid/users/reviewer/ReadReviewHandler.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 ReadReviewHandler
* @ingroup js_controllers_grid_users_reviewer
*
* @brief Handle the advanced reviewer search tab in the add reviewer modal.
*/
(function($) {
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $form the wrapped page element.
* @param {Object} options handler options.
*/
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler =
function($form, options) {
this.parent($form, options);
this.reviewCompleted_ = options.reviewCompleted;
// bind a handler to make sure that a review file has been uploaded.
$form.find('[id^=\'submitFormButton-\']').click(this.callbackWrapper(
this.reviewFilesRequired_));
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private methods.
//
/**
* Is the review completed.
* @private
* @type {boolean}
*/
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler.
prototype.reviewCompleted_ = false;
/**
* Internal callback called on form submit to ensure there are
* some review files uploaded.
* @private
* @param {HTMLElement} submitButton The submit button.
* @param {Event} event The event that triggered the
* submit button.
* @return {boolean} true.
*/
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler.
prototype.reviewFilesRequired_ = function(submitButton, event) {
if (!this.reviewCompleted_ && $('#readReviewAttachmentsGridContainer').
find('tbody.empty:visible').length == 1) {
// There's nothing in the files grid; don't submit the form
this.showWarning_();
return false;
} else {
// There's something in the files grid;
this.hideWarning_();
}
return true;
};
/**
* Hide the "no files" warning.
* @private
*/
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler.
prototype.hideWarning_ = function() {
this.getHtmlElement().find('#noFilesWarning').hide(250);
};
/**
* Show the "no files" warning.
* @private
*/
$.pkp.controllers.grid.users.reviewer.ReadReviewHandler.
prototype.showWarning_ = function() {
this.getHtmlElement().find('#noFilesWarning').show(250);
};
}(jQuery));
@@ -0,0 +1,123 @@
/**
* @file js/controllers/grid/users/reviewer/form/AddReviewerFormHandler.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 AddReviewerFormHandler
* @ingroup js_controllers_grid_users_reviewer_form
*
* @brief Handle the Add Reviewer form (and template for message body).
*/
(function($) {
/**
* @constructor
*
* @extends $.pkp.controllers.grid.users.reviewer.form.EditReviewFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {Object} options form options.
*/
$.pkp.controllers.grid.users.reviewer.form.
AddReviewerFormHandler = function($form, options) {
this.parent($form, options);
// Set the URL to retrieve templates from.
if (options.templateUrl) {
this.templateUrl_ = options.templateUrl;
}
// Attach form elements events.
$form.find('#template').change(
this.callbackWrapper(this.selectTemplateHandler_));
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.reviewer.form.
AddReviewerFormHandler,
$.pkp.controllers.grid.users.reviewer.form.
EditReviewFormHandler);
//
// Private properties
//
/**
* The URL to use to retrieve template bodies
* @private
* @type {string?}
*/
$.pkp.controllers.grid.users.reviewer.form.
AddReviewerFormHandler.prototype.templateUrl_ = null;
//
// Protected methods
//
/**
* Show the "no files" warning.
* @protected
*/
$.pkp.controllers.grid.users.reviewer.form.AddReviewerFormHandler.
prototype.showWarning = function() {
// Call the parent showWarning to show the warning
this.parent('showWarning');
// Ask the reviewer form footer handler to expand the file
// list extras-on-demand if it isn't already expanded.
this.getHtmlElement().find('#reviewerFormFooter')
.trigger('expandFileList');
};
//
// Private methods
//
/**
* Respond to an "item selected" call by triggering a published event.
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @private
*/
$.pkp.controllers.grid.users.reviewer.form.
AddReviewerFormHandler.prototype.selectTemplateHandler_ =
function(sourceElement, event) {
var $form = this.getHtmlElement();
$.post(this.templateUrl_, $form.find('#template').serialize(),
this.callbackWrapper(this.updateTemplate), 'json');
};
/**
* Internal callback to replace the textarea with the contents of the
* template body.
*
* @param {HTMLElement} formElement The wrapped HTML form.
* @param {Object} jsonData The data returned from the server.
* @return {boolean} The response status.
*/
$.pkp.controllers.grid.users.reviewer.form.
AddReviewerFormHandler.prototype.updateTemplate =
function(formElement, jsonData) {
var $form = this.getHtmlElement(),
processedJsonData = this.handleJson(jsonData),
$textarea = $form.find('textarea[name="personalMessage"]'),
editor =
tinyMCE.EditorManager.get(/** @type {string} */ ($textarea.attr('id')));
if (processedJsonData !== false) {
if (processedJsonData.content !== '') {
editor.setContent(processedJsonData.content);
}
}
return processedJsonData.status;
};
}(jQuery));
@@ -0,0 +1,109 @@
/**
* @defgroup js_controllers_grid_users_reviewer_form
*/
/**
* @file js/controllers/grid/users/reviewer/form/EditReviewFormHandler.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 EditReviewFormHandler
* @ingroup js_controllers_grid_users_reviewer_form
*
* @brief Handle the limit reviewer files form. Also used as a base class
* for the add reviewer form handler.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.users.reviewer.form =
$.pkp.controllers.grid.users.reviewer.form || {};
/**
* @constructor
*
* @extends $.pkp.controllers.form.UserFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {Object} options form options.
*/
$.pkp.controllers.grid.users.reviewer.form.
EditReviewFormHandler = function($form, options) {
this.parent($form, options);
// When the form changes, check to see if a warning is necessary
// (if all reviewer files are unchecked)
$form.change(this.callbackWrapper(this.handleFormChange));
// When the reviewer files list loads, trigger the above check
this.bind('urlInDivLoaded', this.handleFileListLoad_);
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.reviewer.form.
EditReviewFormHandler,
$.pkp.controllers.form.UserFormHandler);
//
// Protected methods.
//
/**
* Handle a form change event.
* @protected
*/
$.pkp.controllers.grid.users.reviewer.form.EditReviewFormHandler.
prototype.handleFormChange = function() {
if (this.getHtmlElement()
.find('input[name="selectedFiles[]"]:checked').length) {
this.hideWarning();
} else {
this.showWarning();
}
};
/**
* Hide the "no files" warning.
* @protected
*/
$.pkp.controllers.grid.users.reviewer.form.EditReviewFormHandler.
prototype.hideWarning = function() {
this.getHtmlElement().find('#noFilesWarning').hide(250);
};
/**
* Show the "no files" warning.
* @protected
*/
$.pkp.controllers.grid.users.reviewer.form.EditReviewFormHandler.
prototype.showWarning = function() {
this.getHtmlElement().find('#noFilesWarning').show(250);
};
//
// Private methods.
//
/**
* Handle the loading of the reviewer files list.
* @private
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @param {?string} data additional event data.
*/
$.pkp.controllers.grid.users.reviewer.form.EditReviewFormHandler.
prototype.handleFileListLoad_ =
function(sourceElement, event, data) {
// Trigger a form change event to display the "no files
// selected" warning, if necessary.
this.getHtmlElement().change();
};
}(jQuery));
@@ -0,0 +1,51 @@
/**
* @file js/controllers/grid/users/stageParticipant/StageParticipantGridHandler.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 StageParticipantGridHandler
* @ingroup js_controllers_grid
*
* @brief Stage participant grid handler.
*/
/*global pkp */
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.users.stageParticipant =
$.pkp.controllers.grid.users.stageParticipant || {};
/**
* @constructor
*
* @extends $.pkp.controllers.grid.CategoryGridHandler
*
* @param {jQueryObject} $grid The grid this handler is
* attached to.
* @param {Object} options Grid handler configuration.
*/
$.pkp.controllers.grid.users.stageParticipant.StageParticipantGridHandler =
function($grid, options) {
this.parent($grid, options);
// Reload any editorial actions on the page.
this.bind('dataChanged', function() {
this.refreshGridHandler();
$(['#submissionEditorDecisionsDiv',
'#copyeditingEditorDecisionsDiv',
'[id^=reviewDecisionsDiv]'].join(','))
.each(function() {
$.pkp.classes.Handler.getHandler($(this)).reload();
});
});
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.stageParticipant.StageParticipantGridHandler,
$.pkp.controllers.grid.CategoryGridHandler);
}(jQuery));
@@ -0,0 +1,72 @@
/**
* @defgroup js_controllers_grid_users_stageParticipant_form
*/
/**
* @file js/controllers/grid/users/stageParticipant/form/AddParticipantFormHandler.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 AddParticipantFormHandler
* @ingroup js_controllers_grid_users_stageParticipant_form
*
* @brief Handle the search user filter and
* add the value to the hidden userGroupId field.
*/
(function($) {
/**
* @constructor
*
* @extends $.pkp.controllers.form.ClientFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {Object} options form options.
*/
$.pkp.controllers.grid.users.stageParticipant.form.AddParticipantFormHandler =
function($form, options) {
this.parent($form, options);
$('select[name^=\'filterUserGroupId\']', $form).change(
this.callbackWrapper(this.addUserGroupId));
$form.parent().click(function(e) {
var $target = $(e.target), filterUserIdVal;
if ($target.is('input[name="userId"]')) {
filterUserIdVal = $('input[name=\'userId\']:checked').val();
$('input[name=\'userIdSelected\']').val(
filterUserIdVal).trigger('change');
}
});
// initially populate the input field.
this.addUserGroupId();
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.stageParticipant.form.
AddParticipantFormHandler,
$.pkp.controllers.form.ClientFormHandler);
//
// Public methods
//
/**
* Method to add the value to the hidden userGroupId field
*/
$.pkp.controllers.grid.users.stageParticipant.form.AddParticipantFormHandler.
prototype.addUserGroupId = function() {
var $form = this.getHtmlElement(),
$filterUserGroupId = $form.find('select[name^=\'filterUserGroupId\']'),
filterUserGroupIdVal = /** @type {string} */ ($filterUserGroupId.val());
$('input[name=\'userGroupId\']').val(filterUserGroupIdVal).trigger('change');
};
}(jQuery));
@@ -0,0 +1,374 @@
/**
* @defgroup js_controllers_grid_users_stageParticipant_form
*/
/**
* @file js/controllers/grid/users/stageParticipant/form/StageParticipantNotifyHandler.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 StageParticipantNotifyHandler
* @ingroup js_controllers_grid_users_stageParticipant_form
*
* @brief Handle Stage participant notification forms.
*/
(function($) {
/** @type {Object} */
$.pkp.controllers.grid.users.stageParticipant.form =
$.pkp.controllers.grid.users.stageParticipant.form || {};
/**
* @constructor
*
* @extends $.pkp.controllers.form.AjaxFormHandler
*
* @param {jQueryObject} $form the wrapped HTML form element.
* @param {Object} options form options.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler = function($form, options) {
this.parent($form, options);
// Set the URL to retrieve templates from.
if (options.templateUrl) {
this.templateUrl_ = options.templateUrl;
}
// Set the user group IDs with the recommendOnly possibility
if (options.possibleRecommendOnlyUserGroupIds) {
this.possibleRecommendOnlyUserGroupIds_ =
options.possibleRecommendOnlyUserGroupIds;
}
// Set the user group IDs with the recommendOnly option set
if (options.recommendOnlyUserGroupIds) {
this.recommendOnlyUserGroupIds_ = options.recommendOnlyUserGroupIds;
}
// Set the user group IDs that are not allowed to change the default
// value of permitMetadataEdit
if (options.notChangeMetadataEditPermissionRoles) {
this.notChangeMetadataEditPermissionRoles_ =
options.notChangeMetadataEditPermissionRoles;
}
// Set the user group IDs that have the permitMetadataEdit flag set to true
if (options.permitMetadataEditUserGroupIds) {
this.permitMetadataEditUserGroupIds_ =
options.permitMetadataEditUserGroupIds;
}
if (options.anonymousReviewerIds) {
this.anonymousReviewerIds_ = options.anonymousReviewerIds;
}
if (options.anonymousReviewerWarning) {
this.anonymousReviewerWarning_ = options.anonymousReviewerWarning;
}
if (options.anonymousReviewerWarningOk) {
this.anonymousReviewerWarningOk_ = options.anonymousReviewerWarningOk;
}
// Update the recommendOnly option display when user group changes
// or user is selected
$('input[name=\'userGroupId\'], input[name=\'userIdSelected\']', $form)
.change(this.callbackWrapper(this.updateRecommendOnly));
// Update the recommendOnly option display when user group changes
// or user is selected
$('input[name=\'userGroupId\'], input[name=\'userIdSelected\']', $form)
.change(this.callbackWrapper(
this.updateSubmissionMetadataEditPermitOption));
// Trigger a warning message if an anonymous reviewer is selected
$('input[name=\'userIdSelected\']', $form)
.change(this.callbackWrapper(this.maybeTriggerReviewerWarning));
// Attach form elements events.
$form.find('#template').change(
this.callbackWrapper(this.selectTemplateHandler_));
};
$.pkp.classes.Helper.inherits(
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler,
$.pkp.controllers.form.AjaxFormHandler);
//
// Private properties
//
/**
* The URL to use to retrieve template bodies
* @private
* @type {string?}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.templateUrl_ = null;
/**
* A list of user IDs which are already assigned anonymous reviews for this
* submission.
* @private
* @type {Array}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.anonymousReviewerIds_ = null;
/**
* A warning message to display when an anonymous reviewer is selected to be
* added as a recipient
* @private
* @type {string?}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.anonymousReviewerWarning_ = null;
/**
* The OK button language for the anonymous reviewer warning message
* @private
* @type {string?}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.
anonymousReviewerWarningOk_ = null;
/**
* The list of not allowed to change submission metadata edit permissions roles
* @private
* @type {Object?}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.
notChangeMetadataEditPermissionRoles_ = null;
/**
* The list of group ids that are allowed to edit metadata
* @private
* @type {Object?}
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.
permitMetadataEditUserGroupIds_ = null;
//
// Private methods
//
/**
* Respond to an "item selected" call by triggering a published event.
*
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
* @private
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.selectTemplateHandler_ =
function(sourceElement, event) {
var $form = this.getHtmlElement();
$.post(this.templateUrl_, $form.find('#template').serialize(),
this.callbackWrapper(this.updateTemplate), 'json');
};
/**
* Internal callback to replace the textarea with the contents of the
* template body.
*
* @param {HTMLElement} formElement The wrapped HTML form.
* @param {Object} jsonData The data returned from the server.
* @return {boolean} The response status.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.updateTemplate =
function(formElement, jsonData) {
var $form = this.getHtmlElement(),
processedJsonData = this.handleJson(jsonData),
jsonDataContent =
/** @type {{variables: Object, body: string}} */ (jsonData.content),
$textarea = $form.find('textarea[name="message"]'),
editor =
tinyMCE.EditorManager.get(/** @type {string} */ ($textarea.attr('id')));
if (jsonDataContent.variables) {
$textarea.attr('data-variables', JSON.stringify(jsonDataContent.variables));
}
editor.setContent(jsonDataContent.body);
return processedJsonData.status;
};
/**
* Update the enabled/disabled and checked state of the recommendOnly checkbox.
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.updateRecommendOnly =
function(sourceElement, event) {
var $form = this.getHtmlElement(),
$filterUserGroupId = $form.find('input[name=\'userGroupId\']'),
$checkbox = $form.find('input[id^=\'recommendOnly\']'),
$checkboxDiv = $form.find('.recommendOnlyWrapper'),
i,
found = false,
filterUserGroupIdVal = /** @type {string} */ ($filterUserGroupId.val());
// If user group changes, hide the recommendOnly option
if ($(sourceElement).prop('name') == 'userGroupId') {
$checkbox.attr('disabled', 'disabled');
$checkbox.removeAttr('checked');
$checkboxDiv.hide();
} else if ($(sourceElement).prop('name') == 'userIdSelected' &&
!$checkboxDiv.is(':visible')) {
// Display recommendOnly option if
// an user group with a possible recommendOnly option is selected
for (i = 0; i < this.possibleRecommendOnlyUserGroupIds_.length; i++) {
if (this.possibleRecommendOnlyUserGroupIds_[i] == filterUserGroupIdVal) {
$checkbox.removeAttr('disabled');
$checkboxDiv.show();
// Select the recommendOnly option if
// an user group with a recommendOnly option set is selected
for (i = 0; i < this.recommendOnlyUserGroupIds_.length; i++) {
if (this.recommendOnlyUserGroupIds_[i] == filterUserGroupIdVal) {
$checkbox.prop('checked', true);
break;
}
}
break;
} else {
$checkbox.attr('disabled', 'disabled');
$checkboxDiv.hide();
}
}
}
};
/**
* Update the enabled/disabled and checked state of the recommendOnly checkbox.
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.maybeTriggerReviewerWarning =
function(sourceElement, event) {
var userId = $(sourceElement).val(),
opts;
if (!userId || this.anonymousReviewerIds_.indexOf(userId) < 0) {
return;
}
opts = {
title: '',
okButton: this.anonymousReviewerWarningOk_,
cancelButton: false,
dialogText: this.anonymousReviewerWarning_
};
$('<div id="' + $.pkp.classes.Helper.uuid() + '" ' +
'class="pkp_modal pkpModalWrapper" tabindex="-1"></div>')
.pkpHandler('$.pkp.controllers.modal.ConfirmationModalHandler', opts);
};
/**
* Update the enabled/disabled and checked state of the recommendOnly checkbox.
* @param {HTMLElement} sourceElement The element that
* issued the event.
* @param {Event} event The triggering event.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.
updateSubmissionMetadataEditPermitOption =
function(sourceElement, event) {
var $form = this.getHtmlElement(),
$filterUserGroupId = $form.find('input[name=\'userGroupId\']'),
$checkbox = $form.find('input[id^=\'canChangeMetadata\']'),
$checkboxDiv = $form.find('.submissionEditMetadataPermit'),
i,
found = false,
filterUserGroupIdVal = /** @type {string} */ ($filterUserGroupId.val());
// If user group changes, hide the canChangeMetadata option
if ($(sourceElement).prop('name') == 'userGroupId') {
$checkbox.attr('disabled', 'disabled');
$checkbox.removeAttr('checked');
$checkboxDiv.hide();
} else if ($(sourceElement).prop('name') == 'userIdSelected' &&
!$checkboxDiv.is(':visible')) {
// Display canChangeMetadata option if
// an user group with a possible canChangeMetadata option is selected
for (i = 0; i < this.notChangeMetadataEditPermissionRoles_.length; i++) {
if (this.notChangeMetadataEditPermissionRoles_[i] ==
filterUserGroupIdVal) {
found = true;
break;
}
}
if (!found) {
$checkbox.removeAttr('disabled');
$checkboxDiv.show();
// Select the recommendOnly option if
// an user group with a recommendOnly option set is selected
for (i = 0; i < this.permitMetadataEditUserGroupIds_.length; i++) {
if (this.permitMetadataEditUserGroupIds_[i] == filterUserGroupIdVal) {
$checkbox.prop('checked', true);
break;
}
}
} else {
$checkbox.attr('disabled', 'disabled');
$checkboxDiv.hide();
}
}
};
/**
* Internal callback called after form validation to handle the
* response to a form submission.
*
* You can override this handler if you want to do custom handling
* of a form response.
*
* @param {HTMLElement} formElement The wrapped HTML form.
* @param {Object} jsonData The data returned from the server.
* @return {boolean} The response status.
*/
$.pkp.controllers.grid.users.stageParticipant.form.
StageParticipantNotifyHandler.prototype.handleResponse =
function(formElement, jsonData) {
// Reload the query grid to show the newly created query.
var $queries = $('#queriesGrid .pkp_controllers_grid');
if ($.pkp.classes.Handler.hasHandler($queries)) {
$.pkp.classes.Handler.getHandler($queries).trigger('dataChanged');
}
return /** @type {boolean} */ (this.parent(
'handleResponse', formElement, jsonData));
};
}(jQuery));