aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorewinslow <ewinslow@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-11-14 11:33:29 +0000
committerewinslow <ewinslow@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-11-14 11:33:29 +0000
commitc9f5c056862553d5102d1dfb7d964ea449573d59 (patch)
tree1b005cf7858d8358d76ed3ed8966170a6d4bab99
parent72a4b251503eeb2ae4cc8efdea1f522817652406 (diff)
downloadelgg-c9f5c056862553d5102d1dfb7d964ea449573d59.tar.gz
elgg-c9f5c056862553d5102d1dfb7d964ea449573d59.tar.bz2
Refs #2538: Added vsprintf support to elgg.echo. Added unit tests for normalize_url, added prototype definitions for Array#forEach for compatibility with IE.
git-svn-id: http://code.elgg.org/elgg/trunk@7313 36083f99-b078-4883-b0ff-0f9b5a30f544
-rw-r--r--js/classes/ElggPriorityList.js35
-rw-r--r--js/lib/elgglib.js134
-rw-r--r--js/lib/events.js22
-rw-r--r--js/lib/languages.js51
-rw-r--r--js/lib/prototypes.js44
-rw-r--r--js/tests/ElggEventsTest.js8
-rw-r--r--js/tests/ElggLibTest.js78
-rw-r--r--js/tests/jsTestDriver.conf1
-rw-r--r--vendors/sprintf.js183
-rw-r--r--views/default/js/initialise_elgg.php16
10 files changed, 401 insertions, 171 deletions
diff --git a/js/classes/ElggPriorityList.js b/js/classes/ElggPriorityList.js
index 324b07cac..7b5d16473 100644
--- a/js/classes/ElggPriorityList.js
+++ b/js/classes/ElggPriorityList.js
@@ -28,14 +28,15 @@ elgg.ElggPriorityList.prototype.insert = function(obj, opt_priority) {
elgg.ElggPriorityList.prototype.forEach = function(callback) {
elgg.assertTypeOf('function', callback);
- var index = 0, p, i, elems;
- for (p in this.priorities_) {
- elems = this.priorities_[p];
- for (i in elems) {
- callback(elems[i], index);
- index++;
- }
- }
+ var index = 0;
+
+ this.priorities_.forEach(function(elems) {
+ elems.forEach(function(elem) {
+ callback(elem, index++);
+ });
+ });
+
+ return this;
};
/**
@@ -44,19 +45,13 @@ elgg.ElggPriorityList.prototype.forEach = function(callback) {
elgg.ElggPriorityList.prototype.every = function(callback) {
elgg.assertTypeOf('function', callback);
- var index = 0, p, elems, i;
+ var index = 0;
- for (p in this.priorities_) {
- elems = this.priorities_[p];
- for (i in elems) {
- if (!callback(elems[i], index)) {
- return false;
- }
- index++;
- }
- }
-
- return true;
+ return this.priorities_.every(function(elems) {
+ return elems.every(function(elem) {
+ return callback(elem, index++);
+ });
+ });
};
/**
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js
index a8ab2020c..78a863803 100644
--- a/js/lib/elgglib.js
+++ b/js/lib/elgglib.js
@@ -5,7 +5,7 @@ var elgg = elgg || {};
/**
* Pointer to the global context
- *
+ *
* @see elgg.require
* @see elgg.provide
*/
@@ -13,55 +13,60 @@ elgg.global = this;
/**
* Convenience reference to an empty function.
- *
+ *
* Save memory by not generating multiple empty functions.
*/
elgg.nullFunction = function() {};
/**
- *
+ * This forces an inheriting class to implement the method or
+ * it will throw an error.
+ *
* @example
* AbstractClass.prototype.toBeImplemented = elgg.abstractMethod;
- *
- * Now this forces an inheriting class to implement the method or
- * it will throw an error.
*/
elgg.abstractMethod = function() {
throw new Error("Oops... you forgot to implement an abstract method!");
};
/**
- * Check if the value is an array.
- *
+ * Check if the value is an array.
+ *
* No sense in reinventing the wheel!
- *
+ *
+ * @param {*} val
+ *
* @return boolean
*/
elgg.isArray = jQuery.isArray;
/**
- * Check if the value is a function.
- *
+ * Check if the value is a function.
+ *
* No sense in reinventing the wheel!
- *
+ *
+ * @param {*} val
+ *
* @return boolean
*/
elgg.isFunction = jQuery.isFunction;
/**
* Check if the value is a "plain" object (i.e., created by {} or new Object())
- *
+ *
* No sense in reinventing the wheel!
- *
+ *
+ * @param {*} val
+ *
* @return boolean
*/
elgg.isPlainObject = jQuery.isPlainObject;
/**
* Check if the value is a string
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isString = function(val) {
@@ -70,9 +75,9 @@ elgg.isString = function(val) {
/**
* Check if the value is a number
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isNumber = function(val) {
@@ -81,12 +86,12 @@ elgg.isNumber = function(val) {
/**
* Check if the value is an object
- *
+ *
* @note This returns true for functions and arrays! If you want to return true only
* for "plain" objects (created using {} or new Object()) use elgg.isPlainObject.
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isObject = function(val) {
@@ -95,9 +100,9 @@ elgg.isObject = function(val) {
/**
* Check if the value is undefined
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isUndefined = function(val) {
@@ -106,9 +111,9 @@ elgg.isUndefined = function(val) {
/**
* Check if the value is null
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isNull = function(val) {
@@ -117,9 +122,9 @@ elgg.isNull = function(val) {
/**
* Check if the value is either null or undefined
- *
+ *
* @param {*} val
- *
+ *
* @return boolean
*/
elgg.isNullOrUndefined = function(val) {
@@ -128,25 +133,25 @@ elgg.isNullOrUndefined = function(val) {
/**
* Throw an exception of the type doesn't match
- *
+ *
* @todo Might be more appropriate for debug mode only?
*/
elgg.assertTypeOf = function(type, val) {
if (typeof val !== type) {
- throw new TypeError("Expecting param of " +
- arguments.caller + "to be a(n) " + type + "." +
- " Was actually a(n) " + typeof val + ".");
+ throw new TypeError("Expecting param of " +
+ arguments.caller + "to be a(n) " + type + "." +
+ " Was actually a(n) " + typeof val + ".");
}
};
/**
* Throw an error if the required package isn't present
- *
+ *
* @param {String} pkg The required package (e.g., 'elgg.package')
*/
elgg.require = function(pkg) {
elgg.assertTypeOf('string', pkg);
-
+
var parts = pkg.split('.'),
cur = elgg.global,
part, i;
@@ -162,31 +167,31 @@ elgg.require = function(pkg) {
/**
* Generate the skeleton for a package.
- *
+ *
* <pre>
* elgg.provide('elgg.package.subpackage');
* </pre>
- *
+ *
* is equivalent to
- *
+ *
* <pre>
* elgg = elgg || {};
* elgg.package = elgg.package || {};
* elgg.package.subpackage = elgg.package.subpackage || {};
* </pre>
- *
+ *
* @example elgg.provide('elgg.config.translations')
- *
+ *
* @param {string} pkg The package name.
*/
elgg.provide = function(pkg, opt_context) {
elgg.assertTypeOf('string', pkg);
-
+
var parts = pkg.split('.'),
- context = opt_context || elgg.global,
- part, i;
-
-
+ context = opt_context || elgg.global,
+ part, i;
+
+
for (i = 0; i < parts.length; i += 1) {
part = parts[i];
context[part] = context[part] || {};
@@ -196,11 +201,11 @@ elgg.provide = function(pkg, opt_context) {
/**
* Inherit the prototype methods from one constructor into another.
- *
+ *
* @example
* <pre>
* function ParentClass(a, b) { }
- *
+ *
* ParentClass.prototype.foo = function(a) { alert(a); }
*
* function ChildClass(a, b, c) {
@@ -224,7 +229,7 @@ elgg.inherit = function(Child, Parent) {
/**
* Prepend elgg.config.wwwroot to a url if the url doesn't already have it.
- *
+ *
* @param {String} url The url to extend
* @return {String} The extended url
* @private
@@ -232,18 +237,18 @@ elgg.inherit = function(Child, Parent) {
elgg.normalize_url = function(url) {
url = url || '';
elgg.assertTypeOf('string', url);
-
+
// jslint complains if you use /regexp/ shorthand here... ?!?!
if ((new RegExp("^(https?:)?//")).test(url)) {
return url;
}
-
- return elgg.config.wwwroot + url;
+
+ return elgg.config.wwwroot + url.ltrim('/');
};
/**
* Displays system messages via javascript rather than php.
- *
+ *
* @param {String} msgs The message we want to display
* @param {Number} delay The amount of time to display the message in milliseconds. Defaults to 6 seconds.
* @param {String} type The type of message (typically 'error' or 'message')
@@ -253,18 +258,19 @@ elgg.system_messages = function(msgs, delay, type) {
if (elgg.isUndefined(msgs)) {
return;
}
-
- var classes = [],
+
+ var classes = ['elgg_system_message', 'radius8'],
messages_html = [],
- i;
-
- //validate delay. Must be a positive integer.
- delay = parseInt(delay, 10);
+ appendMessage = function(msg) {
+ messages_html.push('<div class="' + classes.join(' ') + '"><p>' + msg + '</p></div>');
+ }, i;
+
+ //validate delay. Must be a positive integer.
+ delay = parseInt(delay || 6000, 10);
if (isNaN(delay) || delay <= 0) {
delay = 6000;
}
-
- classes = ['elgg_system_message', 'radius8'];
+
if (type === 'error') {
classes.push('messages_error');
}
@@ -273,13 +279,11 @@ elgg.system_messages = function(msgs, delay, type) {
if (!elgg.isArray(msgs)) {
msgs = [msgs];
}
-
- for (i in msgs) {
- messages_html.push('<div class="' + classes.join(' ') + '"><p>' + msgs[i] + '</p></div>');
- }
-
+
+ msgs.forEach(appendMessage);
+
$(messages_html.join('')).appendTo('#elgg_system_messages')
- .animate({opacity: '1.0'}, delay).fadeOut('slow');
+ .animate({opacity: '1.0'}, delay).fadeOut('slow');
};
/**
@@ -303,7 +307,7 @@ elgg.register_error = function(errors, delay) {
/**
* Meant to mimic the php forward() function by simply redirecting the
* user to another page.
- *
+ *
* @param {String} url The url to forward to
*/
elgg.forward = function(url) {
diff --git a/js/lib/events.js b/js/lib/events.js
index ad05a9888..c1aa6fd9a 100644
--- a/js/lib/events.js
+++ b/js/lib/events.js
@@ -1,22 +1,22 @@
elgg.provide('elgg.config.events');
/**
- *
+ *
*/
elgg.register_event_handler = function(event_name, event_type, handler, priority) {
elgg.assertTypeOf('string', event_name);
elgg.assertTypeOf('string', event_type);
elgg.assertTypeOf('function', handler);
-
+
if (!event_name || !event_type) {
return false;
}
-
+
var events = elgg.config.events;
-
+
elgg.provide(event_name + '.' + event_type, events);
-
+
if (!(events[event_name][event_type] instanceof elgg.ElggPriorityList)) {
events[event_name][event_type] = new elgg.ElggPriorityList();
}
@@ -25,22 +25,22 @@ elgg.register_event_handler = function(event_name, event_type, handler, priority
};
/**
- *
+ *
*/
elgg.trigger_event = function(event_name, event_type, opt_object) {
elgg.assertTypeOf('string', event_name);
elgg.assertTypeOf('string', event_type);
var events = elgg.config.events,
- callEventHandler = function(handler) {
- return handler(event_name, event_type, opt_object) !== false;
- }
-
+ callEventHandler = function(handler) {
+ return handler(event_name, event_type, opt_object) !== false;
+ };
+
elgg.provide(event_name + '.' + event_type, events);
elgg.provide('all.' + event_type, events);
elgg.provide(event_name + '.all', events);
elgg.provide('all.all', events);
-
+
return [
events[event_name][event_type],
events['all'][event_type],
diff --git a/js/lib/languages.js b/js/lib/languages.js
index 640764282..82cfa7a01 100644
--- a/js/lib/languages.js
+++ b/js/lib/languages.js
@@ -1,3 +1,4 @@
+/*globals vsprintf*/
/**
* Provides language-related functionality
*/
@@ -7,13 +8,13 @@ elgg.config.language = 'en';
elgg.add_translation = function(lang, translations) {
elgg.provide('elgg.config.translations.' + lang);
-
+
$.extend(elgg.config.translations[lang], translations);
};
/**
* Load the translations for the given language.
- *
+ *
* If no language is specified, the default language is used.
* @param {string} language
* @return {XMLHttpRequest}
@@ -38,41 +39,43 @@ elgg.reload_all_translations = function(language) {
*/
elgg.get_language = function() {
var user = elgg.get_loggedin_user();
-
+
if (user && user.language) {
return user.language;
}
-
+
return elgg.config.language;
};
/**
* Translates a string
- *
- * @param {String} key The string to translate
+ *
+ * @param {String} key The string to translate
+ * @param {Array} argv vsprintf support
* @param {String} language The language to display it in
+ *
* @return {String} The translation
*/
-elgg.echo = function(key, language) {
- var translations,
- dlang = elgg.get_language();
-
- language = language || dlang;
-
- translations = elgg.config.translations[language];
- if (translations && translations[key]) {
- return translations[key];
- }
-
- if (language === dlang) {
- return undefined;
+elgg.echo = function(key, argv, language) {
+ //elgg.echo('str', 'en')
+ if (elgg.isString(argv)) {
+ language = argv;
+ argv = [];
}
-
- translations = elgg.config.translations[dlang];
- if (translations && translations[key]) {
- return translations[key];
+
+ //elgg.echo('str', [...], 'en')
+ var translations = elgg.config.translations,
+ dlang = elgg.get_language(),
+ map;
+
+ language = language || dlang;
+ argv = argv || [];
+
+ map = translations[language] || translations[dlang];
+ if (map && map[key]) {
+ return vsprintf(map[key], argv);
}
-
+
return undefined;
};
diff --git a/js/lib/prototypes.js b/js/lib/prototypes.js
new file mode 100644
index 000000000..0f0014818
--- /dev/null
+++ b/js/lib/prototypes.js
@@ -0,0 +1,44 @@
+/**
+ *
+ */
+if (!Array.prototype.every) {
+ Array.prototype.every = function(callback) {
+ var len = this.length, i;
+
+ for (i = 0; i < len; i++) {
+ if (i in this && !callback.call(null, this[i], i)) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+}
+
+/**
+ *
+ */
+if (!Array.prototype.forEach) {
+ Array.prototype.forEach = function(callback) {
+ var len = this.length, i;
+
+ for (i = 0; i < len; i++) {
+ if (i in this) {
+ callback.call(null, this[i], i);
+ }
+ }
+ };
+}
+
+/**
+ *
+ */
+if (!String.prototype.ltrim) {
+ String.prototype.ltrim = function(str) {
+ if (this.indexOf(str) === 0) {
+ return this.substring(str.length);
+ } else {
+ return this;
+ }
+ };
+} \ No newline at end of file
diff --git a/js/tests/ElggEventsTest.js b/js/tests/ElggEventsTest.js
index 1fc9c8e86..4765878cf 100644
--- a/js/tests/ElggEventsTest.js
+++ b/js/tests/ElggEventsTest.js
@@ -11,7 +11,7 @@ ElggEventsTest.prototype.testEventHandlersMustBeFunctions = function () {
ElggEventsTest.prototype.testReturnValueDefaultsToTrue = function () {
assertTrue(elgg.trigger_event('fee', 'fum'));
-
+
elgg.register_event_handler('fee', 'fum', elgg.nullFunction);
assertTrue(elgg.trigger_event('fee', 'fum'));
};
@@ -19,10 +19,10 @@ ElggEventsTest.prototype.testReturnValueDefaultsToTrue = function () {
ElggEventsTest.prototype.testCanGlomEventsWithAll = function () {
elgg.register_event_handler('all', 'bar', elgg.abstractMethod);
assertException("all,bar", function() { elgg.trigger_event('foo', 'bar'); });
-
+
elgg.register_event_handler('foo', 'all', elgg.abstractMethod);
assertException("foo,all", function() { elgg.trigger_event('foo', 'baz'); });
-
- elgg.register_event_handler('all', 'all', elgg.abstractMethod);
+
+ elgg.register_event_handler('all', 'all', elgg.abstractMethod);
assertException("all,all", function() { elgg.trigger_event('pinky', 'winky'); });
}; \ No newline at end of file
diff --git a/js/tests/ElggLibTest.js b/js/tests/ElggLibTest.js
index e810a47fb..132ad986a 100644
--- a/js/tests/ElggLibTest.js
+++ b/js/tests/ElggLibTest.js
@@ -8,50 +8,42 @@ ElggLibTest.prototype.testGlobal = function() {
};
ElggLibTest.prototype.testAssertTypeOf = function() {
- var noexceptions = [
+ [//Valid inputs
['string', ''],
['object', {}],
- ['boolean', true],
- ['boolean', false],
- ['undefined', undefined],
- ['number', 0],
- ['function', elgg.nullFunction],
- ];
-
- for (var i in noexceptions) {
- assertNoException(function() {
- elgg.assertTypeOf.apply(elgg, noexceptions[i]);
+ ['boolean', true],
+ ['boolean', false],
+ ['undefined', undefined],
+ ['number', 0],
+ ['function', elgg.nullFunction]
+ ].forEach(function(args) {
+ assertNoException(function() {
+ elgg.assertTypeOf.apply(undefined, args);
});
- }
-
- var exceptions = [
+ });
+
+ [//Invalid inputs
['function', {}],
- ['object', elgg.nullFunction],
- ];
-
- for (var i in exceptions) {
- assertException(function() {
- elgg.assertTypeOf.apply(elgg, exceptions[i]);
+ ['object', elgg.nullFunction]
+ ].forEach(function() {
+ assertException(function(args) {
+ elgg.assertTypeOf.apply(undefined, args);
});
- }
+ });
};
-ElggLibTest.prototype.testProvide = function() {
+ElggLibTest.prototype.testProvideDoesntClobber = function() {
elgg.provide('foo.bar.baz');
-
- assertNotUndefined(foo);
- assertNotUndefined(foo.bar);
- assertNotUndefined(foo.bar.baz);
-
- var str = foo.bar.baz.oof = "don't overwrite me";
-
+
+ foo.bar.baz.oof = "test";
+
elgg.provide('foo.bar.baz');
-
- assertEquals(str, foo.bar.baz.oof);
+
+ assertEquals("test", foo.bar.baz.oof);
};
/**
- * Try requiring bogus input
+ * Try requiring bogus input
*/
ElggLibTest.prototype.testRequire = function () {
assertException(function(){ elgg.require(''); });
@@ -69,24 +61,24 @@ ElggLibTest.prototype.testRequire = function () {
ElggLibTest.prototype.testInherit = function () {
function Base() {}
function Child() {}
-
+
elgg.inherit(Child, Base);
-
+
assertInstanceOf(Base, new Child());
assertEquals(Child, Child.prototype.constructor);
};
ElggLibTest.prototype.testNormalizeUrl = function() {
elgg.config.wwwroot = "http://elgg.org/";
-
- var inputs = [
- [elgg.config.wwwroot, ''],
- [elgg.config.wwwroot + 'pg/test', 'pg/test'],
+
+ [
+ ['', elgg.config.wwwroot],
+ ['pg/test', elgg.config.wwwroot + 'pg/test'],
['http://google.com', 'http://google.com'],
['//example.com', '//example.com'],
- ];
-
- for (var i in inputs) {
- assertEquals(inputs[i][0], elgg.normalize_url(inputs[i][1]));
- }
+ ['/pg/page', elgg.config.wwwroot + 'pg/page'],
+ ['mod/plugin/index.php', elgg.config.wwwroot + 'mod/plugin/index.php'],
+ ].forEach(function(args) {
+ assertEquals(args[1], elgg.normalize_url(args[0]));
+ });
}; \ No newline at end of file
diff --git a/js/tests/jsTestDriver.conf b/js/tests/jsTestDriver.conf
index 2f732da7b..606487c03 100644
--- a/js/tests/jsTestDriver.conf
+++ b/js/tests/jsTestDriver.conf
@@ -2,6 +2,7 @@ server: http://localhost:42442
load:
- vendors/jquery/jquery-1.4.2.min.js
+ - vendors/sprintf.js
- js/lib/elgglib.js
- js/classes/*.js
- js/lib/*.js
diff --git a/vendors/sprintf.js b/vendors/sprintf.js
new file mode 100644
index 000000000..0e8d02c98
--- /dev/null
+++ b/vendors/sprintf.js
@@ -0,0 +1,183 @@
+/**
+sprintf() for JavaScript 0.7-beta1
+http://www.diveintojavascript.com/projects/javascript-sprintf
+
+Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of sprintf() for JavaScript nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Changelog:
+2010.09.06 - 0.7-beta1
+ - features: vsprintf, support for named placeholders
+ - enhancements: format cache, reduced global namespace pollution
+
+2010.05.22 - 0.6:
+ - reverted to 0.4 and fixed the bug regarding the sign of the number 0
+ Note:
+ Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
+ who warned me about a bug in 0.5, I discovered that the last update was
+ a regress. I appologize for that.
+
+2010.05.09 - 0.5:
+ - bug fix: 0 is now preceeded with a + sign
+ - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
+ - switched from GPL to BSD license
+
+2007.10.21 - 0.4:
+ - unit test and patch (David Baird)
+
+2007.09.17 - 0.3:
+ - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
+
+2007.09.11 - 0.2:
+ - feature: added argument swapping
+
+2007.04.03 - 0.1:
+ - initial release
+**/
+
+var sprintf = (function() {
+ function get_type(variable) {
+ return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
+ }
+ function str_repeat(input, multiplier) {
+ for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
+ return output.join('');
+ }
+
+ var str_format = function() {
+ if (!str_format.cache.hasOwnProperty(arguments[0])) {
+ str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
+ }
+ return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
+ };
+
+ str_format.format = function(parse_tree, argv) {
+ var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
+ for (i = 0; i < tree_length; i++) {
+ node_type = get_type(parse_tree[i]);
+ if (node_type === 'string') {
+ output.push(parse_tree[i]);
+ }
+ else if (node_type === 'array') {
+ match = parse_tree[i]; // convenience purposes only
+ if (match[2]) { // keyword argument
+ arg = argv[cursor];
+ for (k = 0; k < match[2].length; k++) {
+ if (!arg.hasOwnProperty(match[2][k])) {
+ throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
+ }
+ arg = arg[match[2][k]];
+ }
+ }
+ else if (match[1]) { // positional argument (explicit)
+ arg = argv[match[1]];
+ }
+ else { // positional argument (implicit)
+ arg = argv[cursor++];
+ }
+
+ if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
+ throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
+ }
+ switch (match[8]) {
+ case 'b': arg = arg.toString(2); break;
+ case 'c': arg = String.fromCharCode(arg); break;
+ case 'd': arg = parseInt(arg, 10); break;
+ case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
+ case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
+ case 'o': arg = arg.toString(8); break;
+ case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
+ case 'u': arg = Math.abs(arg); break;
+ case 'x': arg = arg.toString(16); break;
+ case 'X': arg = arg.toString(16).toUpperCase(); break;
+ }
+ arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
+ pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
+ pad_length = match[6] - String(arg).length;
+ pad = match[6] ? str_repeat(pad_character, pad_length) : '';
+ output.push(match[5] ? arg + pad : pad + arg);
+ }
+ }
+ return output.join('');
+ };
+
+ str_format.cache = {};
+
+ str_format.parse = function(fmt) {
+ var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
+ while (_fmt) {
+ if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
+ parse_tree.push(match[0]);
+ }
+ else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
+ parse_tree.push('%');
+ }
+ else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
+ if (match[2]) {
+ arg_names |= 1;
+ var field_list = [], replacement_field = match[2], field_match = [];
+ if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
+ if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ }
+ else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ }
+ else {
+ throw('[sprintf] huh?');
+ }
+ }
+ }
+ else {
+ throw('[sprintf] huh?');
+ }
+ match[2] = field_list;
+ }
+ else {
+ arg_names |= 2;
+ }
+ if (arg_names === 3) {
+ throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
+ }
+ parse_tree.push(match);
+ }
+ else {
+ throw('[sprintf] huh?');
+ }
+ _fmt = _fmt.substring(match[0].length);
+ }
+ return parse_tree;
+ };
+
+ return str_format;
+})();
+
+var vsprintf = function(fmt, argv) {
+ argv.unshift(fmt);
+ return sprintf.apply(null, argv);
+};
diff --git a/views/default/js/initialise_elgg.php b/views/default/js/initialise_elgg.php
index 3de1c020b..49c12e30c 100644
--- a/views/default/js/initialise_elgg.php
+++ b/views/default/js/initialise_elgg.php
@@ -4,7 +4,14 @@
*/
global $CONFIG;
-include("{$CONFIG->path}js/lib/elgglib.js");
+$prereq_files = array(
+ "vendors/sprintf.js",
+ "js/lib/elgglib.js",
+);
+
+foreach ($prereq_files as $file) {
+ include("{$CONFIG->path}$file");
+}
//No such thing as autoloading classes in javascript
$model_files = array(
@@ -13,13 +20,14 @@ $model_files = array(
'ElggPriorityList',
);
-foreach($model_files as $file) {
+foreach ($model_files as $file) {
include("{$CONFIG->path}js/classes/$file.js");
}
//Include library files
$libs = array(
//libraries
+ 'prototypes',
'events',
'security',
'languages',
@@ -31,7 +39,7 @@ $libs = array(
'ui.widgets',
);
-foreach($libs as $file) {
+foreach ($libs as $file) {
include("{$CONFIG->path}js/lib/$file.js");
}
@@ -43,7 +51,7 @@ foreach($libs as $file) {
elgg.version = '<?php echo get_version(); ?>';
elgg.release = '<?php echo get_version(true); ?>';
elgg.config.wwwroot = '<?php echo elgg_get_site_url(); ?>';
-elgg.security.interval = 5 * 60 * 1000; <?php //TODO make this configurable ?>
+elgg.security.interval = 5 * 60 * 1000; <?php //@todo make this configurable ?>
//Mimic PHP engine boot process