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