PageSourceSearch

https://gnulinux.ch/bl-plugins/zz_snicker/themes/default/snicker.js

js gnulinux.ch collected 2026-10-02 05:24:04 UTC 11,939 bytes, 288 lines download raw bytes

1/*
2 |  Snicker     The first native FlatFile Comment Plugin 4 Bludit
3 |  @file       ./system/themes/default/snicker.js
4 |  @author     SamBrishes <[email protected]>
5 |  @version    0.1.2 [0.1.0] - Alpha
6 |
7 |  @website    https://github.com/pytesNET/snicker
8 |  @license    X11 / MIT License
9 |  @copyright  Copyright © 2019 SamBrishes, pytesNET <[email protected]>
10 */
11;(function(root){
12    "use strict";
13    var w = root, d = root.document;
14
15    /*
16     |  AJAX HELPER
17     */
18    function ajax(url, type, data, callback, self){
19        var xhttp = new XMLHttpRequest();
20        xhttp.onreadystatechange = function(){
21            if(this.readyState == 4){
22                callback.call((self? self: this), this.responseText, this);
23            }
24        };
25        xhttp.open(type, url, true);
26        xhttp.setRequestHeader("Cache-Control", "no-cache");
27        xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
28        if(type == "POST"){
29            if(!(data instanceof FormData)){
30                xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
31            }
32            xhttp.send(data);
33        } else {
34            xhttp.send();
35        }
36    }
37
38    /*
39     |  ALERT HELPER
40     */
41    function showAlert(type, message, parent){
42        var alert = d.createElement("DIV");
43            alert.className = "comment-alert alert-" + type;
44            alert.innerText = message;
45
46        // Remove Existing Status
47        var alerts = parent.querySelectorAll(".comment-alert");
48        if(alerts.length > 0){
49            Array.prototype.forEach.call(alerts, function(item){
50                item.parentElement.removeChild(item);
51            });
52        }
53
54        // Add Status
55        if(parent.children.length > 0){
56            parent.insertBefore(alert, parent.children[0]);
57        } else {
58            parent.appendChild(alert);
59        }
60    }
61
62    // Ready?
63    d.addEventListener("DOMContentLoaded", function(){
64        "use strict";
65
66        // Main Elements
67        var form = d.querySelector("form.comment-form"),
68            list = d.querySelector(".snicker-comments-list"),
69            captcha = d.querySelector("a[data-captcha='reload']");
70
71        /*
72         |  HANDLE COMMENT FORM
73         */
74        if(form){
75            form.addEventListener("submit", function(event){
76                event.preventDefault();
77                if(typeof(FormData) !== "function" || !SNICKER_AJAX){
78                    return true;
79                }
80                var data = new FormData(this), self = this;
81
82                // Check Button
83                var btn = this.querySelector("[name='snicker']");
84                if(btn.disabled){
85                    return true;
86                }
87                event.preventDefault();
88
89                // AJAX Call
90                btn.disabled = true;
91                btn.classList.add("loading");
92                data.append("snicker", btn.value);
93                ajax(SNICKER_PATH, "POST", data, function(json){
94                    var data = JSON.parse(json);
95
96                    // Add Comment
97                    if(list && data.status == "success" && "comment" in data){
98                        if(list.querySelector(".comment")){
99                            var parentComment =  form.querySelector('[name="comment[parent_uid]"]');
100                            if(parentComment != null){
101                                var parentCommentId = parentComment.value;
102                                list.querySelector("#comment-"+parentCommentId).insertAdjacentHTML("afterend", data.comment);
103                            }else {
104                                list.querySelector(".comment").insertAdjacentHTML("beforebegin", data.comment);
105                            }
106                        } else {
107                            list.insertAdjacentHTML("afterbegin", data.comment);
108                        }
109                        list.querySelector(".comment").classList.add("new-comment");
110                        list.querySelector(".comment").scrollIntoView({ behavior: "smooth", block: "center" });
111
112                        // Empty Form
113                        var field = self.querySelectorAll("#comment-title,#comment-text");
114                        for(var i = 0, l = field.length; i < l; i++){
115                            if(field[i].tagName == "SELECT"){
116                                field[i].options[0].selected = true;
117                            } else if(field[i].getAttribute("type") === "checkbox"){
118                                field[i].checked = false;
119                            } else {
120                                field[i].value = "";
121                            }
122                        }
123
124                        showAlert("success", data.success, form.querySelector(".comment-article"));
125                    } else if(data.status === "error"){
126                        showAlert("error", data.error, form.querySelector(".comment-article"));
127
128                        if(captcha && "captcha" in data){
129                            d.querySelector("input[name='comment[captcha]']").value = "";
130                            captcha.querySelector("img").src = data.captcha;
131                        }
132                    }
133
134                    // Re-Enable Button
135                    btn.disabled = false;
136                    btn.classList.remove("loading");
137                });
138            });
139        }
140
141        /*
142         |  HANDLE CAPTCHA RELOAD
143         */
144        if(captcha){
145            captcha.addEventListener("click", function(event){
146                if(!SNICKER_AJAX){
147                    return false;
148                }
149                event.preventDefault();
150                captcha.classList.add("reload");
151
152                var data = "action=snicker&snicker=captcha&tokenCSRF=";
153                var token = d.querySelector("input[name='tokenCSRF']").value;
154                ajax(SNICKER_PATH, "POST", data + token, function(json){
155                    var data = JSON.parse(json);
156                    if(data.status !== "success"){
157                        window.location.replace(captcha.getAttribute("href"));
158                    }
159                    captcha.querySelector("img").src = data.captcha;
160                    captcha.classList.remove("reload");
161                });
162            })
163        }
164
165        /*
166         |  HANDLE COMMENT REPLY
167         */
168        if(list){
169            list.addEventListener("click", function(event){
170                if(event.target.tagName != "A" || !form){
171                    return true;
172                }
173
174                // Check Link
175                var href = event.target.getAttribute("href");
176                if(href.indexOf("snicker=reply") < 0){
177                    return true;
178                }
179
180                // Handle Reply
181                event.preventDefault();
182                var comment = (function getComment(element){
183                    var parent = element.parentElement;
184                    return (parent.classList.contains("comment"))? parent: getComment(parent);
185                })(event.target);
186
187                // Create Elements
188                var reply = d.createElement("DIV");
189                    reply.className = "comment-reply";
190                    reply.innerHTML = '<a href="' + window.location.href + '" class="reply-cancel"></a>'
191                                    + '<div class="reply-title">' + comment.querySelector(".author-username").innerText + ' hat kommentiert:</div>'
192                                    + '<div class="reply-content">' + comment.querySelector(".comment-comment").innerHTML + '</div>';
193                var parent = d.createElement("INPUT");
194                    parent.type = "hidden";
195                    parent.name = "comment[parent_uid]";
196                    parent.value = comment.id.replace("comment-", "");
197
198                // Append Cancel
199                reply.querySelector(".reply-cancel").addEventListener("click", function(event){
200                    event.preventDefault();
201
202                    // Remove Elements
203                    reply.parentElement.removeChild(reply);
204                    parent.parentElement.removeChild(parent);
205
206                    // Switch Button Text
207                    // var old = form.querySelector("button").innerText;
208                    // form.querySelector("button").value = "comment";
209                    // form.querySelector("button").innerText = form.querySelector("button").getAttribute("data-string");
210                    // form.querySelector("button").setAttribute("data-string", old);
211                });
212
213                // Inject Elements
214                var art = form.querySelector(".comment-article");
215                if(art.querySelector(".comment-reply")){
216                    art.replaceChild(reply, art.querySelector(".comment-reply"));
217                } else {
218                    art.insertBefore(reply, form.querySelector("textarea").parentElement);
219                }
220
221                var foo = form.querySelector(".comment-footer");
222                if(foo.querySelector("input[name='comment[parent_uid]']")){
223                    foo.replaceChild(parent, foo.querySelector("input[name='comment[parent_uid]']"));
224                } else {
225                    foo.appendChild(parent);
226                }
227                form.querySelector("#comment-text").focus();
228                window.scrollTo(0, form.offsetTop);
229                // Switch Button Text
230                // var old = form.querySelector("button").innerText;
231                // form.querySelector("button").value = "reply";
232                // form.querySelector("button").innerText = form.querySelector("button").getAttribute("data-string");
233                // form.querySelector("button").setAttribute("data-string", old);
234            });
235        }
236
237        /*
238         |  HANDLE COMMENT RATING
239         */
240        if(list){
241            list.addEventListener("click", function(event){
242                if(event.target.tagName != "A" || !SNICKER_AJAX){
243                    return true;
244                }
245                if(event.target.classList.contains("disabled")){
246                    return true;
247                }
248
249                // Check Link
250                var href = event.target.getAttribute("href");
251                if(href.indexOf("&type=like") < 0 && href.indexOf("&type=dislike") < 0){
252                    return true;
253                }
254
255                // Event Handler
256                event.preventDefault();
257                event.target.classList.add("disabled");
258                var comment = (function getComment(element){
259                    var parent = element.parentElement;
260                    return (parent.classList.contains("comment"))? parent: getComment(parent);
261                })(event.target), self = event.target;
262                href = href.split("?");
263
264                // AJAX REQUEST
265                ajax(SNICKER_PATH, "POST", href[1], function(json){
266                    var data = JSON.parse(json);
267
268                    if(data.status === "success" && "rating" in data){
269                        var like = comment.querySelector("[data-snicker='like']");
270                        if(like){
271                            like.innerText = String(data.rating[0]);
272                        }
273                        like.parentElement.classList[(like.parentElement == self? "add": "remove")]("active");
274
275                        var dislike = comment.querySelector("[data-snicker='dislike']");
276                        if(dislike){
277                            dislike.innerText = String(data.rating[1]);
278                        }
279                        dislike.parentElement.classList[(dislike.parentElement == self? "add": "remove")]("active");
280                    }
281
282                    // Re-Enable Button
283                    self.classList.remove("disabled");
284                });
285            });
286        }
287    });
288})(window);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.