2 * Provides the basic core functionality.
4 * @author Alexander Ebert
5 * @copyright 2001-2018 WoltLab GmbH
6 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7 * @module WoltLabSuite/Core/Core
9 define([], function() {
12 var _clone = function(variable
) {
13 if (typeof variable
=== 'object' && (Array
.isArray(variable
) || Core
.isPlainObject(variable
))) {
14 return _cloneObject(variable
);
20 var _cloneObject = function(obj
) {
25 if (Array
.isArray(obj
)) {
30 for (var key
in obj
) {
31 if (obj
.hasOwnProperty(key
) && typeof obj
[key
] !== 'undefined') {
32 newObj
[key
] = _clone(obj
[key
]);
39 //noinspection JSUnresolvedVariable
40 var _prefix
= 'wsc' + window
.WCF_PATH
.hashCode() + '-';
43 * @exports WoltLabSuite/Core/Core
47 * Deep clones an object.
49 * @param {object} obj source object
50 * @return {object} cloned object
52 clone: function(obj
) {
57 * Converts WCF 2.0-style URLs into the default URL layout.
59 * @param string url target url
60 * @return rewritten url
62 convertLegacyUrl: function(url
) {
63 return url
.replace(/^index\.php\/(.*?)\/\?/, function(match
, controller
) {
64 var parts
= controller
.split(/([A-Z][a-z0-9]+)/);
66 for (var i
= 0, length
= parts
.length
; i
< length
; i
++) {
67 var part
= parts
[i
].trim();
69 if (controller
.length
) controller
+= '-';
70 controller
+= part
.toLowerCase();
74 return 'index.php?' + controller
+ '/&';
79 * Merges objects with the first argument.
81 * @param {object} out destination object
82 * @param {...object} arguments variable number of objects to be merged into the destination object
83 * @return {object} destination object with all provided objects merged into
85 extend: function(out
) {
87 var newObj
= this.clone(out
);
89 for (var i
= 1, length
= arguments
.length
; i
< length
; i
++) {
90 var obj
= arguments
[i
];
94 for (var key
in obj
) {
95 if (objOwns(obj
, key
)) {
96 if (!Array
.isArray(obj
[key
]) && typeof obj
[key
] === 'object') {
97 if (this.isPlainObject(obj
[key
])) {
98 // object literals have the prototype of Object which in return has no parent prototype
99 newObj
[key
] = this.extend(out
[key
], obj
[key
]);
102 newObj
[key
] = obj
[key
];
106 newObj
[key
] = obj
[key
];
116 * Inherits the prototype methods from one constructor to another
121 * function MyDerivedClass() {}
122 * Core.inherit(MyDerivedClass, TheAwesomeBaseClass, {
123 * // regular prototype for `MyDerivedClass`
125 * overwrittenMethodFromBaseClass: function(foo, bar) {
129 * MyDerivedClass._super.prototype.overwrittenMethodFromBaseClass.call(this, foo, bar);
133 * @see https://github.com/nodejs/node/blob/7d14dd9b5e78faabb95d454a79faa513d0bbc2a5/lib/util.js#L697-L735
134 * @param {function} constructor inheriting constructor function
135 * @param {function} superConstructor inherited constructor function
136 * @param {object=} propertiesObject additional prototype properties
138 inherit: function(constructor, superConstructor
, propertiesObject
) {
139 if (constructor === undefined || constructor === null) {
140 throw new TypeError("The constructor must not be undefined or null.");
142 if (superConstructor
=== undefined || superConstructor
=== null) {
143 throw new TypeError("The super constructor must not be undefined or null.");
145 if (superConstructor
.prototype === undefined) {
146 throw new TypeError("The super constructor must have a prototype.");
149 constructor._super
= superConstructor
;
150 constructor.prototype = Core
.extend(Object
.create(superConstructor
.prototype, {
157 }), propertiesObject
|| {});
161 * Returns true if `obj` is an object literal.
163 * @param {*} obj target object
164 * @returns {boolean} true if target is an object literal
166 isPlainObject: function(obj
) {
167 if (typeof obj
!== 'object' || obj
=== null || obj
.nodeType
) {
171 return (Object
.getPrototypeOf(obj
) === Object
.prototype);
175 * Returns the object's class name.
177 * @param {object} obj target object
178 * @return {string} object class name
180 getType: function(obj
) {
181 return Object
.prototype.toString
.call(obj
).replace(/^\[object (.+)\]$/, '$1');
185 * Returns a RFC4122 version 4 compilant UUID.
187 * @see http://stackoverflow.com/a/2117523
190 getUuid: function() {
191 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c
) {
192 var r
= Math
.random()*16|0, v
= c
== 'x' ? r
: (r
&0x3|0x8);
193 return v
.toString(16);
198 * Recursively serializes an object into an encoded URI parameter string.
200 * @param {object} obj target object
201 * @param {string=} prefix parameter prefix
202 * @return {string} encoded parameter string
204 serialize: function(obj
, prefix
) {
207 for (var key
in obj
) {
208 if (objOwns(obj
, key
)) {
209 var parameterKey
= (prefix
) ? prefix
+ '[' + key
+ ']' : key
;
210 var value
= obj
[key
];
212 if (typeof value
=== 'object') {
213 parameters
.push(this.serialize(value
, parameterKey
));
216 parameters
.push(encodeURIComponent(parameterKey
) + '=' + encodeURIComponent(value
));
221 return parameters
.join('&');
225 * Triggers a custom or built-in event.
227 * @param {Element} element target element
228 * @param {string} eventName event name
230 triggerEvent: function(element
, eventName
) {
234 event
= new Event(eventName
, {
240 event
= document
.createEvent('Event');
241 event
.initEvent(eventName
, true, true);
244 element
.dispatchEvent(event
);
248 * Returns the unique prefix for the localStorage.
250 * @return {string} prefix for the localStorage
252 getStoragePrefix: function() {