(function($, Site){
var document = window.document;
$.fn.contextualhoversetup = function() {
if (!Site || !Site.ctx_popup) return;
this.each(function() {
if (Site.ctx_popup_userhead)
_initUserhead(this);
if (Site.ctx_popup_icons)
_initIcons(this);
});
};
function _initUserhead(context) {
$("span.ljuser",context).each(function() {
var $usertag = $(this);
$("img", $usertag).each(function() {
// if the parent (a tag with link to userinfo) has userid in its URL, then
// this is an openid user icon and we should use the userid
var $head = $(this);
var href = $head.parent("a").attr("href");
var data = {};
var userid;
if (href && (userid = href.match(/\?userid=(\d+)/i)))
data.userid = userid[1];
else
data.username = $usertag.attr("lj:user");
if ( !data.username && !data.userid ) return;
data.type = "user";
$head.contextualhover( data );
});
});
}
function _initIcons(context) {
var old_icon_url = 'www\\.dreamwidth\\.org/userpic';
var url_prefix = "(^" + Site.iconprefix + "|" + old_icon_url + ")";
var re = new RegExp( url_prefix + "/\\d+\/\\d+$" );
$("img[src^='"+Site.iconprefix+"'],img[src*='"+old_icon_url+"']",context).each(function() {
var $icon = $(this);
if (!$icon.data("no-ctx") && this.src.match(re)) {
$icon.contextualhover({ "icon_url": this.src, type: "icon" });
}
});
}
})(jQuery, Site);
/* The contextual hover menu
appears:
- when you hover over the trigger a short period of time
- NOT if you merely pass the mouse over the trigger
lingers:
- as long as the mouse is over the trigger
- if you move the mouse from the trigger to the contextual popup
- as long as the mouse is over the tooltip
- NOT if you move the mouse away from the trigger before the popup is fully visible
- NOT if you move the mouse away from the trigger before the ajax request is done
disappears:
- when you move the mouse over then out of the contextual popup
- a short time after you move the mouse out of the trigger
(only if you don't then move it to the popup)
*/
$.widget("dw.contextualhover", {
options: {
disableAJAX: false,
username: undefined,
userid: undefined,
icon_url: undefined,
type: undefined // icon or user(head)
},
_create: function() {
var self = this;
var opts = self.options;
if ( opts.type == "icon" ) {
var parent = self.element.parent("a");
if ( parent.length > 0 )
self.element = parent;
}
var trigger = self.element;
trigger.addClass("ContextualPopup-trigger");
trigger.hoverIntent( {
// how long before the popup fades out automatically once you've moved away
timeout: 1500,
over: function() {
if ( self.cachedResults ) {
self._renderPopup();
return;
}
trigger.ajaxtip({
tooltipClass: "ContextualPopup",
loadingContent: "",
// called after the popup is opened
open: function(event, ui) {
var ns = event.handleObj.namespace;
var $trigger = $(this);
var $tooltip = ui.tooltip;
$tooltip.promise().done(function() {
// turn off the mouseleave/focusout events which close the popup immediately
// but only once fade in is done and popup is fully visible
// this is both a technical limitation
// (the callback fires before the events are registered in tooltip)
// and desired behavior
// (if the tooltip isn't fully visible yet, but they've moved away, assume they don't want it)
$trigger.off( "mouseleave." + ns + " focusout." + ns );
});
// the popup will also fade away after a short delay
// once you've moved your mouse away from the trigger
// this is to prevent the annoying behavior of the popup never going away
// HOWEVER we want to ignore the timeout if we've moused over the popup at any point
// so record if this has happened
$tooltip.one( "mouseover." +ns, function() {
// event from $.fn.hoverIntent
$trigger.data( "popup-persist", true );
} )
// attach listeners to links for dynamic actions
.on( "click", "a[data-dw-ctx-action]", function(e){
e.stopPropagation();
e.preventDefault();
self._changeRelation( $(this) );
});
},
// called after the popup has closed
close: function(event, ui) {
// cleanup
ui.tooltip.off( "mouseover." + event.handleObj.namespace );
}
}).ajaxtip( "load", {
endpoint: "ctxpopup",
ajax: {
context: self,
data: {
"user": opts.username || "",
"userid": opts.userid || 0,
"userpic_url": opts.icon_url || "",
"mode": "getinfo"
},
success: function( data, status, jqxhr ) {
if ( data.error ) {
if ( data.noshow ) {
trigger.ajaxtip( "close" );
} else {
trigger.ajaxtip( "error", data.error );
}
} else {
this.cachedResults = data;
this._renderPopup();
// expire cache after 5 minutes
setTimeout(function() {
self.cachedResults = null;
}, 60 * 5 * 1000);
}
}
}
});
},
out: function(e) {
var persist = trigger.data("popup-persist");
if ( ! persist ) {
trigger.ajaxtip( "abort" );
trigger.ajaxtip( "close" );
}
trigger.removeData("popup-persist");
}
} );
},
_addRelationStatus: function( string ) {
this._rel_html.push( "