first commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file js/controllers/modal/AjaxModalHandler.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 AjaxModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A modal that retrieves content from a remote AJAX endpoint.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {Object} options non-default Dialog options
|
||||
* to be passed into the dialog widget.
|
||||
*
|
||||
* Options are:
|
||||
* - url string the remote AJAX endpoint that will be used
|
||||
* to retrieve the content of the modal.
|
||||
* - all options documented for the jQueryUI dialog widget,
|
||||
* except for the buttons parameter which is not supported.
|
||||
*/
|
||||
$.pkp.controllers.modal.AjaxModalHandler = function($handledElement, options) {
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// We assume that AJAX modals usually contain forms and
|
||||
// therefore bind to form events by default.
|
||||
this.bind('formSubmitted', this.formSubmitted);
|
||||
this.bind('formCanceled', this.modalClose);
|
||||
this.bind('ajaxHtmlError', this.modalClose);
|
||||
this.bind('modalFinished', this.modalClose);
|
||||
};
|
||||
$.pkp.classes.Helper.inherits($.pkp.controllers.modal.AjaxModalHandler,
|
||||
$.pkp.controllers.modal.ModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/** @inheritDoc */
|
||||
$.pkp.controllers.modal.AjaxModalHandler.prototype.checkOptions =
|
||||
function(options) {
|
||||
// Check the mandatory options of the ModalHandler handler.
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for our own mandatory options.
|
||||
return typeof options.url === 'string';
|
||||
};
|
||||
|
||||
|
||||
/** @inheritDoc */
|
||||
$.pkp.controllers.modal.AjaxModalHandler.prototype.mergeOptions =
|
||||
function(options) {
|
||||
|
||||
// Call parent.
|
||||
return /** @type {Object} */ (this.parent('mergeOptions', options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Open the modal and fetch content via ajax
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @protected
|
||||
*/
|
||||
$.pkp.controllers.modal.AjaxModalHandler.prototype.modalOpen =
|
||||
function($handledElement) {
|
||||
this.parent('modalOpen', $handledElement);
|
||||
|
||||
// Retrieve remote modal content.
|
||||
$handledElement.find('.content')
|
||||
.pkpAjaxHtml(/** @type {{ url: string }} */ (this.options).url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Close the modal when a form submission is complete
|
||||
* @param {Object} callingContext The calling element or object.
|
||||
* @param {Event} event The triggering event (e.g. a click on
|
||||
* a button.
|
||||
* @protected
|
||||
*/
|
||||
$.pkp.controllers.modal.AjaxModalHandler.prototype.formSubmitted =
|
||||
function(callingContext, event) {
|
||||
|
||||
this.getHtmlElement().parent().trigger('notifyUser');
|
||||
this.modalClose();
|
||||
};
|
||||
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file js/controllers/modal/ButtonConfirmationModalHandler.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 ButtonConfirmationModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A confirmation modal that displays a confirmation message before
|
||||
* actually triggering a click event on the calling element (usually a
|
||||
* button).
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ConfirmationModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The modal.
|
||||
* @param {Object} options Non-default options to configure
|
||||
* the modal.
|
||||
*
|
||||
* Options are:
|
||||
* - button jQuery The button to be clicked on success.
|
||||
* - All options from the ConfirmationModalHandler and ModalHandler
|
||||
* widgets.
|
||||
* - All options documented for the jQueryUI dialog widget,
|
||||
* except for the buttons parameter which is not supported.
|
||||
*/
|
||||
$.pkp.controllers.modal.ButtonConfirmationModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
};
|
||||
$.pkp.classes.Helper.inherits(
|
||||
$.pkp.controllers.modal.ButtonConfirmationModalHandler,
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
$.pkp.controllers.modal.ButtonConfirmationModalHandler.prototype.checkOptions =
|
||||
function(options) {
|
||||
// Check inherited options
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return typeof options.$button == 'object' && options.$button.length == 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback that will be activated when the modal is confirmed
|
||||
*
|
||||
* @param {HTMLElement} dialogElement The element the
|
||||
* dialog was created on.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
$.pkp.controllers.modal.ButtonConfirmationModalHandler.prototype.modalConfirm =
|
||||
function(dialogElement, event) {
|
||||
|
||||
var $button = (/** @type {{ $button: jQueryObject }} */ (this.options))
|
||||
.$button;
|
||||
|
||||
// Close the modal first so that the linkaction is no longer disabled
|
||||
this.modalClose(dialogElement);
|
||||
|
||||
// Trigger the link/button action
|
||||
if ($button.attr('type') == 'submit') {
|
||||
$button.trigger('submit');
|
||||
} else {
|
||||
$button.click();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @file js/controllers/modal/ConfirmationModalHandler.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 ConfirmationModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A modal that displays a static explanatory text and has cancel and
|
||||
* confirmation buttons.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {{
|
||||
* callback: Function,
|
||||
* callbackArgs: Object
|
||||
* }} options Non-default options to configure the modal.
|
||||
*
|
||||
* Options are:
|
||||
* - okButton string the name for the confirmation button.
|
||||
* - cancelButton string the name for the cancel button
|
||||
* (or false for no button).
|
||||
* - dialogText string the text to be displayed in the modal.
|
||||
* - All options from the ModalHandler widget.
|
||||
* - callback function A callback function to close when confirmed
|
||||
* - callbackArgs object Arguments to pass to the callback function
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
this.callback_ = options.callback || null;
|
||||
this.callbackArgs_ = options.callbackArgs || null;
|
||||
|
||||
// Bind to the confirmation button
|
||||
$handledElement.find('.pkpModalConfirmButton')
|
||||
.on('click', this.callbackWrapper(this.modalConfirm));
|
||||
};
|
||||
$.pkp.classes.Helper.inherits($.pkp.controllers.modal.ConfirmationModalHandler,
|
||||
$.pkp.controllers.modal.ModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Private properties
|
||||
//
|
||||
/**
|
||||
* A callback to fire when confirmed
|
||||
* @private
|
||||
* @type {?Function}
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler.prototype.
|
||||
callback_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Arguments to pass to the callback function
|
||||
* @private
|
||||
* @type {?Object}
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler.prototype.
|
||||
callbackArgs_ = null;
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler.prototype.checkOptions =
|
||||
function(options) {
|
||||
// Check the mandatory options of the ModalHandler handler.
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hack to prevent closure compiler type mismatches
|
||||
var castOptions = /** @type {{okButton: string,
|
||||
cancelButton: string, dialogText: string}} */ (options);
|
||||
|
||||
// Check for our own mandatory options.
|
||||
return typeof castOptions.okButton === 'string' &&
|
||||
(/** @type {boolean} */ (castOptions.cancelButton) === false ||
|
||||
typeof castOptions.cancelButton === 'string') &&
|
||||
typeof castOptions.dialogText === 'string';
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
/**
|
||||
* Add content to modal
|
||||
*
|
||||
* @return {jQueryObject} jQuery object representing modal content
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler.prototype.modalBuild =
|
||||
function() {
|
||||
|
||||
var $modal = this.parent('modalBuild'),
|
||||
buttons = '<button class="ok pkpModalConfirmButton">' +
|
||||
(/** @type {{ okButton: string }} */ (this.options)).okButton +
|
||||
'</button>';
|
||||
|
||||
$modal.addClass('pkp_modal_confirmation').find('.content')
|
||||
.append('<div class="message">' +
|
||||
(/** @type {{ dialogText: string }} */ (this.options)).dialogText +
|
||||
'</div>');
|
||||
|
||||
if (this.options.cancelButton) {
|
||||
buttons += '<button class="cancel pkpModalCloseButton">' +
|
||||
this.options.cancelButton + '</button>';
|
||||
}
|
||||
|
||||
$modal.append('<div class="footer">' + buttons + '</div>');
|
||||
|
||||
// Add aria role and label
|
||||
$modal.attr('role', 'dialog')
|
||||
.attr('aria-label', this.options.title);
|
||||
|
||||
return /** @type {jQueryObject} */ ($modal);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback that will be activated when the modal's
|
||||
* confirm button is clicked.
|
||||
*
|
||||
* @param {HTMLElement} dialogElement The element the
|
||||
* dialog was created on.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler.prototype.modalConfirm =
|
||||
function(dialogElement, event) {
|
||||
|
||||
// The default implementation will simply close the modal.
|
||||
this.modalClose(dialogElement);
|
||||
|
||||
if (this.callback_) {
|
||||
this.callback_.call(null, this.callbackArgs_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @file js/controllers/modal/JsEventConfirmationModalHandler.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 JsEventConfirmationModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A confirmation modal that generates a JS event.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ConfirmationModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {Object} options Non-default options to configure
|
||||
* the modal.
|
||||
*
|
||||
* Options are:
|
||||
* - remoteUrl string A URL to be redirected to when the confirmation
|
||||
* button has been clicked.
|
||||
* - All options from the ConfirmationModalHandler and ModalHandler
|
||||
* widgets.
|
||||
* - All options documented for the jQueryUI dialog widget,
|
||||
* except for the buttons parameter which is not supported.
|
||||
*/
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// Configure the event to be generated when
|
||||
// the modal closes.
|
||||
this.jsEvent_ = options.jsEvent;
|
||||
|
||||
this.extraArguments_ = options.extraArguments;
|
||||
};
|
||||
$.pkp.classes.Helper.inherits(
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler,
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Private properties
|
||||
//
|
||||
/**
|
||||
* An event to be generated when the confirmation button
|
||||
* has been clicked.
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler.prototype.
|
||||
jsEvent_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* An array of extra information to be passed along with the event.
|
||||
* @private
|
||||
* @type {?Array}
|
||||
*/
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler.prototype.
|
||||
extraArguments_ = null;
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/** @inheritDoc */
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler.prototype.
|
||||
checkOptions = function(options) {
|
||||
|
||||
// Check the mandatory options of the ModalHandler handler.
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for our own mandatory options.
|
||||
// The cancel button and event are mandatory.
|
||||
return typeof options.cancelButton === 'string' &&
|
||||
typeof options.jsEvent === 'string';
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
/**
|
||||
* Callback that will be activated when the modal's
|
||||
* confirm button is clicked.
|
||||
*
|
||||
* @param {HTMLElement} dialogElement The element the
|
||||
* dialog was created on.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
$.pkp.controllers.modal.JsEventConfirmationModalHandler.prototype.
|
||||
modalConfirm = function(dialogElement, event) {
|
||||
|
||||
this.trigger(/** @type {string} */ (this.jsEvent_),
|
||||
/** @type {Array} */ (this.extraArguments_));
|
||||
this.modalClose(dialogElement);
|
||||
};
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,360 @@
|
||||
/*global pkp */
|
||||
/**
|
||||
* @defgroup js_controllers_modal
|
||||
*/
|
||||
/**
|
||||
* @file js/controllers/modal/ModalHandler.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 ModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief Basic modal implementation.
|
||||
*
|
||||
* A modal that has only one button and expects a simple message string.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
/** @type {Object} */
|
||||
$.pkp.controllers.modal = $.pkp.controllers.modal || { };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.classes.Handler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The modal.
|
||||
* @param {Object.<string, *>} options The modal options.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler = function($handledElement, options) {
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// Check the options.
|
||||
if (!this.checkOptions(options)) {
|
||||
throw new Error('Missing or invalid modal options!');
|
||||
}
|
||||
|
||||
// Clone the options object before we manipulate them.
|
||||
var internalOptions = $.extend(true, {}, options),
|
||||
canClose;
|
||||
|
||||
// Merge user and default options.
|
||||
this.options = /** @type {{ canClose: boolean, textTitle: string,
|
||||
title: string, titleIcon: string,
|
||||
closeCleanVueInstances: Array }} */
|
||||
(this.mergeOptions(internalOptions));
|
||||
|
||||
// Attach content to the modal
|
||||
$handledElement.html(this.modalBuild()[0].outerHTML);
|
||||
|
||||
// Open the modal
|
||||
this.modalOpen($handledElement);
|
||||
|
||||
// Set up close controls
|
||||
$handledElement.find(
|
||||
'.pkpModalCloseButton').click(this.callbackWrapper(this.modalClose));
|
||||
$handledElement.on(
|
||||
'click keyup', this.callbackWrapper(this.handleWrapperEvents));
|
||||
|
||||
// Publish some otherwise private events triggered
|
||||
// by nested widgets so that they can be handled by
|
||||
// the element that opened the modal.
|
||||
this.publishEvent('redirectRequested');
|
||||
this.publishEvent('dataChanged');
|
||||
this.publishEvent('updateHeader');
|
||||
this.publishEvent('gridRefreshRequested');
|
||||
|
||||
this.bind('notifyUser', this.redirectNotifyUserEventHandler_);
|
||||
this.bindGlobal('form-success', this.onFormSuccess_);
|
||||
};
|
||||
$.pkp.classes.Helper.inherits($.pkp.controllers.modal.ModalHandler,
|
||||
$.pkp.classes.Handler);
|
||||
|
||||
|
||||
//
|
||||
// Private static properties
|
||||
//
|
||||
/**
|
||||
* Default options
|
||||
* @private
|
||||
* @type {Object}
|
||||
* @const
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.DEFAULT_OPTIONS_ = {
|
||||
autoOpen: true,
|
||||
width: 710,
|
||||
modal: true,
|
||||
draggable: false,
|
||||
resizable: false,
|
||||
position: {my: 'center', at: 'center center-10%', of: window},
|
||||
canClose: true,
|
||||
closeCallback: false,
|
||||
// Vue components to destroy when when modal is closed
|
||||
closeCleanVueInstances: []
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public properties
|
||||
//
|
||||
/**
|
||||
* Current options
|
||||
*
|
||||
* After passed options are merged with defaults.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.options = null;
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* Check whether the correct options have been
|
||||
* given for this modal.
|
||||
* @protected
|
||||
* @param {Object.<string, *>} options Modal options.
|
||||
* @return {boolean} True if options are ok.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.checkOptions =
|
||||
function(options) {
|
||||
|
||||
// Check for basic configuration requirements.
|
||||
return typeof options === 'object' &&
|
||||
(/** @type {{ buttons: Object }} */ (options)).buttons === undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine the options based on
|
||||
* default options.
|
||||
* @protected
|
||||
* @param {Object.<string, *>} options Non-default modal options.
|
||||
* @return {Object.<string, *>} The default options merged
|
||||
* with the non-default options.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.mergeOptions =
|
||||
function(options) {
|
||||
|
||||
// Merge the user options into the default options.
|
||||
var mergedOptions = $.extend(true, { },
|
||||
this.self('DEFAULT_OPTIONS_'), options);
|
||||
return mergedOptions;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
/**
|
||||
* Build the markup for a modal container, including the header, close
|
||||
* button and a container for the content to be placed in.
|
||||
* TODO: This kind of markup probably shouldn't be embedded within the JS...
|
||||
*
|
||||
* @protected
|
||||
* @return {Object} jQuery object representing modal content
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.modalBuild =
|
||||
function() {
|
||||
|
||||
var $titleDiv, $modal = $('<div class="pkp_modal_panel"></div>');
|
||||
|
||||
// Title bar
|
||||
if (typeof(this.options.textTitle) !== 'undefined') {
|
||||
$titleDiv = $('<div class="header"/>').text(this.options.textTitle);
|
||||
$modal.append($titleDiv);
|
||||
} else if (typeof(this.options.title) !== 'undefined') {
|
||||
$modal.append('<div class="header">' + this.options.title + '</div>');
|
||||
} else {
|
||||
$modal.append('<div class="header">' + '</div>');
|
||||
}
|
||||
|
||||
// Close button
|
||||
if (this.options.canClose) {
|
||||
$modal.append(
|
||||
'<a href="#" class="close pkpModalCloseButton">' +
|
||||
'<span :aria-hidden="true">×</span>' +
|
||||
'<span class="pkp_screen_reader">' +
|
||||
(/** @type {{ closeButtonText: string }} */ (this.options))
|
||||
.closeButtonText + '</span></a>');
|
||||
}
|
||||
|
||||
// Content
|
||||
$modal.append('<div class="content"></div>');
|
||||
|
||||
// Add aria role and label
|
||||
$modal.attr('role', 'dialog')
|
||||
.attr('aria-label', this.options.title);
|
||||
|
||||
return $modal;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attach a modal to the dom and make it visible
|
||||
* @param {jQueryObject} $handledElement The modal.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.modalOpen =
|
||||
function($handledElement) {
|
||||
|
||||
// The $handledElement must be attached to the DOM before events will
|
||||
// bubble up to SiteHandler
|
||||
var $body = $('body');
|
||||
$body.append($handledElement);
|
||||
|
||||
// Trigger visibility state change on the next tick, so that CSS
|
||||
// transform animations will run
|
||||
setTimeout(function() {
|
||||
$handledElement.addClass('is_visible');
|
||||
},10);
|
||||
|
||||
// Set focus to the modal. Leave a sizeable delay here so that the
|
||||
// element can be added to the dom first
|
||||
setTimeout(function() {
|
||||
$handledElement.focus();
|
||||
}, 300);
|
||||
|
||||
// Trigger events
|
||||
$handledElement.trigger('pkpModalOpen', [$handledElement]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Close the modal. Typically invoked via an event of some kind, such as
|
||||
* a `click` or `keyup`
|
||||
*
|
||||
* @param {Object=} opt_callingContext The calling element or object.
|
||||
* @param {Event=} opt_event The triggering event (e.g. a click on
|
||||
* a close button. Not set if called via callback.
|
||||
* @return {boolean} Should return false to stop event processing.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.modalClose =
|
||||
function(opt_callingContext, opt_event) {
|
||||
|
||||
var modalHandler = this,
|
||||
$modalElement = this.getHtmlElement(),
|
||||
$form = $modalElement.find('form').first(),
|
||||
handler, informationObject;
|
||||
|
||||
// Unregister a form if attached to this modalElement
|
||||
// modalClose is called on both 'cancel' and 'close' events. With
|
||||
// callbacks both callingContext and event are undefined. So,
|
||||
// unregister this form with SiteHandler.
|
||||
if ($form.length == 1) {
|
||||
informationObject = {closePermitted: true};
|
||||
$form.trigger('containerClose', [informationObject]);
|
||||
if (!informationObject.closePermitted) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the modal, clean up any mounted vue instances, remove it from the
|
||||
// DOM and remove the handler once the CSS animation is complete
|
||||
$modalElement.removeClass('is_visible');
|
||||
this.trigger('pkpModalClose');
|
||||
setTimeout(function() {
|
||||
var vueInstances = modalHandler.options.closeCleanVueInstances,
|
||||
instance,
|
||||
i,
|
||||
id;
|
||||
if (vueInstances.length) {
|
||||
for (i = 0; i < vueInstances.length; i++) {
|
||||
id = vueInstances[i];
|
||||
if (typeof pkp.registry._instances[id] !== 'undefined') {
|
||||
instance = /** @type {{ $destroy: Function }} */
|
||||
(pkp.registry._instances[id]);
|
||||
instance.$destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
modalHandler.unbindPartial($modalElement);
|
||||
$modalElement.empty();
|
||||
modalHandler.remove();
|
||||
// Fire a callback function if one has been passed with options
|
||||
if (typeof modalHandler.options.closeCallback === 'function') {
|
||||
modalHandler.options.closeCallback.call();
|
||||
}
|
||||
}, 300);
|
||||
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Process events that reach the wrapper element.
|
||||
* Should NOT block other events from bubbling up. Doing so
|
||||
* can disable submit buttons in nested forms.
|
||||
*
|
||||
* @param {Object=} opt_callingContext The calling element or object.
|
||||
* @param {Event=} opt_event The triggering event (e.g. a click on
|
||||
* a close button. Not set if called via callback.
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.handleWrapperEvents =
|
||||
function(opt_callingContext, opt_event) {
|
||||
|
||||
// Close click events directly on modal (background screen)
|
||||
if (opt_event.type == 'click' && opt_callingContext == opt_event.target) {
|
||||
$.pkp.classes.Handler.getHandler($(opt_callingContext))
|
||||
.modalClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// Close for ESC keypresses (27) that have bubbled up
|
||||
if (opt_event.type == 'keyup' && opt_event.which == 27) {
|
||||
$.pkp.classes.Handler.getHandler($(opt_callingContext))
|
||||
.modalClose();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Private methods
|
||||
//
|
||||
/**
|
||||
* Handler to redirect to the correct notification widget the
|
||||
* notify user event.
|
||||
* @param {HTMLElement} sourceElement The element that issued the
|
||||
* "notifyUser" event.
|
||||
* @param {Event} event The "notify user" event.
|
||||
* @param {HTMLElement} triggerElement The element that triggered
|
||||
* the "notifyUser" event.
|
||||
* @private
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.redirectNotifyUserEventHandler_ =
|
||||
function(sourceElement, event, triggerElement) {
|
||||
|
||||
// Use the notification helper to redirect the notify user event.
|
||||
$.pkp.classes.notification.NotificationHelper.
|
||||
redirectNotifyUserEvent(this, triggerElement);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler to listen to global form success events, and close when an event
|
||||
* from a child form has been fired, and this form matches the config id
|
||||
*
|
||||
* @param {Object} source The Vue.js component which fired the event
|
||||
* @param {Object} formId The form component's id prop
|
||||
* @private
|
||||
*/
|
||||
$.pkp.controllers.modal.ModalHandler.prototype.onFormSuccess_ =
|
||||
function(source, formId) {
|
||||
if (this.options.closeOnFormSuccessId &&
|
||||
this.options.closeOnFormSuccessId === formId) {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
self.modalClose();
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file js/controllers/modal/RedirectConfirmationModalHandler.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 RedirectConfirmationModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A confirmation modal that redirects to a URL upon confirmation.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ConfirmationModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {Object} options Non-default options to configure
|
||||
* the modal.
|
||||
*
|
||||
* Options are:
|
||||
* - remoteUrl string A URL to be redirected to when the confirmation
|
||||
* button has been clicked.
|
||||
* - All options from the ConfirmationModalHandler and ModalHandler
|
||||
* widgets.
|
||||
* - All options documented for the jQueryUI dialog widget,
|
||||
* except for the buttons parameter which is not supported.
|
||||
*/
|
||||
$.pkp.controllers.modal.RedirectConfirmationModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// Configure the redirect URL to be called when
|
||||
// the modal closes.
|
||||
this.remoteUrl_ = options.remoteUrl;
|
||||
};
|
||||
$.pkp.classes.Helper.inherits(
|
||||
$.pkp.controllers.modal.RedirectConfirmationModalHandler,
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Private properties
|
||||
//
|
||||
/**
|
||||
* A URL to be redirected to when the confirmation button
|
||||
* has been clicked.
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
$.pkp.controllers.modal.RedirectConfirmationModalHandler.prototype.
|
||||
remoteUrl_ = null;
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/** @inheritDoc */
|
||||
$.pkp.controllers.modal.RedirectConfirmationModalHandler.prototype.
|
||||
checkOptions = function(options) {
|
||||
|
||||
// Check the mandatory options of the ModalHandler handler.
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for our own mandatory options.
|
||||
// The cancel button is mandatory for redirect confirmation modals.
|
||||
return typeof options.cancelButton === 'string' &&
|
||||
typeof options.remoteUrl === 'string';
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
/**
|
||||
* Callback that will be activated when the modal's
|
||||
* confirm button is clicked.
|
||||
*
|
||||
* @param {HTMLElement} dialogElement The element the
|
||||
* dialog was created on.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
$.pkp.controllers.modal.RedirectConfirmationModalHandler.prototype.
|
||||
modalConfirm = function(dialogElement, event) {
|
||||
|
||||
document.location = this.remoteUrl_;
|
||||
};
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file js/controllers/modal/RemoteActionConfirmationModalHandler.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 RemoteActionConfirmationModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A confirmation modal that executes a remote action on confirmation.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.ConfirmationModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {{
|
||||
* remoteAction: string,
|
||||
* postData: Object,
|
||||
* csrfToken: string
|
||||
* }} options Non-default options to configure the modal.
|
||||
*
|
||||
* Options are:
|
||||
* - remoteAction string An action to be executed when the confirmation
|
||||
* button has been clicked.
|
||||
* - All options from the ConfirmationModalHandler and ModalHandler
|
||||
* widgets.
|
||||
* - All options documented for the jQueryUI dialog widget,
|
||||
* except for the buttons parameter which is not supported.
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// Configure the remote action (URL) to be called when
|
||||
// the modal closes.
|
||||
this.remoteAction_ = options.remoteAction;
|
||||
|
||||
// Store the data to send with the post request
|
||||
this.postData_ = options.postData || {};
|
||||
|
||||
// Add the CSRF token to the post data
|
||||
this.postData_.csrfToken = options.csrfToken;
|
||||
};
|
||||
$.pkp.classes.Helper.inherits(
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler,
|
||||
$.pkp.controllers.modal.ConfirmationModalHandler);
|
||||
|
||||
|
||||
//
|
||||
// Private properties
|
||||
//
|
||||
/**
|
||||
* A remote action to be executed when the confirmation button
|
||||
* has been clicked.
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler.prototype.
|
||||
remoteAction_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Data params to send with the post request
|
||||
* @private
|
||||
* @type {?Object}
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler.prototype.
|
||||
postData_ = null;
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler.prototype.
|
||||
checkOptions = function(options) {
|
||||
|
||||
// Check the mandatory options of the ModalHandler handler.
|
||||
if (!this.parent('checkOptions', options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for our own mandatory options.
|
||||
// The cancel button is mandatory for remote action confirmation modals.
|
||||
return typeof options.cancelButton === 'string' &&
|
||||
typeof options.remoteAction === 'string';
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
/**
|
||||
* Callback that will be activated when the modal's
|
||||
* confirm button is clicked.
|
||||
*
|
||||
* @param {HTMLElement} dialogElement The element the
|
||||
* dialog was created on.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler.prototype.
|
||||
modalConfirm = function(dialogElement, event) {
|
||||
event.preventDefault();
|
||||
|
||||
$.post(this.remoteAction_,
|
||||
this.postData_,
|
||||
this.callbackWrapper(this.remoteResponse), 'json');
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
$.pkp.controllers.modal.RemoteActionConfirmationModalHandler.prototype.
|
||||
remoteResponse = function(ajaxOptions, jsonData) {
|
||||
|
||||
var processedJsonData = this.parent('remoteResponse', ajaxOptions, jsonData);
|
||||
if (processedJsonData !== false) {
|
||||
this.modalClose(ajaxOptions);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @file js/controllers/modal/WizardModalHandler.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 WizardModalHandler
|
||||
* @ingroup js_controllers_modal
|
||||
*
|
||||
* @brief A modal that contains a wizard and handles its events.
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @extends $.pkp.controllers.modal.AjaxModalHandler
|
||||
*
|
||||
* @param {jQueryObject} $handledElement The clickable element
|
||||
* the modal will be attached to.
|
||||
* @param {Object} options non-default Dialog options
|
||||
* to be passed into the dialog widget.
|
||||
*
|
||||
* Options are:
|
||||
* - all options documented for the AjaxModalHandler.
|
||||
*/
|
||||
$.pkp.controllers.modal.WizardModalHandler =
|
||||
function($handledElement, options) {
|
||||
|
||||
this.parent($handledElement, options);
|
||||
|
||||
// Subscribe the modal to wizard events.
|
||||
this.bind('wizardClose', this.wizardClose);
|
||||
this.bind('wizardCancel', this.wizardClose);
|
||||
};
|
||||
$.pkp.classes.Helper.inherits($.pkp.controllers.modal.WizardModalHandler,
|
||||
$.pkp.controllers.modal.AjaxModalHandler);
|
||||
|
||||
|
||||
/**
|
||||
* Overridden version of the modal close button handler acting
|
||||
* as a wizard cancel button.
|
||||
*
|
||||
* @protected
|
||||
* @param {Object=} opt_callingElement The close button.
|
||||
* @param {Event=} opt_event The close button click event.
|
||||
* @param {boolean=} opt_closeWithoutCancel Set to true to immediately
|
||||
* close the modal.
|
||||
* @return {boolean} Should return false to stop event processing.
|
||||
*/
|
||||
$.pkp.controllers.modal.WizardModalHandler.prototype.modalClose =
|
||||
function(opt_callingElement, opt_event, opt_closeWithoutCancel) {
|
||||
|
||||
if (opt_closeWithoutCancel) {
|
||||
this.parent('modalClose', opt_callingElement, opt_event);
|
||||
} else {
|
||||
// Trigger a cancel event on the wizard.
|
||||
var wizardCancelRequestedEvent = new $.Event('wizardCancelRequested'),
|
||||
$wizard;
|
||||
|
||||
wizardCancelRequestedEvent.stopPropagation();
|
||||
$wizard = this.getHtmlElement().children().first();
|
||||
$wizard.trigger(wizardCancelRequestedEvent);
|
||||
|
||||
// Only close the modal if the wizard didn't prevent this.
|
||||
if (!wizardCancelRequestedEvent.isDefaultPrevented()) {
|
||||
this.parent('modalClose', opt_callingElement, opt_event);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle the wizard close event.
|
||||
*
|
||||
* @param {HTMLElement} wizardElement The calling
|
||||
* wizard.
|
||||
* @param {Event} event The triggered event.
|
||||
*/
|
||||
$.pkp.controllers.modal.WizardModalHandler.prototype.wizardClose =
|
||||
function(wizardElement, event) {
|
||||
|
||||
this.modalClose(wizardElement, event, true);
|
||||
};
|
||||
|
||||
|
||||
}(jQuery));
|
||||
Reference in New Issue
Block a user