ea20d86d1642c1ac25ff925659a41b8621922f29
1var mainlist;
2var rmspan = ["<span class='remove' id='delete-", "'>–</span>"]
3var tick = "✔";
4var removebg = "#bf616a";
5var hovergrn = "#a3be8c";
6var hoverbg = "#434c5e";
7var hoverbg2 = "#848ead";
8document.addEventListener("DOMContentLoaded", function() {
9 chrome.storage.sync.get(
10 {"lists": [
11 ["General",
12 ["Github", "https://github.com"],
13 ["Wikipedia", "https://en.wikipedia.org"],
14 ["Gmail", "https://mail.google.com"]
15 ],
16 ["Productivity",
17 ["Desmos", "https://www.desmos.com/calculator"],
18 ["Wolfram", "https://wolframalpha.com"],
19 ["Hacker News", "https://news.ycombinator.com"]
20 ],
21 ["Social",
22 ["Reddit", "https://www.reddit.com"],
23 ["YouTube", "https://youtube.com"],
24 ["Instagram", "https://instagram.com"]
25 ]
26 ]
27},
28 userListsCallback);
29});
30
31function columnToArray(list) {
32 var l = [];
33 var elem = list.getElementsByClassName("item");
34 for (var i = 0; i < elem.length; ++i) {
35 l[i] = [elem[i].innerText, elem[i].getAttribute("href")];
36 }
37 return l;
38}
39
40function listToArray(list) {
41 var l = [];
42 console.log("looking at list:");
43 console.log(list);
44 if (editMode == true) {
45 l[0] = list.getElementsByClassName('title')[0].getElementsByTagName("input")[0].value;
46 }
47 else {
48 l[0] = list.getElementsByClassName('title')[0].getElementsByTagName("p")[0].textContent;
49 }
50 var elem = list.getElementsByTagName("li");
51 for (var i = 0; i < elem.length; ++i) {
52 if (elem[i].class == "new") {
53 continue;
54 }
55 else {
56 l[i+1] = [elem[i].getElementsByTagName("a")[0].innerText, elem[i].getElementsByTagName("a")[0].getAttribute("href")];
57 }
58 }
59 return l;
60}
61
62var userListsCallback = function(lists) {
63 mainlist = []
64 for (let x of lists['lists']) {
65 mainlist.push(x[0]);
66 }
67 for(var i=0;i<lists["lists"].length;i++) {
68 document.getElementById('edit').addEventListener('click', edit, false);
69 document.getElementById('addcol').addEventListener('click', addCol, false);
70 var ul = document.createElement("ul");
71 ul.setAttribute("id", mainlist[i]);
72 ul.setAttribute('draggable', 'false'); // Draggable attribute must be set on mousedown event, otherwise any cursor movement causes dragstart()
73 document.getElementById("links").appendChild(ul);
74
75 var grip = document.createElement("span");
76 grip.setAttribute("class", "grip");
77 grip.addEventListener('mousedown', function() {
78 console.log("Drag started");
79 uls = document.getElementsByTagName("ul");
80 for (let ul of uls) {
81 ul.setAttribute("draggable", "true");
82 ul.addEventListener('dragstart', dragStart, false);
83 ul.addEventListener('dragenter', dragEnter, false);
84 ul.addEventListener('dragover', dragOver, false);
85 ul.addEventListener('dragleave', dragLeave, false);
86 ul.addEventListener('drop', drop, false);
87 }
88 });
89
90 grip.addEventListener('mouseup', function() {
91 console.log("Drag ended");
92 uls = document.getElementsByTagName("ul");
93 for (let ul of uls) {
94 ul.setAttribute("draggable", "false");
95 ul.removeEventListener('dragstart');
96 ul.removeEventListener('dragenter');
97 ul.removeEventListener('dragover');
98 ul.removeEventListener('dragleave');
99 ul.removeEventListener('drop');
100 }
101 });
102
103 var title = document.createElement("div");
104 title.setAttribute("class", "title");
105 ul.appendChild(grip)
106 ul.appendChild(title);
107
108 var p = document.createElement("p");
109 p.innerText = mainlist[i];
110 title.appendChild(p);
111
112 title.insertAdjacentHTML("beforeend", "<span class='add' id='add-"+mainlist[i]+"'>+</span>");
113
114 var list = lists["lists"][i];
115 for(var j=1;j<lists["lists"][i].length;j++) {
116 var li = document.createElement("li");
117 li.setAttribute("id", mainlist[i]+"-"+j);
118 var siteurl = list[j][1];
119 var nme = list[j][0];
120 var img = document.createElement("img");
121 img.className = "icon";
122 img.src = "https://www.google.com/s2/favicons?domain="+siteurl+"";
123 li.insertAdjacentHTML("beforeend", "<a class='item' href="+siteurl+"><img src="+img.src+" alt="+extractDomain(siteurl,1)+"/> "+nme+"</a>");
124 li.insertAdjacentHTML("beforeend", rmspan[0] + j + "-" + mainlist[i] + rmspan[1]);
125 ul.appendChild(li);
126 }
127
128 new Sortable(ul, {
129 group: "userlists",
130 animation: 150,
131 onUpdate: function (evt) {
132 save();
133 }
134 });
135 }
136
137 menu();
138
139};
140
141function dragStart(e) {
142 dragSrcEl = this;
143 e.dataTransfer.effectAllowed = 'move';
144 e.dataTransfer.setData('text/html', this.innerHTML);
145}
146
147function dragOver(e) {
148 if (e.preventDefault) {
149 e.preventDefault();
150 }
151 e.dataTransfer.dropEffect = 'move';
152 return false;
153}
154
155function dragEnter(e) {
156 this.classList.add('over');
157}
158
159function dragLeave(e) {
160 this.classList.remove('over');
161}
162
163function drop(e) {
164 if (e.stopPropagation); {
165 e.stopPropagation();
166 }
167 if (dragSrcEl != this) {
168 dragSrcEl.innerHTML = this.innerHTML;
169 this.innerHTML = e.dataTransfer.getData('text/html');
170 save();
171 menu();
172 }
173 return false;
174}
175
176var dragSrcEl = null;
177
178document.onkeyup=function(e){
179 var e = e || window.event; // for IE to cover IEs window event-object
180 fields = document.getElementsByClassName("new");
181 if(e.which == 27 && fields != null) {
182 fields[fields.length-1].remove();
183 return false;
184 }
185 if(e.which == 13 && fields.length > 0) {
186 fields[fields.length-1].getElementsByClassName("save")[0].click();
187 return false;
188 }
189}
190
191var editMode = false;
192
193function edit() {
194 if (editMode == true) {
195 console.log("Exited edit mode");
196 closeEdit(this);
197 return 0;
198 }
199 console.log("Entered edit mode");
200 this.style.background = hovergrn;
201 this.innerText = tick;
202 addbtn = document.getElementById("addcol");
203 addbtn.style.display = "flex";
204 var cols = document.getElementsByTagName("ul");
205 for (let col of cols) {
206 col.style.bottom = "26px";
207 title = col.getElementsByClassName("title")[0];
208 rmbutton = document.createElement("span");
209 rmbutton.setAttribute("class", "rmcol");
210 rmbutton.setAttribute("id", "rmcol-"+col.id);
211 rmbutton.innerText = "-";
212 rmbutton.addEventListener('click', function(event){
213 console.log("Deleting column " + this.parentNode.parentNode);
214 this.parentNode.parentNode.remove();
215 var index = mainlist.indexOf(this.parentNode.parentNode.id);
216 console.log("Found deleted node " + this.parentNode.parentNode.id + " at index " + index);
217 if (index > -1) {
218 mainlist.splice(index, 1);
219 }
220 save();
221 });
222 title.appendChild(rmbutton);
223 title.getElementsByClassName("add")[0].style.display = "flex";
224 titlep = title.getElementsByTagName("p")[0];
225 editTitle = document.createElement("input");
226 titlep.insertAdjacentHTML("afterend", "<input type='text' class='colname' placeholder='category' value='" + titlep.innerText + "'>");
227 titlep.remove();
228 col.getElementsByClassName("grip")[0].style.display = "inline-block";
229 }
230 editMode = true;
231}
232
233function closeEdit(editbtn) {
234 editMode = false;
235 editbtn.style.background = "";
236 editbtn.innerText = "e";
237 addbtn = document.getElementById("addcol");
238 addbtn.style.display = "none";
239 var cols = document.getElementsByTagName("ul");
240 for (let col of cols) {
241 col.style.bottom = "0";
242 rmbutton = col.getElementsByClassName("title")[0].getElementsByClassName("rmcol")[0];
243 rmbutton.remove();
244 title = col.getElementsByClassName("title")[0];
245 title.getElementsByClassName("add")[0].style.display = "";
246 editTitle = title.getElementsByClassName("colname")[0];
247 titlep = document.createElement("p");
248 titlep.innerText = editTitle.value;
249 editTitle.remove();
250 title.appendChild(titlep);
251 col.getElementsByClassName("grip")[0].style.display = "none";
252 }
253 save();
254}
255
256function addCol() {
257 var ul = document.createElement("ul");
258 ul.setAttribute("id", "new");
259 ul.setAttribute('draggable', 'true');
260 ul.addEventListener('dragstart', dragStart, false);
261 ul.addEventListener('dragenter', dragEnter, false);
262 ul.addEventListener('dragover', dragOver, false);
263 ul.addEventListener('dragleave', dragLeave, false);
264 ul.addEventListener('drop', drop, false);
265 document.getElementById("links").appendChild(ul);
266
267 var grip = document.createElement("span");
268 grip.setAttribute("class", "grip");
269
270 var title = document.createElement("div");
271 title.setAttribute("class", "title");
272 title.appendChild(grip)
273 ul.appendChild(title);
274
275 var p = document.createElement("p");
276 p.innerText = "new";
277 title.appendChild(p);
278
279 title.insertAdjacentHTML("beforeend", "<span class='add' id='add-new'>+</span>");
280
281 rmbutton = document.createElement("span");
282 rmbutton.setAttribute("class", "rmcol");
283 rmbutton.setAttribute("id", "rmcol-new");
284 rmbutton.innerText = "-";
285 rmbutton.addEventListener('click', function(event){
286 console.log("Deleting column " + this.parentNode.parentNode);
287 this.parentNode.parentNode.remove();
288 var index = mainlist.indexOf(this.parentNode.parentNode.id);
289 console.log("Found deleted node " + this.parentNode.parentNode.id + " at index " + index);
290 if (index > -1) {
291 mainlist.splice(index, 1);
292 }
293 save();
294 });
295 title.appendChild(rmbutton);
296 title.getElementsByClassName("add")[0].style.display = "flex";
297 titlep = title.getElementsByTagName("p")[0];
298 editTitle = document.createElement("input");
299 titlep.insertAdjacentHTML("afterend", "<input type='text' class='colname' placeholder='category'>");
300 titlep.remove();
301
302 mainlist.push(["new"]);
303 save();
304 listen(title.getElementsByClassName("add")[0]);
305}
306
307function listen(li) {
308 li.addEventListener('click', function(event){
309 var r = event.target.id.split("-");
310 if (r[0] == "delete") {
311 var el = document.getElementById(r[2]+"-"+r[1]);
312 el.outerHTML = "";
313 delete el;
314 save();
315 } else {
316 addItem(r, li);
317 }
318 }, true);
319}
320
321function addItem(caller, li) {
322 if (ul == null) {
323 var ul = li.parentNode.parentNode;
324 var id = ul.id;
325 }
326 else {
327 var ul = document.getElementById(caller[1]);
328 var id = caller[1];
329 }
330
331 if (document.querySelectorAll("#"+id+" .new").length > 0) {
332 fields = document.querySelector("#"+id+" .new .name");
333 fields.focus();
334 return false;
335 }
336 var li = document.createElement("li");
337 li.setAttribute("class", "new");
338 li.insertAdjacentHTML("beforeend", "<span class='save' tabindex='3' id='input-"+columnToArray(li).length.toString()+"'>"+tick+"</span><input type='text' class='name' value='' placeholder='name' tabindex='1'><br /><input type='url' spellcheck=false class='url' value='' placeholder='url' tabindex='2' id='form-"+columnToArray(li).length.toString()+"'>");
339 ul.appendChild(li);
340 var span = document.getElementById("input-"+columnToArray(li).length.toString());
341 var form = document.getElementById("form-"+columnToArray(li).length.toString());
342 span.addEventListener('click', function(event){
343 console.log("Adding item to:");
344 console.log(this);
345 var li = document.getElementsByClassName("new")[0]
346 var ul = li.parentNode;
347 if (li.getElementsByClassName("name")[0].value != "" && li.getElementsByClassName("url")[0].value != "" && li.getElementsByClassName("url")[0].validity.typeMismatch== false) {
348 var newli = document.createElement("li");
349 newli.setAttribute("id",caller[1]+"-"+columnToArray(ul).length.toString());
350 var siteurl = addhttp(li.getElementsByClassName("url")[0].value);
351 var nme = li.getElementsByClassName("name")[0].value;
352 li.remove()
353 delete li;
354
355 newli.insertAdjacentHTML("beforeend", "<a href="+siteurl+">"+nme+"</a>");
356 newli.insertAdjacentHTML("beforeend", rmspan[0]+columnToArray(ul).length.toString()+"-"+caller[1]+rmspan[1]);
357 document.getElementById(id).appendChild(newli);
358 save();
359 listen(newli);
360 }
361 else {
362 if (li.getElementsByClassName("name")[0].value == "" && li.getElementsByClassName("url")[0].value == "") {
363 console.log("No data supplied, deleting form");
364 this.parentNode.remove();
365 }
366 else {
367 console.log("Missing data, press Esc to delete form");
368 }
369 }
370 });
371 span.onmouseover = function() {
372 nme = document.getElementsByClassName("name")[0];
373 url = document.getElementsByClassName("url")[0];
374 if (nme.value === '' || url.value === '' || url.validity.typeMismatch == true) {
375 this.style.background = removebg;
376 }
377 else {
378 this.style.background = hovergrn;
379 }
380 };
381 span.onmouseout = function() {
382 this.style.background = hoverbg2;
383 };
384 menu(); // TODO fix bug where form save button loses its eventlistener after generating form for another column twice
385 fields = document.querySelector("#"+id+" .new .name");
386 fields.focus();
387
388}
389
390function menu() {
391 // Update event listeners for all items, their remove buttons, and the add button for each column
392 var allUserLi = document.querySelectorAll('.remove, .add');
393
394 allUserLi.forEach(function(li, p_index){
395 listen(li);
396 });
397}
398
399function save(l) {
400 console.log(mainlist);
401 var set = l || JSON.parse(JSON.stringify(mainlist));
402 d = []
403 d = set;
404 console.log("Saving settings");
405 for (var i = 0; i < set.length; ++i) {
406 d[i] = listToArray(document.getElementById(set[i]));
407 }
408 chrome.storage.sync.set( {"lists": d} );
409}