]> git.mxchange.org Git - friendica.git/blob - view/theme/frio/js/hovercard.js
[frio] Remove jSmart dependency
[friendica.git] / view / theme / frio / js / hovercard.js
1 /*
2  * The javascript for friendicas hovercard. Bootstraps popover is needed.
3  *
4  * Much parts of the code are from Hannes Mannerheims <h@nnesmannerhe.im>
5  * qvitter code (https://github.com/hannesmannerheim/qvitter)
6  *
7  * It is licensed under the GNU Affero General Public License <http://www.gnu.org/licenses/>
8  *
9  */
10 $(document).ready(function () {
11         // Elements with the class "userinfo" will get a hover-card.
12         // Note that this elements does need a href attribute which links to
13         // a valid profile url
14         $("body").on("mouseover", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function (e) {
15                 let timeNow = new Date().getTime();
16                 removeAllHovercards(e, timeNow);
17                 let contact_url = false;
18                 let targetElement = $(this);
19
20                 // get href-attribute
21                 if (targetElement.is('[href]')) {
22                         contact_url = targetElement.attr('href');
23                 } else {
24                         return true;
25                 }
26
27                 // no hover card if the element has the no-hover-card class
28                 if (targetElement.hasClass('no-hover-card')) {
29                         return true;
30                 }
31
32                 // no hovercard for anchor links
33                 if (contact_url.substring(0, 1) === '#') {
34                         return true;
35                 }
36
37                 targetElement.attr('data-awaiting-hover-card', timeNow);
38
39                 // store the title in an other data attribute beause bootstrap
40                 // popover destroys the title.attribute. We can restore it later
41                 let title = targetElement.attr("title");
42                 targetElement.attr({"data-orig-title": title, title: ""});
43
44                 // if the device is a mobile open the hover card by click and not by hover
45                 if (typeof is_mobile != "undefined") {
46                         targetElement[0].removeAttribute("href");
47                         var hctrigger = 'click';
48                 } else {
49                         var hctrigger = 'manual';
50                 }
51
52                 // Timeout until the hover-card does appear
53                 setTimeout(function () {
54                         if (
55                                 targetElement.is(":hover")
56                                 && parseInt(targetElement.attr('data-awaiting-hover-card'), 10) === timeNow
57                                 && $('.hovercard').length === 0
58                         ) {     // no card if there already is one open
59                                 // get an additional data atribute if the card is active
60                                 targetElement.attr('data-hover-card-active', timeNow);
61                                 // get the whole html content of the hover card and
62                                 // push it to the bootstrap popover
63                                 getHoverCardContent(contact_url, function (data) {
64                                         if (data) {
65                                                 targetElement.popover({
66                                                         html: true,
67                                                         placement: function () {
68                                                                 // Calculate the placement of the the hovercard (if top or bottom)
69                                                                 // The placement depence on the distance between window top and the element
70                                                                 // which triggers the hover-card
71                                                                 var get_position = $(targetElement).offset().top - $(window).scrollTop();
72                                                                 if (get_position < 270) {
73                                                                         return "bottom";
74                                                                 }
75                                                                 return "top";
76                                                         },
77                                                         trigger: hctrigger,
78                                                         template: '<div class="popover hovercard" data-card-created="' + timeNow + '"><div class="arrow"></div><div class="popover-content hovercard-content"></div></div>',
79                                                         content: data,
80                                                         container: "body",
81                                                         sanitizeFn: function (content) {
82                                                                 return DOMPurify.sanitize(content)
83                                                         },
84                                                 }).popover('show');
85                                         }
86                                 });
87                         }
88                 }, 500);
89         }).on("mouseleave", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function (e) { // action when mouse leaves the hover-card
90                 var timeNow = new Date().getTime();
91                 // copy the original title to the title atribute
92                 var title = $(this).attr("data-orig-title");
93                 $(this).attr({"data-orig-title": "", title: title});
94                 removeAllHovercards(e, timeNow);
95         });
96
97         // hover cards should be removed very easily, e.g. when any of these events happen
98         $('body').on("mouseleave touchstart scroll click dblclick mousedown mouseup submit keydown keypress keyup", function (e) {
99                 // remove hover card only for desktiop user, since on mobile we openen the hovercards
100                 // by click event insteadof hover
101                 if (typeof is_mobile == "undefined") {
102                         var timeNow = new Date().getTime();
103                         removeAllHovercards(e, timeNow);
104                 }
105         });
106
107         // if we're hovering a hover card, give it a class, so we don't remove it
108         $('body').on('mouseover', '.hovercard', function (e) {
109                 $(this).addClass('dont-remove-card');
110         });
111
112         $('body').on('mouseleave', '.hovercard', function (e) {
113                 $(this).removeClass('dont-remove-card');
114                 $(this).popover("hide");
115         });
116 }); // End of $(document).ready
117
118 // removes all hover cards
119 function removeAllHovercards(event, priorTo) {
120         // 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)
121         setTimeout(function () {
122                 $.each($('.hovercard'), function () {
123                         var title = $(this).attr("data-orig-title");
124                         // don't remove card if it was created after removeAllhoverCards() was called
125                         if ($(this).data('card-created') < priorTo) {
126                                 // don't remove it if we're hovering it right now!
127                                 if (!$(this).hasClass('dont-remove-card')) {
128                                         $('[data-hover-card-active="' + $(this).data('card-created') + '"]').removeAttr('data-hover-card-active');
129                                         $(this).popover("hide");
130                                 }
131                         }
132                 });
133         }, 100);
134 }
135
136 getHoverCardContent.cache = {};
137
138 function getHoverCardContent(contact_url, callback) {
139         let postdata = {
140                 url: contact_url,
141         };
142
143         // Normalize and clean the profile so we can use a standardized url
144         // as key for the cache
145         let nurl = cleanContactUrl(contact_url).normalizeLink();
146
147         // If the contact is already in the cache use the cached result instead
148         // of doing a new ajax request
149         if (nurl in getHoverCardContent.cache) {
150                 callback(getHoverCardContent.cache[nurl]);
151                 return;
152         }
153
154         $.ajax({
155                 url: baseurl + "/contact/hovercard",
156                 data: postdata,
157                 success: function (data, textStatus, request) {
158                         getHoverCardContent.cache[nurl] = data;
159                         callback(data);
160                 },
161         });
162 }