aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Profitt <brett.profitt@gmail.com>2011-10-15 01:02:01 -0700
committerBrett Profitt <brett.profitt@gmail.com>2011-10-15 01:02:01 -0700
commit52fe9265add0b01699f63dd9b2aeeb4b248b02c1 (patch)
treedebc2d309150fedafab6f67f5c22264ee363c89c
parentbe5e5eaaac3844c19a804347676cdc58f959827a (diff)
downloadelgg-52fe9265add0b01699f63dd9b2aeeb4b248b02c1.tar.gz
elgg-52fe9265add0b01699f63dd9b2aeeb4b248b02c1.tar.bz2
Fixes #3540. Added "instant hooks" to JS hooks engine. elgg.register_instant_hook(name, type) will cause any handler registering to that hook to be immediately executed if the hook has been previously triggered. Open for better suggestions about the name.
-rw-r--r--js/lib/elgglib.js36
-rw-r--r--js/lib/hooks.js75
2 files changed, 108 insertions, 3 deletions
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js
index 96bd04d7c..0f17eeced 100644
--- a/js/lib/elgglib.js
+++ b/js/lib/elgglib.js
@@ -521,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');