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