123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- /**
- * @namespace Singleton object for holding the Elgg javascript library
- */
- var elgg = elgg || {};
- /**
- * Pointer to the global context
- *
- * @see elgg.require
- * @see elgg.provide
- */
- elgg.global = this;
- /**
- * Duplicate of the server side ACCESS_PRIVATE access level.
- *
- * This is a temporary hack to prevent having to mix up js and PHP in js views.
- */
- elgg.ACCESS_PRIVATE = 0;
- /**
- * 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;
- */
- elgg.abstractMethod = function() {
- throw new Error("Oops... you forgot to implement an abstract method!");
- };
- /**
- * Merges two or more objects together and returns the result.
- */
- elgg.extend = jQuery.extend;
- /**
- * 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.
- *
- * 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) {
- return typeof val === 'string';
- };
- /**
- * Check if the value is a number
- *
- * @param {*} val
- *
- * @return boolean
- */
- elgg.isNumber = function(val) {
- return typeof val === 'number';
- };
- /**
- * 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) {
- return typeof val === 'object';
- };
- /**
- * Check if the value is undefined
- *
- * @param {*} val
- *
- * @return boolean
- */
- elgg.isUndefined = function(val) {
- return val === undefined;
- };
- /**
- * Check if the value is null
- *
- * @param {*} val
- *
- * @return boolean
- */
- elgg.isNull = function(val) {
- return val === null;
- };
- /**
- * Check if the value is either null or undefined
- *
- * @param {*} val
- *
- * @return boolean
- */
- elgg.isNullOrUndefined = function(val) {
- return val == null;
- };
- /**
- * 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 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;
- for (i = 0; i < parts.length; i += 1) {
- part = parts[i];
- cur = cur[part];
- if (elgg.isUndefined(cur)) {
- throw new Error("Missing package: " + 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;
- for (i = 0; i < parts.length; i += 1) {
- part = parts[i];
- context[part] = context[part] || {};
- context = context[part];
- }
- };
- /**
- * 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) {
- * //equivalent of parent::__construct(a, b); in PHP
- * ParentClass.call(this, a, b);
- * }
- *
- * elgg.inherit(ChildClass, ParentClass);
- *
- * var child = new ChildClass('a', 'b', 'see');
- * child.foo('boo!'); // alert('boo!');
- * </pre>
- *
- * @param {Function} Child Child class constructor.
- * @param {Function} Parent Parent class constructor.
- */
- elgg.inherit = function(Child, Parent) {
- Child.prototype = new Parent();
- Child.prototype.constructor = Child;
- };
- /**
- * Converts shorthand urls to absolute urls.
- *
- * If the url is already absolute or protocol-relative, no change is made.
- *
- * elgg.normalize_url(''); // 'http://my.site.com/'
- * elgg.normalize_url('dashboard'); // 'http://my.site.com/dashboard'
- * elgg.normalize_url('http://google.com/'); // no change
- * elgg.normalize_url('//google.com/'); // no change
- *
- * @param {String} url The url to normalize
- * @return {String} The extended url
- */
- elgg.normalize_url = function(url) {
- url = url || '';
- elgg.assertTypeOf('string', url);
- function validate(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;
- };
- // ignore anything with a recognized scheme
- if (url.indexOf('http:') === 0 ||
- url.indexOf('https:') === 0 ||
- url.indexOf('javascript:') === 0 ||
- url.indexOf('mailto:') === 0 ) {
- return url;
- }
- // all normal URLs including mailto:
- else if (validate(url)) {
- return url;
- }
- // '//example.com' (Shortcut for protocol.)
- // '?query=test', #target
- else if ((new RegExp("^(\\#|\\?|//)", "i")).test(url)) {
- return url;
- }
- // watch those double escapes in JS.
- // 'install.php', 'install.php?step=step'
- else if ((new RegExp("^[^\/]*\\.php(\\?.*)?$", "i")).test(url)) {
- return elgg.config.wwwroot + url.ltrim('/');
- }
- // 'example.com', 'example.com/subpage'
- else if ((new RegExp("^[^/]*\\.", "i")).test(url)) {
- return 'http://' + url;
- }
- // 'page/handler', 'mod/plugin/file.php'
- else {
- // trim off any leading / because the site URL is stored
- // with a trailing /
- 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')
- * @private
- */
- elgg.system_messages = function(msgs, delay, type) {
- if (elgg.isUndefined(msgs)) {
- return;
- }
- var classes = ['elgg-message'],
- messages_html = [],
- appendMessage = function(msg) {
- messages_html.push('<li class="' + classes.join(' ') + '"><p>' + msg + '</p></li>');
- },
- systemMessages = $('ul.elgg-system-messages'),
- i;
- //validate delay. Must be a positive integer.
- delay = parseInt(delay || 6000, 10);
- if (isNaN(delay) || delay <= 0) {
- delay = 6000;
- }
- //Handle non-arrays
- if (!elgg.isArray(msgs)) {
- msgs = [msgs];
- }
- if (type === 'error') {
- classes.push('elgg-state-error');
- } else {
- classes.push('elgg-state-success');
- }
- msgs.forEach(appendMessage);
- if (type != 'error') {
- $(messages_html.join('')).appendTo(systemMessages)
- .animate({opacity: '1.0'}, delay).fadeOut('slow');
- } else {
- $(messages_html.join('')).appendTo(systemMessages);
- }
- };
- /**
- * Wrapper function for system_messages. Specifies "messages" as the type of message
- * @param {String} msgs The message to display
- * @param {Number} delay How long to display the message (milliseconds)
- */
- elgg.system_message = function(msgs, delay) {
- elgg.system_messages(msgs, delay, "message");
- };
- /**
- * Wrapper function for system_messages. Specifies "errors" as the type of message
- * @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");
- };
- /**
- * Logs a notice about use of a deprecated function or capability
- * @param {String} msg The deprecation message to display
- * @param {Number} dep_version The version the function was deprecated for
- * @since 1.9
- */
- elgg.deprecated_notice = function(msg, dep_version) {
- if (elgg.is_admin_logged_in()) {
- var parts = elgg.release.split('.');
- var elgg_major_version = parseInt(parts[0], 10);
- var elgg_minor_version = parseInt(parts[1], 10);
- var dep_major_version = Math.floor(dep_version);
- var dep_minor_version = 10 * (dep_version - dep_major_version);
- msg = "Deprecated in Elgg " + dep_version + ": " + msg;
- if ((dep_major_version < elgg_major_version) || (dep_minor_version < elgg_minor_version)) {
- elgg.register_error(msg);
- } else {
- if (typeof console !== "undefined") {
- console.warn(msg);
- }
- }
- }
- };
- /**
- * 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) {
- location.href = elgg.normalize_url(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.
- expand = expand || false;
- component = component || false;
-
- var 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 = {},
- result,
- key,
- value,
- re = /([^&=]+)=?([^&]*)/g,
- re2 = /\[\]$/;
- // assignment intentional
- while (result = re.exec(string)) {
- key = decodeURIComponent(result[1].replace(/\+/g, ' '));
- value = decodeURIComponent(result[2].replace(/\+/g, ' '));
- if (re2.test(key)) {
- key = key.replace(re2, '');
- if (!params[key]) {
- params[key] = [];
- }
- params[key].push(value);
- } else {
- 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;
- };
|