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
$('.elgg-system-messages li').live('click', function() {
$(this).stop().fadeOut('fast');
});
$('.elgg-system-messages li').animate({opacity: 0.9}, 6000);
$('.elgg-system-messages li').fadeOut('slow');
$('[rel=toggle]').live('click', elgg.ui.toggles);
$('[rel=popup]').live('click', elgg.ui.popsUp);
$('.elgg-menu-page .elgg-menu-parent').live('click', elgg.ui.toggleMenu);
$('.elgg-requires-confirmation').live('click', elgg.ui.requiresConfirmation);
$('.elgg-autofocus').focus();
if ($('.elgg-input-date').length) {
elgg.ui.initDatePicker();
}
// avatar cropper
$('#user-avatar-cropper').imgAreaSelect({
selectionOpacity: 0,
aspectRatio: '1:1',
onSelectEnd: elgg.ui.avatarSelectChange,
onSelectChange: elgg.ui.avatarPreview
});
}
/**
* Toggles an element based on clicking a separate element
*
* Use rel="toggle" on the toggler element
* Set the href to target the item you want to toggle ()
*
* @param {Object} event
* @return void
*/
elgg.ui.toggles = function(event) {
event.preventDefault();
// @todo might want to switch this to elgg.getSelectorFromUrlFragment().
var target = $(this).toggleClass('elgg-state-active').attr('href');
$(target).slideToggle('medium');
}
/**
* 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 ()
*
* 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.popsUp = function(event) {
event.preventDefault();
event.stopPropagation();
var target = elgg.getSelectorFromUrlFragment($(this).toggleClass('elgg-state-active').attr('href'));
var $target = $(target);
// emit a hook to allow plugins to position and control popups
var params = {
targetSelector: target,
target: $target,
source: $(this)
};
var options = {
my: 'center top',
at: 'center bottom',
of: $(this),
collision: 'fit fit'
}
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
*
* @param {Object} event
* @return void
*/
elgg.ui.toggleMenu = function(event) {
$(this).siblings().slideToggle('medium');
$(this).toggleClass('elgg-menu-closed elgg-menu-opened');
event.preventDefault();
}
/**
* Initialize the hover menu
*
* @param {Object} parent
* @return void
*/
elgg.ui.initHoverMenu = function(parent) {
if (!parent) {
parent = document;
}
// avatar image menu link
$(parent).find(".elgg-avatar").live('mouseover', function() {
$(this).children(".elgg-icon-hover-menu").show();
})
.live('mouseout', function() {
$(this).children(".elgg-icon-hover-menu").hide();
});
// avatar contextual menu
$(".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;
if (!$hovermenu) {
var $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");
// @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');
}
// hide any other open hover menus
$(".elgg-menu-hover:visible").not($hovermenu).fadeOut();
});
// hide avatar menu when user clicks elsewhere
$(document).click(function(event) {
if ($(event.target).parents(".elgg-avatar").length == 0) {
$(".elgg-menu-hover").fadeOut();
}
});
}
/**
* Calls a confirm() and prevents default if denied.
*
* @param {Object} e
* @return void
*/
elgg.ui.requiresConfirmation = function(e) {
var confirmText = $(this).attr('rel') || elgg.echo('question:areyousure');
if (!confirm(confirmText)) {
e.preventDefault();
}
};
/**
* 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() {
$('.elgg-input-date').datepicker({
// ISO-8601
dateFormat: 'yy-mm-dd',
onSelect: function(dateText) {
if ($(this).is('.elgg-input-timestamp')) {
// convert to unix timestamp
var date = $.datepicker.parseDate('yy-mm-dd', dateText);
var timestamp = $.datepicker.formatDate('@', date);
timestamp = timestamp / 1000;
var id = $(this).attr('id');
$('input[name="' + id + '"]').val(timestamp);
}
}
});
}
// Avatar cropping
// display a preview of the users cropped section
elgg.ui.avatarPreview = function(img, selection) {
// catch for the first click on the image
if (selection.width == 0 || selection.height == 0) {
return;
}
var origWidth = $("#user-avatar-cropper").width();
var origHeight = $("#user-avatar-cropper").height();
var scaleX = 100 / selection.width;
var scaleY = 100 / selection.height;
$('#user-avatar-preview > img').css({
width: Math.round(scaleX * origWidth) + 'px',
height: Math.round(scaleY * origHeight) + 'px',
marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px',
marginTop: '-' + Math.round(scaleY * selection.y1) + 'px'
});
}
// populate the form with the correct coordinates once a user has cropped their image
elgg.ui.avatarSelectChange = function(img, selection) {
$('input[name=x1]').val(selection.x1);
$('input[name=x2]').val(selection.x2);
$('input[name=y1]').val(selection.y1);
$('input[name=y2]').val(selection.y2);
}
elgg.register_hook_handler('init', 'system', elgg.ui.init);
elgg.register_hook_handler('getOptions', 'ui.popup', elgg.ui.LoginHandler);