*/
declare namespace TYPO3 {
export let Popover: any;
+ export let Storage: any;
export const lang: any;
export const settings: any;
export namespace CMS {
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
// load the storage API and fill the UC into the PersistentStorage, so no additional AJAX call is needed
- $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Storage', 'function(Storage) {
- Storage.Persistent.load(' . json_encode($this->getBackendUser()->uc) . ');
- }');
+ $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Storage/Persistent', 'function(PersistentStorage) {
+ PersistentStorage.load(' . json_encode($this->getBackendUser()->uc) . ');
+ }');
// load debug console
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DebugConsole');
// @todo: remove this when ExtJS is removed
$states = $this->getBackendUser()->uc['BackendComponents']['States'];
$this->pageRenderer->addExtOnReadyCode('
- var TYPO3ExtJSStateProviderBridge = function() {};
- Ext.extend(TYPO3ExtJSStateProviderBridge, Ext.state.Provider, {
- state: {},
- queue: [],
- dirty: false,
- prefix: "BackendComponents.States.",
- initState: function(state) {
- if (Ext.isArray(state)) {
- Ext.each(state, function(item) {
- this.state[item.name] = item.value;
- }, this);
- } else if (Ext.isObject(state)) {
- Ext.iterate(state, function(key, value) {
- this.state[key] = value;
- }, this);
- } else {
- this.state = {};
- }
- var me = this;
- window.setInterval(function() {
- me.submitState(me)
- }, 750);
- },
- get: function(name, defaultValue) {
- return TYPO3.Storage.Persistent.isset(this.prefix + name) ? TYPO3.Storage.Persistent.get(this.prefix + name) : defaultValue;
- },
- clear: function(name) {
- TYPO3.Storage.Persistent.unset(this.prefix + name);
- },
- set: function(name, value) {
- if (!name) {
- return;
- }
- this.queueChange(name, value);
- },
- queueChange: function(name, value) {
- var o = {};
- var i;
- var found = false;
-
- var lastValue = this.state[name];
- for (i = 0; i < this.queue.length; i++) {
- if (this.queue[i].name === name) {
- lastValue = this.queue[i].value;
+ require([\'TYPO3/CMS/Backend/Storage/Persistent\'], function(PersistentStorage) {
+ var TYPO3ExtJSStateProviderBridge = function() {};
+ Ext.extend(TYPO3ExtJSStateProviderBridge, Ext.state.Provider, {
+ state: {},
+ queue: [],
+ dirty: false,
+ prefix: "BackendComponents.States.",
+ initState: function(state) {
+ if (Ext.isArray(state)) {
+ Ext.each(state, function(item) {
+ this.state[item.name] = item.value;
+ }, this);
+ } else if (Ext.isObject(state)) {
+ Ext.iterate(state, function(key, value) {
+ this.state[key] = value;
+ }, this);
+ } else {
+ this.state = {};
}
- }
- var changed = undefined === lastValue || lastValue !== value;
-
- if (changed) {
- o.name = name;
- o.value = value;
+ var me = this;
+ window.setInterval(function() {
+ me.submitState(me)
+ }, 750);
+ },
+ get: function(name, defaultValue) {
+ return PersistentStorage.isset(this.prefix + name) ? PersistentStorage.get(this.prefix + name) : defaultValue;
+ },
+ clear: function(name) {
+ PersistentStorage.unset(this.prefix + name);
+ },
+ set: function(name, value) {
+ if (!name) {
+ return;
+ }
+ this.queueChange(name, value);
+ },
+ queueChange: function(name, value) {
+ var o = {};
+ var i;
+ var found = false;
+
+ var lastValue = this.state[name];
for (i = 0; i < this.queue.length; i++) {
- if (this.queue[i].name === o.name) {
- this.queue[i] = o;
- found = true;
+ if (this.queue[i].name === name) {
+ lastValue = this.queue[i].value;
}
}
- if (false === found) {
- this.queue.push(o);
- }
- this.dirty = true;
- }
- },
- submitState: function(context) {
- if (!context.dirty) {
- return;
- }
- for (var i = 0; i < context.queue.length; ++i) {
- TYPO3.Storage.Persistent.set(context.prefix + context.queue[i].name, context.queue[i].value).done(function() {
- if (!context.dirty) {
- context.queue = [];
+ var changed = undefined === lastValue || lastValue !== value;
+
+ if (changed) {
+ o.name = name;
+ o.value = value;
+ for (i = 0; i < this.queue.length; i++) {
+ if (this.queue[i].name === o.name) {
+ this.queue[i] = o;
+ found = true;
+ }
}
- });
+ if (false === found) {
+ this.queue.push(o);
+ }
+ this.dirty = true;
+ }
+ },
+ submitState: function(context) {
+ if (!context.dirty) {
+ return;
+ }
+ for (var i = 0; i < context.queue.length; ++i) {
+ PersistentStorage.set(context.prefix + context.queue[i].name, context.queue[i].value).done(function() {
+ if (!context.dirty) {
+ context.queue = [];
+ }
+ });
+ }
+ context.dirty = false;
}
- context.dirty = false;
- }
- });
- Ext.state.Manager.setProvider(new TYPO3ExtJSStateProviderBridge());
- Ext.state.Manager.getProvider().initState(' . (!empty($states) ? json_encode($states) : []) . ');
- ');
+ });
+ Ext.state.Manager.setProvider(new TYPO3ExtJSStateProviderBridge());
+ Ext.state.Manager.getProvider().initState(' . (!empty($states) ? json_encode($states) : []) . ');
+ });');
// Set document title:
$title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
// Renders the module page
--- /dev/null
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+import Client = require('./Storage/Client');
+import Persistent = require('./Storage/Persistent');
+
+/**
+ * Module: TYPO3/CMS/Backend/Storage
+ * Adds a public API for the browsers' localStorage called
+ * TYPO3.Storage.Client and the Backend Users "uc",
+ * available via TYPO3.Storage.Persistent
+ * @exports TYPO3/CMS/Backend/Storage
+ * @deprecated
+ */
+class Storage {
+ public Client: any;
+ public Persistent: any;
+
+ constructor() {
+ if (console) {
+ console.warn(
+ 'TYPO3/CMS/Backend/Storage and TYPO3.Storage are deprecated since TYPO3 v9 and will be removed in TYPO3 v10.',
+ );
+ }
+ this.Client = Client;
+ this.Persistent = Persistent;
+ }
+}
+
+let storageObject;
+try {
+ // fetch from opening window
+ if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Storage) {
+ storageObject = window.opener.TYPO3.Storage;
+ }
+
+ // fetch from parent
+ if (parent && parent.window.TYPO3 && parent.window.TYPO3.Storage) {
+ storageObject = parent.window.TYPO3.Storage;
+ }
+
+ // fetch object from outer frame
+ if (top && top.TYPO3.Storage) {
+ storageObject = top.TYPO3.Storage;
+ }
+} catch (e) {
+ // This only happens if the opener, parent or top is some other url (eg a local file)
+ // which loaded the current window. Then the browser's cross domain policy jumps in
+ // and raises an exception.
+ // For this case we are safe and we can create our global object below.
+}
+
+if (!storageObject) {
+ storageObject = new Storage();
+}
+
+TYPO3.Storage = storageObject;
+export = storageObject;
--- /dev/null
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Module: TYPO3/CMS/Backend/Storage/Client
+ * Wrapper for localStorage
+ * @exports TYPO3/CMS/Backend/Storage/Client
+ */
+class Client {
+ /**
+ * Simple localStorage wrapper, to get value from localStorage
+ * @param {string} key
+ * @returns {string}
+ */
+ public get = (key: string): string => {
+ return localStorage.getItem('t3-' + key);
+ }
+
+ /**
+ * Simple localStorage wrapper, to set value from localStorage
+ *
+ * @param {string} key
+ * @param {string} value
+ * @returns {string}
+ */
+ public set = (key: string, value: string): void => {
+ localStorage.setItem('t3-' + key, value);
+ }
+
+ /**
+ * Simple localStorage wrapper, to unset value from localStorage
+ *
+ * @param {string} key
+ */
+ public unset = (key: string): void => {
+ localStorage.removeItem('t3-' + key);
+ }
+
+ /**
+ * Simple localStorage wrapper, to clear localStorage
+ */
+ public clear = (): void => {
+ localStorage.clear();
+ }
+
+ /**
+ * Checks if a key was set before, useful to not do all the undefined checks all the time
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ public isset = (key: string): boolean => {
+ const value = this.get(key);
+ return (typeof value !== 'undefined' && value !== null);
+ }
+}
+
+export = new Client();
--- /dev/null
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+import $ = require('jquery');
+
+/**
+ * Module: TYPO3/CMS/Backend/Storage/Persistent
+ * Wrapper for persistent storage in UC
+ * @exports TYPO3/CMS/Backend/Storage/Persistent
+ */
+class Persistent {
+ private data: any = false;
+
+ /**
+ * Persistent storage, stores everything on the server via AJAX, does a greedy load on read
+ * common functions get/set/clear
+ *
+ * @param {String} key
+ * @returns {*}
+ */
+ public get = (key: string): any => {
+ const me = this;
+
+ if (this.data === false) {
+ let value;
+ this.loadFromServer().done(() => {
+ value = me.getRecursiveDataByDeepKey(me.data, key.split('.'));
+ });
+ return value;
+ }
+
+ return this.getRecursiveDataByDeepKey(this.data, key.split('.'));
+ }
+
+ /**
+ * Store data persistent on server
+ *
+ * @param {String} key
+ * @param {String} value
+ * @returns {$}
+ */
+ public set = (key: string, value: string): any => {
+ if (this.data !== false) {
+ this.data = this.setRecursiveDataByDeepKey(this.data, key.split('.'), value);
+ }
+ return this.storeOnServer(key, value);
+ }
+
+ /**
+ * @param {string} key
+ * @param {string} value
+ * @returns {$}
+ */
+ public addToList = (key: string, value: string): any => {
+ const me = this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'addToList',
+ key,
+ value,
+ },
+ method: 'post',
+ }).done((data: any): any => {
+ me.data = data;
+ });
+ }
+
+ /**
+ * @param {string} key
+ * @param {string} value
+ * @returns {$}
+ */
+ public removeFromList = (key: string, value: string): any => {
+ const me = this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'removeFromList',
+ key,
+ value,
+ },
+ method: 'post',
+ }).done((data: any): any => {
+ me.data = data;
+ });
+ }
+
+ public unset = (key: string): any => {
+ const me = this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'unset',
+ key,
+ },
+ method: 'post',
+ }).done((data: any): any => {
+ me.data = data;
+ });
+ }
+
+ /**
+ * Clears the UC
+ */
+ public clear = (): any => {
+ $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'clear',
+ },
+ });
+ this.data = false;
+ }
+
+ /**
+ * Checks if a key was set before, useful to not do all the undefined checks all the time
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ public isset = (key: string): boolean => {
+ const value = this.get(key);
+ return (typeof value !== 'undefined' && value !== null);
+ }
+
+ /**
+ * Loads the data from outside, only used for the initial call from BackendController
+ *
+ * @param {String} data
+ */
+ public load = (data: any): any => {
+ this.data = data;
+ }
+
+ /**
+ * Loads all data from the server
+ *
+ * @returns {$}
+ */
+ private loadFromServer = (): any => {
+ const me = this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ async: false,
+ data: {
+ action: 'getAll',
+ },
+ }).done((data) => {
+ me.data = data;
+ });
+ }
+
+ /**
+ * Stores data on the server, and gets the updated data on return
+ * to always be up-to-date inside the browser
+ *
+ * @param {string} key
+ * @param {string} value
+ * @returns {*}
+ */
+ private storeOnServer = (key: string, value: string): any => {
+ const me = this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'set',
+ key,
+ value,
+ },
+ method: 'post',
+ }).done((data): any => {
+ me.data = data;
+ });
+ }
+
+ /**
+ * Helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
+ * data[my][foo][bar] is called recursively by itself
+ *
+ * @param {Object} data the data to be uased as base
+ * @param {String} keyParts the keyParts for the subtree
+ * @returns {Object}
+ */
+ private getRecursiveDataByDeepKey = (data: any, keyParts: any[]): any => {
+ if (keyParts.length === 1) {
+ return (data || {})[keyParts[0]];
+ }
+
+ const firstKey = keyParts.shift();
+ return this.getRecursiveDataByDeepKey(data[firstKey] || {}, keyParts);
+ }
+
+ /**
+ * helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
+ * data[my][foo][bar]
+ * is called recursively by itself
+ *
+ * @param data
+ * @param {any[]} keyParts
+ * @param {string} value
+ * @returns {any[]}
+ */
+ private setRecursiveDataByDeepKey = (data: any, keyParts: any[], value: string): any[] => {
+ if (keyParts.length === 1) {
+ data = data || {};
+ data[keyParts[0]] = value;
+ } else {
+ const firstKey = keyParts.shift();
+ data[firstKey] = this.setRecursiveDataByDeepKey(data[firstKey] || {}, keyParts, value);
+ }
+ return data;
+ }
+}
+
+export = new Persistent();
});
if ($dateTimeFields.length > 0) {
- require(['moment', 'TYPO3/CMS/Backend/Storage', 'twbs/bootstrap-datetimepicker'], function(moment, Storage) {
- var userLocale = Storage.Persistent.get('lang');
+ require(['moment', 'TYPO3/CMS/Backend/Storage/Persistent', 'twbs/bootstrap-datetimepicker'], function(moment, PersistentStorage) {
+ var userLocale = PersistentStorage.get('lang');
var setLocale = userLocale ? moment.locale(userLocale) : false;
// initialize the datepicker on each selected element
require(
[
'jquery',
- 'TYPO3/CMS/Backend/Storage',
+ 'TYPO3/CMS/Backend/Storage/Persistent',
'TYPO3/CMS/Backend/Icons',
'TYPO3/CMS/Backend/Viewport',
'TYPO3/CMS/Backend/Event/ClientRequest',
'TYPO3/CMS/Backend/Event/TriggerRequest'
],
- function ($, Storage, Icons, Viewport, ClientRequest, TriggerRequest) {
+ function ($, PersistentStorage, Icons, Viewport, ClientRequest, TriggerRequest) {
if (typeof TYPO3.ModuleMenu !== 'undefined') {
return TYPO3.ModuleMenu.App;
}
deferred.then(function() {
// check if module menu should be collapsed or not
- var state = Storage.Persistent.get('BackendComponents.States.typo3-module-menu');
+ var state = PersistentStorage.get('BackendComponents.States.typo3-module-menu');
if (state && state.collapsed) {
TYPO3.ModuleMenu.App.toggleMenu(state.collapsed === 'true');
}
}
// Persist collapsed state in the UC of the current user
- Storage.Persistent.set(
+ PersistentStorage.set(
'BackendComponents.States.typo3-module-menu',
{
collapsed: collapse
* @returns {*}
*/
getCollapsedMainMenuItems: function () {
- if (TYPO3.Storage.Persistent.isset('modulemenu')) {
- return JSON.parse(TYPO3.Storage.Persistent.get('modulemenu'));
+ if (PersistentStorage.isset('modulemenu')) {
+ return JSON.parse(PersistentStorage.get('modulemenu'));
} else {
return {};
}
addCollapsedMainMenuItem: function (item) {
var existingItems = this.getCollapsedMainMenuItems();
existingItems[item] = true;
- TYPO3.Storage.Persistent.set('modulemenu', JSON.stringify(existingItems));
+ PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
},
/**
removeCollapseMainMenuItem: function (item) {
var existingItems = this.getCollapsedMainMenuItems();
delete existingItems[item];
- TYPO3.Storage.Persistent.set('modulemenu', JSON.stringify(existingItems));
+ PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
}
};
* Module: TYPO3/CMS/Backend/PageActions
* JavaScript implementations for page actions
*/
-define(['jquery', 'TYPO3/CMS/Backend/Storage'], function($, Storage) {
+define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent'], function($, PersistentStorage) {
'use strict';
/**
$hiddenElements.slideUp();
}
- Storage.Persistent.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() {
+ PersistentStorage.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() {
$spinner.remove();
$me.show();
});
*
* The TYPO3 project - inspiring people to share!
*/
-
-/**
- * Module: TYPO3/CMS/Backend/Storage
- * Adds a public API for the browsers' localStorage called
- * TYPO3.Storage.Client and the Backend Users "uc",
- * available via TYPO3.Storage.Persistent
- */
-define(['jquery'], function ($) {
- 'use strict';
-
- try {
- // fetch from opening window
- if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Storage) {
- return window.opener.TYPO3.Storage;
- }
-
- // fetch from parent
- if (parent && parent.window.TYPO3 && parent.window.TYPO3.Storage) {
- return parent.window.TYPO3.Storage;
- }
-
- // fetch object from outer frame
- if (top && top.TYPO3.Storage) {
- return top.TYPO3.Storage;
- }
- } catch (e) {
- // This only happens if the opener, parent or top is some other url (eg a local file)
- // which loaded the current window. Then the browser's cross domain policy jumps in
- // and raises an exception.
- // For this case we are safe and we can create our global object below.
- }
-
- // we didn't find an existing object, so create it
- /**
- *
- * @type {{Client: {}, Persistent: {_data: boolean}}}
- * @exports TYPO3/CMS/Backend/Storage
- */
- var Storage = {
- Client: {},
- Persistent: {
- _data: false
- }
- };
-
- /**
- * Simple localStorage wrapper, to get value from localStorage
- * @param {String} key
- * @return {String}
- */
- Storage.Client.get = function(key) {
- return localStorage.getItem('t3-' + key);
- };
-
- /**
- * Simple localStorage wrapper, to set value from localStorage
- * @param {String} key
- * @param {String} value
- */
- Storage.Client.set = function(key, value) {
- localStorage.setItem('t3-' + key, value);
- };
-
- /**
- * Simple localStorage wrapper, to unset value from localStorage
- * @param {String} key
- */
- Storage.Client.unset = function(key) {
- localStorage.removeItem('t3-' + key);
- };
-
- /**
- * Simple localStorage wrapper, to clear localStorage
- */
- Storage.Client.clear = function() {
- localStorage.clear();
- };
-
- /**
- * Checks if a key was set before, useful to not do all the undefined checks all the time
- *
- * @param {String} key
- * @returns {Boolean}
- */
- Storage.Client.isset = function(key) {
- var value = this.get(key);
- return (typeof value !== 'undefined' && value !== null);
- };
-
- /**
- * Persistent storage, stores everything on the server via AJAX, does a greedy load on read
- * common functions get/set/clear
- *
- * @param {String} key
- * @returns {*}
- */
- Storage.Persistent.get = function(key) {
- if (this._data === false) {
- var value;
- this._loadFromServer().done(function() {
- value = Storage.Persistent._getRecursiveDataByDeepKey(Storage.Persistent._data, key.split('.'));
- });
- return value;
- } else {
- return this._getRecursiveDataByDeepKey(this._data, key.split('.'));
- }
- };
-
- /**
- * Store data persistent on server
- *
- * @param {String} key
- * @param {String} value
- * @returns {jQuery}
- */
- Storage.Persistent.set = function(key, value) {
- if (this._data !== false) {
- this._data = this._setRecursiveDataByDeepKey(this._data, key.split('.'), value);
- }
- return this._storeOnServer(key, value);
- };
-
- /**
- *
- * @param {String} key
- * @param {String} value
- * @returns {*}
- */
- Storage.Persistent.addToList = function(key, value) {
- return $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {method: 'post', data: {'action': 'addToList', key: key, value: value}}).done(function(data) {
- Storage.Persistent._data = data;
- });
- };
-
- /**
- *
- * @param {String} key
- * @param {String} value
- * @returns {*}
- */
- Storage.Persistent.removeFromList = function(key, value) {
- return $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {method: 'post', data: {'action': 'removeFromList', key: key, value: value}}).done(function(data) {
- Storage.Persistent._data = data;
- });
- };
-
- /**
- *
- * @param {String} key
- * @returns {*}
- */
- Storage.Persistent.unset = function(key) {
- return $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {method: 'post', data: {'action': 'unset', key: key}}).done(function(data) {
- Storage.Persistent._data = data;
- });
- };
-
- /**
- *
- */
- Storage.Persistent.clear = function() {
- $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {data: {'action': 'clear'}});
- this._data = false;
- };
-
- /**
- * Checks if a key was set before, useful to not do all the undefined checks all the time
- *
- * @param {String} key
- * @returns {Boolean}
- */
- Storage.Persistent.isset = function(key) {
- var value = this.get(key);
- return (typeof value !== 'undefined' && typeof value !== 'null' && value != 'undefined');
- };
-
- /**
- * Loads the data from outside, only used for the initial call from BackendController
- *
- * @param {String} data
- */
- Storage.Persistent.load = function(data) {
- this._data = data;
- };
-
- /**
- * Loads all data from the server
- *
- * @returns {*}
- * @private
- */
- Storage.Persistent._loadFromServer = function() {
- return $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {data: {'action': 'getAll'}, async: false}).done(function(data) {
- Storage.Persistent._data = data;
- });
- };
-
- /**
- * Stores data on the server, and gets the updated data on return
- * to always be up-to-date inside the browser
- *
- * @param {String} key
- * @param {String} value
- * @returns {*}
- * @private
- */
- Storage.Persistent._storeOnServer = function(key, value) {
- return $.ajax(TYPO3.settings.ajaxUrls['usersettings_process'], {method: 'post', data: {'action': 'set', key: key, value: value}}).done(function(data) {
- Storage.Persistent._data = data;
- });
- };
-
- /**
- * helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
- * data[my][foo][bar]
- * is called recursively by itself
- *
- * @param {Object} data the data to be uased as base
- * @param {String} keyParts the keyParts for the subtree
- * @param {String} value the value to be set
- * @returns {Object} the data object
- * @private
- */
- Storage.Persistent._setRecursiveDataByDeepKey = function(data, keyParts, value) {
- if (keyParts.length === 1) {
- data = data || {};
- data[keyParts[0]] = value;
- } else {
- var firstKey = keyParts.shift();
- data[firstKey] = this._setRecursiveDataByDeepKey(data[firstKey] || {}, keyParts, value);
- }
- return data;
- };
-
- /**
- * Helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
- * data[my][foo][bar] is called recursively by itself
- *
- * @param {Object} data the data to be uased as base
- * @param {String} keyParts the keyParts for the subtree
- * @returns {Object}
- * @private
- */
- Storage.Persistent._getRecursiveDataByDeepKey = function(data, keyParts) {
- if (keyParts.length === 1) {
- return (data || {})[keyParts[0]];
- } else {
- var firstKey = keyParts.shift();
- return this._getRecursiveDataByDeepKey(data[firstKey] || {}, keyParts);
- }
- };
-
- // attach to global frame
- TYPO3.Storage = Storage;
-
- return Storage;
+define(["require", "exports", "./Storage/Client", "./Storage/Persistent"], function (require, exports, Client, Persistent) {
+ "use strict";
+ /**
+ * Module: TYPO3/CMS/Backend/Storage
+ * Adds a public API for the browsers' localStorage called
+ * TYPO3.Storage.Client and the Backend Users "uc",
+ * available via TYPO3.Storage.Persistent
+ * @exports TYPO3/CMS/Backend/Storage
+ * @deprecated
+ */
+ var Storage = (function () {
+ function Storage() {
+ if (console) {
+ console.warn('TYPO3/CMS/Backend/Storage and TYPO3.Storage are deprecated since TYPO3 v9 and will be removed in TYPO3 v10.');
+ }
+ this.Client = Client;
+ this.Persistent = Persistent;
+ }
+ return Storage;
+ }());
+ var storageObject;
+ try {
+ // fetch from opening window
+ if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Storage) {
+ storageObject = window.opener.TYPO3.Storage;
+ }
+ // fetch from parent
+ if (parent && parent.window.TYPO3 && parent.window.TYPO3.Storage) {
+ storageObject = parent.window.TYPO3.Storage;
+ }
+ // fetch object from outer frame
+ if (top && top.TYPO3.Storage) {
+ storageObject = top.TYPO3.Storage;
+ }
+ }
+ catch (e) {
+ // This only happens if the opener, parent or top is some other url (eg a local file)
+ // which loaded the current window. Then the browser's cross domain policy jumps in
+ // and raises an exception.
+ // For this case we are safe and we can create our global object below.
+ }
+ if (!storageObject) {
+ storageObject = new Storage();
+ }
+ TYPO3.Storage = storageObject;
+ return storageObject;
});
--- /dev/null
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+define(["require", "exports"], function (require, exports) {
+ "use strict";
+ /**
+ * Module: TYPO3/CMS/Backend/Storage/Client
+ * Wrapper for localStorage
+ * @exports TYPO3/CMS/Backend/Storage/Client
+ */
+ var Client = (function () {
+ function Client() {
+ var _this = this;
+ /**
+ * Simple localStorage wrapper, to get value from localStorage
+ * @param {string} key
+ * @returns {string}
+ */
+ this.get = function (key) {
+ return localStorage.getItem('t3-' + key);
+ };
+ /**
+ * Simple localStorage wrapper, to set value from localStorage
+ *
+ * @param {string} key
+ * @param {string} value
+ * @returns {string}
+ */
+ this.set = function (key, value) {
+ localStorage.setItem('t3-' + key, value);
+ };
+ /**
+ * Simple localStorage wrapper, to unset value from localStorage
+ *
+ * @param {string} key
+ */
+ this.unset = function (key) {
+ localStorage.removeItem('t3-' + key);
+ };
+ /**
+ * Simple localStorage wrapper, to clear localStorage
+ */
+ this.clear = function () {
+ localStorage.clear();
+ };
+ /**
+ * Checks if a key was set before, useful to not do all the undefined checks all the time
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ this.isset = function (key) {
+ var value = _this.get(key);
+ return (typeof value !== 'undefined' && value !== null);
+ };
+ }
+ return Client;
+ }());
+ return new Client();
+});
--- /dev/null
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+define(["require", "exports", "jquery"], function (require, exports, $) {
+ "use strict";
+ /**
+ * Module: TYPO3/CMS/Backend/Storage/Persistent
+ * Wrapper for persistent storage in UC
+ * @exports TYPO3/CMS/Backend/Storage/Persistent
+ */
+ var Persistent = (function () {
+ function Persistent() {
+ var _this = this;
+ this.data = false;
+ /**
+ * Persistent storage, stores everything on the server via AJAX, does a greedy load on read
+ * common functions get/set/clear
+ *
+ * @param {String} key
+ * @returns {*}
+ */
+ this.get = function (key) {
+ var me = _this;
+ if (_this.data === false) {
+ var value_1;
+ _this.loadFromServer().done(function () {
+ value_1 = me.getRecursiveDataByDeepKey(me.data, key.split('.'));
+ });
+ return value_1;
+ }
+ return _this.getRecursiveDataByDeepKey(_this.data, key.split('.'));
+ };
+ /**
+ * Store data persistent on server
+ *
+ * @param {String} key
+ * @param {String} value
+ * @returns {$}
+ */
+ this.set = function (key, value) {
+ if (_this.data !== false) {
+ _this.data = _this.setRecursiveDataByDeepKey(_this.data, key.split('.'), value);
+ }
+ return _this.storeOnServer(key, value);
+ };
+ /**
+ * @param {string} key
+ * @param {string} value
+ * @returns {$}
+ */
+ this.addToList = function (key, value) {
+ var me = _this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'addToList',
+ key: key,
+ value: value,
+ },
+ method: 'post',
+ }).done(function (data) {
+ me.data = data;
+ });
+ };
+ /**
+ * @param {string} key
+ * @param {string} value
+ * @returns {$}
+ */
+ this.removeFromList = function (key, value) {
+ var me = _this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'removeFromList',
+ key: key,
+ value: value,
+ },
+ method: 'post',
+ }).done(function (data) {
+ me.data = data;
+ });
+ };
+ this.unset = function (key) {
+ var me = _this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'unset',
+ key: key,
+ },
+ method: 'post',
+ }).done(function (data) {
+ me.data = data;
+ });
+ };
+ /**
+ * Clears the UC
+ */
+ this.clear = function () {
+ $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'clear',
+ },
+ });
+ _this.data = false;
+ };
+ /**
+ * Checks if a key was set before, useful to not do all the undefined checks all the time
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ this.isset = function (key) {
+ var value = _this.get(key);
+ return (typeof value !== 'undefined' && value !== null);
+ };
+ /**
+ * Loads the data from outside, only used for the initial call from BackendController
+ *
+ * @param {String} data
+ */
+ this.load = function (data) {
+ _this.data = data;
+ };
+ /**
+ * Loads all data from the server
+ *
+ * @returns {$}
+ */
+ this.loadFromServer = function () {
+ var me = _this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ async: false,
+ data: {
+ action: 'getAll',
+ },
+ }).done(function (data) {
+ me.data = data;
+ });
+ };
+ /**
+ * Stores data on the server, and gets the updated data on return
+ * to always be up-to-date inside the browser
+ *
+ * @param {string} key
+ * @param {string} value
+ * @returns {*}
+ */
+ this.storeOnServer = function (key, value) {
+ var me = _this;
+ return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
+ data: {
+ action: 'set',
+ key: key,
+ value: value,
+ },
+ method: 'post',
+ }).done(function (data) {
+ me.data = data;
+ });
+ };
+ /**
+ * Helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
+ * data[my][foo][bar] is called recursively by itself
+ *
+ * @param {Object} data the data to be uased as base
+ * @param {String} keyParts the keyParts for the subtree
+ * @returns {Object}
+ */
+ this.getRecursiveDataByDeepKey = function (data, keyParts) {
+ if (keyParts.length === 1) {
+ return (data || {})[keyParts[0]];
+ }
+ var firstKey = keyParts.shift();
+ return _this.getRecursiveDataByDeepKey(data[firstKey] || {}, keyParts);
+ };
+ /**
+ * helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
+ * data[my][foo][bar]
+ * is called recursively by itself
+ *
+ * @param data
+ * @param {any[]} keyParts
+ * @param {string} value
+ * @returns {any[]}
+ */
+ this.setRecursiveDataByDeepKey = function (data, keyParts, value) {
+ if (keyParts.length === 1) {
+ data = data || {};
+ data[keyParts[0]] = value;
+ }
+ else {
+ var firstKey = keyParts.shift();
+ data[firstKey] = _this.setRecursiveDataByDeepKey(data[firstKey] || {}, keyParts, value);
+ }
+ return data;
+ };
+ }
+ return Persistent;
+ }());
+ return new Persistent();
+});
* This class handle the tabs in the TYPO3 backend.
* It stores the last active tab and open it again after a reload,
*/
-define(['jquery', 'TYPO3/CMS/Backend/Storage', 'bootstrap'], function ($, Storage) {
+define(['jquery', 'TYPO3/CMS/Backend/Storage/Client', 'bootstrap'], function ($, ClientStorage) {
'use strict';
/**
* Tabs helper
*
- * @type {{storage: (Storage.Client|*), cacheTimeInSeconds: number, storeLastActiveTab: bool}}
+ * @type {{storage: (ClientStorage|*), cacheTimeInSeconds: number, storeLastActiveTab: bool}}
* @exports TYPO3/CMS/Backend/Tabs
*/
var Tabs = {
- storage: Storage.Client,
+ storage: ClientStorage,
// cache lifetime in seconds
cacheTimeInSeconds: 1800,
storeLastActiveTab: true
define([
'jquery',
'TYPO3/CMS/Backend/Icons',
- 'TYPO3/CMS/Backend/Storage',
+ 'TYPO3/CMS/Backend/Storage/Persistent',
'TYPO3/CMS/Backend/Viewport'
-], function($, Icons, Storage, Viewport) {
+], function($, Icons, PersistentStorage, Viewport) {
'use strict';
/**
requestedModule = $(e.currentTarget).data('modulename'),
timestamp = Math.floor((new Date()).getTime() / 1000);
- if (Storage.Persistent.isset('systeminformation')) {
- storedSystemInformationSettings = JSON.parse(Storage.Persistent.get('systeminformation'));
+ if (PersistentStorage.isset('systeminformation')) {
+ storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation'));
}
moduleStorageObject[requestedModule] = {lastAccess: timestamp};
$.extend(true, storedSystemInformationSettings, moduleStorageObject);
- var $ajax = Storage.Persistent.set('systeminformation', JSON.stringify(storedSystemInformationSettings));
+ var $ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings));
$ajax.done(function() {
// finally, open the module now
TYPO3.ModuleMenu.App.showModule(requestedModule);
--- /dev/null
+.. include:: ../../Includes.txt
+
+==============================================
+Deprecation: #82603 - Deprecate Storage module
+==============================================
+
+See :issue:`82603`
+
+Description
+===========
+
+The RequireJS module :js:`TYPO3/CMS/Backend/Storage` has been marked as deprecated. The module has been split into the
+modules :js:`TYPO3/CMS/Backend/Storage/Client` and :js:`TYPO3/CMS/Backend/Storage/Persistent`.
+
+Impact
+======
+
+Using :js:`TYPO3/CMS/Backend/Storage` will trigger a warning in the browser's developer console.
+
+
+Affected Installations
+======================
+
+All extensions using :js:`TYPO3/CMS/Backend/Storage` are affected.
+
+
+Migration
+=========
+
+Instead of using :js:`Storage.Client` and :js:`Storage.Persistent` use the introduced modules instead.
+
+Example code:
+
+.. code-block:: javascript
+
+ define(['TYPO3/CMS/Backend/Storage/Persistent'], function(PersistentStorage) {
+ if (!PersistentStorage.isset('my-key')) {
+ PersistentStorage.set('my-key', 'foobar');
+ }
+ });
+
+.. index:: JavaScript, NotScanned
* Module: TYPO3/CMS/Recordlist/Recordlist
* Usability improvements for the record list
*/
-define(['jquery', 'TYPO3/CMS/Backend/Storage', 'TYPO3/CMS/Backend/Icons'], function($, Storage, Icons) {
+define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent', 'TYPO3/CMS/Backend/Icons'], function($, PersistentStorage, Icons) {
'use strict';
/**
// Store collapse state in UC
var storedModuleDataList = {};
- if (Storage.Persistent.isset('moduleData.list')) {
- storedModuleDataList = Storage.Persistent.get('moduleData.list');
+ if (PersistentStorage.isset('moduleData.list')) {
+ storedModuleDataList = PersistentStorage.get('moduleData.list');
}
var collapseConfig = {};
collapseConfig[table] = isExpanded ? 1 : 0;
$.extend(true, storedModuleDataList, collapseConfig);
- Storage.Persistent.set('moduleData.list', storedModuleDataList).done(function() {
+ PersistentStorage.set('moduleData.list', storedModuleDataList).done(function() {
$target.data('state', isExpanded ? 'collapsed' : 'expanded');
});
};
*/
define([
'jquery',
- 'TYPO3/CMS/Backend/Storage',
+ 'TYPO3/CMS/Backend/Storage/Persistent',
'jquery-ui/resizable'
-], function($, Storage) {
+], function($, PersistentStorage) {
'use strict';
/**
if (ViewPage.queueIsRunning === false && ViewPage.queue.length >= 1) {
ViewPage.queueIsRunning = true;
var item = ViewPage.queue.shift();
- Storage.Persistent.set(item.storageIdentifier, item.data).done(function() {
+ PersistentStorage.set(item.storageIdentifier, item.data).done(function() {
ViewPage.queueIsRunning = false;
ViewPage.persistQueue();
});