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