From ad35859f02ff5f078111b5d50f8ee79baa7e9fe2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 18 May 2015 18:25:01 +0200 Subject: [PATCH] Add WoltLab/WCF/{Number,String}Util --- wcfsetup/install/files/js/WCF.js | 2 + .../files/js/WoltLab/WCF/NumberUtil.js | 49 ++++++++ .../files/js/WoltLab/WCF/StringUtil.js | 106 ++++++++++++++++++ .../js/WoltLab/WCF/Template.grammar.jison | 6 +- .../files/js/WoltLab/WCF/Template.grammar.js | 6 +- .../install/files/js/WoltLab/WCF/Template.js | 7 +- 6 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 wcfsetup/install/files/js/WoltLab/WCF/NumberUtil.js create mode 100644 wcfsetup/install/files/js/WoltLab/WCF/StringUtil.js diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 732f1c1629..e42aea85dc 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -3724,6 +3724,7 @@ WCF.MultipleLanguageInput = Class.extend({ /** * Number utilities. + * @deprecated Use WoltLab/WCF/NumberUtil */ WCF.Number = { /** @@ -3742,6 +3743,7 @@ WCF.Number = { /** * String utilities. + * @deprecated Use WoltLab/WCF/StringUtil */ WCF.String = { /** diff --git a/wcfsetup/install/files/js/WoltLab/WCF/NumberUtil.js b/wcfsetup/install/files/js/WoltLab/WCF/NumberUtil.js new file mode 100644 index 0000000000..403681d7de --- /dev/null +++ b/wcfsetup/install/files/js/WoltLab/WCF/NumberUtil.js @@ -0,0 +1,49 @@ +/** + * Provides helper functions for Number handling. + * + * @author Tim Duesterhus + * @copyright 2001-2015 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLab/WCF/NumberUtil + */ +define([], function() { + "use strict"; + + /** + * @constructor + */ + function NumberUtil() { }; + NumberUtil.prototype = { + /** + * 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 new NumberUtil(); +}); diff --git a/wcfsetup/install/files/js/WoltLab/WCF/StringUtil.js b/wcfsetup/install/files/js/WoltLab/WCF/StringUtil.js new file mode 100644 index 0000000000..8196b9161e --- /dev/null +++ b/wcfsetup/install/files/js/WoltLab/WCF/StringUtil.js @@ -0,0 +1,106 @@ +/** + * Provides helper functions for String handling. + * + * @author Tim Duesterhus + * @copyright 2001-2015 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLab/WCF/StringUtil + */ +define(['Language', './NumberUtil'], function(Language, NumberUtil) { + "use strict"; + + /** + * @constructor + */ + function StringUtil() { }; + StringUtil.prototype = { + /** + * 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, '>'); + } + }; + + return new StringUtil(); +}); diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.jison b/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.jison index 45dcf1366e..3cd2176a00 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.jison +++ b/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.jison @@ -124,9 +124,9 @@ COMMAND: + "}" + "return (looped ? result : " + ($5 || "''") + "); })()" } -| '{lang}' CHUNK_STAR '{/lang}' -> "WCF.Language.get(" + $2 + ")" -| '{' VARIABLE '}' -> "WCF.String.escapeHTML(" + $2 + ")" -| '{#' VARIABLE '}' -> "WCF.String.formatNumeric(" + $2 + ")" +| '{lang}' CHUNK_STAR '{/lang}' -> "Language.get(" + $2 + ")" +| '{' VARIABLE '}' -> "StringUtil.escapeHTML(" + $2 + ")" +| '{#' VARIABLE '}' -> "StringUtil.formatNumeric(" + $2 + ")" | '{@' VARIABLE '}' -> $2 | '{ldelim}' -> "'{'" | '{rdelim}' -> "'}'" diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.js b/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.js index 1868e8d438..4dad8f3980 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Template.grammar.js @@ -87,13 +87,13 @@ case 22: break; case 23: -this.$ = "WCF.Language.get(" + $$[$0-1] + ")"; +this.$ = "Language.get(" + $$[$0-1] + ")"; break; case 24: -this.$ = "WCF.String.escapeHTML(" + $$[$0-1] + ")"; +this.$ = "StringUtil.escapeHTML(" + $$[$0-1] + ")"; break; case 25: -this.$ = "WCF.String.formatNumeric(" + $$[$0-1] + ")"; +this.$ = "StringUtil.formatNumeric(" + $$[$0-1] + ")"; break; case 26: this.$ = $$[$0-1]; diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Template.js b/wcfsetup/install/files/js/WoltLab/WCF/Template.js index cf8d1c5b95..2ce9afd4d9 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Template.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Template.js @@ -9,7 +9,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/Template */ -define(['./Template.grammar'], function(parser) { +define(['./Template.grammar', './StringUtil', 'Language'], function(parser, StringUtil, Language) { "use strict"; // work around bug in AMD module generation of Jison @@ -27,6 +27,9 @@ define(['./Template.grammar'], function(parser) { * @constructor */ function Template(template) { + // Fetch Language, as it cannot be provided because of a circular dependency + if (Language === undefined) Language = require('Language'); + if (!(this instanceof Template)) { return new Template(template); } @@ -39,7 +42,7 @@ define(['./Template.grammar'], function(parser) { + "v.__wcf = window.WCF; v.__window = window;\n" + "return " + template; - this.fetch = new Function("v", template).bind(null); + this.fetch = new Function("StringUtil", "Language", "v", template).bind(null, StringUtil, Language); } catch (e) { console.debug(e.message); -- 2.20.1