Event handling changes
[adhocweb.git] / js / main.js
1 var BOSH_SERVICE = 'http://localhost:5280/http-bind/';
2 var show_log = false;
3
4 Strophe.addNamespace("ADHOC", "http://jabber.org/protocol/commands");
5
6 var localJID = null;
7 var connection   = null;
8 var sessionid = null;
9 var cmdNode = null;
10 var queryJID = null;
11
12 function log(msg) {
13     var entry = $('<div></div>').append(document.createTextNode(msg));
14     $('#log').append(entry);
15 }
16
17 function rawInput(data) {
18     log('RECV: ' + data);
19 }
20
21 function rawOutput(data) {
22     log('SENT: ' + data);
23 }
24
25 function onConnect(status) {
26     if (status == Strophe.Status.CONNECTING) {
27         log('Strophe is connecting.');
28     } else if (status == Strophe.Status.CONNFAIL) {
29         log('Strophe failed to connect.');
30         showConnect();
31     } else if (status == Strophe.Status.DISCONNECTING) {
32         log('Strophe is disconnecting.');
33     } else if (status == Strophe.Status.DISCONNECTED) {
34         log('Strophe is disconnected.');
35         showConnect();
36     } else if (status == Strophe.Status.AUTHFAIL) {
37         log('Authentication failed');
38         if (connection) {
39             connection.disconnect();
40         }
41     } else if (status == Strophe.Status.CONNECTED) {
42         log('Strophe is connected.');
43         queryJID = connection.domain;
44         $('#query').show();
45         checkFeatures();
46     }
47 }
48
49 function addNote(elem, text, type) {
50     if (!type) {
51        type = "info";
52     }
53     $(elem).append("<p class='" + type + "Note'>" + text + "</p>");
54 }
55
56 function addForm(elem, x) {
57     var form = $("<form/>");
58     form.submit(function(event){event.preventDefault();});
59     var fieldset = $("<fieldset/>");
60     form.append(fieldset);
61     if ($(x).find("title").length > 0)
62         $("<legend/>").text($(x).find("title").text()).appendTo(fieldset);
63     if ($(x).find("instructions").length > 0)
64         $("<p/>").text($(x).find("instructions").text()).appendTo(fieldset);
65     $(x).find("field").each(function(){
66         var item = null;
67         var type = $(this).attr("type");
68         if($(this).attr("label")) {
69             $("<label/>").text($(this).attr("label")).attr("for", $(this).attr("var")).appendTo(fieldset);
70         }
71         switch(type) {
72         case "hidden":
73             item = $("<input type='hidden'/>");
74             break;
75         case "boolean":
76             item = $("<input type='checkbox'/>");
77             break;
78         case "text-multi":
79             item = $("<textarea/>");
80             break;
81         case "text-single":
82             item = $("<input type='text'/>");
83             break;
84         case "fixed":
85             item = $("<input type='text'/>").attr("readonly",true);
86             break;
87         case "jid-multi":
88             item = $("<textarea/>");
89             break;
90         case "jid-single":
91             item = $("<input type='text'/>");
92             break;
93         case "list-multi":
94             item = $("<select multiple='multiple'/>");
95             $(this).find("option").each(function(){
96                     $("<option/>").val($(this).find("value").text()).text($(this).attr("label")).appendTo(item);
97                     });
98             break;
99         case "list-single":
100             item = $("<select/>");
101             $(this).find("option").each(function(){
102                     $("<option/>").val($(this).find("value").text()).text($(this).attr("label")).appendTo(item);
103                     });
104             break;
105         case "text-private":
106             item = $("<input type='password'/>");
107             break;
108         default:
109             item = $("<input/>");
110         }
111         item.addClass("df-item");
112         if ($(this).find("value").length > 0) {
113             var value = null;
114             if ((type == "text-multi") || (type == "jid-multi")) {
115                 value = "";
116                 $(this).find("value").each(function() {
117                     value = value + $(this).text() + "\n";
118                 });
119                 item.val(value);
120             } else if (type == "list-multi") {
121                 value = new Array();
122                 $(this).find("value").each(function() {
123                     value[value.length] = $(this).text();
124                 });
125             } else {
126                 item.val($(this).find("value").text());
127             }
128         }
129         if ($(this).attr("var")) {
130             item.attr("name", $(this).attr("var"));
131             item.attr("id", $(this).attr("var"));
132         }
133         fieldset.append(item);
134         fieldset.append("<br/>");
135     });
136     $(elem).append(form);
137 }
138
139 function serializeToDataform(form, st) {
140     st.c("x", {"xmlns":"jabber:x:data", "type": "submit"});
141     $(form).find(".df-item").each(function(){
142         st.c("field", {"var": $(this).attr("name")});
143         if (this.nodeName.toLowerCase() == "select" && this.multiple) {
144             for (var i = 0; i < this.options.length; i++)
145                 if (options[i].selected)
146                     st.c("value").t(options[i]).up();
147         } else if (this.nodeName.toLowerCase() == "textarea") {
148             var sp_value = this.value.split(/\r?\n|\r/g);
149             for(var i = 0; i < sp_value.length; i++)
150                 st.c("value").t(sp_value[i]).up();
151         } else if (this.nodeName.toLowerCase() == "input" && this.type == "checkbox") {
152             if (this.checked) {
153                 st.c("value").t("1");
154             } else {
155                 st.c("value").t("0");
156             }
157         } else {
158             // if this has value then
159             st.c("value").t($(this).val()).up();
160         }
161         st.up();
162     });
163     st.up();
164 }
165
166 function displayResult(result) {
167     var status = $(result).find("command").attr("status");
168
169     $("#output").empty();
170     $(result).find("command > *").each(function(index, e) {
171         if ($(e).is("note")) {
172             addNote("#output", $(e).text(), $(e).attr("type"));
173         } else if ($(e).is("x[xmlns=jabber:x:data]")) {
174             addForm("#output", e);
175         }
176     });
177     if (status == "executing") {
178         $("#output").append("<input type='button' disabled='true' id='prevButton' value='Prev'/>"+
179                             "<input type='button' disabled='true' id='nextButton' value='Next'/>"+
180                             "<input type='button' disabled='true' id='completeButton' value='Complete'/>"+
181                             "<input type='button' id='executeButton' value='Execute'/>"+
182                             "<input type='button' id='cancelButton' value='Cancel'/>");
183         for (kind in ['prev', 'next', 'complete']) {
184             if ($(result).find('actions ' + kind).length > 0)
185                 $('#' + kind + 'Button').attr("disabled", "false");
186         }
187         $('#executeButton').bind("click", function() {
188             var execIQ = $iq({ type: "set", to: queryJID, id: connection.getUniqueId() })
189                 .c("command", { xmlns: Strophe.NS.ADHOC, node: cmdNode, sessionid: sessionid, action: "execute" });
190             serializeToDataform($('form'), execIQ);
191             connection.sendIQ(execIQ, displayResult);
192         });
193
194         $('#cancelButton').bind("click", function() {
195             var cancelIQ = $iq({ type: "set", to: queryJID, id: connection.getUniqueId() })
196                 .c("command", { xmlns: Strophe.NS.ADHOC, node: cmdNode, sessionid: sessionid, action: "cancel" });
197             cmdNode = null
198             sessionid = null;
199             connection.sendIQ(cancelIQ, displayResult);
200         });
201     } else {
202         input = $("<input type='button' value='Start over'/>").bind("click", function() {
203             $('#output').empty();
204             sessionid = null;
205             cmdNode = null;
206             getCommandNodes();
207         });
208         $("#output").append(input);
209     }
210 }
211
212 function runCommand(event) {
213     cmdNode = $(this).attr("id"); // Save node of executed command (in global var)
214     var execIQ = $iq({ type: "set", to: queryJID, id: connection.getUniqueId() })
215         .c("command", { xmlns: Strophe.NS.ADHOC, node: cmdNode, action: "execute" });
216     connection.sendIQ(execIQ, function(result) {
217         sessionid = $(result).find("command").attr("sessionid");
218         displayResult(result);
219     });
220     event.preventDefault();
221 }
222
223 function getCommandNodes() {
224     var nodesIQ = $iq({ type: "get", to: queryJID, id: "nodes1" }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS, node: Strophe.NS.ADHOC});
225     connection.sendIQ(nodesIQ, function(result) {
226         $('#output').append("<ul id='items'></ul>");
227         $(result).find("item").each(function(index, e) {
228             link = $("<a href='#' id='" + $(e).attr("node") + "'>" + $(e).attr("name") + "</a>").click(runCommand)
229             item = $("<li></li>").append(link);
230             $("#items").append(item);
231         });
232     });
233 }
234
235 function checkFeatures() {
236     featureIQ = $iq({ type: "get", to: queryJID, id: "features1" }).c("query", {xmlns: Strophe.NS.DISCO_INFO});
237     connection.sendIQ(featureIQ, function(result) {
238         if ($(result).find("feature[var='" + Strophe.NS.ADHOC + "']").length > 0) {
239             $('#output').append("<p>This entitiy does support AdHoc commands</p>");
240         } else {
241             $('#output').append("<p>This entitiy does NOT support AdHoc commands</p>");
242         }
243     });
244     $('#output').empty();
245     getCommandNodes();
246 }
247
248 function showConnect() {
249     var jid = $('#jid');
250     var pass = $('#pass');
251     var button = $('#connect').get(0);        
252
253     button.value = 'connect';
254     $('#query').hide();
255     pass.show();
256     jid.show();
257     $('label').show();
258     $('#output').empty();
259 }
260
261 function showDisconnect() {
262     var jid = $('#jid');
263     var pass = $('#pass');
264     var button = $('#connect').get(0);        
265
266     button.value = 'disconnect';
267     pass.hide();
268     jid.hide();
269     $('#cred label').hide();
270 }
271
272 $(document).ready(function () {
273     connection = new Strophe.Connection(BOSH_SERVICE);
274     if (show_log) {
275         $('#log_container').show();
276         connection.rawInput = rawInput;
277         connection.rawOutput = rawOutput;
278     }
279
280     $("#log_toggle").click(function () {
281         $("#log").toggle();
282       });
283
284     $('#cred').bind('submit', function (event) {
285         var button = $('#connect').get(0);
286         var jid = $('#jid');
287         var pass = $('#pass');        
288         localJID = jid.get(0).value;
289
290         if (button.value == 'connect') {
291             showDisconnect();
292             $('#log').empty();
293             connection.connect(localJID,
294                pass.get(0).value,
295                onConnect);
296         } else {
297             connection.disconnect();
298         }
299         event.preventDefault();
300     });
301
302     $('#queryForm').bind('submit', function (event) {
303         queryJID = $('#queryJID').val();
304         checkFeatures();
305         event.preventDefault();
306     });
307 });
308
309 onunload = function() {
310     if (connection) {
311         connection.disconnect();
312     }
313 }
314