diff options
Diffstat (limited to 'js/lib/elgglib.js')
| -rw-r--r-- | js/lib/elgglib.js | 241 |
1 files changed, 223 insertions, 18 deletions
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js index 7a329621b..a8e187f1d 100644 --- a/js/lib/elgglib.js +++ b/js/lib/elgglib.js @@ -224,8 +224,8 @@ elgg.provide = function(pkg, opt_context) { * child.foo('boo!'); // alert('boo!'); * </pre> * - * @param {Function} childCtor Child class. - * @param {Function} parentCtor Parent class. + * @param {Function} Child Child class constructor. + * @param {Function} Parent Parent class constructor. */ elgg.inherit = function(Child, Parent) { Child.prototype = new Parent(); @@ -238,7 +238,7 @@ elgg.inherit = function(Child, Parent) { * If the url is already absolute or protocol-relative, no change is made. * * elgg.normalize_url(''); // 'http://my.site.com/' - * elgg.normalize_url('pg/dashboard'); // 'http://my.site.com/pg/dashboard' + * elgg.normalize_url('dashboard'); // 'http://my.site.com/dashboard' * elgg.normalize_url('http://google.com/'); // no change * elgg.normalize_url('//google.com/'); // no change * @@ -250,13 +250,40 @@ elgg.normalize_url = function(url) { url = url || ''; elgg.assertTypeOf('string', url); - // jslint complains if you use /regexp/ shorthand here... ?!?! - if ((new RegExp("^(https?:)?//", "i")).test(url)) { + validated = (function(url) { + url = elgg.parse_url(url); + if (url.scheme){ + url.scheme = url.scheme.toLowerCase(); + } + if (url.scheme == 'http' || url.scheme == 'https') { + if (!url.host) { + return false; + } + /* hostname labels may contain only alphanumeric characters, dots and hypens. */ + if (!(new RegExp("^([a-zA-Z0-9][a-zA-Z0-9\\-\\.]*)$", "i")).test(url.host) || url.host.charAt(-1) == '.') { + return false; + } + } + /* some schemas allow the host to be empty */ + if (!url.scheme || !url.host && url.scheme != 'mailto' && url.scheme != 'news' && url.scheme != 'file') { + return false; + } + return true; + })(url); + + // all normal URLs including mailto: + if (validated) { + return url; + } + + // '//example.com' (Shortcut for protocol.) + // '?query=test', #target + else if ((new RegExp("^(\\#|\\?|//)", "i")).test(url)) { return url; } // 'javascript:' - else if (url.indexOf('javascript:') === 0) { + else if (url.indexOf('javascript:') === 0 || url.indexOf('mailto:') === 0 ) { return url; } @@ -272,7 +299,7 @@ elgg.normalize_url = function(url) { return 'http://' + url; } - // 'pg/page/handler', 'mod/plugin/file.php' + // 'page/handler', 'mod/plugin/file.php' else { // trim off any leading / because the site URL is stored // with a trailing / @@ -296,7 +323,7 @@ elgg.system_messages = function(msgs, delay, type) { var classes = ['elgg-message'], messages_html = [], appendMessage = function(msg) { - messages_html.push('<li class="' + classes.join(' ') + '"><div class="elgg-text"><p>' + msg + '</p></div></li>'); + messages_html.push('<li class="' + classes.join(' ') + '"><p>' + msg + '</p></li>'); }, systemMessages = $('ul.elgg-system-messages'), i; @@ -320,18 +347,17 @@ elgg.system_messages = function(msgs, delay, type) { msgs.forEach(appendMessage); - // create the system messages ul element if needed - if (!systemMessages.length) { - systemMessages = $('<ul class="elgg-system-messages"></ul>').appendTo('body'); + if (type != 'error') { + $(messages_html.join('')).appendTo(systemMessages) + .animate({opacity: '1.0'}, delay).fadeOut('slow'); + } else { + $(messages_html.join('')).appendTo(systemMessages); } - - $(messages_html.join('')).appendTo(systemMessages) - .animate({opacity: '1.0'}, delay).fadeOut('slow'); }; /** * Wrapper function for system_messages. Specifies "messages" as the type of message - * @param {String} msg The message to display + * @param {String} msgs The message to display * @param {Number} delay How long to display the message (milliseconds) */ elgg.system_message = function(msgs, delay) { @@ -340,8 +366,8 @@ elgg.system_message = function(msgs, delay) { /** * Wrapper function for system_messages. Specifies "errors" as the type of message - * @param {String} error The error message to display - * @param {Number} delay How long to dispaly the error message (milliseconds) + * @param {String} errors The error message to display + * @param {Number} delay How long to dispaly the error message (milliseconds) */ elgg.register_error = function(errors, delay) { elgg.system_messages(errors, delay, "error"); @@ -355,4 +381,183 @@ elgg.register_error = function(errors, delay) { */ elgg.forward = function(url) { location.href = elgg.normalize_url(url); -};
\ No newline at end of file +}; + +/** + * 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 = { + 1: "scheme", + 4: "user", + 5: "pass", + 6: "host", + 7: "port", + 9: "path", + 12: "query", + 13: "fragment" + }, + results = {}; + + if (url.indexOf('mailto:') === 0) { + results['scheme'] = 'mailto'; + results['path'] = url.replace('mailto:', ''); + return results; + } + + if (url.indexOf('javascript:') === 0) { + results['scheme'] = 'javascript'; + results['path'] = url.replace('javascript:', ''); + return results; + } + + var re = new RegExp(re_str); + var matches = re.exec(url); + + for (var i in keys) { + if (matches[i]) { + results[keys[i]] = matches[i]; + } + } + + 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].replace(/\+/g, ' ')); + value = decodeURIComponent(result[2].replace(/\+/g, ' ')); + params[key] = value; + } + + return params; +}; + +/** + * Returns a jQuery selector from a URL's fragement. Defaults to expecting an ID. + * + * Examples: + * http://elgg.org/download.php returns '' + * http://elgg.org/download.php#id returns #id + * http://elgg.org/download.php#.class-name return .class-name + * http://elgg.org/download.php#a.class-name return a.class-name + * + * @param {String} url The URL + * @return {String} The selector + */ +elgg.getSelectorFromUrlFragment = function(url) { + var fragment = url.split('#')[1]; + + if (fragment) { + // this is a .class or a tag.class + if (fragment.indexOf('.') > -1) { + return fragment; + } + + // this is an id + else { + return '#' + fragment; + } + } + return ''; +}; + +/** + * 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 ($.inArray(value, object[parent]) < 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' && $.inArray(value, object[parent]) >= 0; +}; + +/** + * Triggers the init hook when the library is ready + * + * Current requirements: + * - DOM is ready + * - languages loaded + * + */ +elgg.initWhenReady = function() { + if (elgg.config.languageReady && elgg.config.domReady) { + elgg.trigger_hook('init', 'system'); + elgg.trigger_hook('ready', 'system'); + } +}; |
