aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-03-12 21:51:07 +0000
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-03-12 21:51:07 +0000
commit19b7ea9a394af6e8366c64faa77badb716d743a5 (patch)
tree81382762378c7e5c2f62f4208c5cf6ff3a048b1d
parent120488c29722c1cde9a4715ccbe0f1626d4738ae (diff)
downloadelgg-19b7ea9a394af6e8366c64faa77badb716d743a5.tar.gz
elgg-19b7ea9a394af6e8366c64faa77badb716d743a5.tar.bz2
Fixes #3065, #3089. Merged JS events and hooks to a single system. Updated plugins and core to use it. Added elgg.getURLFragment() and using it elgg.ui.popsUp().
git-svn-id: http://code.elgg.org/elgg/trunk@8671 36083f99-b078-4883-b0ff-0f9b5a30f544
-rw-r--r--js/lib/autocomplete.js2
-rw-r--r--js/lib/elgglib.js16
-rw-r--r--js/lib/events.js52
-rw-r--r--js/lib/hooks.js94
-rw-r--r--js/lib/languages.js2
-rw-r--r--js/lib/security.js2
-rw-r--r--js/lib/ui.js84
-rw-r--r--js/lib/ui.widgets.js2
-rw-r--r--js/lib/userpicker.js2
-rw-r--r--js/tests/ElggEventsTest.js28
-rw-r--r--js/tests/ElggHooksTest.js28
-rw-r--r--mod/blog/views/default/js/blog/save_draft.php2
-rw-r--r--mod/bookmarks/views/default/bookmarks/js.php2
-rw-r--r--mod/messageboard/views/default/messageboard/js.php2
-rw-r--r--mod/tinymce/views/default/js/tinymce.php2
-rw-r--r--mod/uservalidationbyemail/views/default/uservalidationbyemail/js.php2
-rw-r--r--views/default/core/account/login_box.php2
-rw-r--r--views/default/core/account/login_dropdown.php11
-rw-r--r--views/default/core/river/filter.php2
-rw-r--r--views/default/js/admin.php2
-rw-r--r--views/default/js/elgg.php7
21 files changed, 202 insertions, 144 deletions
diff --git a/js/lib/autocomplete.js b/js/lib/autocomplete.js
index eb59f51aa..917326d4f 100644
--- a/js/lib/autocomplete.js
+++ b/js/lib/autocomplete.js
@@ -36,4 +36,4 @@ elgg.autocomplete.init = function() {
};
};
-elgg.register_event_handler('init', 'system', elgg.autocomplete.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.autocomplete.init); \ No newline at end of file
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js
index 3b409d134..4137c4a7a 100644
--- a/js/lib/elgglib.js
+++ b/js/lib/elgglib.js
@@ -350,4 +350,18 @@ elgg.register_error = function(errors, delay) {
*/
elgg.forward = function(url) {
location.href = elgg.normalize_url(url);
-}; \ No newline at end of file
+};
+
+/**
+ * Returns the fragment part of the URL, including the #. Returns '' if no fragment.
+ *
+ * @param {String} url The URL.
+ */
+elgg.getUrlFragment = function(url) {
+ var fragment = url.split('#')[1];
+
+ if (fragment) {
+ return '#' + fragment;
+ }
+ return '';
+} \ No newline at end of file
diff --git a/js/lib/events.js b/js/lib/events.js
deleted file mode 100644
index c1aa6fd9a..000000000
--- a/js/lib/events.js
+++ /dev/null
@@ -1,52 +0,0 @@
-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();
- }
-
- return events[event_name][event_type].insert(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;
- };
-
- 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],
- events[event_name]['all'],
- events['all']['all']
- ].every(function(handlers) {
- return !(handlers instanceof elgg.ElggPriorityList) || handlers.every(callEventHandler);
- });
-}; \ No newline at end of file
diff --git a/js/lib/hooks.js b/js/lib/hooks.js
new file mode 100644
index 000000000..9c86a1fec
--- /dev/null
+++ b/js/lib/hooks.js
@@ -0,0 +1,94 @@
+/*
+ * Javascript hook interface
+ */
+
+elgg.provide('elgg.config.hooks');
+
+/**
+ * Registers an 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.
+ *
+ * @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
+ * @param {Number} priority Priority to call the event handler
+ * @return {Bool}
+ */
+elgg.register_hook_handler = function(name, type, handler, priority) {
+ elgg.assertTypeOf('string', name);
+ elgg.assertTypeOf('string', type);
+ elgg.assertTypeOf('function', handler);
+
+ if (!name || !type) {
+ return false;
+ }
+
+ var priorities = elgg.config.hooks;
+
+ elgg.provide(name + '.' + type, priorities);
+
+ if (!(priorities[name][type] instanceof elgg.ElggPriorityList)) {
+ priorities[name][type] = new elgg.ElggPriorityList();
+ }
+
+ return priorities[name][type].insert(handler, priority);
+};
+
+/**
+ * Emits a hook.
+ *
+ * Loops through all registered hooks and calls the handler functions in order.
+ * 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!
+ *
+ * Hooks are called in this order:
+ * specifically registered (event_name and event_type match)
+ * all names, specific type
+ * specific name, all types
+ * all names, all types
+ *
+ * @param {String} name Name of the hook to emit
+ * @param {String} type Type of the hook to emit
+ * @param {Object} params Optional parameters to pass to the handlers
+ * @param {Object} value Initial value of the return. Can be mangled by handlers
+ *
+ * @return {Bool}
+ */
+elgg.trigger_hook = function(name, type, params, value) {
+ elgg.assertTypeOf('string', name);
+ elgg.assertTypeOf('string', type);
+
+ // default to true if unpassed
+ value = value || true;
+
+ var hooks = elgg.config.hooks,
+ tempReturnValue = null,
+ returnValue = value,
+ callHookHandler = function(handler) {
+ tempReturnValue = handler(name, type, params, value);
+ // always continue through all the handlers
+ return true;
+ };
+
+ elgg.provide(name + '.' + type, hooks);
+ elgg.provide('all.' + type, hooks);
+ elgg.provide(name + '.all', hooks);
+ elgg.provide('all.all', hooks);
+
+ [ hooks[name][type],
+ hooks['all'][type],
+ hooks[name]['all'],
+ hooks['all']['all']
+ ].every(function(handlers) {
+ if (handlers instanceof elgg.ElggPriorityList) {
+ handlers.every(callHookHandler);
+ }
+ return true;
+ });
+
+ return tempReturnValue || returnValue;
+}; \ No newline at end of file
diff --git a/js/lib/languages.js b/js/lib/languages.js
index 10afa24b0..79768c471 100644
--- a/js/lib/languages.js
+++ b/js/lib/languages.js
@@ -86,4 +86,4 @@ elgg.config.translations.init = function() {
elgg.reload_all_translations();
};
-elgg.register_event_handler('boot', 'system', elgg.config.translations.init); \ No newline at end of file
+elgg.register_hook_handler('boot', 'system', elgg.config.translations.init); \ No newline at end of file
diff --git a/js/lib/security.js b/js/lib/security.js
index def775c05..d449d8887 100644
--- a/js/lib/security.js
+++ b/js/lib/security.js
@@ -73,4 +73,4 @@ elgg.security.init = function() {
setInterval(elgg.security.refreshToken, elgg.security.interval);
};
-elgg.register_event_handler('boot', 'system', elgg.security.init); \ No newline at end of file
+elgg.register_hook_handler('boot', 'system', elgg.security.init); \ No newline at end of file
diff --git a/js/lib/ui.js b/js/lib/ui.js
index c77c85aed..8d519a995 100644
--- a/js/lib/ui.js
+++ b/js/lib/ui.js
@@ -1,7 +1,6 @@
elgg.provide('elgg.ui');
elgg.ui.init = function () {
-
elgg.ui.initHoverMenu();
//if the user clicks a system message, make it disappear
@@ -46,13 +45,14 @@ elgg.ui.toggles = function(event) {
* Set the rel="popup" on the popper and set the href to target the
* item you want to toggle (<a rel="popup" href="#id-of-target">)
*
- * This function emits the popup, ui event that plugins can register for to provide custom
- * positioning for elements. The handler is passed an object with the values:
- * popupSelector: The selector used to find the popup
- * popup: The popup jQuery element as found by the selector
- * popper: The jquery element whose click event initiated a popup.
- *
- * The handler function must return false to tell this function to abort automatic placement.
+ * This function emits the getOptions, ui.popup hook that plugins can register for to provide custom
+ * positioning for elements. The handler is passed the following params:
+ * targetSelector: The selector used to find the popup
+ * target: The popup jQuery element as found by the selector
+ * source: The jquery element whose click event initiated a popup.
+ *
+ * The return value of the function is used as the options object to .position().
+ * Handles can also return false to abort the default behvior and override it with their own.
*
* @param {Object} event
* @return void
@@ -60,17 +60,26 @@ elgg.ui.toggles = function(event) {
elgg.ui.popsUp = function(event) {
event.preventDefault();
- var target = $(this).toggleClass('elgg-state-active').attr('href');
+ var target = elgg.getUrlFragment($(this).toggleClass('elgg-state-active').attr('href'));
var $target = $(target);
// emit a hook to allow plugins to position and control popups
- var obj = {
- popupSelector: target,
- popup: $target,
- popper: $(this)
+ var params = {
+ targetSelector: target,
+ target: $target,
+ source: $(this)
};
-
- if (!elgg.trigger_event('popup', 'ui', obj)) {
+
+ var options = {
+ my: 'center top',
+ at: 'center bottom',
+ of: $(this)
+ }
+
+ options = elgg.trigger_hook('getOptions', 'ui.popup', params, options);
+
+ // allow plugins to cancel event
+ if (!options) {
return;
}
@@ -82,11 +91,7 @@ elgg.ui.popsUp = function(event) {
$target.appendTo('body')
.fadeIn()
- .position({
- 'my': 'left top',
- 'at': 'right bottom',
- 'of': $(this)
- });
+ .position(options);
}
/**
@@ -164,7 +169,7 @@ elgg.ui.initHoverMenu = function(parent) {
/**
* Calls a confirm() and prevents default if denied.
*
- * @param {Object} event
+ * @param {Object} e
* @return void
*/
elgg.ui.requiresConfirmation = function(e) {
@@ -175,25 +180,24 @@ elgg.ui.requiresConfirmation = function(e) {
};
/**
- * Repositions the likes popup.
+ * Repositions the likes popup
+ *
+ * @param {String} hook 'getOptions'
+ * @param {String} type 'ui.popup'
+ * @param {Object} params An array of info about the target and source.
+ * @param {Object} options Options to pass to
+ *
+ * @return {Object}
*/
-elgg.ui.likesPopupHandler = function(event, type, object) {
- if (object.popup.hasClass('elgg-likes-list')) {
- if (object.popup.is(':visible')) {
- object.popup.fadeOut();
- return false;
- }
-
- object.popup.appendTo('body')
- .fadeIn()
- .position({
- 'my': 'right bottom',
- 'at': 'left top',
- 'of': object.popper
- });
+elgg.ui.likesPopupHandler = function(hook, type, params, options) {
+ if (params.target.hasClass('elgg-likes-list')) {
+ options.my = 'right bottom';
+ options.at = 'left top';
+ return options;
}
- return false;
-}
+ return null;
+};
-elgg.register_event_handler('init', 'system', elgg.ui.init);
-elgg.register_event_handler('popup', 'ui', elgg.ui.likesPopupHandler); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.ui.init);
+//elgg.register_hook_handler('popup', 'ui', elgg.ui.likesPopupHandler);
+elgg.register_hook_handler('getOptions', 'ui.popup', elgg.ui.likesPopupHandler); \ No newline at end of file
diff --git a/js/lib/ui.widgets.js b/js/lib/ui.widgets.js
index 1acc22928..fb256672a 100644
--- a/js/lib/ui.widgets.js
+++ b/js/lib/ui.widgets.js
@@ -199,4 +199,4 @@ elgg.ui.widgets.equalHeight = function(selector) {
$(selector).css('min-height', maxHeight);
}
-elgg.register_event_handler('init', 'system', elgg.ui.widgets.init);
+elgg.register_hook_handler('init', 'system', elgg.ui.widgets.init);
diff --git a/js/lib/userpicker.js b/js/lib/userpicker.js
index 5fc39bce3..b551ea830 100644
--- a/js/lib/userpicker.js
+++ b/js/lib/userpicker.js
@@ -81,4 +81,4 @@ elgg.userpicker.getSearchParams = function(e) {
}
}
-elgg.register_event_handler('init', 'system', elgg.userpicker.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.userpicker.init); \ No newline at end of file
diff --git a/js/tests/ElggEventsTest.js b/js/tests/ElggEventsTest.js
deleted file mode 100644
index 4765878cf..000000000
--- a/js/tests/ElggEventsTest.js
+++ /dev/null
@@ -1,28 +0,0 @@
-ElggEventsTest = TestCase("ElggEventsTest");
-
-ElggEventsTest.prototype.setUp = function() {
- elgg.config.events = {};
- elgg.provide('elgg.config.events.all.all');
-};
-
-ElggEventsTest.prototype.testEventHandlersMustBeFunctions = function () {
- assertException(function() { elgg.register_event_handler('str', 'str', 'oops'); });
-};
-
-ElggEventsTest.prototype.testReturnValueDefaultsToTrue = function () {
- assertTrue(elgg.trigger_event('fee', 'fum'));
-
- elgg.register_event_handler('fee', 'fum', elgg.nullFunction);
- assertTrue(elgg.trigger_event('fee', 'fum'));
-};
-
-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);
- assertException("all,all", function() { elgg.trigger_event('pinky', 'winky'); });
-}; \ No newline at end of file
diff --git a/js/tests/ElggHooksTest.js b/js/tests/ElggHooksTest.js
new file mode 100644
index 000000000..e7a2440e7
--- /dev/null
+++ b/js/tests/ElggHooksTest.js
@@ -0,0 +1,28 @@
+ElggHooksTest = TestCase("ElggHooksTest");
+
+ElggHooksTest.prototype.setUp = function() {
+ elgg.config.hooks = {};
+ elgg.provide('elgg.config.hooks.all.all');
+};
+
+ElggHooksTest.prototype.testHookHandlersMustBeFunctions = function () {
+ assertException(function() { elgg.register_hook_handler('str', 'str', 'oops'); });
+};
+
+ElggHooksTest.prototype.testReturnValueDefaultsToTrue = function () {
+ assertTrue(elgg.trigger_hook('fee', 'fum'));
+
+ elgg.register_hook_handler('fee', 'fum', elgg.nullFunction);
+ assertTrue(elgg.trigger_hook('fee', 'fum'));
+};
+
+ElggHooksTest.prototype.testCanGlomHooksWithAll = function () {
+ elgg.register_hook_handler('all', 'bar', elgg.abstractMethod);
+ assertException("all,bar", function() { elgg.trigger_hook('foo', 'bar'); });
+
+ elgg.register_hook_handler('foo', 'all', elgg.abstractMethod);
+ assertException("foo,all", function() { elgg.trigger_hook('foo', 'baz'); });
+
+ elgg.register_hook_handler('all', 'all', elgg.abstractMethod);
+ assertException("all,all", function() { elgg.trigger_hook('pinky', 'winky'); });
+}; \ No newline at end of file
diff --git a/mod/blog/views/default/js/blog/save_draft.php b/mod/blog/views/default/js/blog/save_draft.php
index 1d5ae5c39..fd76c870c 100644
--- a/mod/blog/views/default/js/blog/save_draft.php
+++ b/mod/blog/views/default/js/blog/save_draft.php
@@ -64,4 +64,4 @@ elgg.blog.init = function() {
setInterval(elgg.blog.saveDraft, 60000);
};
-elgg.register_event_handler('init', 'system', elgg.blog.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.blog.init); \ No newline at end of file
diff --git a/mod/bookmarks/views/default/bookmarks/js.php b/mod/bookmarks/views/default/bookmarks/js.php
index 35dc82f70..b2fcd88bd 100644
--- a/mod/bookmarks/views/default/bookmarks/js.php
+++ b/mod/bookmarks/views/default/bookmarks/js.php
@@ -8,4 +8,4 @@ elgg.bookmarks.init = function() {
e.attr('href', link);
}
-elgg.register_event_handler('init', 'system', elgg.bookmarks.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.bookmarks.init); \ No newline at end of file
diff --git a/mod/messageboard/views/default/messageboard/js.php b/mod/messageboard/views/default/messageboard/js.php
index 22aad10b7..b7da18a56 100644
--- a/mod/messageboard/views/default/messageboard/js.php
+++ b/mod/messageboard/views/default/messageboard/js.php
@@ -50,4 +50,4 @@ elgg.messageboard.deletePost = function(e) {
}
-elgg.register_event_handler('init', 'system', elgg.messageboard.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.messageboard.init); \ No newline at end of file
diff --git a/mod/tinymce/views/default/js/tinymce.php b/mod/tinymce/views/default/js/tinymce.php
index 4697e33a7..9809aa841 100644
--- a/mod/tinymce/views/default/js/tinymce.php
+++ b/mod/tinymce/views/default/js/tinymce.php
@@ -70,4 +70,4 @@ elgg.tinymce.init = function() {
}
-elgg.register_event_handler('init', 'system', elgg.tinymce.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.tinymce.init); \ No newline at end of file
diff --git a/mod/uservalidationbyemail/views/default/uservalidationbyemail/js.php b/mod/uservalidationbyemail/views/default/uservalidationbyemail/js.php
index c1ca58559..66cfcd6f6 100644
--- a/mod/uservalidationbyemail/views/default/uservalidationbyemail/js.php
+++ b/mod/uservalidationbyemail/views/default/uservalidationbyemail/js.php
@@ -24,4 +24,4 @@ elgg.uservalidationbyemail.init = function() {
});
};
-elgg.register_event_handler('init', 'system', elgg.uservalidationbyemail.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.uservalidationbyemail.init); \ No newline at end of file
diff --git a/views/default/core/account/login_box.php b/views/default/core/account/login_box.php
index 40b5f5637..274172bdb 100644
--- a/views/default/core/account/login_box.php
+++ b/views/default/core/account/login_box.php
@@ -20,7 +20,7 @@ echo elgg_view_module('aside', $title, $body);
<script type="text/javascript">
- elgg.register_event_handler('init', 'system', function() {
+ elgg.register_hook_handler('init', 'system', function() {
$('input[name=username]').focus();
});
</script>
diff --git a/views/default/core/account/login_dropdown.php b/views/default/core/account/login_dropdown.php
index f3f105be1..a1d64a768 100644
--- a/views/default/core/account/login_dropdown.php
+++ b/views/default/core/account/login_dropdown.php
@@ -1,8 +1,6 @@
<?php
/**
* Elgg drop-down login form
- *
- * @todo Forms 1.8: Convert to use elgg_view_form()
*/
if (elgg_is_logged_in()) {
@@ -19,12 +17,11 @@ $body = elgg_view_form('login', array('action' => "{$login_url}action/login"), a
<div id="login-dropdown">
<?php
echo elgg_view('output/url', array(
- 'href' => 'login',
+ 'href' => 'login#login-dropdown-box',
+ 'rel' => 'popup',
+ 'class' => 'elgg-button elgg-button-dropdown',
'text' => elgg_echo('login'),
));
echo elgg_view_module('dropdown', '', $body, array('id' => 'login-dropdown-box'));
?>
-</div>
-<script>
- $('#login-dropdown > a').attr('href', '#login-dropdown-box').addClass('elgg-toggler elgg-button elgg-button-dropdown');
-</script> \ No newline at end of file
+</div> \ No newline at end of file
diff --git a/views/default/core/river/filter.php b/views/default/core/river/filter.php
index 0df10675c..87380b561 100644
--- a/views/default/core/river/filter.php
+++ b/views/default/core/river/filter.php
@@ -37,7 +37,7 @@ echo elgg_view('input/dropdown', $params);
?>
<?php //@todo JS 1.8: no ?>
<script type="text/javascript">
-elgg.register_event_handler('init', 'system', function() {
+elgg.register_hook_handler('init', 'system', function() {
$('#elgg-river-selector').change(function() {
var url = window.location.href;
if (window.location.search.length) {
diff --git a/views/default/js/admin.php b/views/default/js/admin.php
index 15c74d4de..afffe95f0 100644
--- a/views/default/js/admin.php
+++ b/views/default/js/admin.php
@@ -146,4 +146,4 @@ elgg.admin.moveProfileField = function(e, ui) {
});
}
-elgg.register_event_handler('init', 'system', elgg.admin.init, 1000); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.admin.init, 1000); \ No newline at end of file
diff --git a/views/default/js/elgg.php b/views/default/js/elgg.php
index 9ddd6907a..018db7967 100644
--- a/views/default/js/elgg.php
+++ b/views/default/js/elgg.php
@@ -28,7 +28,7 @@ foreach ($model_files as $file) {
$libs = array(
//libraries
'prototypes',
- 'events',
+ 'hooks',
'security',
'languages',
'ajax',
@@ -59,11 +59,12 @@ elgg.security.interval = 5 * 60 * 1000; <?php //@todo make this configurable ?>
//Mimic PHP engine boot process
//Before the DOM is ready -- note that plugins aren't loaded yet
-elgg.trigger_event('boot', 'system');
+elgg.trigger_hook('boot', 'system');
//After the DOM is ready
$(function() {
- elgg.trigger_event('init', 'system');
+ elgg.trigger_hook('init', 'system');
+ elgg.trigger_hook('ready', 'system');
});
<?php