]> git.mxchange.org Git - friendica-addons.git/blob - jappixmini/jappix/js/dataform.js
Twitter: Fetch the contact relation
[friendica-addons.git] / jappixmini / jappix / js / dataform.js
1 /*
2
3 Jappix - An open social platform
4 These are the dataform JS scripts for Jappix
5
6 -------------------------------------------------
7
8 License: AGPL
9 Author: Vanaryon
10 Last revision: 28/08/11
11
12 */
13
14 // Gets the defined dataform elements
15 function dataForm(host, type, node, action, target) {
16         // Clean the current session
17         cleanDataForm(target);
18         
19         // We tell the user that a search has been launched
20         $('#' + target + ' .wait').show();
21         
22         // If we have enough data
23         if(host && type) {
24                 // Generate a session ID
25                 var sessionID = Math.round(100000.5 + (((900000.49999) - (100000.5)) * Math.random()));
26                 var id = target + '-' + sessionID + '-' + genID();
27                 $('.' + target + '-results').attr('data-session', target + '-' + sessionID);
28                 
29                 // We request the service item
30                 var iq = new JSJaCIQ();
31                 iq.setID(id);
32                 iq.setTo(host);
33                 iq.setType('get');
34                 
35                 // MUC admin query
36                 if(type == 'muc') {
37                         iq.setQuery(NS_MUC_OWNER);
38                         con.send(iq, handleDataFormMuc);
39                 }
40                 
41                 // Browse query
42                 else if(type == 'browse') {
43                         var iqQuery = iq.setQuery(NS_DISCO_ITEMS);
44                         
45                         if(node)
46                                 iqQuery.setAttribute('node', node);
47                         
48                         con.send(iq, handleDataFormBrowse);
49                 }
50                 
51                 // Command
52                 else if(type == 'command') {
53                         var items;
54                         
55                         if(node)
56                                 items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS});
57                         
58                         else {
59                                 items = iq.setQuery(NS_DISCO_ITEMS);
60                                 items.setAttribute('node', NS_COMMANDS);
61                         }
62                         
63                         if(action && node) {
64                                 iq.setType('set');
65                                 items.setAttribute('action', action);
66                         }
67                         
68                         con.send(iq, handleDataFormCommand);
69                 }
70                 
71                 // Search query
72                 else if(type == 'search') {
73                         iq.setQuery(NS_SEARCH);
74                         con.send(iq, handleDataFormSearch);
75                 }
76                 
77                 // Subscribe query
78                 else if(type == 'subscribe') {
79                         iq.setQuery(NS_REGISTER);
80                         con.send(iq, handleDataFormSubscribe);
81                 }
82                 
83                 // Join
84                 else if(type == 'join') {
85                         if(target == 'discovery')
86                                 closeDiscovery();
87                         
88                         checkChatCreate(host, 'groupchat');
89                 }
90         }
91         
92         return false;
93 }
94
95 // Sends a given dataform
96 function sendDataForm(type, action, x_type, id, xid, node, sessionid, target) {
97         // Path
98         var pathID = '#' + target + ' .results[data-session=' + id + ']';
99         
100         // New IQ
101         var iq = new JSJaCIQ();
102         iq.setTo(xid);
103         iq.setType('set');
104         
105         // Set the correct query
106         var query;
107         
108         if(type == 'subscribe')
109                 iqQuery = iq.setQuery(NS_REGISTER);
110         else if(type == 'search')
111                 iqQuery = iq.setQuery(NS_SEARCH);
112         else if(type == 'command')
113                 iqQuery = iq.appendNode('command', {'xmlns': NS_COMMANDS, 'node': node, 'sessionid': sessionid, 'action': action});
114         else if(type == 'x')
115                 iqQuery = iq.setQuery(NS_MUC_OWNER);
116         
117         // Build the XML document
118         if(action != 'cancel') {
119                 // No X node
120                 if(exists('input.register-special') && (type == 'subscribe')) {
121                         $('input.register-special').each(function() {
122                                 var iName = $(this).attr('name');
123                                 var iValue = $(this).val();
124                                 
125                                 iqQuery.appendChild(iq.buildNode(iName, {'xmlns': NS_REGISTER}, iValue));
126                         });
127                 }
128                 
129                 // Can create the X node
130                 else {
131                         var iqX = iqQuery.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': x_type}));
132                         
133                         // Each input
134                         $(pathID + ' .oneresult input, ' + pathID + ' .oneresult textarea, ' + pathID + ' .oneresult select').each(function() {
135                                 // Get the current input value
136                                 var iVar = $(this).attr('name');
137                                 var iType = $(this).attr('data-type');
138                                 var iValue = $(this).val();
139                                 
140                                 // Build a new field node
141                                 var field = iqX.appendChild(iq.buildNode('field', {'var': iVar, 'type': iType, 'xmlns': NS_XDATA}));
142                                 
143                                 // Boolean input?
144                                 if(iType == 'boolean') {
145                                         if($(this).filter(':checked').size())
146                                                 iValue = '1';
147                                         else
148                                                 iValue = '0';
149                                 }
150                                 
151                                 // JID-multi input?
152                                 if(iType == 'jid-multi') {
153                                         // Values array
154                                         var xid_arr = [iValue];
155                                         var xid_check = [];
156                                         
157                                         // Try to split it
158                                         if(iValue.indexOf(',') != -1)
159                                                 xid_arr = iValue.split(',');
160                                         
161                                         // Append each value to the XML document
162                                         for(i in xid_arr) {
163                                                 // Get the current value
164                                                 xid_current = trim(xid_arr[i]);
165                                                 
166                                                 // No current value?
167                                                 if(!xid_current)
168                                                         continue;
169                                                 
170                                                 // Add the current value
171                                                 if(!existArrayValue(xid_check, xid_current)) {
172                                                         xid_check.push(xid_current);
173                                                         field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, xid_current));
174                                                 }
175                                         }
176                                 }
177                                 
178                                 // List-multi selector?
179                                 else if(iType == 'list-multi') {
180                                         // Any value?
181                                         if(iValue && iValue.length) {
182                                                 for(i in iValue)
183                                                         field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue[i]));
184                                         }
185                                 }
186                                 
187                                 // Other inputs?
188                                 else
189                                         field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue));
190                         });
191                 }
192         }
193         
194         // Clean the current session
195         cleanDataForm(target);
196         
197         // Show the waiting item
198         $('#' + target + ' .wait').show();
199         
200         // Change the ID of the current discovered item
201         var iqID = target + '-' + genID();
202         $('#' + target + ' .' + target + '-results').attr('data-session', iqID);
203         iq.setID(iqID);
204         
205         // Send the IQ
206         if(type == 'subscribe')
207                 con.send(iq, handleDataFormSubscribe);
208         else if(type == 'search')
209                 con.send(iq, handleDataFormSearch);
210         else if(type == 'command')
211                 con.send(iq, handleDataFormCommand);
212         else
213                 con.send(iq);
214         
215         return false;
216 }
217
218 // Displays the good dataform buttons
219 function buttonsDataForm(type, action, id, xid, node, sessionid, target, pathID) {
220         // No need to use buttons?
221         if(type == 'muc')
222                 return;
223         
224         // Override the "undefined" output
225         if(!id)
226                 id = '';
227         if(!xid)
228                 xid = '';
229         if(!node)
230                 node = '';
231         if(!sessionid)
232                 sessionid = '';
233         
234         // We generate the buttons code
235         var buttonsCode = '<div class="oneresult ' + target + '-oneresult ' + target + '-formtools">';
236         
237         if(action == 'submit') {
238                 if((target == 'adhoc') && (type == 'command')) {
239                         buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'execute\', \'submit\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Submit") + '</a>';
240                         
241                         // When keyup on one text input
242                         $(pathID + ' input').keyup(function(e) {
243                                 if(e.keyCode == 13) {
244                                         sendDataForm(type, 'execute', 'submit', id, xid, node, sessionid, target);
245                                         
246                                         return false;
247                                 }
248                         });
249                 }
250                 
251                 else {
252                         buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'submit\', \'submit\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Submit") + '</a>';
253                         
254                         // When keyup on one text input
255                         $(pathID + ' input').keyup(function(e) {
256                                 if(e.keyCode == 13) {
257                                         sendDataForm(type, 'submit', 'submit', id, xid, node, sessionid, target);
258                                         
259                                         return false;
260                                 }
261                         });
262                 }
263         }
264         
265         if((action == 'submit') && (type != 'subscribe') && (type != 'search'))
266                 buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'cancel\', \'cancel\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Cancel") + '</a>';
267         
268         if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery'))
269                 buttonsCode += '<a href="#" class="back" onclick="return startDiscovery();">' + _e("Close") + '</a>';
270         
271         if((action == 'back') && ((target == 'welcome') || (target == 'directory')))
272                 buttonsCode += '<a href="#" class="back" onclick="return dataForm(HOST_VJUD, \'search\', \'\', \'\', \'' + target + '\');">' + _e("Previous") + '</a>';
273         
274         if((action == 'back') && (target == 'adhoc'))
275                 buttonsCode += '<a href="#" class="back" onclick="return dataForm(\'' + encodeOnclick(xid) + '\', \'command\', \'\', \'\', \'adhoc\');">' + _e("Previous") + '</a>';
276         
277         buttonsCode += '</div>';
278         
279         // We display the buttons code
280         $(pathID).append(buttonsCode);
281         
282         // If no submit link, lock the form
283         if(!exists(pathID + ' a.submit'))
284                 $(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true);
285 }
286
287 // Handles the MUC dataform
288 function handleDataFormMuc(iq) {
289         handleErrorReply(iq);
290         handleDataFormContent(iq, 'muc');
291 }
292
293 // Handles the browse dataform
294 function handleDataFormBrowse(iq) {
295         handleErrorReply(iq);
296         handleDataFormContent(iq, 'browse');
297 }
298
299 // Handles the command dataform
300 function handleDataFormCommand(iq) {
301         handleErrorReply(iq);
302         handleDataFormContent(iq, 'command');
303 }
304
305 // Handles the subscribe dataform
306 function handleDataFormSubscribe(iq) {
307         handleErrorReply(iq);
308         handleDataFormContent(iq, 'subscribe');
309 }
310
311 // Handles the search dataform
312 function handleDataFormSearch(iq) {
313         handleErrorReply(iq);
314         handleDataFormContent(iq, 'search');
315 }
316
317 // Handles the dataform content
318 function handleDataFormContent(iq, type) {
319         // Get the ID
320         var sID = iq.getID();
321         
322         // Get the target
323         var splitted = sID.split('-');
324         var target = splitted[0];
325         var sessionID = target + '-' + splitted[1];
326         var from = fullXID(getStanzaFrom(iq));
327         var pathID = '#' + target + ' .results[data-session=' + sessionID + ']';
328         
329         // If an error occured
330         if(!iq || (iq.getType() != 'result'))
331                 noResultDataForm(pathID);
332         
333         // If we got something okay
334         else {
335                 var handleXML = iq.getNode();
336                 
337                 if(type == 'browse') {
338                         if($(handleXML).find('item').attr('jid')) {
339                                 // Get the query node
340                                 var queryNode = $(handleXML).find('query').attr('node');
341                                 
342                                 $(handleXML).find('item').each(function() {
343                                         // We parse the received xml
344                                         var itemHost = $(this).attr('jid');
345                                         var itemNode = $(this).attr('node');
346                                         var itemName = $(this).attr('name');
347                                         var itemHash = hex_md5(itemHost);
348                                         
349                                         // Node
350                                         if(itemNode)
351                                                 $(pathID).append(
352                                                         '<div class="oneresult ' + target + '-oneresult" onclick="return dataForm(\'' + encodeOnclick(itemHost) + '\', \'browse\', \'' + encodeOnclick(itemNode) + '\', \'\', \'' + encodeOnclick(target) + '\');">' + 
353                                                                 '<div class="one-name">' + itemNode.htmlEnc() + '</div>' + 
354                                                         '</div>'
355                                                 );
356                                         
357                                         // Item
358                                         else if(queryNode && itemName)
359                                                 $(pathID).append(
360                                                         '<div class="oneresult ' + target + '-oneresult">' + 
361                                                                 '<div class="one-name">' + itemName.htmlEnc() + '</div>' + 
362                                                         '</div>'
363                                                 );
364                                         
365                                         // Item with children
366                                         else {
367                                                 // We display the waiting element
368                                                 $(pathID + ' .disco-wait .disco-category-title').after(
369                                                         '<div class="oneresult ' + target + '-oneresult ' + itemHash + '">' + 
370                                                                 '<div class="one-icon loading talk-images"></div>' + 
371                                                                 '<div class="one-host">' + itemHost + '</div>' + 
372                                                                 '<div class="one-type">' + _e("Requesting this service...") + '</div>' + 
373                                                         '</div>'
374                                                 );
375                                                 
376                                                 // We display the category
377                                                 $('#' + target + ' .disco-wait').show();
378                                                 
379                                                 // We ask the server what's the service type
380                                                 getDataFormType(itemHost, itemNode, sessionID);
381                                         }
382                                 });
383                         }
384                         
385                         // Else, there are no items for this query
386                         else
387                                 noResultDataForm(pathID);
388                 }
389                 
390                 else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) {
391                         // Get some values
392                         var xCommand = $(handleXML).find('command');
393                         var bNode = xCommand.attr('node');
394                         var bSession = xCommand.attr('sessionid');
395                         var bStatus = xCommand.attr('status');
396                         var xRegister = $(handleXML).find('query[xmlns=' + NS_REGISTER + ']').text();
397                         var xElement = $(handleXML).find('x');
398                         
399                         // Search done
400                         if((xElement.attr('type') == 'result') && (type == 'search')) {
401                                 var bPath = pathID;
402                                 
403                                 // Display the result
404                                 $(handleXML).find('item').each(function() {
405                                         var bXID = $(this).find('field[var=jid] value:first').text();
406                                         var bName = $(this).find('field[var=fn] value:first').text();
407                                         var bCountry = $(this).find('field[var=ctry] value:first').text();
408                                         var dName = bName;
409                                         
410                                         // Override "undefined" value
411                                         if(!bXID)
412                                                 bXID = '';
413                                         if(!bName)
414                                                 bName = _e("Unknown name");
415                                         if(!bCountry)
416                                                 bCountry = _e("Unknown country");
417                                         
418                                         // User hash
419                                         var bHash = hex_md5(bXID);
420                                         
421                                         // HTML code
422                                         var bHTML = '<div class="oneresult ' + target + '-oneresult ' + bHash + '">' + 
423                                                         '<div class="avatar-container">' + 
424                                                                 '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
425                                                         '</div>' + 
426                                                         '<div class="one-fn">' + bName + '</div>' + 
427                                                         '<div class="one-ctry">' + bCountry + '</div>' + 
428                                                         '<div class="one-jid">' + bXID + '</div>' + 
429                                                         '<div class="buttons-container">';
430                                         
431                                         // The buddy is not in our buddy list?
432                                         if(!exists('#buddy-list .buddy[data-xid=' + escape(bXID) + ']'))
433                                                 bHTML += '<a href="#" class="one-add one-vjud one-button talk-images">' + _e("Add") + '</a>';
434                                         
435                                         // Chat button, if not in welcome/directory mode
436                                         if(target == 'discovery')
437                                                 bHTML += '<a href="#" class="one-chat one-vjud one-button talk-images">' + _e("Chat") + '</a>';
438                                         
439                                         // Close the HTML element
440                                         bHTML += '</div></div>';
441                                         
442                                         $(bPath).append(bHTML);
443                                         
444                                         // Click events
445                                         $(bPath + ' .' + bHash + ' a').click(function() {
446                                                 // Buddy add
447                                                 if($(this).is('.one-add')) {
448                                                         $(this).hide();
449                                                         
450                                                         addThisContact(bXID, dName);
451                                                 }
452                                                 
453                                                 // Buddy chat
454                                                 if($(this).is('.one-chat')) {
455                                                         if(target == 'discovery')
456                                                                 closeDiscovery();
457                                                         
458                                                         checkChatCreate(bXID , 'chat', '', '', dName);
459                                                 }
460                                                 
461                                                 return false;
462                                         });
463                                         
464                                         // Get the user's avatar
465                                         if(bXID)
466                                                 getAvatar(bXID, 'cache', 'true', 'forget');
467                                 });
468                                 
469                                 // No result?
470                                 if(!$(handleXML).find('item').size())
471                                         noResultDataForm(pathID);
472                                 
473                                 // Previous button
474                                 buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID);
475                         }
476                         
477                         // Command to complete
478                         else if(xElement.attr('xmlns') || ((type == 'subscribe') && xRegister)) {
479                                 // We display the elements
480                                 fillDataForm(handleXML, sessionID);
481                                 
482                                 // We display the buttons
483                                 if(bStatus != 'completed')
484                                         buttonsDataForm(type, 'submit', sessionID, from, bNode, bSession, target, pathID);
485                                 else
486                                         buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID);
487                         }
488                         
489                         // Command completed or subscription done
490                         else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) {
491                                 // Display the good text
492                                 var cNote = $(xCommand).find('note');
493                                 
494                                 // Any note?
495                                 if(cNote.size()) {
496                                         cNote.each(function() {
497                                                 $(pathID).append(
498                                                         '<div class="onetitle ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
499                                                 );
500                                         });
501                                 }
502                                 
503                                 // Default text
504                                 else
505                                         $(pathID).append('<div class="oneinstructions ' + target + '-oneresult">' + _e("Your form has been sent.") + '</div>');
506                                 
507                                 // Display the back button
508                                 buttonsDataForm(type, 'back', sessionID, from, '', '', target, pathID);
509                                 
510                                 // Add the gateway to our roster if subscribed
511                                 if(type == 'subscribe')
512                                         addThisContact(from);
513                         }
514                         
515                         // Command canceled
516                         else if((bStatus == 'canceled') && (type == 'command')) {
517                                 if(target == 'discovery')
518                                         startDiscovery();
519                                 else if(target == 'adhoc')
520                                         dataForm(from, 'command', '', '', 'adhoc');
521                         }
522                         
523                         // No items for this query
524                         else
525                                 noResultDataForm(pathID);
526                 }
527                 
528                 else if(type == 'command') {
529                         if($(handleXML).find('item').attr('jid')) {
530                                 // We display the elements
531                                 $(handleXML).find('item').each(function() {
532                                         // We parse the received xml
533                                         var itemHost = $(this).attr('jid');
534                                         var itemNode = $(this).attr('node');
535                                         var itemName = $(this).attr('name');
536                                         var itemHash = hex_md5(itemHost);
537                                         
538                                         // We display the waiting element
539                                         $(pathID).prepend(
540                                                 '<div class="oneresult ' + target + '-oneresult ' + itemHash + '" onclick="return dataForm(\'' + encodeOnclick(itemHost) + '\', \'command\', \'' + encodeOnclick(itemNode) + '\', \'execute\', \'' + encodeOnclick(target) + '\');">' + 
541                                                         '<div class="one-name">' + itemName + '</div>' + 
542                                                         '<div class="one-next">»</div>' + 
543                                                 '</div>'
544                                         );
545                                 });
546                         }
547                         
548                         // Else, there are no items for this query
549                         else
550                                 noResultDataForm(pathID);
551                 }
552         }
553         
554         // Focus on the first input
555         $(document).oneTime(10, function() {
556                 $(pathID + ' input:visible:first').focus();
557         });
558         
559         // Hide the wait icon
560         $('#' + target + ' .wait').hide();
561 }
562
563 // Fills the dataform elements
564 function fillDataForm(xml, id) {
565         /* REF: http://xmpp.org/extensions/xep-0004.html */
566         
567         // Initialize new vars
568         var target = id.split('-')[0];
569         var pathID = '#' + target + ' .results[data-session=' + id + ']';
570         var selector, is_dataform;
571         
572         // Is it a dataform?
573         if($(xml).find('x[xmlns=' + NS_XDATA + ']').size())
574                 is_dataform = true;
575         else
576                 is_dataform = false;
577         
578         // Determines the good selector to use
579         if(is_dataform)
580                 selector = $(xml).find('x[xmlns=' + NS_XDATA + ']');
581         else
582                 selector = $(xml);
583         
584         // Form title
585         selector.find('title').each(function() {
586                 $(pathID).append(
587                         '<div class="onetitle ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
588                 );
589         });
590         
591         // Form instructions
592         selector.find('instructions').each(function() {
593                 $(pathID).append(
594                         '<div class="oneinstructions ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
595                 );
596         });
597         
598         // Register?
599         if(!is_dataform) {
600                 // Items to detect
601                 var reg_names = [_e("Nickname"), _e("Name"), _e("Password"), _e("E-mail")];
602                 var reg_ids = ['username', 'name', 'password', 'email'];
603                 
604                 // Append these inputs
605                 for(a in reg_names) {
606                         selector.find(reg_ids[a]).each(function() {
607                                 $(pathID).append(
608                                         '<div class="oneresult ' + target + '-oneresult">' + 
609                                                 '<label>' + reg_names[a] + '</label>' + 
610                                                 '<input name="' + reg_ids[a] + '" type="text" class="register-special dataform-i" />' + 
611                                         '</div>'
612                                 );
613                         });
614                 }
615                 
616                 return false;
617         }
618         
619         // Dataform?
620         selector.find('field').each(function() {
621                 // We parse the received xml
622                 var type = $(this).attr('type');
623                 var label = $(this).attr('label');
624                 var field = $(this).attr('var');
625                 var value = $(this).find('value:first').text();
626                 var required = '';
627                 
628                 // No value?
629                 if(!field)
630                         return;
631                 
632                 // Required input?
633                 if($(this).find('required').size())
634                         required = ' required=""';
635                 
636                 // Compatibility fix
637                 if(!label)
638                         label = field;
639                 
640                 if(!type)
641                         type = '';
642                 
643                 // Generate some values
644                 var input;
645                 var hideThis = '';
646                 
647                 // Fixed field
648                 if(type == 'fixed')
649                         $(pathID).append('<div class="oneinstructions">' + value.htmlEnc() + '</div>');
650                 
651                 else {
652                         // Hidden field
653                         if(type == 'hidden') {
654                                 hideThis = ' style="display: none;"';
655                                 input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="hidden" class="dataform-i" value="' + encodeQuotes(value) + '" ' + required + ' />';
656                         }
657
658                         // Boolean field
659                         else if(type == 'boolean') {
660                                 var checked;
661                                 
662                                 if(value == '1')
663                                         checked = 'checked';
664                                 else
665                                         checked = '';
666                                 
667                                 input = '<input name="' + encodeQuotes(field) + '" type="checkbox" data-type="' + encodeQuotes(type) + '" class="dataform-i df-checkbox" ' + checked + required + ' />';
668                         }
669                         
670                         // List-single/list-multi field
671                         else if((type == 'list-single') || (type == 'list-multi')) {
672                                 var multiple = '';
673                                 
674                                 // Multiple options?
675                                 if(type == 'list-multi')
676                                         multiple = ' multiple=""';
677                                 
678                                 // Append the select field
679                                 input = '<select name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" class="dataform-i"' + required + multiple + '>';
680                                 var selected;
681                                 
682                                 // Append the available options
683                                 $(this).find('option').each(function() {
684                                         var nLabel = $(this).attr('label');
685                                         var nValue = $(this).find('value').text();
686                                         
687                                         // No label?
688                                         if(!nLabel)
689                                                 nLabel = nValue;
690                                         
691                                         // If this is the selected value
692                                         if(nValue == value)
693                                                 selected = 'selected';
694                                         else
695                                                 selected = '';
696                                         
697                                         input += '<option ' + selected + ' value="' + encodeQuotes(nValue) + '">' + nLabel.htmlEnc() + '</option>';
698                                 });
699                                 
700                                 input += '</select>';
701                         }
702                         
703                         // Text-multi field
704                         else if(type == 'text-multi')
705                                 input = '<textarea rows="8" cols="60" data-type="' + encodeQuotes(type) + '" name="' + encodeQuotes(field) + '" class="dataform-i"' + required + '>' + value.htmlEnc() + '</textarea>';
706                         
707                         // JID-multi field
708                         else if(type == 'jid-multi') {
709                                 // Put the XID into an array
710                                 var xid_arr = [];
711                                 
712                                 $(this).find('value').each(function() {
713                                         var cValue = $(this).text();
714                                         
715                                         if(!existArrayValue(xid_arr, cValue))
716                                                 xid_arr.push(cValue);
717                                 });
718                                 
719                                 // Sort the array
720                                 xid_arr.sort();
721                                 
722                                 // Create the input
723                                 var xid_value = '';
724                                 
725                                 if(xid_arr.length) {
726                                         for(i in xid_arr) {
727                                                 // Any pre-value
728                                                 if(xid_value)
729                                                         xid_value += ', ';
730                                                 
731                                                 // Add the current XID
732                                                 xid_value += xid_arr[i];
733                                         }
734                                 }
735                                 
736                                 input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="text" class="dataform-i" value="' + encodeQuotes(xid_value) + '" placeholder="jack@jappix.com, jones@jappix.com"' + required + ' />';
737                         }
738                         
739                         // Other stuffs that are similar
740                         else {
741                                 // Text-single field
742                                 var iType = 'text';
743                                 
744                                 // Text-private field
745                                 if(type == 'text-private')
746                                         iType = 'password';
747                                 
748                                 // JID-single field
749                                 else if(type == 'jid-single')
750                                         iType = 'email';
751                                 
752                                 input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="' + iType + '" class="dataform-i" value="' + encodeQuotes(value) + '"' + required + ' />';
753                         }
754                         
755                         // Append the HTML markup for this field
756                         $(pathID).append(
757                                 '<div class="oneresult ' + target + '-oneresult"' + hideThis + '>' + 
758                                         '<label>' + label.htmlEnc() + '</label>' + 
759                                         input + 
760                                 '</div>'
761                         );
762                 }
763         });
764         
765         return false;
766 }
767
768 // Gets the dataform type
769 function getDataFormType(host, node, id) {
770         var iq = new JSJaCIQ();
771         iq.setID(id + '-' + genID());
772         iq.setTo(host);
773         iq.setType('get');
774         
775         var iqQuery = iq.setQuery(NS_DISCO_INFO);
776         
777         if(node)
778                 iqQuery.setAttribute('node', node);
779         
780         con.send(iq, handleThisBrowse);
781 }
782
783 // Handles the browse stanza
784 function handleThisBrowse(iq) {
785         /* REF: http://xmpp.org/registrar/disco-categories.html */
786         
787         var id = iq.getID();
788         var splitted = id.split('-');
789         var target = splitted[0];
790         var sessionID = target + '-' + splitted[1];
791         var from = fullXID(getStanzaFrom(iq));
792         var hash = hex_md5(from);
793         var handleXML = iq.getQuery();
794         var pathID = '#' + target + ' .results[data-session=' + sessionID + ']';
795         
796         // We first remove the waiting element
797         $(pathID + ' .disco-wait .' + hash).remove();
798         
799         if($(handleXML).find('identity').attr('type')) {
800                 var category = $(handleXML).find('identity').attr('category');
801                 var type = $(handleXML).find('identity').attr('type');
802                 var named = $(handleXML).find('identity').attr('name');
803                 
804                 if(named)
805                         gName = named;
806                 else
807                         gName = '';
808                 
809                 var one, two, three, four, five;
810                 
811                 // Get the features that this entity supports
812                 var findFeature = $(handleXML).find('feature');
813                 
814                 for(i in findFeature) {
815                         var current = findFeature.eq(i).attr('var');
816                         
817                         switch(current) {
818                                 case NS_SEARCH:
819                                         one = 1;
820                                         break;
821                                 
822                                 case NS_MUC:
823                                         two = 1;
824                                         break;
825                                 
826                                 case NS_REGISTER:
827                                         three = 1;
828                                         break;
829                                 
830                                 case NS_COMMANDS:
831                                         four = 1;
832                                         break;
833                                 
834                                 case NS_DISCO_ITEMS:
835                                         five = 1;
836                                         break;
837                                 
838                                 default:
839                                         break;
840                         }
841                 }
842                 
843                 var buttons = Array(one, two, three, four, five);
844                 
845                 // We define the toolbox links depending on the supported features
846                 var tools = '';
847                 var aTools = Array('search', 'join', 'subscribe', 'command', 'browse');
848                 var bTools = Array(_e("Search"), _e("Join"), _e("Subscribe"), _e("Command"), _e("Browse"));
849                 
850                 for(i in buttons) {
851                         if(buttons[i])
852                                 tools += '<a href="#" class="one-button ' + aTools[i] + ' talk-images" onclick="return dataForm(\'' + encodeOnclick(from) + '\', \'' + encodeOnclick(aTools[i]) + '\', \'\', \'\', \'' + encodeOnclick(target) + '\');" title="' + encodeOnclick(bTools[i]) + '"></a>';
853                 }
854                 
855                 // As defined in the ref, we detect the type of each category to put an icon
856                 switch(category) {
857                         case 'account':
858                         case 'auth':
859                         case 'automation':
860                         case 'client':
861                         case 'collaboration':
862                         case 'component':
863                         case 'conference':
864                         case 'directory':
865                         case 'gateway':
866                         case 'headline':
867                         case 'hierarchy':
868                         case 'proxy':
869                         case 'pubsub':
870                         case 'server':
871                         case 'store':
872                                 break;
873                         
874                         default:
875                                 category = 'others';
876                 }
877                 
878                 // We display the item we found
879                 $(pathID + ' .disco-' + category + ' .disco-category-title').after(
880                         '<div class="oneresult ' + target + '-oneresult ' + hash + '">' + 
881                                 '<div class="one-icon ' + category + ' talk-images"></div>' + 
882                                 '<div class="one-host">' + from + '</div>' + 
883                                 '<div class="one-type">' + gName + '</div>' + 
884                                 '<div class="one-actions">' + tools + '</div>' + 
885                         '</div>'
886                 );
887                 
888                 // We display the category
889                 $(pathID + ' .disco-' + category).show();
890         }
891         
892         else {
893                 $(pathID + ' .disco-others .disco-category-title').after(
894                         '<div class="oneresult ' + target + '-oneresult">' + 
895                                 '<div class="one-icon down talk-images"></div>' + 
896                                 '<div class="one-host">' + from + '</div>' + 
897                                 '<div class="one-type">' + _e("Service offline or broken") + '</div>' + 
898                         '</div>'
899                 );
900                 
901                 // We display the category
902                 $(pathID + ' .disco-others').show();
903         }
904         
905         // We hide the waiting stuffs if there's no remaining loading items
906         if(!$(pathID + ' .disco-wait .' + target + '-oneresult').size())
907                 $(pathID + ' .disco-wait, #' + target + ' .wait').hide();
908 }
909
910 // Cleans the current data-form popup
911 function cleanDataForm(target) {
912         if(target == 'discovery')
913                 cleanDiscovery();
914         else
915                 $('#' + target + ' div.results').empty();
916 }
917
918 // Displays the no result indicator
919 function noResultDataForm(path) {
920         $(path).prepend('<p class="no-results">' + _e("Sorry, but the entity didn't return any result!") + '</p>');
921 }