File Manager
Upload
Current Directory: /home/lartcid/public_html/journal.lartc.id
[Back]
..
[Open]
Hapus
Rename
.htaccess
[Edit]
Hapus
Rename
.well-known
[Open]
Hapus
Rename
README.md
[Edit]
Hapus
Rename
api
[Open]
Hapus
Rename
cache
[Open]
Hapus
Rename
cgi-bin
[Open]
Hapus
Rename
classes
[Open]
Hapus
Rename
config.TEMPLATE.inc.php
[Edit]
Hapus
Rename
config.inc.php
[Edit]
Hapus
Rename
controllers
[Open]
Hapus
Rename
cypress.json
[Edit]
Hapus
Rename
dbscripts
[Open]
Hapus
Rename
docs
[Open]
Hapus
Rename
error_log
[Edit]
Hapus
Rename
favicon.ico
[Edit]
Hapus
Rename
index.php
[Edit]
Hapus
Rename
js
[Open]
Hapus
Rename
lib
[Open]
Hapus
Rename
locale
[Open]
Hapus
Rename
mini.php
[Edit]
Hapus
Rename
pages
[Open]
Hapus
Rename
php.ini
[Edit]
Hapus
Rename
plugins
[Open]
Hapus
Rename
public
[Open]
Hapus
Rename
registry
[Open]
Hapus
Rename
scheduledTaskLogs
[Open]
Hapus
Rename
schemas
[Open]
Hapus
Rename
styles
[Open]
Hapus
Rename
templates
[Open]
Hapus
Rename
tools
[Open]
Hapus
Rename
Edit File
/** * @defgroup js_controllers */ /** * @file js/controllers/SiteHandler.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 SiteHandler * @ingroup js_controllers * * @brief Handle the site widget. */ (function($) { /** * @constructor * * @extends $.pkp.classes.Handler * * @param {jQueryObject} $widgetWrapper An HTML element that this handle will * be attached to. * @param {{ * fetchNotificationUrl: string, * requestOptions: Object * }} options Handler options. */ $.pkp.controllers.SiteHandler = function($widgetWrapper, options) { this.parent($widgetWrapper, options); this.options_ = options; this.unsavedFormElements_ = []; $('.go').button(); this.bind('redirectRequested', this.redirectToUrl); this.bind('notifyUser', this.fetchNotificationHandler_); this.bind('reloadTab', this.reloadTabHandler_); this.bind('callWhenClickOutside', this.callWhenClickOutsideHandler_); this.bind('mousedown', this.mouseDownHandler_); // Bind the pageUnloadHandler_ method to the DOM so it is // called. $(window).bind('beforeunload', this.pageUnloadHandler_); // Avoid IE8 caching ajax results. If it does, widgets like // grids will not refresh correctly. $.ajaxSetup({cache: false}); // Check if we have notifications to show. if (options.hasSystemNotifications) { this.trigger('notifyUser'); } // bind event handlers for form status change events. this.bind('formChanged', this.callbackWrapper( this.registerUnsavedFormElement_)); this.bind('unregisterChangedForm', this.callbackWrapper( this.unregisterUnsavedFormElement_)); this.bind('unregisterAllForms', this.callbackWrapper( this.unregisterAllFormElements_)); // React to a modal events this.bind('pkpModalOpen', this.callbackWrapper(this.openModal_)); this.bind('pkpModalClose', this.callbackWrapper(this.closeModal_)); this.bind('pkpObserveScrolling', this.callbackWrapper( this.registerScrollingObserver_)); this.bind('pkpRemoveScrollingObserver', this.callbackWrapper( this.unregisterScrollingObserver_)); this.outsideClickChecks_ = {}; this.initializeTinyMCE(); }; $.pkp.classes.Helper.inherits( $.pkp.controllers.SiteHandler, $.pkp.classes.Handler); // // Private properties // /** * Help context. * @private * @type {string?} */ $.pkp.controllers.SiteHandler.prototype.helpContext_ = null; /** * Site handler options. * @private * @type {Object} */ $.pkp.controllers.SiteHandler.prototype.options_ = null; /** * Object with data to be used when checking if user * clicked outside a site element. See callWhenClickOutsideHandler_() * to check the expected check options. * @private * @type {Object} */ $.pkp.controllers.SiteHandler.prototype.outsideClickChecks_ = null; /** * A state variable to store the form elements that have unsaved data. * @private * @type {Array} */ $.pkp.controllers.SiteHandler.prototype.unsavedFormElements_ = null; // // Public static methods. // /** * Initialize the tinyMCE plugin */ $.pkp.controllers.SiteHandler.prototype.initializeTinyMCE = function() { if (typeof tinyMCE !== 'undefined') { tinyMCE.PluginManager.load('pkpTags', $.pkp.app.baseUrl + '/plugins/generic/tinymce/plugins/pkpTags/plugin.js'); tinyMCE.PluginManager.load('pkpwordcount', $.pkp.app.baseUrl + '/plugins/generic/tinymce/plugins/pkpWordcount/plugin.js'); var contentCSS = $.pkp.app.tinyMceContentCSS, tinymceParams, tinymceParamDefaults; tinymceParamDefaults = { width: '100%', resize: 'both', entity_encoding: 'raw', plugins: 'paste,fullscreen,link,lists,code,' + 'image,-pkpTags,noneditable', convert_urls: false, forced_root_block: 'p', paste_auto_cleanup_on_paste: true, apply_source_formatting: false, theme: 'modern', toolbar: 'copy paste | bold italic underline | link unlink ' + 'code fullscreen | image | pkpTags', richToolbar: 'copy paste | bold italic underline | bullist numlist | ' + 'superscript subscript | link unlink code fullscreen | ' + 'image | pkpTags', statusbar: false, content_css: contentCSS, browser_spellcheck: true }; // Support image uploads if (typeof $.pkp.plugins.generic.tinymceplugin !== 'undefined' && typeof $.pkp.plugins.generic.tinymceplugin.uploadUrl !== 'undefined') { tinymceParamDefaults.paste_data_images = true; tinymceParamDefaults.relative_urls = false; tinymceParamDefaults.remove_script_host = false; // https://www.tiny.cloud/docs/general-configuration-guide/upload-images/ tinymceParamDefaults.images_upload_handler = function( blobInfo, success, failure) { /*global FormData: false */ var data = new FormData(); data.append('file', blobInfo.blob(), blobInfo.filename()); $.ajax({ method: 'POST', url: $.pkp.plugins.generic.tinymceplugin.uploadUrl, data: data, processData: false, contentType: false, headers: { 'X-Csrf-Token': pkp.currentUser.csrfToken }, success: function(r) { success(r.url); }, error: function(r) { failure(r.responseJSON.errorMessage); } }); }; } // Allow default params to be overridden if (typeof $.pkp.plugins.generic.tinymceplugin !== 'undefined' && typeof $.pkp.plugins.generic.tinymceplugin.tinymceParams) { tinymceParams = $.extend({}, tinymceParamDefaults, $.pkp.plugins.generic.tinymceplugin.tinymceParams); } else { tinymceParams = $.extend({}, tinymceParamDefaults); } // Don't allow the following settings to be overridden tinymceParams.init_instance_callback = $.pkp.controllers.SiteHandler.prototype.triggerTinyMCEInitialized; tinymceParams.setup = $.pkp.controllers.SiteHandler.prototype.triggerTinyMCESetup; tinyMCE.init(tinymceParams); } }; /** * Callback used by the tinyMCE plugin to trigger the tinyMCEInitialized * event in the DOM. * @param {Object} tinyMCEObject The tinyMCE object instance being * initialized. */ $.pkp.controllers.SiteHandler.prototype.triggerTinyMCEInitialized = function(tinyMCEObject) { var $inputElement = $('#' + $.pkp.classes.Helper.escapeJQuerySelector(tinyMCEObject.id)); $inputElement.trigger('tinyMCEInitialized', [tinyMCEObject]); }; /** * Callback used by the tinyMCE plugin upon setup. * @param {Object} tinyMCEObject The tinyMCE object instance being * set up. */ $.pkp.controllers.SiteHandler.prototype.triggerTinyMCESetup = function(tinyMCEObject) { var target = $('#' + $.pkp.classes.Helper.escapeJQuerySelector(tinyMCEObject.id)), height; // For read-only controls, set up TinyMCE read-only mode. if (target.attr('readonly')) { tinyMCEObject.settings.readonly = true; } if (target.attr('wordCount') && target.attr('wordCount') > 0) { tinyMCEObject.settings.plugins = tinyMCEObject.settings.plugins + ',pkpwordcount'; tinyMCEObject.settings.statusbar = true; } if (target.attr('dir')) { tinyMCEObject.settings.directionality = target.attr('dir'); } // Set height based on textarea rows height = target.attr('rows') || 10; // default: 10 height *= 20; // 20 pixels per row tinyMCEObject.settings.height = height.toString() + 'px'; // Add a fake HTML5 placeholder when the editor is intitialized tinyMCEObject.on('init', function(tinyMCEObject) { var $element = $('#' + tinyMCEObject.id), placeholderText, $placeholder, $placeholderParent; // Don't add anything if we don't have a placeholder placeholderText = $('#' + tinyMCEObject.id).attr('placeholder'); if (placeholderText === '') { return; } // Create placeholder element $placeholder = $('<span></span>'); $placeholder.html(/** @type {string} */ (placeholderText)); $placeholder.addClass('mcePlaceholder'); $placeholder.attr('id', 'mcePlaceholder-' + tinyMCEObject.id); if (tinyMCEObject.target.getContent().length) { $placeholder.hide(); } // Create placeholder wrapper $placeholderParent = $('<div></div>'); $placeholderParent.addClass('mcePlaceholderParent'); $element.wrap($placeholderParent); $element.parent().append($placeholder); }); tinyMCEObject.on('activate', function(tinyMCEObject) { // Hide the placeholder when the editor is activated $('#mcePlaceholder-' + tinyMCEObject.id).hide(); }); tinyMCEObject.on('deactivate', function(tinyMCEObject) { // Show the placholder when the editor is deactivated if (!tinyMCEObject.target.getContent().length) { $('#mcePlaceholder-' + tinyMCEObject.id).show(); } tinyMCEObject.target.dom.addClass( tinyMCEObject.target.dom.select('li'), 'show'); }); tinyMCEObject.on('BeforeSetContent', function(e) { var variablesParsed = $.pkp.classes.TinyMCEHelper.prototype.getVariableMap( '#' + $.pkp.classes.Helper.escapeJQuerySelector(tinyMCEObject.id)); e.content = e.content.replace( /\{\$([a-zA-Z]+)\}(?![^<]*>)/g, function(match, contents, offset, s) { if (variablesParsed[contents] !== undefined) { return $.pkp.classes.TinyMCEHelper.prototype.getVariableElement( contents, variablesParsed[contents], '#' + tinyMCEObject.id) .html(); } return match; }); }); // When the field is being saved, replace any tag placeholders tinyMCEObject.on('SaveContent', function(e) { var $content = $('<div>' + e.content + '</div>'); // Replace tag span elements with the raw tags $content.find('.pkpTag').replaceWith(function() { return '{$' + $(this).attr('data-symbolic') + '}'; }); e.content = $content.html(); }); // In fullscreen mode, also present the toolbar. tinyMCEObject.on('FullscreenStateChanged init', function(e) { var target = e.target, $container = $(target.editorContainer); if (target.plugins.fullscreen) { if (target.plugins.fullscreen.isFullscreen()) { $container.find('.mce-toolbar[role=\'menubar\']').show(); } else { $container.find('.mce-toolbar[role=\'menubar\']').hide(); } } }); }; /** * Get the current window dimensions. * @return {Object} The current window dimensions (height and width) * in pixels. */ $.pkp.controllers.SiteHandler.prototype.getWindowDimensions = function() { var dimensions = {'height': $(window).height(), 'width': $(window).width()}; return dimensions; }; // // Public methods // /** * Callback that is triggered when the page should redirect. * * @param {HTMLElement} sourceElement The element that issued the * "redirectRequested" event. * @param {Event} event The "redirect requested" event. * @param {string} url The URL to redirect to. */ $.pkp.controllers.SiteHandler.prototype.redirectToUrl = function(sourceElement, event, url) { window.location = url; }; /** * Handler bound to 'formChanged' events propagated by forms * that wish to have their form data tracked. * @private * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {HTMLElement} sourceElement The element wishes to * register. * @param {Event} event The formChanged event. */ $.pkp.controllers.SiteHandler.prototype.registerUnsavedFormElement_ = function(siteHandlerElement, sourceElement, event) { var $formElement, formId, index; $formElement = $(event.target.lastElementChild); formId = $formElement.attr('id'); index = $.inArray(formId, this.unsavedFormElements_); if (index == -1) { this.unsavedFormElements_.push(formId); } }; /** * Handler bound to 'unregisterChangedForm' events propagated by forms * that wish to inform that they no longer wish to be tracked as 'unsaved'. * @private * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {HTMLElement} sourceElement The element that wishes to * unregister. * @param {Event} event The unregisterChangedForm event. */ $.pkp.controllers.SiteHandler.prototype.unregisterUnsavedFormElement_ = function(siteHandlerElement, sourceElement, event) { var $formElement, formId, index; $formElement = $(event.target.lastElementChild); formId = $formElement.attr('id'); index = $.inArray(formId, this.unsavedFormElements_); if (index !== -1) { delete this.unsavedFormElements_[index]; } }; /** * Unregister all unsaved form elements. * @private */ $.pkp.controllers.SiteHandler.prototype.unregisterAllFormElements_ = function() { this.unsavedFormElements_ = []; }; // // Private methods. // /** * Fetch the notification data. * @private * @param {HTMLElement} sourceElement The element that issued the * "fetchNotification" event. * @param {Event} event The "fetch notification" event. * @param {Object} jsonData The JSON content representing the * notification. */ $.pkp.controllers.SiteHandler.prototype.fetchNotificationHandler_ = function(sourceElement, event, jsonData) { if (jsonData !== undefined) { // This is an event that came from an inplace notification // widget that was not visible because of the scrolling. this.showNotification_(jsonData); return; } // Avoid race conditions with in place notifications. $.ajax({ url: this.options_.fetchNotificationUrl, data: this.options_.requestOptions, success: this.callbackWrapper(this.showNotificationResponseHandler_), dataType: 'json', async: false }); }; /** * Reload a tab. * @private * @param {HTMLElement} sourceElement The element that issued the * "reloadTab" event. * @param {Event} event The "reload tab" event. * @param {Object} jsonData The JSON content representing the * reload request. */ $.pkp.controllers.SiteHandler.prototype.reloadTabHandler_ = function(sourceElement, event, jsonData) { $(jsonData.tabsSelector).tabs('load', jsonData.tabSelector); }; /** * Call when click outside event handler. Stores the event * parameters as checks to be used later by mouse down handler so we * can track if user clicked outside the passed element or not. * @private * @param {HTMLElement} sourceElement The element that issued the * callWhenClickOutside event. * @param {Event} event The "call when click outside" event. * @param {{ * container: jQueryObject, * callback: Function * }} eventParams The event parameters. * - container: a jQuery element to be used to test if user click * outside of it or not. * - callback: a callback function in case test is true. */ $.pkp.controllers.SiteHandler.prototype.callWhenClickOutsideHandler_ = function(sourceElement, event, eventParams) { // Check the required parameters. if (eventParams.container === undefined) { return; } var id = eventParams.container.attr('id'); if (eventParams.clear) { delete this.outsideClickChecks_[id]; } else if (eventParams.callback !== undefined) { this.outsideClickChecks_[id] = eventParams; } }; /** * Mouse down event handler attached to the site element. * @private * @param {HTMLElement} sourceElement The element that issued the * click event. * @param {Event} event The "mousedown" event. * @return {?boolean} Event handling status. */ $.pkp.controllers.SiteHandler.prototype.mouseDownHandler_ = function(sourceElement, event) { var $container, callback, id; if (!$.isEmptyObject(this.outsideClickChecks_)) { for (id in this.outsideClickChecks_) { this.processOutsideClickCheck_( this.outsideClickChecks_[id], event); } } return true; }; /** * Check if the passed event target is outside the element * inside the passed check data. If true and no other check * option avoids it, use the callback. * @private * @param {{ * container: Object, * callback: Function * }} checkOptions Object with data to be used to * check the click. * @param {Event} event The click event to be checked. * @return {boolean} Whether the check was processed or not. */ $.pkp.controllers.SiteHandler.prototype.processOutsideClickCheck_ = function(checkOptions, event) { // Make sure we have a click event. if (event.type !== 'click' && event.type !== 'mousedown' && event.type !== 'mouseup') { throw new Error('Can not check outside click with the passed event: ' + event.type + '.'); } // Get the container element. var $container = checkOptions.container; // Doesn't make sense to check an outside click // with an invisible element, so skip test if // container is hidden. if ($container.is(':hidden')) { return false; } // Do the click origin checking. if ($container.has(event.target).length === 0) { // Once the check was processed, delete it. delete this.outsideClickChecks_[$container.attr('id')]; checkOptions.callback(); return true; } return false; }; /** * Internal callback called upon page unload. If it returns * anything other than void, a message will be displayed to * the user. * @private * @param {Object} object The window object. * @param {Event} event The before unload event. * @return {string|undefined} The warning message string, if needed. */ $.pkp.controllers.SiteHandler.prototype.pageUnloadHandler_ = function(object, event) { var handler, unsavedElementCount, element; // any registered and then unregistered forms will exist // as properties in the unsavedFormElements_ object. They // will just be undefined. See if there are any that are // not. // we need to get the handler this way since this event is bound // to window, not to SiteHandler. handler = $.pkp.classes.Handler.getHandler($('body')); unsavedElementCount = 0; for (element in handler.unsavedFormElements_) { if (element) { unsavedElementCount++; } } if (unsavedElementCount > 0) { return pkp.localeKeys['form.dataHasChanged']; } return undefined; }; /** * Method to determine if a form is currently registered as having * unsaved changes. * * @param {string} id the id of the form to check. * @return {boolean} true if the form is unsaved. */ $.pkp.controllers.SiteHandler.prototype.isFormUnsaved = function(id) { if (this.unsavedFormElements_ !== null && this.unsavedFormElements_[id] !== undefined) { return true; } return false; }; /** * Response handler to the notification fetch. * @private * @param {Object} ajaxContext The data returned from the server. * @param {Object} jsonData A parsed JSON response object. */ $.pkp.controllers.SiteHandler.prototype.showNotificationResponseHandler_ = function(ajaxContext, jsonData) { this.showNotification_(jsonData); }; /** * Show the notification content. * @private * @param {Object} jsonData The JSON-encoded notification data. */ $.pkp.controllers.SiteHandler.prototype.showNotification_ = function(jsonData) { var workingJsonData, notificationsData, levelId, notificationId, addclass, type; workingJsonData = this.handleJson(jsonData); if (workingJsonData !== false) { if (workingJsonData.content.general) { notificationsData = workingJsonData.content.general; for (levelId in notificationsData) { for (notificationId in notificationsData[levelId]) { addclass = notificationsData[levelId][notificationId].addclass; type = 'notice'; if (addclass == 'notifySuccess') { type = 'success'; } else if (addclass == 'notifyWarning' || addclass == 'notifyError' || addclass == 'notifyFormError' || addclass == 'notifyForbidden') { type = 'warning'; } pkp.eventBus.$emit('notify', notificationsData[levelId][notificationId].text, type); } } } } }; /** * Reacts to a modal being opened. Adds a class to the body representing * a modal open state. * @private * @param {HTMLElement} handledElement The modal that has been added * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {HTMLElement} sourceElement The element wishes to * register. * @param {Event} event The formChanged event. */ $.pkp.controllers.SiteHandler.prototype.openModal_ = function(handledElement, siteHandlerElement, sourceElement, event) { this.getHtmlElement().addClass('modal_is_visible'); }; /** * Reacts to a modal being closed. Removes a class from the body * representing a modal closed state, after checking if no other modals are * open. * @private * @param {HTMLElement} handledElement The modal that has been added * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {HTMLElement} sourceElement The element wishes to * register. * @param {Event} event The formChanged event. */ $.pkp.controllers.SiteHandler.prototype.closeModal_ = function(handledElement, siteHandlerElement, sourceElement, event) { var $htmlElement = this.getHtmlElement(); if (!$htmlElement.find('.pkp_modal.is_visible').length) { $htmlElement.removeClass('modal_is_visible'); } }; /** * Register a function to observe the body scrolling event. * @private * @param {Object} siteHandler The site handler object. * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {Object} event The pkpObserveScrolling event object. * @param {Function} observerFunction The observer function. * @return {boolean} */ $.pkp.controllers.SiteHandler.prototype.registerScrollingObserver_ = function(siteHandler, siteHandlerElement, event, observerFunction) { $(document).scroll(observerFunction); return false; }; /** * Unregister a function that was observing the body scrolling event. * @private * @param {Object} siteHandler The site handler object. * @param {HTMLElement} siteHandlerElement The html element * attached to this handler. * @param {Object} event The pkpRemoveScrollingObserver event object. * @param {Function} observerFunction The observer function. * @return {boolean} */ $.pkp.controllers.SiteHandler.prototype.unregisterScrollingObserver_ = function(siteHandler, siteHandlerElement, event, observerFunction) { var castObserverFunction = /** @type {function()} */ (observerFunction); $(document).unbind('scroll', castObserverFunction); return false; }; }(jQuery));
Simpan