eeddc02b816edb3b53fe3c4e150f3ddde051c458
[citadel.git] / webcit-ng / static / js / main.js
1 //
2 // Copyright (c) 2016-2017 by the citadel.org team
3 //
4 // This program is open source software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License version 3.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11
12
13 var current_room = "_BASEROOM_";
14 var new_messages = 0;
15 var total_messages = 0;
16 var default_view = 0;
17 var current_view = 0;
18 var logged_in = 0;
19 var current_user = _("Not logged in.");
20 var serv_info;
21 var messages_per_page = 20;
22
23
24 // Placeholder for when we add i18n later
25 function _(x) {
26         return x;
27 }
28
29
30 // Generate a random string of the specified length
31 // Useful for generating one-time-use div names
32 //
33 function randomString(length) {
34         var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split('');
35
36         if (! length) {
37                 length = Math.floor(Math.random() * chars.length);
38         }
39
40         var str = '';
41         for (var i = 0; i < length; i++) {
42                 str += chars[Math.floor(Math.random() * chars.length)];
43         }
44         return str;
45 }
46
47
48 // string escape for html display
49 //
50 function escapeHTML(text) {
51     'use strict';
52     return text.replace(/[\"&<>]/g, function (a) {
53         return {
54                 '"': '&quot;',
55                 '&': '&amp;',
56                 '<': '&lt;',
57                 '>': '&gt;'
58         }[a];
59     });
60 }
61
62
63 // string escape for html display
64 //
65 function escapeHTMLURI(text) {
66     'use strict';
67     return text.replace(/./g, function (a) {
68         return '%' + a.charCodeAt(0).toString(16);
69     });
70 }
71
72
73 // string escape for JavaScript string
74 //
75 function escapeJS(text) {
76     'use strict';
77     return text.replace(/[\"\']/g, function (a) {
78         return '\\' + a ;
79     });
80 }
81
82
83 // This is called at the very beginning of the main page load.
84 //
85 function ctdl_startup() {
86         var request = new XMLHttpRequest();
87         request.open("GET", "/ctdl/c/info", true);
88         request.onreadystatechange = function() {
89                 if ((this.readyState === 4) && ((this.status / 100) == 2)) {
90                         ctdl_startup_2(JSON.parse(this.responseText));
91                 }
92         };
93         request.send();
94         request = null;
95 }
96
97 // Continuation of ctdl_startup() after serv_info is retrieved
98 //
99 function ctdl_startup_2(data) {
100         serv_info = data;
101
102         if (data.serv_rev_level < 905) {
103                 alert("Citadel server is too old, some functions may not work");
104         }
105
106         update_banner();
107
108         // for now, show a room list in the main div
109         gotoroom("_BASEROOM_");
110         display_room_list();
111 }
112
113 // Display a room list in the main div.
114 //
115 function display_room_list() {
116         document.getElementById("roomlist").innerHTML = "<img src=\"/ctdl/s/throbber.gif\" />" ;                // show throbber while loading
117
118         var request = new XMLHttpRequest();
119         request.open("GET", "/ctdl/r/", true);
120         request.onreadystatechange = function() {
121                 if ((this.readyState === 4) && ((this.status / 100) == 2)) {
122                         display_room_list_renderer(JSON.parse(this.responseText));
123                 }
124         };
125         request.send();
126         request = null;
127 }
128
129 // Renderer for display_room_list()
130 //
131 function display_room_list_renderer(data) {
132         data = data.sort(function(a,b) {
133                 if (a.floor != b.floor) {
134                         return(a.floor - b.floor);
135                 }
136                 if (a.rorder != b.rorder) {
137                         return(a.rorder - b.rorder);
138                 }
139                 return(a.name < b.name);
140         });
141
142         new_roomlist_text = "<ul>" ;
143
144         for (var i in data) {
145                 if (i > 0) {
146                         if (data[i].floor != data[i-1].floor) {
147                                 new_roomlist_text = new_roomlist_text + "<li class=\"divider\"></li>" ;
148                         }
149                 }
150                 new_roomlist_text = new_roomlist_text +
151                         "<li>"
152                         + "<a href=\"javascript:gotoroom('" + escapeJS(escapeHTML(data[i].name)) + "');\">"
153                         + escapeHTML(data[i].name)
154                         + "</a></li>"
155                 ;
156         }
157         new_roomlist_text = new_roomlist_text + "</ul>";
158         document.getElementById("roomlist").innerHTML = new_roomlist_text ;
159 }
160
161 // Update the "banner" div with all relevant info.
162 //
163 function update_banner() {
164         detect_logged_in();
165         if (current_room) {
166                 document.getElementById("ctdl_banner_title").innerHTML = current_room;
167                 document.title = current_room;
168         }
169         else {
170                 document.getElementById("ctdl_banner_title").innerHTML = serv_info.serv_humannode;
171         }
172         document.getElementById("current_user").innerHTML = current_user ;
173         if (logged_in) {
174                 document.getElementById("lilo").innerHTML = "<a href=\"/ctdl/a/logout\">" + _("Log off") + "</a>" ;
175         }
176         else {
177                 document.getElementById("lilo").innerHTML = "<a href=\"javascript:display_login_screen('')\">" + _("Log in") + "</a>" ;
178         }
179 }
180
181
182 // goto room
183 //
184 function gotoroom(roomname) {
185         var request = new XMLHttpRequest();
186         request.open("GET", "/ctdl/r/" + escapeHTMLURI(roomname) + "/", true);
187         request.onreadystatechange = function() {
188                 if ((this.readyState === 4) && ((this.status / 100) == 2)) {
189                         gotoroom_2(JSON.parse(this.responseText));
190                 }
191         };
192         request.send();
193         request = null;
194 }
195 function gotoroom_2(data) {
196         current_room = data.name;
197         new_messages = data.new_messages;
198         total_messages = data.total_messages;
199         current_view = data.current_view;
200         default_view = data.default_view;
201         update_banner();
202         render_room_view();
203 }