diff options
Diffstat (limited to 'js/lib')
-rw-r--r-- | js/lib/elgglib.js | 175 | ||||
-rw-r--r-- | js/lib/hooks.js | 75 | ||||
-rw-r--r-- | js/lib/security.js | 20 | ||||
-rw-r--r-- | js/lib/ui.js | 2 |
4 files changed, 263 insertions, 9 deletions
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js index 9a372738d..0f17eeced 100644 --- a/js/lib/elgglib.js +++ b/js/lib/elgglib.js @@ -353,6 +353,145 @@ elgg.forward = function(url) { }; /** + * Parse a URL into its parts. Mimicks http://php.net/parse_url + * + * @param {String} url The URL to parse + * @param {Int} component A component to return + * @param {Bool} expand Expand the query into an object? Else it's a string. + * + * @return {Object} The parsed URL + */ +elgg.parse_url = function(url, component, expand) { + // Adapted from http://blog.stevenlevithan.com/archives/parseuri + // which was release under the MIT + // It was modified to fix mailto: and javascript: support. + var + expand = expand || false, + component = component || false, + + re_str = + // scheme (and user@ testing) + '^(?:(?![^:@]+:[^:@/]*@)([^:/?#.]+):)?(?://)?' + // possibly a user[:password]@ + + '((?:(([^:@]*)(?::([^:@]*))?)?@)?' + // host and port + + '([^:/?#]*)(?::(\\d*))?)' + // path + + '(((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[?#]|$)))*/?)?([^?#/]*))' + // query string + + '(?:\\?([^#]*))?' + // fragment + + '(?:#(.*))?)', + keys = { + 'mailto': { + 4: "scheme", + 5: "user", + 6: "host", + 9: "path", + 12: "query", + 13: "fragment" + }, + + 'standard': { + 1: "scheme", + 4: "user", + 5: "pass", + 6: "host", + 7: "port", + 9: "path", + 12: "query", + 13: "fragment" + } + }, + results = {}, + match_keys, + is_mailto = false; + + var re = new RegExp(re_str); + var matches = re.exec(url); + + // if the scheme field is undefined it means we're using a protocol + // without :// and an @. Feel free to fix this in the re if you can >:O + if (matches[1] == undefined) { + match_keys = keys['mailto']; + is_mailto = true; + } else { + match_keys = keys['standard']; + } + + for (var i in match_keys) { + if (matches[i]) { + results[match_keys[i]] = matches[i]; + } + } + + // merge everything to path if not standard + if (is_mailto) { + var path = '', + new_results = {}; + + if (typeof(results['user']) != 'undefined' && typeof(results['host']) != 'undefined') { + path = results['user'] + '@' + results['host']; + delete results['user']; + delete results['host']; + } else if (typeof(results['user'])) { + path = results['user']; + delete results['user']; + } else if (typeof(results['host'])) { + path = results['host']; + delete results['host']; + } + + if (typeof(results['path']) != 'undefined') { + results['path'] = path + results['path']; + } else { + results['path'] = path; + } + + for (var prop in results) { + new_results[prop] = results[prop]; + } + + results = new_results; + } + + if (expand && typeof(results['query']) != 'undefined') { + results['query'] = elgg.parse_str(results['query']); + } + + if (component) { + if (typeof(results[component]) != 'undefined') { + return results[component]; + } else { + return false; + } + } + return results; +} + +/** + * Returns an object with key/values of the parsed query string. + * + * @param {String} string The string to parse + * @return {Object} The parsed object string + */ +elgg.parse_str = function(string) { + var params = {}; + var result, + key, + value, + re = /([^&=]+)=?([^&]*)/g; + + while (result = re.exec(string)) { + key = decodeURIComponent(result[1]) + value = decodeURIComponent(result[2]) + params[key] = value; + } + + return params; +}; + +/** * Returns a jQuery selector from a URL's fragement. Defaults to expecting an ID. * * Examples: @@ -382,6 +521,42 @@ elgg.getSelectorFromUrlFragment = function(url) { }; /** + * Adds child to object[parent] array. + * + * @param {Object} object The object to add to + * @param {String} parent The parent array to add to. + * @param {Mixed} value The value + */ +elgg.push_to_object_array = function(object, parent, value) { + elgg.assertTypeOf('object', object); + elgg.assertTypeOf('string', parent); + + if (!(object[parent] instanceof Array)) { + object[parent] = [] + } + + if (object[parent].indexOf(value) < 0) { + return object[parent].push(value); + } + + return false; +} + +/** + * Tests if object[parent] contains child + * + * @param {Object} object The object to add to + * @param {String} parent The parent array to add to. + * @param {Mixed} value The value + */ +elgg.is_in_object_array = function(object, parent, value) { + elgg.assertTypeOf('object', object); + elgg.assertTypeOf('string', parent); + + return typeof(object[parent]) != 'undefined' && object[parent].indexOf(value) >= 0; +} + +/** * Triggers the init hook when the library is ready * * Current requirements: diff --git a/js/lib/hooks.js b/js/lib/hooks.js index ab3a8a224..edfd28f24 100644 --- a/js/lib/hooks.js +++ b/js/lib/hooks.js @@ -3,13 +3,18 @@ */ elgg.provide('elgg.config.hooks'); +elgg.provide('elgg.config.instant_hooks'); +elgg.provide('elgg.config.triggered_hooks'); /** - * Registers an hook handler with the event system. + * Registers a hook handler with the event system. * * The special keyword "all" can be used for either the name or the type or both * and means to call that handler for all of those hooks. * + * Note that handlers registering for instant hooks will be executed immediately if the instant + * hook has been previously triggered. + * * @param {String} name Name of the plugin hook to register for * @param {String} type Type of the event to register for * @param {Function} handler Handle to call @@ -33,6 +38,11 @@ elgg.register_hook_handler = function(name, type, handler, priority) { priorities[name][type] = new elgg.ElggPriorityList(); } + // call if instant and already triggered. + if (elgg.is_instant_hook(name, type) && elgg.is_triggered_hook(name, type)) { + handler(name, type, null, null); + } + return priorities[name][type].insert(handler, priority); }; @@ -43,7 +53,9 @@ elgg.register_hook_handler = function(name, type, handler, priority) { * Every handler function will always be called, regardless of the return value. * * @warning Handlers take the same 4 arguments in the same order as when calling this function. - * This is different to the PHP version! + * This is different from the PHP version! + * + * @note Instant hooks do not support params or values. * * Hooks are called in this order: * specifically registered (event_name and event_type match) @@ -62,6 +74,9 @@ elgg.trigger_hook = function(name, type, params, value) { elgg.assertTypeOf('string', name); elgg.assertTypeOf('string', type); + // mark as triggered + elgg.set_triggered_hook(name, type); + // default to true if unpassed value = value || true; @@ -101,4 +116,58 @@ elgg.trigger_hook = function(name, type, params, value) { }); return (tempReturnValue !== null) ? tempReturnValue : returnValue; -};
\ No newline at end of file +}; + +/** + * Registers a hook as an instant hook. + * + * After being trigger once, registration of a handler to an instant hook will cause the + * handle to be executed immediately. + * + * @note Instant hooks must be triggered without params or defaults. Any params or default + * passed will *not* be passed to handlers executed upon registration. + * + * @param {String} name The hook name. + * @param {String} type The hook type. + * @return {Int} + */ +elgg.register_instant_hook = function(name, type) { + elgg.assertTypeOf('string', name); + elgg.assertTypeOf('string', type); + + return elgg.push_to_object_array(elgg.config.instant_hooks, name, type); +} + +/** + * Is this hook registered as an instant hook? + * + * @param {String} name The hook name. + * @param {String} type The hook type. + */ +elgg.is_instant_hook = function(name, type) { + return elgg.is_in_object_array(elgg.config.instant_hooks, name, type); +} + +/** + * Records that a hook has been triggered. + * + * @param {String} name The hook name. + * @param {String} type The hook type. + */ +elgg.set_triggered_hook = function(name, type) { + return elgg.push_to_object_array(elgg.config.triggered_hooks, name, type); +} + +/** + * Has this hook been triggered yet? + * + * @param {String} name The hook name. + * @param {String} type The hook type. + */ +elgg.is_triggered_hook = function(name, type) { + return elgg.is_in_object_array(elgg.config.triggered_hooks, name, type); +} + +elgg.register_instant_hook('init', 'system'); +elgg.register_instant_hook('ready', 'system'); +elgg.register_instant_hook('boot', 'system'); diff --git a/js/lib/security.js b/js/lib/security.js index 486347b88..d14ddff95 100644 --- a/js/lib/security.js +++ b/js/lib/security.js @@ -70,14 +70,22 @@ elgg.security.addToken = function(data) { // 'http://example.com?data=sofar' if (elgg.isString(data)) { - var args = []; - if (data) { - args.push(data); + var args = {}, + base = ''; + + // check for query strings + if (data.indexOf('?') != -1) { + var split = data.split('?'); + base = split[0]; + args = elgg.parse_str(split[1]); + } else { + base = data; } - args.push("__elgg_ts=" + elgg.security.token.__elgg_ts); - args.push("__elgg_token=" + elgg.security.token.__elgg_token); + + args["__elgg_ts"] = elgg.security.token.__elgg_ts; + args["__elgg_token"] = elgg.security.token.__elgg_token; - return args.join('&'); + return base + '?' + jQuery.param(args); } // no input! acts like a getter diff --git a/js/lib/ui.js b/js/lib/ui.js index 7abf7626f..57378a4d6 100644 --- a/js/lib/ui.js +++ b/js/lib/ui.js @@ -19,6 +19,8 @@ elgg.ui.init = function () { $('.elgg-requires-confirmation').live('click', elgg.ui.requiresConfirmation); + $('.elgg-autofocus').focus(); + if ($('.elgg-input-date').length) { elgg.ui.initDatePicker(); } |