aboutsummaryrefslogtreecommitdiff
path: root/js/lib/ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib/ui.js')
-rw-r--r--js/lib/ui.js255
1 files changed, 198 insertions, 57 deletions
diff --git a/js/lib/ui.js b/js/lib/ui.js
index 3448d6b35..413078b4f 100644
--- a/js/lib/ui.js
+++ b/js/lib/ui.js
@@ -1,7 +1,7 @@
elgg.provide('elgg.ui');
elgg.ui.init = function () {
-
+ // add user hover menus
elgg.ui.initHoverMenu();
//if the user clicks a system message, make it disappear
@@ -10,45 +10,136 @@ elgg.ui.init = function () {
});
$('.elgg-system-messages li').animate({opacity: 0.9}, 6000);
- $('.elgg-system-messages li').fadeOut('slow');
+ $('.elgg-system-messages li.elgg-state-success').fadeOut('slow');
- $('.elgg-toggle').live('click', elgg.ui.toggle);
- $('.elgg-toggler').live('click', elgg.ui.toggles);
+ $('[rel=toggle]').live('click', elgg.ui.toggles);
- $('.elgg-menu-page .elgg-menu-parent').live('click', elgg.ui.toggleMenu);
+ $('[rel=popup]').live('click', elgg.ui.popupOpen);
- $('.elgg-like-toggle').live('click', elgg.ui.toggleLikes);
+ $('.elgg-menu-page .elgg-menu-parent').live('click', elgg.ui.toggleMenu);
$('.elgg-requires-confirmation').live('click', elgg.ui.requiresConfirmation);
-}
+
+ $('.elgg-autofocus').focus();
+};
/**
* Toggles an element based on clicking a separate element
*
- * Use .elgg-toggle on the toggler element
- * The id of the toggler is elgg-toggler-<id>
- * The id of the element being toggled is elgg-togglee-<id>
+ * Use rel="toggle" on the toggler element
+ * Set the href to target the item you want to toggle (<a rel="toggle" href="#id-of-target">)
*
* @param {Object} event
* @return void
*/
-elgg.ui.toggle = function(event) {
+elgg.ui.toggles = function(event) {
event.preventDefault();
- var id = $(this).toggleClass('elgg-state-active').attr('id').replace('toggler', 'togglee');
+ // @todo might want to switch this to elgg.getSelectorFromUrlFragment().
+ var target = $(this).toggleClass('elgg-state-active').attr('href');
- $('#' + id).slideToggle('medium');
-}
+ $(target).slideToggle('medium');
+};
-elgg.ui.toggles = function(event) {
+/**
+ * Pops up an element based on clicking a separate element
+ *
+ * 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 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
+ */
+elgg.ui.popupOpen = function(event) {
event.preventDefault();
+ event.stopPropagation();
+
+ var target = elgg.getSelectorFromUrlFragment($(this).toggleClass('elgg-state-active').attr('href'));
+ var $target = $(target);
- $(this).toggleClass('elgg-state-active');
+ // emit a hook to allow plugins to position and control popups
+ var params = {
+ targetSelector: target,
+ target: $target,
+ source: $(this)
+ };
- var togglees = $(this).attr('class').match(/elgg-toggles-[^ ]*/i);
+ var options = {
+ my: 'center top',
+ at: 'center bottom',
+ of: $(this),
+ collision: 'fit fit'
+ }
- $('#' + togglees[0].replace('elgg-toggles-', '')).slideToggle('medium');
-}
+ options = elgg.trigger_hook('getOptions', 'ui.popup', params, options);
+
+ // allow plugins to cancel event
+ if (!options) {
+ return;
+ }
+
+ // hide if already open
+ if ($target.is(':visible')) {
+ $target.fadeOut();
+ $('body').die('click', elgg.ui.popupClose);
+ return;
+ }
+
+ $target.appendTo('body')
+ .fadeIn()
+ .position(options);
+
+ $('body')
+ .die('click', elgg.ui.popupClose)
+ .live('click', elgg.ui.popupClose);
+};
+
+/**
+ * Catches clicks that aren't in a popup and closes all popups.
+ */
+elgg.ui.popupClose = function(event) {
+ $eventTarget = $(event.target);
+ var inTarget = false;
+ var $popups = $('[rel=popup]');
+
+ // if the click event target isn't in a popup target, fade all of them out.
+ $popups.each(function(i, e) {
+ var target = elgg.getSelectorFromUrlFragment($(e).attr('href')) + ':visible';
+ var $target = $(target);
+
+ if (!$target.is(':visible')) {
+ return;
+ }
+
+ // didn't click inside the target
+ if ($eventTarget.closest(target).length > 0) {
+ inTarget = true;
+ return false;
+ }
+ });
+
+ if (!inTarget) {
+ $popups.each(function(i, e) {
+ var $e = $(e);
+ var $target = $(elgg.getSelectorFromUrlFragment($e.attr('href')) + ':visible');
+ if ($target.length > 0) {
+ $target.fadeOut();
+ $e.removeClass('elgg-state-active');
+ }
+ });
+
+ $('body').die('click', elgg.ui.popClose);
+ }
+};
/**
* Toggles a child menu when the parent is clicked
@@ -60,34 +151,7 @@ elgg.ui.toggleMenu = function(event) {
$(this).siblings().slideToggle('medium');
$(this).toggleClass('elgg-menu-closed elgg-menu-opened');
event.preventDefault();
-}
-
-/**
- * Toggles the likes list
- *
- * @param {Object} event
- * @return void
- */
-elgg.ui.toggleLikes = function(event) {
- var $list = $(this).next(".elgg-likes-list");
- var position = $(this).position();
- var startTop = position.top;
- var stopTop = position.top - $list.height();
- if ($list.css('display') == 'none') {
- $('.elgg-likes-list').fadeOut();
-
- $list.css('top', startTop);
- $list.css('left', position.left - $list.width());
- $list.animate({opacity: "toggle", top: stopTop}, 500);
-
- $list.click(function(event) {
- $list.fadeOut();
- });
- } else {
- $list.animate({opacity: "toggle", top: startTop}, 500);
- }
- event.preventDefault();
-}
+};
/**
* Initialize the hover menu
@@ -101,26 +165,39 @@ elgg.ui.initHoverMenu = function(parent) {
}
// avatar image menu link
- $(parent).find(".elgg-avatar").mouseover(function() {
+ $(parent).find(".elgg-avatar").live('mouseover', function() {
$(this).children(".elgg-icon-hover-menu").show();
})
- .mouseout(function() {
+ .live('mouseout', function() {
$(this).children(".elgg-icon-hover-menu").hide();
});
// avatar contextual menu
- $(".elgg-avatar > .elgg-icon-hover-menu").click(function(e) {
+ $(".elgg-avatar > .elgg-icon-hover-menu").live('click', function(e) {
+ // check if we've attached the menu to this element already
+ var $hovermenu = $(this).data('hovermenu') || null;
- var $hovermenu = $(this).parent().find(".elgg-menu-hover");
+ if (!$hovermenu) {
+ $hovermenu = $(this).parent().find(".elgg-menu-hover");
+ $(this).data('hovermenu', $hovermenu);
+ }
// close hovermenu if arrow is clicked & menu already open
if ($hovermenu.css('display') == "block") {
$hovermenu.fadeOut();
} else {
$avatar = $(this).closest(".elgg-avatar");
- $hovermenu.css("top", ($avatar.height()) + "px")
- .css("left", ($avatar.width()-15) + "px")
+
+ // @todo Use jQuery-ui position library instead -- much simpler
+ var offset = $avatar.offset();
+ var top = $avatar.height() + offset.top + 'px';
+ var left = $avatar.width() - 15 + offset.left + 'px';
+
+ $hovermenu.appendTo('body')
+ .css('position', 'absolute')
+ .css("top", top)
+ .css("left", left)
.fadeIn('normal');
}
@@ -134,19 +211,83 @@ elgg.ui.initHoverMenu = function(parent) {
$(".elgg-menu-hover").fadeOut();
}
});
-}
+};
/**
* Calls a confirm() and prevents default if denied.
*
- * @param {Object} event
+ * @param {Object} e
* @return void
*/
elgg.ui.requiresConfirmation = function(e) {
- var confirmText = $(this).attr('title') || elgg.echo('question:areyousure');
+ var confirmText = $(this).attr('rel') || elgg.echo('question:areyousure');
if (!confirm(confirmText)) {
e.preventDefault();
}
};
-elgg.register_event_handler('init', 'system', elgg.ui.init); \ No newline at end of file
+/**
+ * Repositions the login 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.loginHandler = function(hook, type, params, options) {
+ if (params.target.attr('id') == 'login-dropdown-box') {
+ options.my = 'right top';
+ options.at = 'right bottom';
+ return options;
+ }
+ return null;
+};
+
+/**
+ * Initialize the date picker
+ *
+ * Uses the class .elgg-input-date as the selector.
+ *
+ * If the class .elgg-input-timestamp is set on the input element, the onSelect
+ * method converts the date text to a unix timestamp in seconds. That value is
+ * stored in a hidden element indicated by the id on the input field.
+ *
+ * @return void
+ */
+elgg.ui.initDatePicker = function() {
+ var loadDatePicker = function() {
+ $('.elgg-input-date').datepicker({
+ // ISO-8601
+ dateFormat: 'yy-mm-dd',
+ onSelect: function(dateText) {
+ if ($(this).is('.elgg-input-timestamp')) {
+ // convert to unix timestamp
+ var dateParts = dateText.split("-");
+ var timestamp = Date.UTC(dateParts[0], dateParts[1] - 1, dateParts[2]);
+ timestamp = timestamp / 1000;
+
+ var id = $(this).attr('id');
+ $('input[name="' + id + '"]').val(timestamp);
+ }
+ }
+ });
+ };
+
+ if ($('.elgg-input-date').length && elgg.get_language() == 'en') {
+ loadDatePicker();
+ } else if ($('.elgg-input-date').length) {
+ elgg.get({
+ url: elgg.config.wwwroot + 'vendors/jquery/i18n/jquery.ui.datepicker-'+ elgg.get_language() +'.js',
+ dataType: "script",
+ cache: true,
+ success: loadDatePicker,
+ error: loadDatePicker // english language is already loaded.
+ });
+ }
+};
+
+elgg.register_hook_handler('init', 'system', elgg.ui.init);
+elgg.register_hook_handler('init', 'system', elgg.ui.initDatePicker);
+elgg.register_hook_handler('getOptions', 'ui.popup', elgg.ui.loginHandler);