Change link hover behaviour
[bloat] / static / fluoride.js
1 var actionIcons = {
2         "like": "/static/icons/star-o.png",
3         "dark-like": "/static/icons/dark-star-o.png",
4         "unlike": "/static/icons/liked.png",
5         "dark-unlike": "/static/icons/liked.png",
6         "retweet": "/static/icons/retweet.png",
7         "dark-retweet": "/static/icons/dark-retweet.png",
8         "unretweet": "/static/icons/retweeted.png",
9         "dark-unretweet": "/static/icons/retweeted.png"
10 };
11
12 var reverseActions = {
13         "like": "unlike",
14         "unlike": "like",
15         "retweet": "unretweet",
16         "unretweet": "retweet"
17 };
18
19 function getCSRFToken() {
20         var tag = document.querySelector("meta[name='csrf_token']")
21         if (tag)
22                 return tag.getAttribute("content");
23         return "";
24 }
25
26 function http(method, url, body, type, success, error) {
27         var req = new XMLHttpRequest();
28         req.onload = function() {
29                 if (this.status === 200 && typeof success === "function") {
30                         success(this.responseText, this.responseType);
31                 } else if (typeof error === "function") {
32                         error(this.responseText);
33                 }
34         };
35         req.onerror = function() {
36                 if (typeof error === "function") {
37                         error(this.responseText);
38                 }
39         };
40         req.open(method, url);
41         req.setRequestHeader("Content-Type", type);
42         req.send(body);
43 }
44
45 function updateActionForm(id, f, action) {
46         if (Array.from(document.body.classList).indexOf("dark") > -1) {
47                 f.querySelector(".icon").src = actionIcons["dark-" + action];
48         } else {
49                 f.querySelector(".icon").src = actionIcons[action];
50         }
51         f.action = "/" + action + "/" + id;
52         f.dataset.action = action;
53 }
54
55 function handleLikeForm(id, f) {
56         f.onsubmit = function(event) {
57                 event.preventDefault();
58
59                 var action = f.dataset.action;
60                 var forms = document.querySelectorAll(".status-"+id+" .status-like");
61                 forms.forEach(function(f) {
62                         updateActionForm(id, f, reverseActions[action]);
63                 });
64
65                 var body = "csrf_token=" + encodeURIComponent(getCSRFToken());
66                 var contentType = "application/x-www-form-urlencoded";
67                 http("POST", "/fluoride/" + action + "/" + id, body, contentType, function(res, type) {
68                         var data = JSON.parse(res);
69                         var count = data.data;
70                         if (count === 0) {
71                                 count = "";
72                         }
73                         var counts = document.querySelectorAll(".status-"+id+" .status-like-count");
74                         counts.forEach(function(c) {
75                                 c.innerHTML = count;
76                         });
77                 }, function(err) {
78                         forms.forEach(function(f) {
79                                 updateActionForm(id, f, action);
80                         });
81                 });
82         }
83 }
84
85 function handleRetweetForm(id, f) {
86         f.onsubmit = function(event) {
87                 event.preventDefault();
88
89                 var action = f.dataset.action;
90                 var forms = document.querySelectorAll(".status-"+id+" .status-retweet");
91                 forms.forEach(function(f) {
92                         updateActionForm(id, f, reverseActions[action]);
93                 });
94
95                 var body = "csrf_token=" + encodeURIComponent(getCSRFToken());
96                 var contentType = "application/x-www-form-urlencoded";
97                 http("POST", "/fluoride/" + action + "/" + id, body, contentType, function(res, type) {
98                         var data = JSON.parse(res);
99                         var count = data.data;
100                         if (count === 0) {
101                                 count = "";
102                         }
103                         var counts = document.querySelectorAll(".status-"+id+" .status-retweet-count");
104                         counts.forEach(function(c) {
105                                 c.innerHTML = count;
106                         });
107                 }, function(err) {
108                         forms.forEach(function(f) {
109                                 updateActionForm(id, f, action);
110                         });
111                 });
112         }
113 }
114
115 function isInView(el) {
116         var ract = el.getBoundingClientRect();
117         if (ract.top > 0 && ract.bottom < window.innerHeight) {
118                 return true;
119         }
120         return false;
121 }
122
123 function handleReplyToLink(div) {
124         if (!div) {
125                 return;
126         }
127         var id = div.firstElementChild.getAttribute('href');
128         if (!id || id[0] != '#') {
129                 return;
130         }
131         div.firstElementChild.onmouseenter = function(event) {
132                 var id = event.target.getAttribute('href');
133                 var status = document.querySelector(id);
134                 if (!status) {
135                         return;
136                 }
137                 if (isInView(status)) {
138                         status.classList.add("highlight");
139                 } else {
140                         var copy = status.cloneNode(true);
141                         copy.id = "reply-to-popup";
142                         event.target.parentElement.appendChild(copy);
143                 }
144         }
145         div.firstElementChild.onmouseleave = function(event) {
146                 var popup = document.getElementById("reply-to-popup");
147                 if (popup) {
148                         event.target.parentElement.removeChild(popup);    
149                 } else {
150                         var id = event.target.getAttribute('href');
151                         document.querySelector(id)
152                                 .classList.remove("highlight");
153                 }
154         }
155 }
156
157 function handleReplyLink(div) {
158         div.firstElementChild.onmouseenter = function(event) {
159                 var id = event.target.getAttribute('href');
160                 var status = document.querySelector(id);
161                 if (!status) {
162                         return;
163                 }
164                 if (isInView(status)) {
165                         status.classList.add("highlight");
166                 } else {
167                         var copy = status.cloneNode(true);
168                         copy.id = "reply-popup";
169                         event.target.parentElement.appendChild(copy);
170                 }
171         }
172         div.firstElementChild.onmouseleave = function(event) {
173                 var popup = document.getElementById("reply-popup");
174                 if (popup) {
175                         event.target.parentElement.removeChild(popup);    
176                 } else {
177                         var id = event.target.getAttribute('href');
178                         document.querySelector(id)
179                                 .classList.remove("highlight");
180                 }
181         }
182 }
183
184 document.addEventListener("DOMContentLoaded", function() { 
185         var statuses = document.querySelectorAll(".status-container");
186         statuses.forEach(function(s) {
187                 var id = s.dataset.id;
188
189                 var likeForm = s.querySelector(".status-like");
190                 handleLikeForm(id, likeForm);
191
192                 var retweetForm = s.querySelector(".status-retweet");
193                 handleRetweetForm(id, retweetForm);
194
195                 var replyToLink = s.querySelector(".status-reply-to");
196                 handleReplyToLink(replyToLink);
197
198                 var replyLinks = s.querySelectorAll(".status-reply");
199                 replyLinks.forEach(handleReplyLink);
200         });
201 });