/**\r
* Escapes an ID to work with jQuery selectors.\r
*\r
- * @see http://docs.jquery.com/Frequently_Asked_Questions#How_do_I_select_an_element_by_an_ID_that_has_characters_used_in_CSS_notation.3F\r
+ * @see http://docs.jquery.com/Frequently_Asked_Questions#How_do_I_select_an_element_by_an_ID_that_has_characters_used_in_CSS_notation.3F\r
* @param string id\r
* @return string\r
*/\r
* String utilities.\r
*/\r
WCF.String = {\r
+ /**\r
+ * Escapes special HTML-characters within a string\r
+ * \r
+ * @param string string\r
+ * @return string\r
+ */\r
+ escapeHTML: function (string) {\r
+ return string.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');\r
+ },\r
+ \r
+ /**\r
+ * Escapes a String to work with RegExp.\r
+ *\r
+ * @see https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/regexp.js#L25\r
+ * @param string string\r
+ * @return string\r
+ */\r
+ escapeRegExp: function(string) {\r
+ return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');\r
+ },\r
+ \r
/**\r
* Makes a string's first character uppercase\r
* \r
}\r
};\r
\r
+/**\r
+ * Templates that may be fetched more than once with different variables. Based upon ideas from Prototype's template\r
+ * \r
+ * Usage:\r
+ * var myTemplate = new WCF.Template('{$hello} World');\r
+ * myTemplate.fetch({ hello: 'Hi' }); // Hi World\r
+ * myTemplate.fetch({ hello: 'Hello' }); // Hello World\r
+ * \r
+ * my2ndTemplate = new WCF.Template('{@$html}{$html}');\r
+ * my2ndTemplate.fetch({ html: '<b>Test</b>' }); // <b>Test</b><b>Test</b>\r
+ * \r
+ * var my3rdTemplate = new WCF.Template('You can use {literal}{$variable}{/literal}-Tags here');\r
+ * my3rdTemplate.fetch({ variable: 'Not shown' }); // You can use {$variable}-Tags here\r
+ * \r
+ * \r
+ * @param template template-content\r
+ * @see https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/template.js\r
+ */\r
+WCF.Template = function(template) { this.init(template); };\r
+WCF.Template.prototype = {\r
+ /**\r
+ * Template-content\r
+ * \r
+ * @var string\r
+ */\r
+ _template: '',\r
+ \r
+ /**\r
+ * Saved literal-tags\r
+ * \r
+ * @var WCF.Dictionary\r
+ */\r
+ _literals: new WCF.Dictionary(),\r
+ \r
+ /**\r
+ * Prepares template\r
+ * \r
+ * @param $template template-content\r
+ */\r
+ init: function($template) {\r
+ this._template = $template;\r
+ \r
+ // save literal-tags\r
+ this._template = this._template.replace(/\{literal\}(.*?)\{\/literal\}/g, $.proxy(function ($match) {\r
+ // hopefully no one uses this string in one of his templates\r
+ var id = '@@@@@@@@@@@'+Math.random()+'@@@@@@@@@@@';\r
+ this._literals.add(id, $match.replace(/\{\/?literal\}/g, ''));\r
+ \r
+ return id;\r
+ }, this));\r
+ },\r
+ \r
+ /**\r
+ * Fetches the template with the given variables\r
+ *\r
+ * @param $variables variables to insert\r
+ * @return parsed template\r
+ */\r
+ fetch: function($variables) {\r
+ var $result = this._template;\r
+ \r
+ // insert them :)\r
+ for (var $key in $variables) {\r
+ $result = $result.replace(new RegExp(WCF.String.escapeRegExp('{$'+$key+'}'), 'g'), WCF.String.escapeHTML($variables[$key]));\r
+ $result = $result.replace(new RegExp(WCF.String.escapeRegExp('{@$'+$key+'}'), 'g'), $variables[$key]);\r
+ }\r
+ \r
+ // insert delimiter tags\r
+ $result = $result.replace('{ldelim}', '{').replace('{rdelim}', '}');\r
+ \r
+ // and re-insert saved literals\r
+ return this.insertLiterals($result);\r
+ },\r
+ \r
+ /**\r
+ * Inserts literals into given string\r
+ * \r
+ * @param $template string to insert into\r
+ * @return string with inserted literals\r
+ */\r
+ insertLiterals: function ($template) {\r
+ this._literals.each(function ($pair) {\r
+ $template = $template.replace($pair.key, $pair.value);\r
+ });\r
+ \r
+ return $template;\r
+ },\r
+ \r
+ /**\r
+ * Compiles this template into javascript-code\r
+ * \r
+ * @return WCF.Template.Compiled\r
+ */\r
+ compile: function () {\r
+ var $compiled = this._template;\r
+ \r
+ // escape \ and '\r
+ $compiled = $compiled.replace('\\', '\\\\').replace("'", "\\'");\r
+ \r
+ // parse our variable-tags\r
+ $compiled = $compiled.replace(/\{\$(.*?)\}/g, function ($match) {\r
+ var $name = '$v.' + $match.substring(2, $match.length - 1);\r
+ // trinary operator to maintain compatibility with uncompiled template\r
+ // ($name) ? $name : '$match'\r
+ // -> $v.muh ? $v.muh : '{$muh}'\r
+ return "' + WCF.String.escapeHTML("+ $name + " ? " + $name + " : '" + $match + "') + '";\r
+ }).replace(/\{@\$(.*?)\}/g, function ($match) {\r
+ var $name = '$v.' + $match.substring(3, $match.length - 1);\r
+ // trinary operator to maintain compatibility with uncompiled template\r
+ // ($name) ? $name : '$match'\r
+ // -> $v.muh ? $v.muh : '{$muh}'\r
+ return "' + ("+ $name + " ? " + $name + " : '" + $match + "') + '";\r
+ });\r
+ \r
+ // insert delimiter tags\r
+ $compiled = $compiled.replace('{ldelim}', '{').replace('{rdelim}', '}');\r
+ \r
+ // and re-insert saved literals\r
+ return new WCF.Template.Compiled("'" + this.insertLiterals($compiled) + "';");\r
+ }\r
+};\r
+\r
+/**\r
+ * Represents a compiled template\r
+ * \r
+ * @param compiled compiled template\r
+ */\r
+WCF.Template.Compiled = function(compiled) { this.init(compiled); };\r
+WCF.Template.Compiled.prototype = {\r
+ /**\r
+ * Compiled template\r
+ * \r
+ * @var string\r
+ */\r
+ _compiled: '',\r
+ \r
+ /**\r
+ * Initializes our compiled template\r
+ * \r
+ * @param $compiled compiled template\r
+ */\r
+ init: function($compiled) {\r
+ this._compiled = $compiled;\r
+ },\r
+ \r
+ /**\r
+ * @see WCF.Template.fetch\r
+ */\r
+ fetch: function($v) {\r
+ return eval(this._compiled);\r
+ }\r
+};\r
+\r
/**\r
* Toggles options.\r
* \r