X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=view%2Ftheme%2Ffrio%2Fjs%2Fhovercard.js;h=464c7e06e1af84e015fab5f3a9f527d547157892;hb=8536b313a1eb1c3e11f9ba5317fdcef33118bcb8;hp=c3396b7626aecc4eb2923d76d067008132066f48;hpb=e4917503dae5b3b97a6414f55b716a1fd7d24bc1;p=friendica.git
diff --git a/view/theme/frio/js/hovercard.js b/view/theme/frio/js/hovercard.js
index c3396b7626..464c7e06e1 100644
--- a/view/theme/frio/js/hovercard.js
+++ b/view/theme/frio/js/hovercard.js
@@ -7,279 +7,179 @@
* It is licensed under the GNU Affero General Public License
*
*/
-$(document).ready(function(){
- // Elements with the class "userinfo" will get a hover-card.
- // Note that this elements does need a href attribute which links to
- // a valid profile url
- $("body").on("mouseover", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function(e) {
- var timeNow = new Date().getTime();
- removeAllhoverCards(e,timeNow);
- var hoverCardData = false;
- var hrefAttr = false;
- var targetElement = $(this);
-
- // get href-attribute
- if(targetElement.is('[href]')) {
- hrefAttr = targetElement.attr('href');
- } else {
- return true;
- }
-
- // no hover card if the element has the no-hover-card class
- if(targetElement.hasClass('no-hover-card')) {
- return true;
- }
-
- // no hovercard for anchor links
- if(hrefAttr.substring(0,1) == '#') {
- return true;
- }
+$(document).ready(function () {
+ let $body = $('body');
+ // Prevents normal click action on click hovercard elements
+ $body.on('click', '.userinfo.click-card', function (e) {
+ e.preventDefault();
+ });
+ // This event listener needs to be declared before the one that removes
+ // all cards so that we can stop the immediate propagation of the event
+ // Since the manual popover appears instantly and the hovercard removal is
+ // on a 100ms delay, leaving event propagation immediately hides any click hovercard
+ $body.on('mousedown', '.userinfo.click-card', function (e) {
+ e.stopImmediatePropagation();
+ let timeNow = new Date().getTime();
+
+ let contactUrl = false;
+ let targetElement = $(this);
+
+ // get href-attribute
+ if (targetElement.is('[href]')) {
+ contactUrl = targetElement.attr('href');
+ } else {
+ return true;
+ }
- targetElement.attr('data-awaiting-hover-card',timeNow);
+ // no hovercard for anchor links
+ if (contactUrl.substring(0, 1) === '#') {
+ return true;
+ }
- // Take link href attribute as link to the profile
- var profileurl = hrefAttr;
- // the url to get the contact and template data
- var url = baseurl + "/hovercard";
+ openHovercard(targetElement, contactUrl, timeNow);
+ });
- // store the title in an other data attribute beause bootstrap
- // popover destroys the title.attribute. We can restore it later
- var title = targetElement.attr("title");
- targetElement.attr({"data-orig-title": title, title: ""});
+ // hover cards should be removed very easily, e.g. when any of these events happens
+ $body.on('mouseleave touchstart scroll mousedown submit keydown', function (e) {
+ // remove hover card only for desktiop user, since on mobile we open the hovercards
+ // by click event insteadof hover
+ removeAllHovercards(e, new Date().getTime());
+ });
- // if the device is a mobile open the hover card by click and not by hover
- if(typeof is_mobile != "undefined") {
- targetElement[0].removeAttribute("href");
- var hctrigger = 'click';
- } else {
- var hctrigger = 'manual';
- };
+ $body.on('mouseover', '.userinfo.hover-card, .wall-item-responses a, .wall-item-bottom .mention a', function (e) {
+ let timeNow = new Date().getTime();
+ removeAllHovercards(e, timeNow);
+ let contactUrl = false;
+ let targetElement = $(this);
+
+ // get href-attribute
+ if (targetElement.is('[href]')) {
+ contactUrl = targetElement.attr('href');
+ } else {
+ return true;
+ }
- // Timeoute until the hover-card does appear
- setTimeout(function(){
- if(targetElement.is(":hover") && parseInt(targetElement.attr('data-awaiting-hover-card'),10) == timeNow) {
- if($('.hovercard').length == 0) { // no card if there already is one open
- // get an additional data atribute if the card is active
- targetElement.attr('data-hover-card-active',timeNow);
- // get the whole html content of the hover card and
- // push it to the bootstrap popover
- getHoverCardContent(profileurl, url, function(data){
- if(data) {
- targetElement.popover({
- html: true,
- placement: function () {
- // Calculate the placement of the the hovercard (if top or bottom)
- // The placement depence on the distance between window top and the element
- // which triggers the hover-card
- var get_position = $(targetElement).offset().top - $(window).scrollTop();
- if (get_position < 270 ){
- return "bottom";
- }
- return "top";
- },
- trigger: hctrigger,
- template: '
',
- content: data,
- container: "body",
- }).popover('show');
- }
- });
- }
- }
- }, 500);
- }).on("mouseleave", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function(e) { // action when mouse leaves the hover-card
- var timeNow = new Date().getTime();
- // copy the original title to the title atribute
- var title = $(this).attr("data-orig-title");
- $(this).attr({"data-orig-title": "", title: title});
- removeAllhoverCards(e,timeNow);
- });
+ // no hover card if the element has the no-hover-card class
+ if (targetElement.hasClass('no-hover-card')) {
+ return true;
+ }
+ // no hovercard for anchor links
+ if (contactUrl.substring(0, 1) === '#') {
+ return true;
+ }
+ targetElement.attr('data-awaiting-hover-card', timeNow);
- // hover cards should be removed very easily, e.g. when any of these events happen
- $('body').on("mouseleave touchstart scroll click dblclick mousedown mouseup submit keydown keypress keyup", function(e){
- // remove hover card only for desktiop user, since on mobile we openen the hovercards
- // by click event insteadof hover
- if(typeof is_mobile == "undefined") {
- var timeNow = new Date().getTime();
- removeAllhoverCards(e,timeNow);
- };
+ // Delay until the hover-card does appear
+ setTimeout(function () {
+ if (
+ targetElement.is(':hover')
+ && parseInt(targetElement.attr('data-awaiting-hover-card'), 10) === timeNow
+ && $('.hovercard').length === 0
+ ) {
+ openHovercard(targetElement, contactUrl, timeNow);
+ }
+ }, 500);
+ }).on('mouseleave', '.userinfo.hover-card, .wall-item-responses a, .wall-item-bottom .mention a', function (e) { // action when mouse leaves the hover-card
+ removeAllHovercards(e, new Date().getTime());
});
// if we're hovering a hover card, give it a class, so we don't remove it
- $('body').on('mouseover','.hovercard', function(e) {
+ $body.on('mouseover', '.hovercard', function (e) {
$(this).addClass('dont-remove-card');
});
- $('body').on('mouseleave','.hovercard', function(e) {
+
+ $body.on('mouseleave', '.hovercard', function (e) {
$(this).removeClass('dont-remove-card');
- $(this).popover("hide");
+ $(this).popover('hide');
});
-
}); // End of $(document).ready
// removes all hover cards
-function removeAllhoverCards(event,priorTo) {
+function removeAllHovercards(event, priorTo) {
// don't remove hovercards until after 100ms, so user have time to move the cursor to it (which gives it the dont-remove-card class)
- setTimeout(function(){
- $.each($('.hovercard'),function(){
- var title = $(this).attr("data-orig-title");
+ setTimeout(function () {
+ $.each($('.hovercard'), function () {
+ let title = $(this).attr('data-orig-title');
// don't remove card if it was created after removeAllhoverCards() was called
- if($(this).data('card-created') < priorTo) {
+ if ($(this).data('card-created') < priorTo) {
// don't remove it if we're hovering it right now!
- if(!$(this).hasClass('dont-remove-card')) {
- $('[data-hover-card-active="' + $(this).data('card-created') + '"]').removeAttr('data-hover-card-active');
- $(this).popover("hide");
- }
- }
- });
- },100);
-}
+ if (!$(this).hasClass('dont-remove-card')) {
+ let $handle = $('[data-hover-card-active="' + $(this).data('card-created') + '"]');
+ $handle.removeAttr('data-hover-card-active');
-// Ajax request to get json contact data
-function getContactData(purl, url, actionOnSuccess) {
- var postdata = {
- mode : 'none',
- profileurl : purl,
- datatype : 'json',
- };
+ // Restoring the popover handle title
+ let title = $handle.attr('data-orig-title');
+ $handle.attr({'data-orig-title': '', title: title});
- // Normalize and clean the profile so we can use a standardized url
- // as key for the cache
- var nurl = cleanContactUrl(purl).normalizeLink();
-
- // If the contact is allready in the cache use the cached result instead
- // of doing a new ajax request
- if(nurl in getContactData.cache) {
- setTimeout(function() { actionOnSuccess(getContactData.cache[nurl]); } , 1);
- return;
- }
-
- $.ajax({
- url: url,
- data: postdata,
- dataType: "json",
- success: function(data, textStatus, request){
- // Check if the nurl (normalized profile url) is present and store it to the cache
- // The nurl will be the identifier in the object
- if(data.nurl.length > 0) {
- // Test if the contact is allready connected with the user (if url containing
- // the expression ("redir/") We will store different cache keys
- if((data.url.search("redir/")) >= 0 ) {
- var key = data.url;
- } else {
- var key = data.nurl;
+ $(this).popover('hide');
}
- getContactData.cache[key] = data;
}
- actionOnSuccess(data, url, request);
- },
- error: function(data) {
- actionOnSuccess(false, data, url);
- }
- });
+ });
+ }, 100);
}
-getContactData.cache = {};
-
-// Get hover-card template data and the contact-data and transform it with
-// the help of jSmart. At the end we have full html content of the hovercard
-function getHoverCardContent(purl, url, callback) {
- // fetch the raw content of the template
- getHoverCardTemplate(url, function(stpl) {
- var template = unescape(stpl);
-
- // get the contact data
- getContactData (purl, url, function(data) {
- if(typeof template != 'undefined') {
- // get the hover-card variables
- var variables = getHoverCardVariables(data);
- var tpl;
-
- // use friendicas template delimiters instead of
- // the original one
- jSmart.prototype.left_delimiter = '{{';
- jSmart.prototype.right_delimiter = '}}';
- // create a new jSmart instant with the raw content
- // of the template
- var tpl = new jSmart (template);
- // insert the variables content into the template content
- var HoverCardContent = tpl.fetch(variables);
-
- callback(HoverCardContent);
- }
- });
+function openHovercard(targetElement, contactUrl, timeNow) {
+ // store the title in a data attribute because Bootstrap
+ // popover destroys the title attribute.
+ let title = targetElement.attr('title');
+ targetElement.attr({'data-orig-title': title, title: ''});
+
+ // get an additional data atribute if the card is active
+ targetElement.attr('data-hover-card-active', timeNow);
+ // get the whole html content of the hover card and
+ // push it to the bootstrap popover
+ getHoverCardContent(contactUrl, function (data) {
+ if (data) {
+ targetElement.popover({
+ html: true,
+ placement: function () {
+ // Calculate the placement of the the hovercard (if top or bottom)
+ // The placement depence on the distance between window top and the element
+ // which triggers the hover-card
+ let get_position = $(targetElement).offset().top - $(window).scrollTop();
+ if (get_position < 270) {
+ return 'bottom';
+ }
+ return 'top';
+ },
+ trigger: 'manual',
+ template: '',
+ content: data,
+ container: 'body',
+ sanitizeFn: function (content) {
+ return DOMPurify.sanitize(content)
+ },
+ }).popover('show');
+ }
});
-
-// This is interisting. this pice of code ajax request are done asynchron.
-// To make it work getHOverCardTemplate() and getHOverCardData have to return it's
-// data (no succes handler for each of this). I leave it here, because it could be useful.
-// https://lostechies.com/joshuaflanagan/2011/10/20/coordinating-multiple-ajax-requests-with-jquery-when/
-// $.when(
-// getHoverCardTemplate(url),
-// getContactData (term, url )
-//
-// ).done(function(template, profile){
-// if(typeof template != 'undefined') {
-// var variables = getHoverCardVariables(profile);
-//
-// jSmart.prototype.left_delimiter = '{{';
-// jSmart.prototype.right_delimiter = '}}';
-// var tpl = new jSmart (template);
-// var html = tpl.fetch(variables);
-//
-// return html;
-// }
-// });
}
+getHoverCardContent.cache = {};
-// Ajax request to get the raw template content
-function getHoverCardTemplate (url, callback) {
- var postdata = {
- mode: 'none',
- datatype: 'tpl'
+function getHoverCardContent(contact_url, callback) {
+ let postdata = {
+ url: contact_url,
};
- // Look if we have the template already in the cace, so we don't have
- // request it again
- if('hovercard' in getHoverCardTemplate.cache) {
- setTimeout(function() { callback(getHoverCardTemplate.cache['hovercard']); } , 1);
+ // Normalize and clean the profile so we can use a standardized url
+ // as key for the cache
+ let nurl = cleanContactUrl(contact_url).normalizeLink();
+
+ // If the contact is already in the cache use the cached result instead
+ // of doing a new ajax request
+ if (nurl in getHoverCardContent.cache) {
+ callback(getHoverCardContent.cache[nurl]);
return;
}
$.ajax({
- url: url,
+ url: baseurl + '/contact/hovercard',
data: postdata,
- success: function(data, textStatus) {
- // write the data in the cache
- getHoverCardTemplate.cache['hovercard'] = data;
+ success: function (data, textStatus, request) {
+ getHoverCardContent.cache[nurl] = data;
callback(data);
- }
- }).fail(function () {callback([]); });
-}
-getHoverCardTemplate.cache = {};
-
-// The Variables used for the template
-function getHoverCardVariables(object) {
- var profile = {
- name: object.name,
- nick: object.nick,
- addr: object.addr,
- thumb: object.thumb,
- url: object.url,
- nurl: object.nurl,
- location: object.location,
- gender: object.gender,
- about: object.about,
- network: object.network,
- tags: object.tags,
- bd: object.bd,
- account_type: object.account_type,
- actions: object.actions
- };
-
- var variables = { profile: profile};
-
- return variables;
+ },
+ });
}