From: woltlab.com Date: Sat, 29 Jun 2019 20:35:37 +0000 (+0000) Subject: Updating minified JavaScript files X-Git-Tag: 5.2.0_Alpha_1~9 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=3ffe79c8077da6d5d4aa7739f819b39806a1ff42;p=GitHub%2FWoltLab%2FWCF.git Updating minified JavaScript files --- diff --git a/wcfsetup/install/files/js/WoltLabSuite.Core.min.js b/wcfsetup/install/files/js/WoltLabSuite.Core.min.js index 59d479a8f3..ec6744bf98 100644 --- a/wcfsetup/install/files/js/WoltLabSuite.Core.min.js +++ b/wcfsetup/install/files/js/WoltLabSuite.Core.min.js @@ -3,41900 +3,20 @@ // WoltLabSuite.Core.min.js -/** - * @license alameda 1.2.0 Copyright jQuery Foundation and other contributors. - * Released under MIT license, https://github.com/requirejs/alameda/blob/master/LICENSE - */ -// Going sloppy because loader plugin execs may depend on non-strict execution. -/*jslint sloppy: true, nomen: true, regexp: true */ -/*global document, navigator, importScripts, Promise, setTimeout */ - -var requirejs, require, define; -(function (global, Promise, undef) { - if (!Promise) { - throw new Error('No Promise implementation available'); - } - - var topReq, dataMain, src, subPath, - bootstrapConfig = requirejs || require, - hasOwn = Object.prototype.hasOwnProperty, - contexts = {}, - queue = [], - currDirRegExp = /^\.\//, - urlRegExp = /^\/|\:|\?|\.js$/, - commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - slice = Array.prototype.slice; - - if (typeof requirejs === 'function') { - return; - } - - var asap = Promise.resolve(undefined); - - // Could match something like ')//comment', do not lose the prefix to comment. - function commentReplace(match, singlePrefix) { - return singlePrefix || ''; - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - function getOwn(obj, prop) { - return obj && hasProp(obj, prop) && obj[prop]; - } - - function obj() { - return Object.create(null); - } - - /** - * Cycles over properties in an object and calls a function for each - * property value. If the function returns a truthy value, then the - * iteration is stopped. - */ - function eachProp(obj, func) { - var prop; - for (prop in obj) { - if (hasProp(obj, prop)) { - if (func(obj[prop], prop)) { - break; - } - } - } - } - - /** - * Simple function to mix in properties from source into target, - * but only if target does not already have a property of the same name. - */ - function mixin(target, source, force, deepStringMixin) { - if (source) { - eachProp(source, function (value, prop) { - if (force || !hasProp(target, prop)) { - if (deepStringMixin && typeof value === 'object' && value && - !Array.isArray(value) && typeof value !== 'function' && - !(value instanceof RegExp)) { - - if (!target[prop]) { - target[prop] = {}; - } - mixin(target[prop], value, force, deepStringMixin); - } else { - target[prop] = value; - } - } - }); - } - return target; - } - - // Allow getting a global that expressed in - // dot notation, like 'a.b.c'. - function getGlobal(value) { - if (!value) { - return value; - } - var g = global; - value.split('.').forEach(function (part) { - g = g[part]; - }); - return g; - } - - function newContext(contextName) { - var req, main, makeMap, callDep, handlers, checkingLater, load, context, - defined = obj(), - waiting = obj(), - config = { - // Defaults. Do not set a default for map - // config to speed up normalize(), which - // will run faster if there is no default. - waitSeconds: 7, - baseUrl: './', - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - mapCache = obj(), - requireDeferreds = [], - deferreds = obj(), - calledDefine = obj(), - calledPlugin = obj(), - loadCount = 0, - startTime = (new Date()).getTime(), - errCount = 0, - trackedErrors = obj(), - urlFetched = obj(), - bundlesMap = obj(), - asyncResolve = Promise.resolve(); - - /** - * Trims the . and .. from an array of path segments. - * It will keep a leading path segment if a .. will become - * the first path segment, to help with module name lookups, - * which act like paths, but can be remapped. But the end result, - * all paths that use this function should look normalized. - * NOTE: this method MODIFIES the input array. - * @param {Array} ary the array of path segments. - */ - function trimDots(ary) { - var i, part, length = ary.length; - for (i = 0; i < length; i++) { - part = ary[i]; - if (part === '.') { - ary.splice(i, 1); - i -= 1; - } else if (part === '..') { - // If at the start, or previous value is still .., - // keep them so that when converted to a path it may - // still work when converted to a path, even though - // as an ID it is less than ideal. In larger point - // releases, may be better to just kick out an error. - if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') { - continue; - } else if (i > 0) { - ary.splice(i - 1, 2); - i -= 2; - } - } - } - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @param {Boolean} applyMap apply the map config to the value. Should - * only be done if this normalization is for a dependency ID. - * @returns {String} normalized name - */ - function normalize(name, baseName, applyMap) { - var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, - foundMap, foundI, foundStarMap, starI, - baseParts = baseName && baseName.split('/'), - normalizedBaseParts = baseParts, - map = config.map, - starMap = map && map['*']; - - - //Adjust any relative paths. - if (name) { - name = name.split('/'); - lastIndex = name.length - 1; - - // If wanting node ID compatibility, strip .js from end - // of IDs. Have to do this here, and not in nameToUrl - // because node allows either .js or non .js to map - // to same file. - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - // Starts with a '.' so need the baseName - if (name[0].charAt(0) === '.' && baseParts) { - //Convert baseName to array, and lop off the last part, - //so that . matches that 'directory' and not name of the baseName's - //module. For instance, baseName of 'one/two/three', maps to - //'one/two/three.js', but we want the directory, 'one/two' for - //this normalization. - normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - name = normalizedBaseParts.concat(name); - } - - trimDots(name); - name = name.join('/'); - } - - // Apply map config if available. - if (applyMap && map && (baseParts || starMap)) { - nameParts = name.split('/'); - - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join('/'); - - if (baseParts) { - // Find the longest baseName segment match in the config. - // So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = getOwn(map, baseParts.slice(0, j).join('/')); - - // baseName segment has config, find if it has one for - // this name. - if (mapValue) { - mapValue = getOwn(mapValue, nameSegment); - if (mapValue) { - // Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break outerLoop; - } - } - } - } - - // Check for a star map match, but just hold on to it, - // if there is a shorter segment match later in a matching - // config, then favor over this star map. - if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { - foundStarMap = getOwn(starMap, nameSegment); - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - // If the name points to a package's name, use - // the package main instead. - pkgMain = getOwn(config.pkgs, name); - - return pkgMain ? pkgMain : name; - } - - function makeShimExports(value) { - function fn() { - var ret; - if (value.init) { - ret = value.init.apply(global, arguments); - } - return ret || (value.exports && getGlobal(value.exports)); - } - return fn; - } - - function takeQueue(anonId) { - var i, id, args, shim; - for (i = 0; i < queue.length; i += 1) { - // Peek to see if anon - if (typeof queue[i][0] !== 'string') { - if (anonId) { - queue[i].unshift(anonId); - anonId = undef; - } else { - // Not our anon module, stop. - break; - } - } - args = queue.shift(); - id = args[0]; - i -= 1; - - if (!(id in defined) && !(id in waiting)) { - if (id in deferreds) { - main.apply(undef, args); - } else { - waiting[id] = args; - } - } - } - - // if get to the end and still have anonId, then could be - // a shimmed dependency. - if (anonId) { - shim = getOwn(config.shim, anonId) || {}; - main(anonId, shim.deps || [], shim.exportsFn); - } - } - - function makeRequire(relName, topLevel) { - var req = function (deps, callback, errback, alt) { - var name, cfg; - - if (topLevel) { - takeQueue(); - } - - if (typeof deps === "string") { - if (handlers[deps]) { - return handlers[deps](relName); - } - // Just return the module wanted. In this scenario, the - // deps arg is the module name, and second arg (if passed) - // is just the relName. - // Normalize module name, if it contains . or .. - name = makeMap(deps, relName, true).id; - if (!(name in defined)) { - throw new Error('Not loaded: ' + name); - } - return defined[name]; - } else if (deps && !Array.isArray(deps)) { - // deps is a config object, not an array. - cfg = deps; - deps = undef; - - if (Array.isArray(callback)) { - // callback is an array, which means it is a dependency list. - // Adjust args if there are dependencies - deps = callback; - callback = errback; - errback = alt; - } - - if (topLevel) { - // Could be a new context, so call returned require - return req.config(cfg)(deps, callback, errback); - } - } - - // Support require(['a']) - callback = callback || function () { - // In case used later as a promise then value, return the - // arguments as an array. - return slice.call(arguments, 0); - }; - - // Complete async to maintain expected execution semantics. - return asyncResolve.then(function () { - // Grab any modules that were defined after a require call. - takeQueue(); - - return main(undef, deps || [], callback, errback, relName); - }); - }; - - req.isBrowser = typeof document !== 'undefined' && - typeof navigator !== 'undefined'; - - req.nameToUrl = function (moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, - parentPath, bundleId, - pkgMain = getOwn(config.pkgs, moduleName); - - if (pkgMain) { - moduleName = pkgMain; - } - - bundleId = getOwn(bundlesMap, moduleName); - - if (bundleId) { - return req.nameToUrl(bundleId, ext, skipExt); - } - - // If a colon is in the URL, it indicates a protocol is used and it is - // just an URL to a file, or if it starts with a slash, contains a query - // arg (i.e. ?) or ends with .js, then assume the user meant to use an - // url and not a module id. The slash is important for protocol-less - // URLs as well as full paths. - if (urlRegExp.test(moduleName)) { - // Just a plain path, not module name lookup, so just return it. - // Add extension if it is included. This is a bit wonky, only non-.js - // things pass an extension, this method probably needs to be - // reworked. - url = moduleName + (ext || ''); - } else { - // A module that needs to be converted to a path. - paths = config.paths; - - syms = moduleName.split('/'); - // For each module name segment, see if there is a path - // registered for it. Start with most specific name - // and work up from it. - for (i = syms.length; i > 0; i -= 1) { - parentModule = syms.slice(0, i).join('/'); - - parentPath = getOwn(paths, parentModule); - if (parentPath) { - // If an array, it means there are a few choices, - // Choose the one that is desired - if (Array.isArray(parentPath)) { - parentPath = parentPath[0]; - } - syms.splice(0, i, parentPath); - break; - } - } - - // Join the path parts together, then figure out if baseUrl is needed. - url = syms.join('/'); - url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js')); - url = (url.charAt(0) === '/' || - url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; - } - - return config.urlArgs && !/^blob\:/.test(url) ? - url + config.urlArgs(moduleName, url) : url; - }; - - /** - * Converts a module name + .extension into an URL path. - * *Requires* the use of a module name. It does not support using - * plain URLs like nameToUrl. - */ - req.toUrl = function (moduleNamePlusExt) { - var ext, - index = moduleNamePlusExt.lastIndexOf('.'), - segment = moduleNamePlusExt.split('/')[0], - isRelative = segment === '.' || segment === '..'; - - // Have a file extension alias, and it is not the - // dots from a relative path. - if (index !== -1 && (!isRelative || index > 1)) { - ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); - moduleNamePlusExt = moduleNamePlusExt.substring(0, index); - } - - return req.nameToUrl(normalize(moduleNamePlusExt, relName), ext, true); - }; - - req.defined = function (id) { - return makeMap(id, relName, true).id in defined; - }; - - req.specified = function (id) { - id = makeMap(id, relName, true).id; - return id in defined || id in deferreds; - }; - - return req; - } - - function resolve(name, d, value) { - if (name) { - defined[name] = value; - if (requirejs.onResourceLoad) { - requirejs.onResourceLoad(context, d.map, d.deps); - } - } - d.finished = true; - d.resolve(value); - } - - function reject(d, err) { - d.finished = true; - d.rejected = true; - d.reject(err); - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName, true); - }; - } - - function defineModule(d) { - d.factoryCalled = true; - - var ret, - name = d.map.id; - - try { - ret = context.execCb(name, d.factory, d.values, defined[name]); - } catch(err) { - return reject(d, err); - } - - if (name) { - // Favor return value over exports. If node/cjs in play, - // then will not have a return value anyway. Favor - // module.exports assignment over exports object. - if (ret === undef) { - if (d.cjsModule) { - ret = d.cjsModule.exports; - } else if (d.usingExports) { - ret = defined[name]; - } - } - } else { - // Remove the require deferred from the list to - // make cycle searching faster. Do not need to track - // it anymore either. - requireDeferreds.splice(requireDeferreds.indexOf(d), 1); - } - resolve(name, d, ret); - } - - // This method is attached to every module deferred, - // so the "this" in here is the module deferred object. - function depFinished(val, i) { - if (!this.rejected && !this.depDefined[i]) { - this.depDefined[i] = true; - this.depCount += 1; - this.values[i] = val; - if (!this.depending && this.depCount === this.depMax) { - defineModule(this); - } - } - } - - function makeDefer(name, calculatedMap) { - var d = {}; - d.promise = new Promise(function (resolve, reject) { - d.resolve = resolve; - d.reject = function(err) { - if (!name) { - requireDeferreds.splice(requireDeferreds.indexOf(d), 1); - } - reject(err); - }; - }); - d.map = name ? (calculatedMap || makeMap(name)) : {}; - d.depCount = 0; - d.depMax = 0; - d.values = []; - d.depDefined = []; - d.depFinished = depFinished; - if (d.map.pr) { - // Plugin resource ID, implicitly - // depends on plugin. Track it in deps - // so cycle breaking can work - d.deps = [makeMap(d.map.pr)]; - } - return d; - } - - function getDefer(name, calculatedMap) { - var d; - if (name) { - d = (name in deferreds) && deferreds[name]; - if (!d) { - d = deferreds[name] = makeDefer(name, calculatedMap); - } - } else { - d = makeDefer(); - requireDeferreds.push(d); - } - return d; - } - - function makeErrback(d, name) { - return function (err) { - if (!d.rejected) { - if (!err.dynaId) { - err.dynaId = 'id' + (errCount += 1); - err.requireModules = [name]; - } - reject(d, err); - } - }; - } - - function waitForDep(depMap, relName, d, i) { - d.depMax += 1; - - // Do the fail at the end to catch errors - // in the then callback execution. - callDep(depMap, relName).then(function (val) { - d.depFinished(val, i); - }, makeErrback(d, depMap.id)).catch(makeErrback(d, d.map.id)); - } - - function makeLoad(id) { - var fromTextCalled; - function load(value) { - // Protect against older plugins that call load after - // calling load.fromText - if (!fromTextCalled) { - resolve(id, getDefer(id), value); - } - } - - load.error = function (err) { - getDefer(id).reject(err); - }; - - load.fromText = function (text, textAlt) { - /*jslint evil: true */ - var d = getDefer(id), - map = makeMap(makeMap(id).n), - plainId = map.id; - - fromTextCalled = true; - - // Set up the factory just to be a return of the value from - // plainId. - d.factory = function (p, val) { - return val; - }; - - // As of requirejs 2.1.0, support just passing the text, to reinforce - // fromText only being called once per resource. Still - // support old style of passing moduleName but discard - // that moduleName in favor of the internal ref. - if (textAlt) { - text = textAlt; - } - - // Transfer any config to this other module. - if (hasProp(config.config, id)) { - config.config[plainId] = config.config[id]; - } - - try { - req.exec(text); - } catch (e) { - reject(d, new Error('fromText eval for ' + plainId + - ' failed: ' + e)); - } - - // Execute any waiting define created by the plainId - takeQueue(plainId); - - // Mark this as a dependency for the plugin - // resource - d.deps = [map]; - waitForDep(map, null, d, d.deps.length); - }; - - return load; - } - - load = typeof importScripts === 'function' ? - function (map) { - var url = map.url; - if (urlFetched[url]) { - return; - } - urlFetched[url] = true; - - // Ask for the deferred so loading is triggered. - // Do this before loading, since loading is sync. - getDefer(map.id); - importScripts(url); - takeQueue(map.id); - } : - function (map) { - var script, - id = map.id, - url = map.url; - - if (urlFetched[url]) { - return; - } - urlFetched[url] = true; - - script = document.createElement('script'); - script.setAttribute('data-requiremodule', id); - script.type = config.scriptType || 'text/javascript'; - script.charset = 'utf-8'; - script.async = true; - - loadCount += 1; - - script.addEventListener('load', function () { - loadCount -= 1; - takeQueue(id); - }, false); - script.addEventListener('error', function () { - loadCount -= 1; - var err, - pathConfig = getOwn(config.paths, id); - if (pathConfig && Array.isArray(pathConfig) && - pathConfig.length > 1) { - script.parentNode.removeChild(script); - // Pop off the first array value, since it failed, and - // retry - pathConfig.shift(); - var d = getDefer(id); - d.map = makeMap(id); - // mapCache will have returned previous map value, update the - // url, which will also update mapCache value. - d.map.url = req.nameToUrl(id); - load(d.map); - } else { - err = new Error('Load failed: ' + id + ': ' + script.src); - err.requireModules = [id]; - getDefer(id).reject(err); - } - }, false); - - script.src = url; - - // If the script is cached, IE10 executes the script body and the - // onload handler synchronously here. That's a spec violation, - // so be sure to do this asynchronously. - if (document.documentMode === 10) { - asap.then(function() { - document.head.appendChild(script); - }); - } else { - document.head.appendChild(script); - } - }; - - function callPlugin(plugin, map, relName) { - plugin.load(map.n, makeRequire(relName), makeLoad(map.id), config); - } - - callDep = function (map, relName) { - var args, bundleId, - name = map.id, - shim = config.shim[name]; - - if (name in waiting) { - args = waiting[name]; - delete waiting[name]; - main.apply(undef, args); - } else if (!(name in deferreds)) { - if (map.pr) { - // If a bundles config, then just load that file instead to - // resolve the plugin, as it is built into that bundle. - if ((bundleId = getOwn(bundlesMap, name))) { - map.url = req.nameToUrl(bundleId); - load(map); - } else { - return callDep(makeMap(map.pr)).then(function (plugin) { - // Redo map now that plugin is known to be loaded - var newMap = map.prn ? map : makeMap(name, relName, true), - newId = newMap.id, - shim = getOwn(config.shim, newId); - - // Make sure to only call load once per resource. Many - // calls could have been queued waiting for plugin to load. - if (!(newId in calledPlugin)) { - calledPlugin[newId] = true; - if (shim && shim.deps) { - req(shim.deps, function () { - callPlugin(plugin, newMap, relName); - }); - } else { - callPlugin(plugin, newMap, relName); - } - } - return getDefer(newId).promise; - }); - } - } else if (shim && shim.deps) { - req(shim.deps, function () { - load(map); - }); - } else { - load(map); - } - } - - return getDefer(name).promise; - }; - - // Turns a plugin!resource to [plugin, resource] - // with the plugin being undefined if the name - // did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - return [prefix, name]; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - makeMap = function (name, relName, applyMap) { - if (typeof name !== 'string') { - return name; - } - - var plugin, url, parts, prefix, result, prefixNormalized, - cacheKey = name + ' & ' + (relName || '') + ' & ' + !!applyMap; - - parts = splitPrefix(name); - prefix = parts[0]; - name = parts[1]; - - if (!prefix && (cacheKey in mapCache)) { - return mapCache[cacheKey]; - } - - if (prefix) { - prefix = normalize(prefix, relName, applyMap); - plugin = (prefix in defined) && defined[prefix]; - } - - // Normalize according - if (prefix) { - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relName)); - prefixNormalized = true; - } else { - // If nested plugin references, then do not try to - // normalize, as it will not normalize correctly. This - // places a restriction on resourceIds, and the longer - // term solution is not to normalize until plugins are - // loaded and all normalizations to allow for async - // loading of a loader plugin. But for now, fixes the - // common uses. Details in requirejs#1131 - name = name.indexOf('!') === -1 ? - normalize(name, relName, applyMap) : - name; - } - } else { - name = normalize(name, relName, applyMap); - parts = splitPrefix(name); - prefix = parts[0]; - name = parts[1]; - - url = req.nameToUrl(name); - } - - // Using ridiculous property names for space reasons - result = { - id: prefix ? prefix + '!' + name : name, // fullName - n: name, - pr: prefix, - url: url, - prn: prefix && prefixNormalized - }; - - if (!prefix) { - mapCache[cacheKey] = result; - } - - return result; - }; - - handlers = { - require: function (name) { - return makeRequire(name); - }, - exports: function (name) { - var e = defined[name]; - if (typeof e !== 'undefined') { - return e; - } else { - return (defined[name] = {}); - } - }, - module: function (name) { - return { - id: name, - uri: '', - exports: handlers.exports(name), - config: function () { - return getOwn(config.config, name) || {}; - } - }; - } - }; - - function breakCycle(d, traced, processed) { - var id = d.map.id; - - traced[id] = true; - if (!d.finished && d.deps) { - d.deps.forEach(function (depMap) { - var depId = depMap.id, - dep = !hasProp(handlers, depId) && getDefer(depId, depMap); - - // Only force things that have not completed - // being defined, so still in the registry, - // and only if it has not been matched up - // in the module already. - if (dep && !dep.finished && !processed[depId]) { - if (hasProp(traced, depId)) { - d.deps.forEach(function (depMap, i) { - if (depMap.id === depId) { - d.depFinished(defined[depId], i); - } - }); - } else { - breakCycle(dep, traced, processed); - } - } - }); - } - processed[id] = true; - } - - function check(d) { - var err, mid, dfd, - notFinished = [], - waitInterval = config.waitSeconds * 1000, - // It is possible to disable the wait interval by using waitSeconds 0. - expired = waitInterval && - (startTime + waitInterval) < (new Date()).getTime(); - - if (loadCount === 0) { - // If passed in a deferred, it is for a specific require call. - // Could be a sync case that needs resolution right away. - // Otherwise, if no deferred, means it was the last ditch - // timeout-based check, so check all waiting require deferreds. - if (d) { - if (!d.finished) { - breakCycle(d, {}, {}); - } - } else if (requireDeferreds.length) { - requireDeferreds.forEach(function (d) { - breakCycle(d, {}, {}); - }); - } - } - - // If still waiting on loads, and the waiting load is something - // other than a plugin resource, or there are still outstanding - // scripts, then just try back later. - if (expired) { - // If wait time expired, throw error of unloaded modules. - for (mid in deferreds) { - dfd = deferreds[mid]; - if (!dfd.finished) { - notFinished.push(dfd.map.id); - } - } - err = new Error('Timeout for modules: ' + notFinished); - err.requireModules = notFinished; - req.onError(err); - } else if (loadCount || requireDeferreds.length) { - // Something is still waiting to load. Wait for it, but only - // if a later check is not already scheduled. Using setTimeout - // because want other things in the event loop to happen, - // to help in dependency resolution, and this is really a - // last ditch check, mostly for detecting timeouts (cycles - // should come through the main() use of check()), so it can - // wait a bit before doing the final check. - if (!checkingLater) { - checkingLater = true; - setTimeout(function () { - checkingLater = false; - check(); - }, 70); - } - } - } - - // Used to break out of the promise try/catch chains. - function delayedError(e) { - setTimeout(function () { - if (!e.dynaId || !trackedErrors[e.dynaId]) { - trackedErrors[e.dynaId] = true; - req.onError(e); - } - }); - return e; - } - - main = function (name, deps, factory, errback, relName) { - if (name) { - // Only allow main calling once per module. - if (name in calledDefine) { - return; - } - calledDefine[name] = true; - } - - var d = getDefer(name); - - // This module may not have dependencies - if (deps && !Array.isArray(deps)) { - // deps is not an array, so probably means - // an object literal or factory function for - // the value. Adjust args. - factory = deps; - deps = []; - } - - // Create fresh array instead of modifying passed in value. - deps = deps ? slice.call(deps, 0) : null; - - if (!errback) { - if (hasProp(config, 'defaultErrback')) { - if (config.defaultErrback) { - errback = config.defaultErrback; - } - } else { - errback = delayedError; - } - } - - if (errback) { - d.promise.catch(errback); - } - - // Use name if no relName - relName = relName || name; - - // Call the factory to define the module, if necessary. - if (typeof factory === 'function') { - - if (!deps.length && factory.length) { - // Remove comments from the callback string, - // look for require calls, and pull them into the dependencies, - // but only if there are function args. - factory - .toString() - .replace(commentRegExp, commentReplace) - .replace(cjsRequireRegExp, function (match, dep) { - deps.push(dep); - }); - - // May be a CommonJS thing even without require calls, but still - // could use exports, and module. Avoid doing exports and module - // work though if it just needs require. - // REQUIRES the function to expect the CommonJS variables in the - // order listed below. - deps = (factory.length === 1 ? - ['require'] : - ['require', 'exports', 'module']).concat(deps); - } - - // Save info for use later. - d.factory = factory; - d.deps = deps; - - d.depending = true; - deps.forEach(function (depName, i) { - var depMap; - deps[i] = depMap = makeMap(depName, relName, true); - depName = depMap.id; - - // Fast path CommonJS standard dependencies. - if (depName === "require") { - d.values[i] = handlers.require(name); - } else if (depName === "exports") { - // CommonJS module spec 1.1 - d.values[i] = handlers.exports(name); - d.usingExports = true; - } else if (depName === "module") { - // CommonJS module spec 1.1 - d.values[i] = d.cjsModule = handlers.module(name); - } else if (depName === undefined) { - d.values[i] = undefined; - } else { - waitForDep(depMap, relName, d, i); - } - }); - d.depending = false; - - // Some modules just depend on the require, exports, modules, so - // trigger their definition here if so. - if (d.depCount === d.depMax) { - defineModule(d); - } - } else if (name) { - // May just be an object definition for the module. Only - // worry about defining if have a module name. - resolve(name, d, factory); - } - - startTime = (new Date()).getTime(); - - if (!name) { - check(d); - } - - return d.promise; - }; - - req = makeRequire(null, true); - - /* - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - if (cfg.context && cfg.context !== contextName) { - var existingContext = getOwn(contexts, cfg.context); - if (existingContext) { - return existingContext.req.config(cfg); - } else { - return newContext(cfg.context).config(cfg); - } - } - - // Since config changed, mapCache may not be valid any more. - mapCache = obj(); - - // Make sure the baseUrl ends in a slash. - if (cfg.baseUrl) { - if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { - cfg.baseUrl += '/'; - } - } - - // Convert old style urlArgs string to a function. - if (typeof cfg.urlArgs === 'string') { - var urlArgs = cfg.urlArgs; - cfg.urlArgs = function(id, url) { - return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs; - }; - } - - // Save off the paths and packages since they require special processing, - // they are additive. - var shim = config.shim, - objs = { - paths: true, - bundles: true, - config: true, - map: true - }; - - eachProp(cfg, function (value, prop) { - if (objs[prop]) { - if (!config[prop]) { - config[prop] = {}; - } - mixin(config[prop], value, true, true); - } else { - config[prop] = value; - } - }); - - // Reverse map the bundles - if (cfg.bundles) { - eachProp(cfg.bundles, function (value, prop) { - value.forEach(function (v) { - if (v !== prop) { - bundlesMap[v] = prop; - } - }); - }); - } - - // Merge shim - if (cfg.shim) { - eachProp(cfg.shim, function (value, id) { - // Normalize the structure - if (Array.isArray(value)) { - value = { - deps: value - }; - } - if ((value.exports || value.init) && !value.exportsFn) { - value.exportsFn = makeShimExports(value); - } - shim[id] = value; - }); - config.shim = shim; - } - - // Adjust packages if necessary. - if (cfg.packages) { - cfg.packages.forEach(function (pkgObj) { - var location, name; - - pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; - - name = pkgObj.name; - location = pkgObj.location; - if (location) { - config.paths[name] = pkgObj.location; - } - - // Save pointer to main module ID for pkg name. - // Remove leading dot in main, so main paths are normalized, - // and remove any trailing .js, since different package - // envs have different conventions: some use a module name, - // some use a file name. - config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main') - .replace(currDirRegExp, '') - .replace(jsSuffixRegExp, ''); - }); - } - - // If a deps array or a config callback is specified, then call - // require with those args. This is useful when require is defined as a - // config object before require.js is loaded. - if (cfg.deps || cfg.callback) { - req(cfg.deps, cfg.callback); - } - - return req; - }; - - req.onError = function (err) { - throw err; - }; - - context = { - id: contextName, - defined: defined, - waiting: waiting, - config: config, - deferreds: deferreds, - req: req, - execCb: function execCb(name, callback, args, exports) { - return callback.apply(exports, args); - } - }; - - contexts[contextName] = context; - - return req; - } - - requirejs = topReq = newContext('_'); - - if (typeof require !== 'function') { - require = topReq; - } - - /** - * Executes the text. Normally just uses eval, but can be modified - * to use a better, environment-specific call. Only used for transpiling - * loader plugins, not for plain JS modules. - * @param {String} text the text to execute/evaluate. - */ - topReq.exec = function (text) { - /*jslint evil: true */ - return eval(text); - }; - - topReq.contexts = contexts; - - define = function () { - queue.push(slice.call(arguments, 0)); - }; - - define.amd = { - jQuery: true - }; - - if (bootstrapConfig) { - topReq.config(bootstrapConfig); - } - - // data-main support. - if (topReq.isBrowser && !contexts._.config.skipDataMain) { - dataMain = document.querySelectorAll('script[data-main]')[0]; - dataMain = dataMain && dataMain.getAttribute('data-main'); - if (dataMain) { - // Strip off any trailing .js since dataMain is now - // like a module name. - dataMain = dataMain.replace(jsSuffixRegExp, ''); - - // Set final baseUrl if there is not already an explicit one, - // but only do so if the data-main value is not a loader plugin - // module ID. - if ((!bootstrapConfig || !bootstrapConfig.baseUrl) && - dataMain.indexOf('!') === -1) { - // Pull off the directory of data-main for use as the - // baseUrl. - src = dataMain.split('/'); - dataMain = src.pop(); - subPath = src.length ? src.join('/') + '/' : './'; - - topReq.config({baseUrl: subPath}); - } - - topReq([dataMain]); - } - } -}(this, (typeof Promise !== 'undefined' ? Promise : undefined))); - -define("requireLib", function(){}); - -//noinspection JSUnresolvedVariable -requirejs.config({ - paths: { - enquire: '3rdParty/enquire', - favico: '3rdParty/favico', - 'perfect-scrollbar': '3rdParty/perfect-scrollbar', - 'Pica': '3rdParty/pica', - prism: '3rdParty/prism', - }, - shim: { - enquire: { exports: 'enquire' }, - favico: { exports: 'Favico' }, - 'perfect-scrollbar': { exports: 'PerfectScrollbar' } - }, - map: { - '*': { - 'Ajax': 'WoltLabSuite/Core/Ajax', - 'AjaxJsonp': 'WoltLabSuite/Core/Ajax/Jsonp', - 'AjaxRequest': 'WoltLabSuite/Core/Ajax/Request', - 'CallbackList': 'WoltLabSuite/Core/CallbackList', - 'ColorUtil': 'WoltLabSuite/Core/ColorUtil', - 'Core': 'WoltLabSuite/Core/Core', - 'DateUtil': 'WoltLabSuite/Core/Date/Util', - 'Devtools': 'WoltLabSuite/Core/Devtools', - 'Dictionary': 'WoltLabSuite/Core/Dictionary', - 'Dom/ChangeListener': 'WoltLabSuite/Core/Dom/Change/Listener', - 'Dom/Traverse': 'WoltLabSuite/Core/Dom/Traverse', - 'Dom/Util': 'WoltLabSuite/Core/Dom/Util', - 'Environment': 'WoltLabSuite/Core/Environment', - 'EventHandler': 'WoltLabSuite/Core/Event/Handler', - 'EventKey': 'WoltLabSuite/Core/Event/Key', - 'Language': 'WoltLabSuite/Core/Language', - 'List': 'WoltLabSuite/Core/List', - 'ObjectMap': 'WoltLabSuite/Core/ObjectMap', - 'Permission': 'WoltLabSuite/Core/Permission', - 'StringUtil': 'WoltLabSuite/Core/StringUtil', - 'Ui/Alignment': 'WoltLabSuite/Core/Ui/Alignment', - 'Ui/CloseOverlay': 'WoltLabSuite/Core/Ui/CloseOverlay', - 'Ui/Confirmation': 'WoltLabSuite/Core/Ui/Confirmation', - 'Ui/Dialog': 'WoltLabSuite/Core/Ui/Dialog', - 'Ui/Notification': 'WoltLabSuite/Core/Ui/Notification', - 'Ui/ReusableDropdown': 'WoltLabSuite/Core/Ui/Dropdown/Reusable', - 'Ui/Screen': 'WoltLabSuite/Core/Ui/Screen', - 'Ui/Scroll': 'WoltLabSuite/Core/Ui/Scroll', - 'Ui/SimpleDropdown': 'WoltLabSuite/Core/Ui/Dropdown/Simple', - 'Ui/TabMenu': 'WoltLabSuite/Core/Ui/TabMenu', - 'Upload': 'WoltLabSuite/Core/Upload', - 'User': 'WoltLabSuite/Core/User' - } - }, - waitSeconds: 0 -}); - -/* Define jQuery shim. We cannot use the shim object in the configuration above, - because it tries to load the file, even if the exported global already exists. - This shim is needed for jQuery plugins supporting an AMD loaded jQuery, because - we break the AMD support of jQuery for BC reasons. -*/ -define('jquery', [],function() { - return window.jQuery; -}); - - -define("require.config", function(){}); - -/** - * Collection of global short hand functions. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - */ -(function(window, document) { - /** - * Shorthand function to retrieve or set an attribute. - * - * @param {Element} element target element - * @param {string} attribute attribute name - * @param {?=} value attribute value, omit if attribute should be read - * @return {(string|undefined)} attribute value, empty string if attribute is not set or undefined if `value` was omitted - */ - window.elAttr = function(element, attribute, value) { - if (value === undefined) { - return element.getAttribute(attribute) || ''; - } - - element.setAttribute(attribute, value); - }; - - /** - * Shorthand function to retrieve a boolean attribute. - * - * @param {Element} element target element - * @param {string} attribute attribute name - * @return {boolean} true if value is either `1` or `true` - */ - window.elAttrBool = function(element, attribute) { - var value = elAttr(element, attribute); - - return (value === "1" || value === "true"); - }; - - /** - * Shorthand function to find elements by class name. - * - * @param {string} className CSS class name - * @param {Element=} context target element, assuming `document` if omitted - * @return {NodeList} matching elements - */ - window.elByClass = function(className, context) { - return (context || document).getElementsByClassName(className); - }; - - /** - * Shorthand function to retrieve an element by id. - * - * @param {string} id element id - * @return {(Element|null)} matching element or null if not found - */ - window.elById = function(id) { - return document.getElementById(id); - }; - - /** - * Shorthand function to find an element by CSS selector. - * - * @param {string} selector CSS selector - * @param {Element=} context target element, assuming `document` if omitted - * @return {(Element|null)} matching element or null if no match - */ - window.elBySel = function(selector, context) { - return (context || document).querySelector(selector); - }; - - /** - * Shorthand function to find elements by CSS selector. - * - * @param {string} selector CSS selector - * @param {Element=} context target element, assuming `document` if omitted - * @param {function=} callback callback function passed to forEach() - * @return {NodeList} matching elements - */ - window.elBySelAll = function(selector, context, callback) { - var nodeList = (context || document).querySelectorAll(selector); - if (typeof callback === 'function') { - Array.prototype.forEach.call(nodeList, callback); - } - - return nodeList; - }; - - /** - * Shorthand function to find elements by tag name. - * - * @param {string} tagName element tag name - * @param {Element=} context target element, assuming `document` if omitted - * @return {NodeList} matching elements - */ - window.elByTag = function(tagName, context) { - return (context || document).getElementsByTagName(tagName); - }; - - /** - * Shorthand function to create a DOM element. - * - * @param {string} tagName element tag name - * @return {Element} new DOM element - */ - window.elCreate = function(tagName) { - return document.createElement(tagName); - }; - - /** - * Returns the closest element (parent for text nodes), optionally matching - * the provided selector. - * - * @param {Node} node start node - * @param {string=} selector optional CSS selector - * @return {Element} closest matching element - */ - window.elClosest = function (node, selector) { - if (!(node instanceof Node)) { - throw new TypeError('Provided element is not a Node.'); - } - - // retrieve the parent element for text nodes - if (node.nodeType === Node.TEXT_NODE) { - node = node.parentNode; - - // text node had no parent - if (node === null) return null; - } - - if (typeof selector !== 'string') selector = ''; - - if (selector.length === 0) return node; - - return node.closest(selector); - }; - - /** - * Shorthand function to retrieve or set a 'data-' attribute. - * - * @param {Element} element target element - * @param {string} attribute attribute name - * @param {?=} value attribute value, omit if attribute should be read - * @return {(string|undefined)} attribute value, empty string if attribute is not set or undefined if `value` was omitted - */ - window.elData = function(element, attribute, value) { - attribute = 'data-' + attribute; - - if (value === undefined) { - return element.getAttribute(attribute) || ''; - } - - element.setAttribute(attribute, value); - }; - - /** - * Shorthand function to retrieve a boolean 'data-' attribute. - * - * @param {Element} element target element - * @param {string} attribute attribute name - * @return {boolean} true if value is either `1` or `true` - */ - window.elDataBool = function(element, attribute) { - var value = elData(element, attribute); - - return (value === "1" || value === "true"); - }; - - /** - * Shorthand function to hide an element by setting its 'display' value to 'none'. - * - * @param {Element} element DOM element - */ - window.elHide = function(element) { - element.style.setProperty('display', 'none', ''); - }; - - /** - * Shorthand function to check if given element is hidden by setting its 'display' - * value to 'none'. - * - * @param {Element} element DOM element - * @return {boolean} - */ - window.elIsHidden = function(element) { - return element.style.getPropertyValue('display') === 'none'; - } - - /** - * Displays or removes an error message below the provided element. - * - * @param {Element} element DOM element - * @param {string?} errorMessage error message; `false`, `null` and `undefined` are treated as an empty string - * @param {boolean?} isHtml defaults to false, causes `errorMessage` to be treated as text only - * @return {?Element} the inner error element or null if it was removed - */ - window.elInnerError = function (element, errorMessage, isHtml) { - var parent = element.parentNode; - if (parent === null) { - throw new Error('Only elements that have a parent element or document are valid.'); - } - - if (typeof errorMessage !== 'string') { - if (errorMessage === undefined || errorMessage === null || errorMessage === false) { - errorMessage = ''; - } - else { - throw new TypeError('The error message must be a string; `false`, `null` or `undefined` can be used as a substitute for an empty string.'); - } - } - - var innerError = element.nextElementSibling; - if (innerError === null || innerError.nodeName !== 'SMALL' || !innerError.classList.contains('innerError')) { - if (errorMessage === '') { - innerError = null; - } - else { - innerError = elCreate('small'); - innerError.className = 'innerError'; - parent.insertBefore(innerError, element.nextSibling); - } - } - - if (errorMessage === '') { - if (innerError !== null) { - parent.removeChild(innerError); - innerError = null; - } - } - else { - innerError[(isHtml ? 'innerHTML' : 'textContent')] = errorMessage; - } - - return innerError; - }; - - /** - * Shorthand function to remove an element. - * - * @param {Node} element DOM node - */ - window.elRemove = function(element) { - element.parentNode.removeChild(element); - }; - - /** - * Shorthand function to show an element previously hidden by using `elHide()`. - * - * @param {Element} element DOM element - */ - window.elShow = function(element) { - element.style.removeProperty('display'); - }; - - /** - * Toggles visibility of an element using the display style. - * - * @param {Element} element DOM element - */ - window.elToggle = function (element) { - if (element.style.getPropertyValue('display') === 'none') { - elShow(element); - } - else { - elHide(element); - } - }; - - /** - * Shorthand function to iterative over an array-like object, arguments passed are the value and the index second. - * - * Do not use this function if a simple `for()` is enough or `list` is a plain object. - * - * @param {object} list array-like object - * @param {function} callback callback function - */ - window.forEach = function(list, callback) { - for (var i = 0, length = list.length; i < length; i++) { - callback(list[i], i); - } - }; - - /** - * Shorthand function to check if an object has a property while ignoring the chain. - * - * @param {object} obj target object - * @param {string} property property name - * @return {boolean} false if property does not exist or belongs to the chain - */ - window.objOwns = function(obj, property) { - return obj.hasOwnProperty(property); - }; - - /* assigns a global constant defining the proper 'click' event depending on the browser, - enforcing 'touchstart' on mobile devices for a better UX. We're using defineProperty() - here because at the time of writing Safari does not support 'const'. Thanks Safari. - */ - var clickEvent = ('touchstart' in document.documentElement || 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0) ? 'touchstart' : 'click'; - Object.defineProperty(window, 'WCF_CLICK_EVENT', { - value: 'click' //clickEvent - }); - - /* Overwrites any history states after 'initial' with 'skip' on initial page load. - This is done, as the necessary DOM of other history states may not exist any more. - On forward navigation these 'skip' states are automatically skipped, otherwise the - user might have to press the forward button several times. - Note: A 'skip' state cannot be hit in the 'popstate' event when navigation backwards, - because the history already is left of all the 'skip' states for the current page. - Note 2: Setting the URL component of `history.replaceState()` to an empty string will - cause the Internet Explorer to discard the path and query string from the - address bar. - */ - (function() { - var stateDepth = 0; - function check() { - if (window.history.state && window.history.state.name && window.history.state.name !== 'initial') { - window.history.replaceState({ - name: 'skip', - depth: ++stateDepth - }, ''); - window.history.back(); - - // window.history does not update in this iteration of the event loop - setTimeout(check, 1); - } - else { - window.history.replaceState({name: 'initial'}, ''); - } - } - check(); - - window.addEventListener('popstate', function(event) { - if (event.state && event.state.name && event.state.name === 'skip') { - window.history.go(event.state.depth); - } - }); - })(); - - /** - * Provides a hashCode() method for strings, similar to Java's String.hashCode(). - * - * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ - */ - window.String.prototype.hashCode = function() { - var $char; - var $hash = 0; - - if (this.length) { - for (var $i = 0, $length = this.length; $i < $length; $i++) { - $char = this.charCodeAt($i); - $hash = (($hash << 5) - $hash) + $char; - $hash = $hash & $hash; // convert to 32bit integer - } - } - - return $hash; - }; -})(window, document); - -define("wcf.globalHelper", function(){}); - -/** - * Provides the basic core functionality. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Core - */ -define('WoltLabSuite/Core/Core',[], function() { - "use strict"; - - var _clone = function(variable) { - if (typeof variable === 'object' && (Array.isArray(variable) || Core.isPlainObject(variable))) { - return _cloneObject(variable); - } - - return variable; - }; - - var _cloneObject = function(obj) { - if (!obj) { - return null; - } - - if (Array.isArray(obj)) { - return obj.slice(); - } - - var newObj = {}; - for (var key in obj) { - if (obj.hasOwnProperty(key) && typeof obj[key] !== 'undefined') { - newObj[key] = _clone(obj[key]); - } - } - - return newObj; - }; - - //noinspection JSUnresolvedVariable - var _prefix = 'wsc' + window.WCF_PATH.hashCode() + '-'; - - /** - * @exports WoltLabSuite/Core/Core - */ - var Core = { - /** - * Deep clones an object. - * - * @param {object} obj source object - * @return {object} cloned object - */ - clone: function(obj) { - return _clone(obj); - }, - - /** - * Converts WCF 2.0-style URLs into the default URL layout. - * - * @param string url target url - * @return rewritten url - */ - convertLegacyUrl: function(url) { - return url.replace(/^index\.php\/(.*?)\/\?/, function(match, controller) { - var parts = controller.split(/([A-Z][a-z0-9]+)/); - controller = ''; - for (var i = 0, length = parts.length; i < length; i++) { - var part = parts[i].trim(); - if (part.length) { - if (controller.length) controller += '-'; - controller += part.toLowerCase(); - } - } - - return 'index.php?' + controller + '/&'; - }); - }, - - /** - * Merges objects with the first argument. - * - * @param {object} out destination object - * @param {...object} arguments variable number of objects to be merged into the destination object - * @return {object} destination object with all provided objects merged into - */ - extend: function(out) { - out = out || {}; - var newObj = this.clone(out); - - for (var i = 1, length = arguments.length; i < length; i++) { - var obj = arguments[i]; - - if (!obj) continue; - - for (var key in obj) { - if (objOwns(obj, key)) { - if (!Array.isArray(obj[key]) && typeof obj[key] === 'object') { - if (this.isPlainObject(obj[key])) { - // object literals have the prototype of Object which in return has no parent prototype - newObj[key] = this.extend(out[key], obj[key]); - } - else { - newObj[key] = obj[key]; - } - } - else { - newObj[key] = obj[key]; - } - } - } - } - - return newObj; - }, - - /** - * Inherits the prototype methods from one constructor to another - * constructor. - * - * Usage: - * - * function MyDerivedClass() {} - * Core.inherit(MyDerivedClass, TheAwesomeBaseClass, { - * // regular prototype for `MyDerivedClass` - * - * overwrittenMethodFromBaseClass: function(foo, bar) { - * // do stuff - * - * // invoke parent - * MyDerivedClass._super.prototype.overwrittenMethodFromBaseClass.call(this, foo, bar); - * } - * }); - * - * @see https://github.com/nodejs/node/blob/7d14dd9b5e78faabb95d454a79faa513d0bbc2a5/lib/util.js#L697-L735 - * @param {function} constructor inheriting constructor function - * @param {function} superConstructor inherited constructor function - * @param {object=} propertiesObject additional prototype properties - */ - inherit: function(constructor, superConstructor, propertiesObject) { - if (constructor === undefined || constructor === null) { - throw new TypeError("The constructor must not be undefined or null."); - } - if (superConstructor === undefined || superConstructor === null) { - throw new TypeError("The super constructor must not be undefined or null."); - } - if (superConstructor.prototype === undefined) { - throw new TypeError("The super constructor must have a prototype."); - } - - constructor._super = superConstructor; - constructor.prototype = Core.extend(Object.create(superConstructor.prototype, { - constructor: { - configurable: true, - enumerable: false, - value: constructor, - writable: true - } - }), propertiesObject || {}); - }, - - /** - * Returns true if `obj` is an object literal. - * - * @param {*} obj target object - * @returns {boolean} true if target is an object literal - */ - isPlainObject: function(obj) { - if (typeof obj !== 'object' || obj === null || obj.nodeType) { - return false; - } - - return (Object.getPrototypeOf(obj) === Object.prototype); - }, - - /** - * Returns the object's class name. - * - * @param {object} obj target object - * @return {string} object class name - */ - getType: function(obj) { - return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1'); - }, - - /** - * Returns a RFC4122 version 4 compilant UUID. - * - * @see http://stackoverflow.com/a/2117523 - * @return {string} - */ - getUuid: function() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); - return v.toString(16); - }); - }, - - /** - * Recursively serializes an object into an encoded URI parameter string. - * - * @param {object} obj target object - * @param {string=} prefix parameter prefix - * @return {string} encoded parameter string - */ - serialize: function(obj, prefix) { - var parameters = []; - - for (var key in obj) { - if (objOwns(obj, key)) { - var parameterKey = (prefix) ? prefix + '[' + key + ']' : key; - var value = obj[key]; - - if (typeof value === 'object') { - parameters.push(this.serialize(value, parameterKey)); - } - else { - parameters.push(encodeURIComponent(parameterKey) + '=' + encodeURIComponent(value)); - } - } - } - - return parameters.join('&'); - }, - - /** - * Triggers a custom or built-in event. - * - * @param {Element} element target element - * @param {string} eventName event name - */ - triggerEvent: function(element, eventName) { - var event; - - try { - event = new Event(eventName, { - bubbles: true, - cancelable: true - }); - } - catch (e) { - event = document.createEvent('Event'); - event.initEvent(eventName, true, true); - } - - element.dispatchEvent(event); - }, - - /** - * Returns the unique prefix for the localStorage. - * - * @return {string} prefix for the localStorage - */ - getStoragePrefix: function() { - return _prefix; - } - }; - - return Core; -}); - -/** - * Dictionary implementation relying on an object or if supported on a Map to hold key => value data. - * - * If you're looking for a dictionary with object keys, please see `WoltLabSuite/Core/ObjectMap`. - * - * @author Tim Duesterhus, Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Dictionary - */ -define('WoltLabSuite/Core/Dictionary',['Core'], function(Core) { - "use strict"; - - var _hasMap = objOwns(window, 'Map') && typeof window.Map === 'function'; - - /** - * @constructor - */ - function Dictionary() { - this._dictionary = (_hasMap) ? new Map() : {}; - } - Dictionary.prototype = { - /** - * Sets a new key with given value, will overwrite an existing key. - * - * @param {(number|string)} key key - * @param {?} value value - */ - set: function(key, value) { - if (typeof key === 'number') key = key.toString(); - - if (typeof key !== "string") { - throw new TypeError("Only strings can be used as keys, rejected '" + key + "' (" + typeof key + ")."); - } - - if (_hasMap) this._dictionary.set(key, value); - else this._dictionary[key] = value; - }, - - /** - * Removes a key from the dictionary. - * - * @param {(number|string)} key key - */ - 'delete': function(key) { - if (typeof key === 'number') key = key.toString(); - - if (_hasMap) this._dictionary['delete'](key); - else this._dictionary[key] = undefined; - }, - - /** - * Returns true if dictionary contains a value for given key and is not undefined. - * - * @param {(number|string)} key key - * @return {boolean} true if key exists and value is not undefined - */ - has: function(key) { - if (typeof key === 'number') key = key.toString(); - - if (_hasMap) return this._dictionary.has(key); - else { - return (objOwns(this._dictionary, key) && typeof this._dictionary[key] !== "undefined"); - } - }, - - /** - * Retrieves a value by key, returns undefined if there is no match. - * - * @param {(number|string)} key key - * @return {*} - */ - get: function(key) { - if (typeof key === 'number') key = key.toString(); - - if (this.has(key)) { - if (_hasMap) return this._dictionary.get(key); - else return this._dictionary[key]; - } - - return undefined; - }, - - /** - * Iterates over the dictionary keys and values, callback function should expect the - * value as first parameter and the key name second. - * - * @param {function<*, string>} callback callback for each iteration - */ - forEach: function(callback) { - if (typeof callback !== "function") { - throw new TypeError("forEach() expects a callback as first parameter."); - } - - if (_hasMap) { - this._dictionary.forEach(callback); - } - else { - var keys = Object.keys(this._dictionary); - for (var i = 0, length = keys.length; i < length; i++) { - callback(this._dictionary[keys[i]], keys[i]); - } - } - }, - - /** - * Merges one or more Dictionary instances into this one. - * - * @param {...Dictionary} var_args one or more Dictionary instances - */ - merge: function() { - for (var i = 0, length = arguments.length; i < length; i++) { - var dictionary = arguments[i]; - if (!(dictionary instanceof Dictionary)) { - throw new TypeError("Expected an object of type Dictionary, but argument " + i + " is not."); - } - - dictionary.forEach((function(value, key) { - this.set(key, value); - }).bind(this)); - } - }, - - /** - * Returns the object representation of the dictionary. - * - * @return {object} dictionary's object representation - */ - toObject: function() { - if (!_hasMap) return Core.clone(this._dictionary); - - var object = { }; - this._dictionary.forEach(function(value, key) { - object[key] = value; - }); - - return object; - } - }; - - /** - * Creates a new Dictionary based on the given object. - * All properties that are owned by the object will be added - * as keys to the resulting Dictionary. - * - * @param {object} object - * @return {Dictionary} - */ - Dictionary.fromObject = function(object) { - var result = new Dictionary(); - - for (var key in object) { - if (objOwns(object, key)) { - result.set(key, object[key]); - } - } - - return result; - }; - - Object.defineProperty(Dictionary.prototype, 'size', { - enumerable: false, - configurable: true, - get: function() { - if (_hasMap) { - return this._dictionary.size; - } - else { - return Object.keys(this._dictionary).length; - } - } - }); - - return Dictionary; -}); - - - -define('WoltLabSuite/Core/Template.grammar',['require'],function(require){ -var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,37],$V1=[5,9,11,12,13,18,19,21,22,23,25,26,27,28,30,31,32,33,35,37,39],$V2=[1,24],$V3=[1,25],$V4=[1,31],$V5=[1,29],$V6=[1,30],$V7=[1,26],$V8=[1,27],$V9=[1,33],$Va=[11,12,15,40,41,45,47,49,50,52],$Vb=[9,11,12,13,18,19,21,23,26,28,30,31,32,33,35,37],$Vc=[11,12,15,40,41,44,45,46,47,49,50,52],$Vd=[18,35,37],$Ve=[12,15]; -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"TEMPLATE":3,"CHUNK_STAR":4,"EOF":5,"CHUNK_STAR_repetition0":6,"CHUNK":7,"PLAIN_ANY":8,"T_LITERAL":9,"COMMAND":10,"T_ANY":11,"T_WS":12,"{if":13,"COMMAND_PARAMETERS":14,"}":15,"COMMAND_repetition0":16,"COMMAND_option0":17,"{/if}":18,"{include":19,"COMMAND_PARAMETER_LIST":20,"{implode":21,"{/implode}":22,"{foreach":23,"COMMAND_option1":24,"{/foreach}":25,"{lang}":26,"{/lang}":27,"{":28,"VARIABLE":29,"{#":30,"{@":31,"{ldelim}":32,"{rdelim}":33,"ELSE":34,"{else}":35,"ELSE_IF":36,"{elseif":37,"FOREACH_ELSE":38,"{foreachelse}":39,"T_VARIABLE":40,"T_VARIABLE_NAME":41,"VARIABLE_repetition0":42,"VARIABLE_SUFFIX":43,"[":44,"]":45,".":46,"(":47,"VARIABLE_SUFFIX_option0":48,")":49,"=":50,"COMMAND_PARAMETER_VALUE":51,"T_QUOTED_STRING":52,"COMMAND_PARAMETERS_repetition_plus0":53,"COMMAND_PARAMETER":54,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOF",9:"T_LITERAL",11:"T_ANY",12:"T_WS",13:"{if",15:"}",18:"{/if}",19:"{include",21:"{implode",22:"{/implode}",23:"{foreach",25:"{/foreach}",26:"{lang}",27:"{/lang}",28:"{",30:"{#",31:"{@",32:"{ldelim}",33:"{rdelim}",35:"{else}",37:"{elseif",39:"{foreachelse}",40:"T_VARIABLE",41:"T_VARIABLE_NAME",44:"[",45:"]",46:".",47:"(",49:")",50:"=",52:"T_QUOTED_STRING"}, -productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[8,1],[8,1],[10,7],[10,3],[10,5],[10,6],[10,3],[10,3],[10,3],[10,3],[10,1],[10,1],[34,2],[36,4],[38,2],[29,3],[43,3],[43,2],[43,3],[20,5],[20,3],[51,1],[51,1],[14,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,3],[6,0],[6,2],[16,0],[16,2],[17,0],[17,1],[24,0],[24,1],[42,0],[42,2],[48,0],[48,1],[53,1],[53,2]], -performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { -/* this == yyval */ - -var $0 = $$.length - 1; -switch (yystate) { -case 1: - return $$[$0-1] + ";"; -break; -case 2: - - var result = $$[$0].reduce(function (carry, item) { - if (item.encode && !carry[1]) carry[0] += " + '" + item.value; - else if (item.encode && carry[1]) carry[0] += item.value; - else if (!item.encode && carry[1]) carry[0] += "' + " + item.value; - else if (!item.encode && !carry[1]) carry[0] += " + " + item.value; - - carry[1] = item.encode; - return carry; - }, [ "''", false ]); - if (result[1]) result[0] += "'"; - - this.$ = result[0]; - -break; -case 3: case 4: -this.$ = { encode: true, value: $$[$0].replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/(\r\n|\n|\r)/g, '\\n') }; -break; -case 5: -this.$ = { encode: false, value: $$[$0] }; -break; -case 8: - - this.$ = "(function() { if (" + $$[$0-5] + ") { return " + $$[$0-3] + "; } " + $$[$0-2].join(' ') + " " + ($$[$0-1] || '') + " return ''; })()"; - -break; -case 9: - - if (!$$[$0-1]['file']) throw new Error('Missing parameter file'); - - this.$ = $$[$0-1]['file'] + ".fetch(v)"; - -break; -case 10: - - if (!$$[$0-3]['from']) throw new Error('Missing parameter from'); - if (!$$[$0-3]['item']) throw new Error('Missing parameter item'); - if (!$$[$0-3]['glue']) $$[$0-3]['glue'] = "', '"; - - this.$ = "(function() { return " + $$[$0-3]['from'] + ".map(function(item) { v[" + $$[$0-3]['item'] + "] = item; return " + $$[$0-1] + "; }).join(" + $$[$0-3]['glue'] + "); })()"; - -break; -case 11: - - if (!$$[$0-4]['from']) throw new Error('Missing parameter from'); - if (!$$[$0-4]['item']) throw new Error('Missing parameter item'); - - this.$ = "(function() {" - + "var looped = false, result = '';" - + "if (" + $$[$0-4]['from'] + " instanceof Array) {" - + "for (var i = 0; i < " + $$[$0-4]['from'] + ".length; i++) { looped = true;" - + "v[" + $$[$0-4]['key'] + "] = i;" - + "v[" + $$[$0-4]['item'] + "] = " + $$[$0-4]['from'] + "[i];" - + "result += " + $$[$0-2] + ";" - + "}" - + "} else {" - + "for (var key in " + $$[$0-4]['from'] + ") {" - + "if (!" + $$[$0-4]['from'] + ".hasOwnProperty(key)) continue;" - + "looped = true;" - + "v[" + $$[$0-4]['key'] + "] = key;" - + "v[" + $$[$0-4]['item'] + "] = " + $$[$0-4]['from'] + "[key];" - + "result += " + $$[$0-2] + ";" - + "}" - + "}" - + "return (looped ? result : " + ($$[$0-1] || "''") + "); })()" - -break; -case 12: -this.$ = "Language.get(" + $$[$0-1] + ", v)"; -break; -case 13: -this.$ = "StringUtil.escapeHTML(" + $$[$0-1] + ")"; -break; -case 14: -this.$ = "StringUtil.formatNumeric(" + $$[$0-1] + ")"; -break; -case 15: -this.$ = $$[$0-1]; -break; -case 16: -this.$ = "'{'"; -break; -case 17: -this.$ = "'}'"; -break; -case 18: -this.$ = "else { return " + $$[$0] + "; }"; -break; -case 19: -this.$ = "else if (" + $$[$0-2] + ") { return " + $$[$0] + "; }"; -break; -case 20: -this.$ = $$[$0]; -break; -case 21: -this.$ = "v['" + $$[$0-1] + "']" + $$[$0].join('');; -break; -case 22: -this.$ = $$[$0-2] + $$[$0-1] + $$[$0]; -break; -case 23: -this.$ = "['" + $$[$0] + "']"; -break; -case 24: case 36: -this.$ = $$[$0-2] + ($$[$0-1] || '') + $$[$0]; -break; -case 25: - this.$ = $$[$0]; this.$[$$[$0-4]] = $$[$0-2]; -break; -case 26: - this.$ = {}; this.$[$$[$0-2]] = $$[$0]; -break; -case 29: -this.$ = $$[$0].join(''); -break; -case 37: case 39: case 45: -this.$ = []; -break; -case 38: case 40: case 46: case 50: -$$[$0-1].push($$[$0]); -break; -case 49: -this.$ = [$$[$0]]; -break; -} -}, -table: [o([5,9,11,12,13,19,21,23,26,28,30,31,32,33],$V0,{3:1,4:2,6:3}),{1:[3]},{5:[1,4]},o([5,18,22,25,27,35,37,39],[2,2],{7:5,8:6,10:8,9:[1,7],11:[1,9],12:[1,10],13:[1,11],19:[1,12],21:[1,13],23:[1,14],26:[1,15],28:[1,16],30:[1,17],31:[1,18],32:[1,19],33:[1,20]}),{1:[2,1]},o($V1,[2,38]),o($V1,[2,3]),o($V1,[2,4]),o($V1,[2,5]),o($V1,[2,6]),o($V1,[2,7]),{11:$V2,12:$V3,14:21,29:28,40:$V4,41:$V5,47:$V6,50:$V7,52:$V8,53:22,54:23},{20:32,41:$V9},{20:34,41:$V9},{20:35,41:$V9},o([9,11,12,13,19,21,23,26,27,28,30,31,32,33],$V0,{6:3,4:36}),{29:37,40:$V4},{29:38,40:$V4},{29:39,40:$V4},o($V1,[2,16]),o($V1,[2,17]),{15:[1,40]},o([15,45,49],[2,29],{29:28,54:41,11:$V2,12:$V3,40:$V4,41:$V5,47:$V6,50:$V7,52:$V8}),o($Va,[2,49]),o($Va,[2,30]),o($Va,[2,31]),o($Va,[2,32]),o($Va,[2,33]),o($Va,[2,34]),o($Va,[2,35]),{11:$V2,12:$V3,14:42,29:28,40:$V4,41:$V5,47:$V6,50:$V7,52:$V8,53:22,54:23},{41:[1,43]},{15:[1,44]},{50:[1,45]},{15:[1,46]},{15:[1,47]},{27:[1,48]},{15:[1,49]},{15:[1,50]},{15:[1,51]},o($Vb,$V0,{6:3,4:52}),o($Va,[2,50]),{49:[1,53]},o($Vc,[2,45],{42:54}),o($V1,[2,9]),{29:57,40:$V4,51:55,52:[1,56]},o([9,11,12,13,19,21,22,23,26,28,30,31,32,33],$V0,{6:3,4:58}),o([9,11,12,13,19,21,23,25,26,28,30,31,32,33,39],$V0,{6:3,4:59}),o($V1,[2,12]),o($V1,[2,13]),o($V1,[2,14]),o($V1,[2,15]),o($Vd,[2,39],{16:60}),o($Va,[2,36]),o([11,12,15,40,41,45,49,50,52],[2,21],{43:61,44:[1,62],46:[1,63],47:[1,64]}),{12:[1,65],15:[2,26]},o($Ve,[2,27]),o($Ve,[2,28]),{22:[1,66]},{24:67,25:[2,43],38:68,39:[1,69]},{17:70,18:[2,41],34:72,35:[1,74],36:71,37:[1,73]},o($Vc,[2,46]),{11:$V2,12:$V3,14:75,29:28,40:$V4,41:$V5,47:$V6,50:$V7,52:$V8,53:22,54:23},{41:[1,76]},{11:$V2,12:$V3,14:78,29:28,40:$V4,41:$V5,47:$V6,48:77,49:[2,47],50:$V7,52:$V8,53:22,54:23},{20:79,41:$V9},o($V1,[2,10]),{25:[1,80]},{25:[2,44]},o([9,11,12,13,19,21,23,25,26,28,30,31,32,33],$V0,{6:3,4:81}),{18:[1,82]},o($Vd,[2,40]),{18:[2,42]},{11:$V2,12:$V3,14:83,29:28,40:$V4,41:$V5,47:$V6,50:$V7,52:$V8,53:22,54:23},o([9,11,12,13,18,19,21,23,26,28,30,31,32,33],$V0,{6:3,4:84}),{45:[1,85]},o($Vc,[2,23]),{49:[1,86]},{49:[2,48]},{15:[2,25]},o($V1,[2,11]),{25:[2,20]},o($V1,[2,8]),{15:[1,87]},{18:[2,18]},o($Vc,[2,22]),o($Vc,[2,24]),o($Vb,$V0,{6:3,4:88}),o($Vd,[2,19])], -defaultActions: {4:[2,1],68:[2,44],72:[2,42],78:[2,48],79:[2,25],81:[2,20],84:[2,18]}, -parseError: function parseError(str, hash) { - if (hash.recoverable) { - this.trace(str); - } else { - function _parseError (msg, hash) { - this.message = msg; - this.hash = hash; - } - _parseError.prototype = Error; - - throw new _parseError(str, hash); - } -}, -parse: function parse(input) { - var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; - var args = lstack.slice.call(arguments, 1); - var lexer = Object.create(this.lexer); - var sharedState = { yy: {} }; - for (var k in this.yy) { - if (Object.prototype.hasOwnProperty.call(this.yy, k)) { - sharedState.yy[k] = this.yy[k]; - } - } - lexer.setInput(input, sharedState.yy); - sharedState.yy.lexer = lexer; - sharedState.yy.parser = this; - if (typeof lexer.yylloc == 'undefined') { - lexer.yylloc = {}; - } - var yyloc = lexer.yylloc; - lstack.push(yyloc); - var ranges = lexer.options && lexer.options.ranges; - if (typeof sharedState.yy.parseError === 'function') { - this.parseError = sharedState.yy.parseError; - } else { - this.parseError = Object.getPrototypeOf(this).parseError; - } - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - _token_stack: - var lex = function () { - var token; - token = lexer.lex() || EOF; - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - }; - var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol === null || typeof symbol == 'undefined') { - symbol = lex(); - } - action = table[state] && table[state][symbol]; - } - if (typeof action === 'undefined' || !action.length || !action[0]) { - var errStr = ''; - expected = []; - for (p in table[state]) { - if (this.terminals_[p] && p > TERROR) { - expected.push('\'' + this.terminals_[p] + '\''); - } - } - if (lexer.showPosition) { - errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; - } else { - errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); - } - this.parseError(errStr, { - text: lexer.match, - token: this.terminals_[symbol] || symbol, - line: lexer.yylineno, - loc: yyloc, - expected: expected - }); - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(lexer.yytext); - lstack.push(lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = lexer.yyleng; - yytext = lexer.yytext; - yylineno = lexer.yylineno; - yyloc = lexer.yylloc; - if (recovering > 0) { - recovering--; - } - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = { - first_line: lstack[lstack.length - (len || 1)].first_line, - last_line: lstack[lstack.length - 1].last_line, - first_column: lstack[lstack.length - (len || 1)].first_column, - last_column: lstack[lstack.length - 1].last_column - }; - if (ranges) { - yyval._$.range = [ - lstack[lstack.length - (len || 1)].range[0], - lstack[lstack.length - 1].range[1] - ]; - } - r = this.performAction.apply(yyval, [ - yytext, - yyleng, - yylineno, - sharedState.yy, - action[1], - vstack, - lstack - ].concat(args)); - if (typeof r !== 'undefined') { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -}}; - -/* generated by jison-lex 0.3.4 */ -var lexer = (function(){ -var lexer = ({ - -EOF:1, - -parseError:function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, - -// resets the lexer, sets new input -setInput:function (input, yy) { - this.yy = yy || this.yy || {}; - this._input = input; - this._more = this._backtrack = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = { - first_line: 1, - first_column: 0, - last_line: 1, - last_column: 0 - }; - if (this.options.ranges) { - this.yylloc.range = [0,0]; - } - this.offset = 0; - return this; - }, - -// consumes and returns one char from the input -input:function () { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) { - this.yylloc.range[1]++; - } - - this._input = this._input.slice(1); - return ch; - }, - -// unshifts one char (or a string) into the input -unput:function (ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); - - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length - len); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length - 1); - this.matched = this.matched.substr(0, this.matched.length - 1); - - if (lines.length - 1) { - this.yylineno -= lines.length - 1; - } - var r = this.yylloc.range; - - this.yylloc = { - first_line: this.yylloc.first_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.first_column, - last_column: lines ? - (lines.length === oldLines.length ? this.yylloc.first_column : 0) - + oldLines[oldLines.length - lines.length].length - lines[0].length : - this.yylloc.first_column - len - }; - - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - this.yyleng = this.yytext.length; - return this; - }, - -// When called from action, caches matched text and appends it on next action -more:function () { - this._more = true; - return this; - }, - -// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. -reject:function () { - if (this.options.backtrack_lexer) { - this._backtrack = true; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); - - } - return this; - }, - -// retain first n characters of the match -less:function (n) { - this.unput(this.match.slice(n)); - }, - -// displays already matched input, i.e. for error messages -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, - -// displays upcoming input, i.e. for error messages -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); - }, - -// displays the character position where the lexing error occurred, i.e. for error messages -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c + "^"; - }, - -// test the lexed token: return FALSE when not a match, otherwise return token -test_match:function (match, indexed_rule) { - var token, - lines, - backup; - - if (this.options.backtrack_lexer) { - // save context - backup = { - yylineno: this.yylineno, - yylloc: { - first_line: this.yylloc.first_line, - last_line: this.last_line, - first_column: this.yylloc.first_column, - last_column: this.yylloc.last_column - }, - yytext: this.yytext, - match: this.match, - matches: this.matches, - matched: this.matched, - yyleng: this.yyleng, - offset: this.offset, - _more: this._more, - _input: this._input, - yy: this.yy, - conditionStack: this.conditionStack.slice(0), - done: this.done - }; - if (this.options.ranges) { - backup.yylloc.range = this.yylloc.range.slice(0); - } - } - - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno += lines.length; - } - this.yylloc = { - first_line: this.yylloc.last_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.last_column, - last_column: lines ? - lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : - this.yylloc.last_column + match[0].length - }; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._backtrack = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); - if (this.done && this._input) { - this.done = false; - } - if (token) { - return token; - } else if (this._backtrack) { - // recover context - for (var k in backup) { - this[k] = backup[k]; - } - return false; // rule action called reject() implying the next rule should be tested instead. - } - return false; - }, - -// return next match in input -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) { - this.done = true; - } - - var token, - match, - tempMatch, - index; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i = 0; i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (this.options.backtrack_lexer) { - token = this.test_match(tempMatch, rules[i]); - if (token !== false) { - return token; - } else if (this._backtrack) { - match = false; - continue; // rule action called reject() implying a rule MISmatch. - } else { - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - } else if (!this.options.flex) { - break; - } - } - } - if (match) { - token = this.test_match(match, rules[index]); - if (token !== false) { - return token; - } - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); - } - }, - -// return next match that has a token -lex:function lex() { - var r = this.next(); - if (r) { - return r; - } else { - return this.lex(); - } - }, - -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -begin:function begin(condition) { - this.conditionStack.push(condition); - }, - -// pop the previously active lexer condition state off the condition stack -popState:function popState() { - var n = this.conditionStack.length - 1; - if (n > 0) { - return this.conditionStack.pop(); - } else { - return this.conditionStack[0]; - } - }, - -// produce the lexer rule set which is active for the currently active lexer condition state -_currentRules:function _currentRules() { - if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { - return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; - } else { - return this.conditions["INITIAL"].rules; - } - }, - -// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available -topState:function topState(n) { - n = this.conditionStack.length - 1 - Math.abs(n || 0); - if (n >= 0) { - return this.conditionStack[n]; - } else { - return "INITIAL"; - } - }, - -// alias for begin(condition) -pushState:function pushState(condition) { - this.begin(condition); - }, - -// return the number of states currently on the stack -stateStackSize:function stateStackSize() { - return this.conditionStack.length; - }, -options: {}, -performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { -var YYSTATE=YY_START; -switch($avoiding_name_collisions) { -case 0:/* comment */ -break; -case 1: yy_.yytext = yy_.yytext.substring(9, yy_.yytext.length - 10); return 9; -break; -case 2:return 52; -break; -case 3:return 52; -break; -case 4:return 40; -break; -case 5: return 41; -break; -case 6:return 46; -break; -case 7:return 44; -break; -case 8:return 45; -break; -case 9:return 47; -break; -case 10:return 49; -break; -case 11:return 50; -break; -case 12:return 32; -break; -case 13:return 33; -break; -case 14: this.begin('command'); return 30; -break; -case 15: this.begin('command'); return 31; -break; -case 16: this.begin('command'); return 13; -break; -case 17: this.begin('command'); return 37; -break; -case 18: this.begin('command'); return 37; -break; -case 19:return 35; -break; -case 20:return 18; -break; -case 21:return 26; -break; -case 22:return 27; -break; -case 23: this.begin('command'); return 19; -break; -case 24: this.begin('command'); return 21; -break; -case 25:return 22; -break; -case 26: this.begin('command'); return 23; -break; -case 27:return 39; -break; -case 28:return 25; -break; -case 29: this.begin('command'); return 28; -break; -case 30: this.popState(); return 15; -break; -case 31:return 12; -break; -case 32:return 5; -break; -case 33:return 11; -break; -} -}, -rules: [/^(?:\{\*[\s\S]*?\*\})/,/^(?:\{literal\}[\s\S]*?\{\/literal\})/,/^(?:"([^"]|\\\.)*")/,/^(?:'([^']|\\\.)*')/,/^(?:\$)/,/^(?:[_a-zA-Z][_a-zA-Z0-9]*)/,/^(?:\.)/,/^(?:\[)/,/^(?:\])/,/^(?:\()/,/^(?:\))/,/^(?:=)/,/^(?:\{ldelim\})/,/^(?:\{rdelim\})/,/^(?:\{#)/,/^(?:\{@)/,/^(?:\{if )/,/^(?:\{else if )/,/^(?:\{elseif )/,/^(?:\{else\})/,/^(?:\{\/if\})/,/^(?:\{lang\})/,/^(?:\{\/lang\})/,/^(?:\{include )/,/^(?:\{implode )/,/^(?:\{\/implode\})/,/^(?:\{foreach )/,/^(?:\{foreachelse\})/,/^(?:\{\/foreach\})/,/^(?:\{(?!\s))/,/^(?:\})/,/^(?:\s+)/,/^(?:$)/,/^(?:[^{])/], -conditions: {"command":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"inclusive":true},"INITIAL":{"rules":[0,1,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,31,32,33],"inclusive":true}} -}); -return lexer; -})(); -parser.lexer = lexer; -return parser; -}); -/** - * Provides helper functions for Number handling. - * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/NumberUtil - */ -define('WoltLabSuite/Core/NumberUtil',[], function() { - "use strict"; - - /** - * @exports WoltLabSuite/Core/NumberUtil - */ - var NumberUtil = { - /** - * Decimal adjustment of a number. - * - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round - * @param {Number} value The number. - * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base). - * @returns {Number} The adjusted value. - */ - round: function (value, exp) { - // If the exp is undefined or zero... - if (typeof exp === 'undefined' || +exp === 0) { - return Math.round(value); - } - value = +value; - exp = +exp; - - // If the value is not a number or the exp is not an integer... - if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { - return NaN; - } - - // Shift - value = value.toString().split('e'); - value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); - - // Shift back - value = value.toString().split('e'); - return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); - } - }; - - return NumberUtil; -}); - -/** - * Provides helper functions for String handling. - * - * @author Tim Duesterhus, Joshua Ruesweg - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/StringUtil - */ -define('WoltLabSuite/Core/StringUtil',['Language', './NumberUtil'], function(Language, NumberUtil) { - "use strict"; - - /** - * @exports WoltLabSuite/Core/StringUtil - */ - return { - /** - * Adds thousands separators to a given number. - * - * @see http://stackoverflow.com/a/6502556/782822 - * @param {?} number - * @return {String} - */ - addThousandsSeparator: function(number) { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) Language = require('Language'); - - return String(number).replace(/(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1' + Language.get('wcf.global.thousandsSeparator')); - }, - - /** - * Escapes special HTML-characters within a string - * - * @param {?} string - * @return {String} - */ - escapeHTML: function (string) { - return String(string).replace(/&/g, '&').replace(/"/g, '"').replace(//g, '>'); - }, - - /** - * Escapes a String to work with RegExp. - * - * @see https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/regexp.js#L25 - * @param {?} string - * @return {String} - */ - escapeRegExp: function(string) { - return String(string).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); - }, - - /** - * Rounds number to given count of floating point digits, localizes decimal-point and inserts thousands separators. - * - * @param {?} number - * @param {int} decimalPlaces The number of decimal places to leave after rounding. - * @return {String} - */ - formatNumeric: function(number, decimalPlaces) { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) Language = require('Language'); - - number = String(NumberUtil.round(number, decimalPlaces || -2)); - var numberParts = number.split('.'); - - number = this.addThousandsSeparator(numberParts[0]); - if (numberParts.length > 1) number += Language.get('wcf.global.decimalPoint') + numberParts[1]; - - number = number.replace('-', '\u2212'); - - return number; - }, - - /** - * Makes a string's first character lowercase. - * - * @param {?} string - * @return {String} - */ - lcfirst: function(string) { - return String(string).substring(0, 1).toLowerCase() + string.substring(1); - }, - - /** - * Makes a string's first character uppercase. - * - * @param {?} string - * @return {String} - */ - ucfirst: function(string) { - return String(string).substring(0, 1).toUpperCase() + string.substring(1); - }, - - /** - * Unescapes special HTML-characters within a string. - * - * @param {?} string - * @return {String} - */ - unescapeHTML: function(string) { - return String(string).replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); - }, - - /** - * Shortens numbers larger than 1000 by using unit suffixes. - * - * @param {?} number - * @return {String} - */ - shortUnit: function(number) { - var unitSuffix = ''; - - if (number >= 1000000) { - number /= 1000000; - - if (number > 10) { - number = Math.floor(number); - } - else { - number = NumberUtil.round(number, -1); - } - - unitSuffix = 'M'; - } - else if (number >= 1000) { - number /= 1000; - - if (number > 10) { - number = Math.floor(number); - } - else { - number = NumberUtil.round(number, -1); - } - - unitSuffix = 'k'; - } - - return this.formatNumeric(number) + unitSuffix; - } - }; -}); - -/** - * WoltLabSuite/Core/Template provides a template scripting compiler similar - * to the PHP one of WoltLab Suite Core. It supports a limited - * set of useful commands and compiles templates down to a pure - * JavaScript Function. - * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Template - */ -define('WoltLabSuite/Core/Template',['./Template.grammar', './StringUtil', 'Language'], function(parser, StringUtil, Language) { - "use strict"; - - // work around bug in AMD module generation of Jison - function Parser() { - this.yy = {}; - } - Parser.prototype = parser; - parser.Parser = Parser; - parser = new Parser(); - - /** - * Compiles the given template. - * - * @param {string} template Template to compile. - * @constructor - */ - function Template(template) { - // Fetch Language/StringUtil, as it cannot be provided because of a circular dependency - if (Language === undefined) Language = require('Language'); - if (StringUtil === undefined) StringUtil = require('StringUtil'); - - try { - template = parser.parse(template); - template = "var tmp = {};\n" - + "for (var key in v) tmp[key] = v[key];\n" - + "v = tmp;\n" - + "v.__wcf = window.WCF; v.__window = window;\n" - + "return " + template; - - this.fetch = new Function("StringUtil", "Language", "v", template).bind(undefined, StringUtil, Language); - } - catch (e) { - console.debug(e.message); - throw e; - } - } - - Object.defineProperty(Template, 'callbacks', { - enumerable: false, - configurable: false, - get: function() { - throw new Error('WCF.Template.callbacks is no longer supported'); - }, - set: function(value) { - throw new Error('WCF.Template.callbacks is no longer supported'); - } - }); - - Template.prototype = { - /** - * Evaluates the Template using the given parameters. - * - * @param {object} v Parameters to pass to the template. - */ - fetch: function(v) { - // this will be replaced in the init function - throw new Error('This Template is not initialized.'); - } - }; - - return Template; -}); - -/** - * Manages language items. - * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Language - */ -define('WoltLabSuite/Core/Language',['Dictionary', './Template'], function(Dictionary, Template) { - "use strict"; - - var _languageItems = new Dictionary(); - - /** - * @exports WoltLabSuite/Core/Language - */ - var Language = { - /** - * Adds all the language items in the given object to the store. - * - * @param {Object.} object - */ - addObject: function(object) { - _languageItems.merge(Dictionary.fromObject(object)); - }, - - /** - * Adds a single language item to the store. - * - * @param {string} key - * @param {string} value - */ - add: function(key, value) { - _languageItems.set(key, value); - }, - - /** - * Fetches the language item specified by the given key. - * If the language item is a string it will be evaluated as - * WoltLabSuite/Core/Template with the given parameters. - * - * @param {string} key Language item to return. - * @param {Object=} parameters Parameters to provide to WoltLabSuite/Core/Template. - * @return {string} - */ - get: function(key, parameters) { - if (!parameters) parameters = { }; - - var value = _languageItems.get(key); - - if (value === undefined) { - return key; - } - - // fetch Template, as it cannot be provided because of a circular dependency - if (Template === undefined) Template = require('WoltLabSuite/Core/Template'); - - if (typeof value === 'string') { - // lazily convert to WCF.Template - try { - _languageItems.set(key, new Template(value)); - } - catch (e) { - _languageItems.set(key, new Template('{literal}' + value.replace(/\{\/literal\}/g, '{/literal}{ldelim}/literal}{literal}') + '{/literal}')); - } - value = _languageItems.get(key); - } - - if (value instanceof Template) { - value = value.fetch(parameters); - } - - return value; - } - }; - - return Language; -}); - -/** - * Simple API to store and invoke multiple callbacks per identifier. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/CallbackList - */ -define('WoltLabSuite/Core/CallbackList',['Dictionary'], function(Dictionary) { - "use strict"; - - /** - * @constructor - */ - function CallbackList() { - this._dictionary = new Dictionary(); - } - CallbackList.prototype = { - /** - * Adds a callback for given identifier. - * - * @param {string} identifier arbitrary string to group and identify callbacks - * @param {function} callback callback function - */ - add: function(identifier, callback) { - if (typeof callback !== 'function') { - throw new TypeError("Expected a valid callback as second argument for identifier '" + identifier + "'."); - } - - if (!this._dictionary.has(identifier)) { - this._dictionary.set(identifier, []); - } - - this._dictionary.get(identifier).push(callback); - }, - - /** - * Removes all callbacks registered for given identifier - * - * @param {string} identifier arbitrary string to group and identify callbacks - */ - remove: function(identifier) { - this._dictionary['delete'](identifier); - }, - - /** - * Invokes callback function on each registered callback. - * - * @param {string|null} identifier arbitrary string to group and identify callbacks. - * null is a wildcard to match every identifier - * @param {function(function)} callback function called with the individual callback as parameter - */ - forEach: function(identifier, callback) { - if (identifier === null) { - this._dictionary.forEach(function(callbacks, identifier) { - callbacks.forEach(callback); - }); - } - else { - var callbacks = this._dictionary.get(identifier); - if (callbacks !== undefined) { - callbacks.forEach(callback); - } - } - } - }; - - return CallbackList; -}); - -/** - * Allows to be informed when the DOM may have changed and - * new elements that are relevant to you may have been added. - * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Dom/Change/Listener - */ -define('WoltLabSuite/Core/Dom/Change/Listener',['CallbackList'], function(CallbackList) { - "use strict"; - - var _callbackList = new CallbackList(); - var _hot = false; - - /** - * @exports WoltLabSuite/Core/Dom/Change/Listener - */ - return { - /** - * @see WoltLabSuite/Core/CallbackList#add - */ - add: _callbackList.add.bind(_callbackList), - - /** - * @see WoltLabSuite/Core/CallbackList#remove - */ - remove: _callbackList.remove.bind(_callbackList), - - /** - * Triggers the execution of all the listeners. - * Use this function when you added new elements to the DOM that might - * be relevant to others. - * While this function is in progress further calls to it will be ignored. - */ - trigger: function() { - if (_hot) return; - - try { - _hot = true; - _callbackList.forEach(null, function(callback) { - callback(); - }); - } - finally { - _hot = false; - } - } - }; -}); - -/** - * Provides basic details on the JavaScript environment. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Environment - */ -define('WoltLabSuite/Core/Environment',[], function() { - "use strict"; - - var _browser = 'other'; - var _editor = 'none'; - var _platform = 'desktop'; - var _touch = false; - - /** - * @exports WoltLabSuite/Core/Environment - */ - return { - /** - * Determines environment variables. - */ - setup: function() { - if (typeof window.chrome === 'object') { - // this detects Opera as well, we could check for window.opr if we need to - _browser = 'chrome'; - } - else { - var styles = window.getComputedStyle(document.documentElement); - for (var i = 0, length = styles.length; i < length; i++) { - var property = styles[i]; - - if (property.indexOf('-ms-') === 0) { - // it is tempting to use 'msie', but it wouldn't really represent 'Edge' - _browser = 'microsoft'; - } - else if (property.indexOf('-moz-') === 0) { - _browser = 'firefox'; - } - else if (_browser !== 'firefox' && property.indexOf('-webkit-') === 0) { - _browser = 'safari'; - } - } - } - - var ua = window.navigator.userAgent.toLowerCase(); - if (ua.indexOf('crios') !== -1) { - _browser = 'chrome'; - _platform = 'ios'; - } - else if (/(?:iphone|ipad|ipod)/.test(ua)) { - _browser = 'safari'; - _platform = 'ios'; - } - else if (ua.indexOf('android') !== -1) { - _platform = 'android'; - } - else if (ua.indexOf('iemobile') !== -1) { - _browser = 'microsoft'; - _platform = 'windows'; - } - - if (_platform === 'desktop' && (ua.indexOf('mobile') !== -1 || ua.indexOf('tablet') !== -1)) { - _platform = 'mobile'; - } - - _editor = 'redactor'; - _touch = (!!('ontouchstart' in window) || (!!('msMaxTouchPoints' in window.navigator) && window.navigator.msMaxTouchPoints > 0) || window.DocumentTouch && document instanceof DocumentTouch); - }, - - /** - * Returns the lower-case browser identifier. - * - * Possible values: - * - chrome: Chrome and Opera - * - firefox - * - microsoft: Internet Explorer and Microsoft Edge - * - safari - * - * @return {string} browser identifier - */ - browser: function() { - return _browser; - }, - - /** - * Returns the available editor's name or an empty string. - * - * @return {string} editor name - */ - editor: function() { - return _editor; - }, - - /** - * Returns the browser platform. - * - * Possible values: - * - desktop - * - android - * - ios: iPhone, iPad and iPod - * - windows: Windows on phones/tablets - * - * @return {string} browser platform - */ - platform: function() { - return _platform; - }, - - /** - * Returns true if browser is potentially used with a touchscreen. - * - * Warning: Detecting touch is unreliable and should be avoided at all cost. - * - * @deprecated 3.0 - exists for backward-compatibility only, will be removed in the future - * - * @return {boolean} true if a touchscreen is present - */ - touch: function() { - return _touch; - } - }; -}); - -/** - * Provides helper functions to work with DOM nodes. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Dom/Util - */ -define('WoltLabSuite/Core/Dom/Util',['Environment', 'StringUtil'], function(Environment, StringUtil) { - "use strict"; - - function _isBoundaryNode(element, ancestor, position) { - if (!ancestor.contains(element)) { - throw new Error("Ancestor element does not contain target element."); - } - - var node, whichSibling = position + 'Sibling'; - while (element !== null && element !== ancestor) { - if (element[position + 'ElementSibling'] !== null) { - return false; - } - else if (element[whichSibling]) { - node = element[whichSibling]; - while (node) { - if (node.textContent.trim() !== '') { - return false; - } - - node = node[whichSibling]; - } - } - - element = element.parentNode; - } - - return true; - } - - var _idCounter = 0; - - /** - * @exports WoltLabSuite/Core/Dom/Util - */ - var DomUtil = { - /** - * Returns a DocumentFragment containing the provided HTML string as DOM nodes. - * - * @param {string} html HTML string - * @return {DocumentFragment} fragment containing DOM nodes - */ - createFragmentFromHtml: function(html) { - var tmp = elCreate('div'); - this.setInnerHtml(tmp, html); - - var fragment = document.createDocumentFragment(); - while (tmp.childNodes.length) { - fragment.appendChild(tmp.childNodes[0]); - } - - return fragment; - }, - - /** - * Returns a unique element id. - * - * @return {string} unique id - */ - getUniqueId: function() { - var elementId; - - do { - elementId = 'wcf' + _idCounter++; - } - while (elById(elementId) !== null); - - return elementId; - }, - - /** - * Returns the element's id. If there is no id set, a unique id will be - * created and assigned. - * - * @param {Element} el element - * @return {string} element id - */ - identify: function(el) { - if (!(el instanceof Element)) { - throw new TypeError("Expected a valid DOM element as argument."); - } - - var id = elAttr(el, 'id'); - if (!id) { - id = this.getUniqueId(); - elAttr(el, 'id', id); - } - - return id; - }, - - /** - * Returns the outer height of an element including margins. - * - * @param {Element} el element - * @param {CSSStyleDeclaration=} styles result of window.getComputedStyle() - * @return {int} outer height in px - */ - outerHeight: function(el, styles) { - styles = styles || window.getComputedStyle(el); - - var height = el.offsetHeight; - height += ~~styles.marginTop + ~~styles.marginBottom; - - return height; - }, - - /** - * Returns the outer width of an element including margins. - * - * @param {Element} el element - * @param {CSSStyleDeclaration=} styles result of window.getComputedStyle() - * @return {int} outer width in px - */ - outerWidth: function(el, styles) { - styles = styles || window.getComputedStyle(el); - - var width = el.offsetWidth; - width += ~~styles.marginLeft + ~~styles.marginRight; - - return width; - }, - - /** - * Returns the outer dimensions of an element including margins. - * - * @param {Element} el element - * @return {{height: int, width: int}} dimensions in px - */ - outerDimensions: function(el) { - var styles = window.getComputedStyle(el); - - return { - height: this.outerHeight(el, styles), - width: this.outerWidth(el, styles) - }; - }, - - /** - * Returns the element's offset relative to the document's top left corner. - * - * @param {Element} el element - * @return {{left: int, top: int}} offset relative to top left corner - */ - offset: function(el) { - var rect = el.getBoundingClientRect(); - - return { - top: Math.round(rect.top + (window.scrollY || window.pageYOffset)), - left: Math.round(rect.left + (window.scrollX || window.pageXOffset)) - }; - }, - - /** - * Prepends an element to a parent element. - * - * @param {Element} el element to prepend - * @param {Element} parentEl future containing element - */ - prepend: function(el, parentEl) { - if (parentEl.childNodes.length === 0) { - parentEl.appendChild(el); - } - else { - parentEl.insertBefore(el, parentEl.childNodes[0]); - } - }, - - /** - * Inserts an element after an existing element. - * - * @param {Element} newEl element to insert - * @param {Element} el reference element - */ - insertAfter: function(newEl, el) { - if (el.nextSibling !== null) { - el.parentNode.insertBefore(newEl, el.nextSibling); - } - else { - el.parentNode.appendChild(newEl); - } - }, - - /** - * Applies a list of CSS properties to an element. - * - * @param {Element} el element - * @param {Object} styles list of CSS styles - */ - setStyles: function(el, styles) { - var important = false; - for (var property in styles) { - if (styles.hasOwnProperty(property)) { - if (/ !important$/.test(styles[property])) { - important = true; - - styles[property] = styles[property].replace(/ !important$/, ''); - } - else { - important = false; - } - - // for a set style property with priority = important, some browsers are - // not able to overwrite it with a property != important; removing the - // property first solves this issue - if (el.style.getPropertyPriority(property) === 'important' && !important) { - el.style.removeProperty(property); - } - - el.style.setProperty(property, styles[property], (important ? 'important' : '')); - } - } - }, - - /** - * Returns a style property value as integer. - * - * The behavior of this method is undefined for properties that are not considered - * to have a "numeric" value, e.g. "background-image". - * - * @param {CSSStyleDeclaration} styles result of window.getComputedStyle() - * @param {string} propertyName property name - * @return {int} property value as integer - */ - styleAsInt: function(styles, propertyName) { - var value = styles.getPropertyValue(propertyName); - if (value === null) { - return 0; - } - - return parseInt(value); - }, - - /** - * Sets the inner HTML of given element and reinjects