Файловый менеджер - Редактировать - /home/pimjdymy/public_html/revisionroad/themes/ee/asset/javascript/compressed/cp/global_start.js
Назад
/*! * This source file is part of the open source project * ExpressionEngine (https://expressionengine.com) * * @link https://expressionengine.com/ * @copyright Copyright (c) 2003-2023, Packet Tide, LLC (https://www.packettide.com) * @license https://expressionengine.com/license Licensed under Apache License, Version 2.0 */ (function($) { "use strict"; /** * Namespace function that non-destructively creates "namespace" objects (e.g. EE.publish.example) * * @param {String} namespace_string The namespace string (e.g. EE.publish.example) * @returns The object to create */ EE.namespace = function(namespace_string) { var parts = namespace_string.split('.'), parent = EE; // strip redundant leading global if (parts[0] === "EE") { parts = parts.slice(1); } // @todo disallow 'prototype', duh // create a property if it doesn't exist for (var i = 0, max = parts.length; i < max; i += 1) { if (typeof parent[parts[i]] === "undefined") { parent[parts[i]] = {}; }; parent = parent[parts[i]]; } return parent; }; // Create the base cp namespace EE.namespace('EE.cp'); /** * Hook into jQuery's ajax functionality to build in handling of our * csrf tokens and custom response headers. * * We also add a custom error handler in case the developer does not specify * one. This prevents silent failure. */ $.ajaxPrefilter(function(options, originalOptions, jqXHR) { var old_token = EE.CSRF_TOKEN, type = options.type.toUpperCase(); // Throw all errors if ( ! _.has(options, 'error')) { jqXHR.fail(function(xhr, status, error) { _.defer(function() { throw error; }); }); } // Add CSRF TOKEN to EE POST requests if (type == 'POST' && options.crossDomain === false) { jqXHR.setRequestHeader('X-CSRF-TOKEN', old_token); } var defaultHeaderResponses = { // Refresh xids (deprecated) 'eexid': function(new_xid) { if (new_xid) { EE.cp.setCsrfToken(new_xid); } }, // Refresh csrf tokens 'csrf-token': function(new_token) { if (new_token) { EE.cp.setCsrfToken(new_token); } }, // Force redirects (e.g. logout) 'ee-redirect': function(url) { window.location = EE.BASE + '&' + url.replace('//', '/'); // replace to prevent //example.com }, // Trigger broadcast events 'ee-broadcast': function(event) { EE.cp.broadcastEvents[event](); $(window).trigger('broadcast', event); } }; // Set EE response header defaults var eeResponseHeaders = $.merge( defaultHeaderResponses, originalOptions.eeResponseHeaders || {} ); jqXHR.always(function(xhr) { if (options.crossDomain === false) { _.each(eeResponseHeaders, function(callback, name) { var headerValue = jqXHR.getResponseHeader('X-'+name); if (headerValue) { callback(headerValue); } }); } }); }); // Grid has become a dependency for a few fieldtypes. However, sometimes it's not // on the page or loaded after the fieldtype. So instead of tryin to always load // grid or doing weird dependency juggling, we're just going to cache any calls // to grid.bind for now. Grid will override this definition and replay them if/when // it becomes available on the page. Long term we need a better solution for js // dependencies. EE.grid_cache = []; window.Grid = { bind: function() { EE.grid_cache.push(arguments); } }; // Handles events for the field manager channel create/edit form var FluidField = window.FluidField = { _eventHandlers: [], /** * Binds an event * * Available events are: * 'add' - When a field is added * 'remove' - When a field is removed * 'beforeSort' - Before sort starts * 'afterSort' - After sort ends * * @param {string} fieldtypeName Class name of fieldtype * @param {string} action Name of action * @param {func} func Callback function for event */ on: function(fieldtypeName, action, func) { if (this._eventHandlers[action] == undefined) { this._eventHandlers[action] = [] } // Each fieldtype gets one method per handler this._eventHandlers[action][fieldtypeName] = func; }, /** * Fires an event * * @param {string} action Name of action * @param {object} element Element object to pass along to the callback */ fireEvent: function(fieldtypeName, action, args) { // If no events regsitered, don't bother if (this._eventHandlers[action] === undefined) { return; } // If no events regsitered, don't bother if (this._eventHandlers[action][fieldtypeName] === undefined) { return; } this._eventHandlers[action][fieldtypeName].apply(this, args); } }; // Handles events for the field manager channel create/edit form var FieldManager = window.FieldManager = { _eventHandlers: [], /** * Binds an event * * Available events are: * 'fieldModalDisplay' - When the new field modal form is displayed * * @param {string} action Name of action * @param {func} func Callback function for event */ on: function(action, func) { if (this._eventHandlers[action] == undefined) { this._eventHandlers[action] = [] } this._eventHandlers[action].push(func) }, /** * Fires an event * * @param {string} action Name of action * @param {object} element Element object to pass along to the callback */ fireEvent: function(action, element) { var handlers = this._eventHandlers[action] || [] for (var i = 0; i < handlers.length; i++) { handlers[i](element) } } }; // Setup Base EE Control Panel $(document).ready(function () { // call the input placeholder polyfill early so that we don't get // weird flashes of content if ( ! 'placeholder' in document.createElement('input')) { EE.insert_placeholders(); } EE.cp.cleanUrls(); EE.cp.bindCpMessageClose(); EE.cp.bindSortableFolderLists(); EE.cp.addLastToChecklists(); EE.cp.bindPostLinks(); EE.cp.validateLicense(); }); /** * Posts the current EE license to the EE main site for validation purposes. */ EE.cp.validateLicense = function() { // Verify we have a license validation URL and the last update check was more than a minute ago. if (!EE.cp.lvUrl || (EE.cp.lastUpdateCheck && EE.cp.lastUpdateCheck <= 60)) { return; } var installedAddons = JSON.parse(EE.cp.installedAddons); $.ajax({ type: 'POST', url: EE.cp.lvUrl, dataType: 'json', data: { appVer: EE.cp.appVer, license: EE.cp.licenseKey, addons: installedAddons, meta: [ { site_name: EE.site_name, site_id: EE.site_id, site_url: EE.site_url, usesPro: EE.cp.usesPro } ] }, success: function(result) { if (EE.cp.accessResponseURL) { // Fill in some missing data between the request and response. for (var addon of result.addons) { installedAddons[addon.slug].status = addon.status; installedAddons[addon.slug].update = addon.update; } // Post the response to the backend. $.ajax({ type: 'POST', url: EE.cp.accessResponseURL, dataType: 'json', data: { appVer: EE.cp.appVer, license: EE.cp.licenseKey, licenseStatus: result, addons: installedAddons, site_name: EE.site_name, site_id: EE.site_id, site_url: EE.site_url }, success: function (result) { }, error: function (data, textStatus, errorThrown) { console.error('Error Data:', (typeof(data.responseJSON) !== 'undefined') ? data.responseJSON : data, 'textStatus:', textStatus, 'errorThrown:', errorThrown); return true; } }); } }, error: function(data, textStatus, errorThrown) { console.error('Error Data:', (typeof(data.responseJSON) !== 'undefined') ? data.responseJSON : data, 'textStatus:', textStatus, 'errorThrown:', errorThrown); return true; } }); } /** * Finds links with a data-post-url attribute and on click, fires off a POST * request to that URL via a form submission. This is so that certain actions * can have the protection from CSRF but still be regular links in the UI. */ EE.cp.bindPostLinks = function() { $('body').on('click', 'a[data-post-url]', function(event) { event.preventDefault(); var form = $('<form/>', { action: $(this).data('postUrl'), method: 'post' }); form.append($('<input/>', { name: 'csrf_token', value: EE.CSRF_TOKEN })); form.appendTo('body').submit(); }); } /** * For nested checklists, the very last item that APPEARS in the list * needs a class of "last". */ EE.cp.addLastToChecklists = function() { $('ul.nested-list li').removeClass('last'); $('ul.nested-list').each(function(){ $('li:last-child', this).not('ul.toolbar li').last().addClass('last'); }); } // Close alert modal when close button is clicked EE.cp.bindCpMessageClose = function() { $('body').on('click', '.js-notice-dismiss', function(event) { event.preventDefault(); $(this).closest('.app-notice').remove(); }); // Clear floating alerts after some time var floatingAlerts = $('.app-notice--alert') if (floatingAlerts.length) { setTimeout(function() { floatingAlerts.fadeOut(function() { floatingAlerts.remove() }) }, 20000) } } // Binds jQuery UI sortable to reorderable folder lists EE.cp.bindSortableFolderLists = function() { $('.sidebar .folder-list.reorderable').sortable({ axis: 'y', // Only allow vertical dragging containment: 'parent', // Contain to parent handle: 'a', // Set drag handle cancel: 'ul.toolbar', // Do not allow sort on this handle items: '> .sidebar__link', // Only allow these to be sortable sort: EE.sortable_sort_helper, // Custom sort handler // After sort finishes stop: function(event, ui) { var name = $(this).data('name'), i; if (EE.cp.folderList.eventHandlers[name] === undefined) { return; } // A list may have multiple callbacks, call them all for (i = 0; i < EE.cp.folderList.eventHandlers[name].length; i++) { EE.cp.folderList.eventHandlers[name][i]($(this)); } } }); } EE.cp.folderList = { eventHandlers: [], /** * Binds a callback to the sort event of a folder list * * @param {string} listName Unique name of folder list * @param {func} func Callback function for event */ onSort: function(listName, func) { if (this.eventHandlers[listName] == undefined) { this.eventHandlers[listName] = []; } this.eventHandlers[listName].push(func); } }; // Simple function to deal with csrf tokens EE.cp.setCsrfToken = function(newToken, skipBroadcast /* internal */) { $('input[name="XID"]').val(newToken); $('input[name="csrf_token"]').val(newToken); EE.XID = newToken; EE.CSRF_TOKEN = newToken; if ( ! skipBroadcast) { $(window.parent).trigger('broadcast.setCsrfToken', newToken); } }; $(window).bind('broadcast.setCsrfToken', function(event, data) { EE.cp.setCsrfToken(data, true); }); // Simple function to deal with base paths tokens var sessionIdRegex = /[&?](S=[A-Za-z0-9]+)/; EE.cp.setBasePath = function(newBase, skipBroadcast /* internal */) { var newBase = newBase.replace(/&/g, '&'), newBaseS = newBase.match(sessionIdRegex) || ['', ''], oldBaseS = EE.BASE.match(sessionIdRegex) || ['', '']; var replaceBase = function(i, value) { if (value && oldBaseS[1]) { return value.replace(oldBaseS[1], newBaseS[1]); } }; $('a').attr('href', replaceBase); $('form').attr('action', replaceBase); // Since the session id in the current url is no longer correct, a // refresh will end up on the login page. We will replace the current // url to avoid that issue. You still cannot use the back button after // logging back in, but how likely are you to remember what page you // were on before leaving this one open for 20 minutes anyways? if (typeof window.history.pushState == 'function' && oldBaseS[1] != '') { window.history.replaceState( null, document.title, window.location.href.replace(oldBaseS[1], newBaseS[1]) ); } // Set it as the new base EE.BASE = newBase; if ( ! skipBroadcast) { $(window.parent).trigger('broadcast.setBasePath', newBase); } }; $(window).bind('broadcast.setBasePath', function(event, data) { EE.cp.setBasePath(data, true); }); $(window).bind('broadcast.setRememberMe', function(event, remember) { EE.hasRememberMe = remember; }) EE.cp.refreshSessionData = function(event, base) { if (base) { EE.cp.setBasePath(base); } // running the request will return the x-csrf-header, which will trigger // our prefilter. We still need to replace the base though. var session_data = /&(.+)$/.exec(EE.BASE); var json_str = EE.BASE + '/login/refresh_csrf_token'; if (session_data) { session_data = session_data[0]; var base_url = /^([^&]+)/.exec(EE.BASE); json_str = base_url[0] + '/login/refresh_csrf_token' + session_data; } $.getJSON(json_str, function(result) { EE.cp.setBasePath(result.base); }); }; var urlRegex = /(.*?)[?](.*?&)?(D=cp(?:&C=[^&]+(?:&M=[^&]+)?)?)(?:&(.+))?$/, slashify = /&?[DCM]=/g, lTrimAmp = /^&+/, rTrimAmp = /&+$/, removeEmptySession = /(^|&)S=0(&|$)/; EE.cp.cleanUrl = function(i, url) { url = url || i; // i exists if coming from jQuery attr callback url = url || ''; // Move session to the end url = url.toString().replace(/^(\S*?)S=(\S+?)&(\S*?)$/g, "$1$3&S=$2"); var result = urlRegex.exec(url); if ( ! result) { return; } // result[1] // index.php // result[2] // S=49204& // result[3] // D=cp&C=foo&M=bar // result[4] // &foobarbaz var path = result[3].replace(slashify, '/'), preQs = result[2] || '', postQs = result[4] || '', newUrl = result[1] + '?' + path; var QS = postQs.replace(removeEmptySession, '') + '&' + preQs.replace(removeEmptySession, ''); QS = QS.replace(lTrimAmp, '').replace(rTrimAmp, ''); if (QS) { newUrl += '&' + QS; } return newUrl.replace(rTrimAmp, ''); }; EE.cp.cleanUrls = function() { $('a:not([href^=javascript])').attr('href', EE.cp.cleanUrl); $('form').attr('action', EE.cp.cleanUrl); }; // Fallback for browsers without placeholder= support EE.insert_placeholders = function () { $('input[type="text"]').each(function() { if ( ! this.placeholder) { return; } var input = $(this), placeholder = this.placeholder, orig_color = input.css('color'); if (input.val() == '') { input.data('user_data', 'n'); } input.focus(function () { // Reset color & remove placeholder text input.css('color', orig_color); if (input.val() === placeholder) { input.val(''); input.data('user_data', 'y'); } }) .blur(function () { // If no user content -> add placeholder text and dim if (input.val() === '' || input.val === placeholder) { input.val(placeholder).css('color', '#888'); input.data('user_data', 'n'); } }) .trigger('blur'); }); }; /** * Handle idle / inaction between windows * * This code relies heavily on timing. In order to reduce complexity everything is * handled in steps (ticks) of 1 second. We count for how many ticks we have been * in a given state and act accordingly. This gives us reasonable timing information * without having to set, cancel, and track multiple timeouts. * * The conditions currently are as follows: * * - If an ee tab has focus we call it idle after 30 minutes of no interaction * - If no ee tab has focus, we call it idle after 45 minutes of no activity * - If they work around the modal (inspector), all request will land on the login page. * - Logging out of one tab will show the modal on all other tabs. * - Logging into the modal on one tab, will show it on all other tabs. * * The object returned is one that allows manual triggering of an event. For * example, to force the modal to show you could call: * * EE.cp.broadcastEvents['modal'](); * * This is used by our ajax filter to allow triggering an event with the * X-EE-BROADCAST header * */ EE.cp.broadcastEvents = (function() { // Define our time limits: var TICK_TIME = 1 * 1000, // Check state every second FOCUSED_IDLE_LIMIT = 30 * 60 * 1000, // 30 minutes: time before modal if window focused BLURRED_IDLE_LIMIT = 45 * 60 * 1000, // 45 minutes: time before modal if no focus REFRESH_TIME_LIMIT = 50 * 60 * 1000, // 50 minutes: refresh if active or remember me logoutModal, overlay; // Setup Base EE Control Panel $(document).ready(function () { // Make sure we have our modal available when we need it logoutModal = $('#idle-modal'), overlay = $('.overlay'); // May be inside a modal form or elsewhere if ( ! logoutModal) { return; } // If the modal hasn't been interacted with in over 10 minutes we'll send a request for // the current csrf token. It can flip on us during long waits due to the session timeout. // If the session times out this will get us a cookie based csrf token, which is what you // would normally log in with, so it's fine. logoutModal.find('form').on('interact', _.throttle(EE.cp.refreshSessionData, 10 * 60 * 1000)); // Bind on the modal submission logoutModal.find('form').on('submit', function() { $.ajax({ type: 'POST', url: this.action, data: $(this).serialize(), dataType: 'json', success: function(result) { if (result.messageType != 'success') { alert(result.message); return; } // Hide the dialog Events.login(); // Grab the new token EE.cp.refreshSessionData(null, result.base); $(window).trigger('broadcast.idleState', 'login'); }, error: function(data) { alert(data.message); } }); return false; }); }); /** * This object tracks the current state of the page. * * The resolve function is called once per tick. The individual events will * set hasFocus and lastActive time. */ var State = { hasFocus: true, modalActive: false, pingReceived: false, lastActive: $.now(), lastRefresh: $.now(), setActiveTime: function() { // Before we set someone as not idle we need to check if they've // sneakily been idle for a long time. When you close your laptop // the timer stops. Reopening it hours later creates a race between // the tick timer and the non-idle events. When that happens, you're // way past the threshold and therefore too late. if (this.modalActive || ! this.modalThresholdReached()) { // If they're active on the page for an extend period of time // without hitting the backend, we can sometimes run past the // session timeout. To prevent that from happening we'll refresh // their session last activity in the background. if (this.refreshThresholdReached()) { this.doRefresh(); } this.lastActive = $.now(); } }, modalThresholdReached: function() { var idleTimeDelta = $.now() - this.lastActive, mustShowModal = (this.hasFocus && idleTimeDelta > FOCUSED_IDLE_LIMIT) || ( ! this.hasFocus && idleTimeDelta > BLURRED_IDLE_LIMIT); return (this.modalActive === false && mustShowModal === true); }, refreshThresholdReached: function() { var refreshTimeDelta = $.now() - this.lastRefresh; return refreshTimeDelta > REFRESH_TIME_LIMIT; }, doRefresh: function() { this.lastRefresh = $.now(); EE.cp.refreshSessionData(); }, resolve: function() { if (EE.hasRememberMe) { if (this.refreshThresholdReached()) { this.doRefresh(); } return; } if (this.modalThresholdReached()) { Events.modal(); $(window).trigger('broadcast.idleState', 'modal'); var session_data = /&(.+)$/.exec(EE.BASE); var json_str = EE.BASE + '/login/lock_cp'; if (session_data) { session_data = session_data[0]; var base_url = /^([^&]+)/.exec(EE.BASE); json_str = base_url[0] + '/login/lock_cp' + session_data; } $.get(json_str); // lock them out of the cp in the background to prevent tampering } else if (this.hasFocus && this.pingReceived === false) { $(window).trigger('broadcast.idleState', 'active'); } // Reset this.pingReceived = false; } }; /** * List of events that might happen during our 15 second interval */ var Events = { // received another window's active event, user active active: function() { State.setActiveTime(); }, // user focused, they are active focus: function() { State.setActiveTime(); State.hasFocus = true; }, // user left, they are idle blur: function() { State.setActiveTime(); State.hasFocus = false; }, // user typing / mousing, possibly active interact: function() { if (State.hasFocus) { State.setActiveTime(); } }, // received another window's modal event, open it modal: function() { if ( ! State.modalActive && logoutModal) { logoutModal.trigger('modal:open'); logoutModal.on('modal:close', function(e) { if (State.modalActive) { e.preventDefault(); Events.logout(); // prevent tampering. If they close it, they go. } }); State.modalActive = true; } State.setActiveTime(); }, // received another window's login event, check and hide modal login: function() { State.modalActive = false; if (logoutModal) { logoutModal.trigger('modal:close'); logoutModal.find(':password').val(''); } State.setActiveTime(); }, // received another window's logout event, leave page logout: function() { window.location = EE.BASE + '/login/logout'; } }; /** * The event tracker spools up all events that happened during this tick * and replays them when the timer fires. */ var EventTracker = { _t: null, init: function() { $(window).trigger('broadcast.setBasePath', EE.BASE); $(window).trigger('broadcast.setCsrfToken', EE.CSRF_TOKEN); $(window).trigger('broadcast.setRememberMe', EE.hasRememberMe); $(window).trigger('broadcast.idleState', 'login'); this._bindEvents(); this.track(); }, /** * Bind our events * * We keep track of focus, blur, scrolling, clicking, etc. * Some broadcast events can be fired immediately as nothing will stop * them once the tick fires anyways. * We have an extra throttle on interactions to keep the browser happy * and not fill up the queue uselessly. */ _bindEvents: function() { var track = $.proxy(this, 'track'), that = this; // Bind on the broadcast event $(window).on('broadcast.idleState', function(event, idleState) { switch (idleState) { case 'active': State.pingReceived = true; track(idleState); break; case 'modal': case 'login': case 'logout': Events[idleState](); break; } }); // Bind on window focus and blur $(window).bind('blur', _.partial(track, 'blur')); $(window).bind('focus', _.partial(track, 'focus')); // Bind on interactions var interaction = 'DOMMouseScroll keydown mousedown mousemove mousewheel touchmove touchstart'; $(document).on( interaction.split(' ').join('.idleState '), // namespace the events _.throttle(_.partial(track, 'interact'), 500) // throttle event firing ); // Clicking the logout button fires "modal" on all the others $('.logOutButton').click(function() { $(window).trigger('broadcast.idleState', 'modal'); }); }, /** * Helper method to record an event */ track: function(name) { clearTimeout(this._t); this._t = setTimeout($.proxy(this, 'track'), TICK_TIME); if (name) { Events[name](); } State.resolve(); } }; // Go go go! EventTracker.init(); return Events; })(); })(jQuery);
| ver. 1.4 |
Github
|
.
| PHP 8.2.30 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка