/* Jappix - An open social platform These are the dataform JS scripts for Jappix ------------------------------------------------- License: AGPL Author: Vanaryon Last revision: 28/08/11 */ // Gets the defined dataform elements function dataForm(host, type, node, action, target) { // Clean the current session cleanDataForm(target); // We tell the user that a search has been launched $('#' + target + ' .wait').show(); // If we have enough data if(host && type) { // Generate a session ID var sessionID = Math.round(100000.5 + (((900000.49999) - (100000.5)) * Math.random())); var id = target + '-' + sessionID + '-' + genID(); $('.' + target + '-results').attr('data-session', target + '-' + sessionID); // We request the service item var iq = new JSJaCIQ(); iq.setID(id); iq.setTo(host); iq.setType('get'); // MUC admin query if(type == 'muc') { iq.setQuery(NS_MUC_OWNER); con.send(iq, handleDataFormMuc); } // Browse query else if(type == 'browse') { var iqQuery = iq.setQuery(NS_DISCO_ITEMS); if(node) iqQuery.setAttribute('node', node); con.send(iq, handleDataFormBrowse); } // Command else if(type == 'command') { var items; if(node) items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS}); else { items = iq.setQuery(NS_DISCO_ITEMS); items.setAttribute('node', NS_COMMANDS); } if(action && node) { iq.setType('set'); items.setAttribute('action', action); } con.send(iq, handleDataFormCommand); } // Search query else if(type == 'search') { iq.setQuery(NS_SEARCH); con.send(iq, handleDataFormSearch); } // Subscribe query else if(type == 'subscribe') { iq.setQuery(NS_REGISTER); con.send(iq, handleDataFormSubscribe); } // Join else if(type == 'join') { if(target == 'discovery') closeDiscovery(); checkChatCreate(host, 'groupchat'); } } return false; } // Sends a given dataform function sendDataForm(type, action, x_type, id, xid, node, sessionid, target) { // Path var pathID = '#' + target + ' .results[data-session=' + id + ']'; // New IQ var iq = new JSJaCIQ(); iq.setTo(xid); iq.setType('set'); // Set the correct query var query; if(type == 'subscribe') iqQuery = iq.setQuery(NS_REGISTER); else if(type == 'search') iqQuery = iq.setQuery(NS_SEARCH); else if(type == 'command') iqQuery = iq.appendNode('command', {'xmlns': NS_COMMANDS, 'node': node, 'sessionid': sessionid, 'action': action}); else if(type == 'x') iqQuery = iq.setQuery(NS_MUC_OWNER); // Build the XML document if(action != 'cancel') { // No X node if(exists('input.register-special') && (type == 'subscribe')) { $('input.register-special').each(function() { var iName = $(this).attr('name'); var iValue = $(this).val(); iqQuery.appendChild(iq.buildNode(iName, {'xmlns': NS_REGISTER}, iValue)); }); } // Can create the X node else { var iqX = iqQuery.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': x_type})); // Each input $(pathID + ' .oneresult input, ' + pathID + ' .oneresult textarea, ' + pathID + ' .oneresult select').each(function() { // Get the current input value var iVar = $(this).attr('name'); var iType = $(this).attr('data-type'); var iValue = $(this).val(); // Build a new field node var field = iqX.appendChild(iq.buildNode('field', {'var': iVar, 'type': iType, 'xmlns': NS_XDATA})); // Boolean input? if(iType == 'boolean') { if($(this).filter(':checked').size()) iValue = '1'; else iValue = '0'; } // JID-multi input? if(iType == 'jid-multi') { // Values array var xid_arr = [iValue]; var xid_check = []; // Try to split it if(iValue.indexOf(',') != -1) xid_arr = iValue.split(','); // Append each value to the XML document for(i in xid_arr) { // Get the current value xid_current = trim(xid_arr[i]); // No current value? if(!xid_current) continue; // Add the current value if(!existArrayValue(xid_check, xid_current)) { xid_check.push(xid_current); field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, xid_current)); } } } // List-multi selector? else if(iType == 'list-multi') { // Any value? if(iValue && iValue.length) { for(i in iValue) field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue[i])); } } // Other inputs? else field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue)); }); } } // Clean the current session cleanDataForm(target); // Show the waiting item $('#' + target + ' .wait').show(); // Change the ID of the current discovered item var iqID = target + '-' + genID(); $('#' + target + ' .' + target + '-results').attr('data-session', iqID); iq.setID(iqID); // Send the IQ if(type == 'subscribe') con.send(iq, handleDataFormSubscribe); else if(type == 'search') con.send(iq, handleDataFormSearch); else if(type == 'command') con.send(iq, handleDataFormCommand); else con.send(iq); return false; } // Displays the good dataform buttons function buttonsDataForm(type, action, id, xid, node, sessionid, target, pathID) { // No need to use buttons? if(type == 'muc') return; // Override the "undefined" output if(!id) id = ''; if(!xid) xid = ''; if(!node) node = ''; if(!sessionid) sessionid = ''; // We generate the buttons code var buttonsCode = '
'; if(action == 'submit') { if((target == 'adhoc') && (type == 'command')) { buttonsCode += '' + _e("Submit") + ''; // When keyup on one text input $(pathID + ' input').keyup(function(e) { if(e.keyCode == 13) { sendDataForm(type, 'execute', 'submit', id, xid, node, sessionid, target); return false; } }); } else { buttonsCode += '' + _e("Submit") + ''; // When keyup on one text input $(pathID + ' input').keyup(function(e) { if(e.keyCode == 13) { sendDataForm(type, 'submit', 'submit', id, xid, node, sessionid, target); return false; } }); } } if((action == 'submit') && (type != 'subscribe') && (type != 'search')) buttonsCode += '' + _e("Cancel") + ''; if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery')) buttonsCode += '' + _e("Close") + ''; if((action == 'back') && ((target == 'welcome') || (target == 'directory'))) buttonsCode += '' + _e("Previous") + ''; if((action == 'back') && (target == 'adhoc')) buttonsCode += '' + _e("Previous") + ''; buttonsCode += '
'; // We display the buttons code $(pathID).append(buttonsCode); // If no submit link, lock the form if(!exists(pathID + ' a.submit')) $(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true); } // Handles the MUC dataform function handleDataFormMuc(iq) { handleErrorReply(iq); handleDataFormContent(iq, 'muc'); } // Handles the browse dataform function handleDataFormBrowse(iq) { handleErrorReply(iq); handleDataFormContent(iq, 'browse'); } // Handles the command dataform function handleDataFormCommand(iq) { handleErrorReply(iq); handleDataFormContent(iq, 'command'); } // Handles the subscribe dataform function handleDataFormSubscribe(iq) { handleErrorReply(iq); handleDataFormContent(iq, 'subscribe'); } // Handles the search dataform function handleDataFormSearch(iq) { handleErrorReply(iq); handleDataFormContent(iq, 'search'); } // Handles the dataform content function handleDataFormContent(iq, type) { // Get the ID var sID = iq.getID(); // Get the target var splitted = sID.split('-'); var target = splitted[0]; var sessionID = target + '-' + splitted[1]; var from = fullXID(getStanzaFrom(iq)); var pathID = '#' + target + ' .results[data-session=' + sessionID + ']'; // If an error occured if(!iq || (iq.getType() != 'result')) noResultDataForm(pathID); // If we got something okay else { var handleXML = iq.getNode(); if(type == 'browse') { if($(handleXML).find('item').attr('jid')) { // Get the query node var queryNode = $(handleXML).find('query').attr('node'); $(handleXML).find('item').each(function() { // We parse the received xml var itemHost = $(this).attr('jid'); var itemNode = $(this).attr('node'); var itemName = $(this).attr('name'); var itemHash = hex_md5(itemHost); // Node if(itemNode) $(pathID).append( '
' + '
' + itemNode.htmlEnc() + '
' + '
' ); // Item else if(queryNode && itemName) $(pathID).append( '
' + '
' + itemName.htmlEnc() + '
' + '
' ); // Item with children else { // We display the waiting element $(pathID + ' .disco-wait .disco-category-title').after( '
' + '
' + '
' + itemHost + '
' + '
' + _e("Requesting this service...") + '
' + '
' ); // We display the category $('#' + target + ' .disco-wait').show(); // We ask the server what's the service type getDataFormType(itemHost, itemNode, sessionID); } }); } // Else, there are no items for this query else noResultDataForm(pathID); } else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) { // Get some values var xCommand = $(handleXML).find('command'); var bNode = xCommand.attr('node'); var bSession = xCommand.attr('sessionid'); var bStatus = xCommand.attr('status'); var xRegister = $(handleXML).find('query[xmlns=' + NS_REGISTER + ']').text(); var xElement = $(handleXML).find('x'); // Search done if((xElement.attr('type') == 'result') && (type == 'search')) { var bPath = pathID; // Display the result $(handleXML).find('item').each(function() { var bXID = $(this).find('field[var=jid] value:first').text(); var bName = $(this).find('field[var=fn] value:first').text(); var bCountry = $(this).find('field[var=ctry] value:first').text(); var dName = bName; // Override "undefined" value if(!bXID) bXID = ''; if(!bName) bName = _e("Unknown name"); if(!bCountry) bCountry = _e("Unknown country"); // User hash var bHash = hex_md5(bXID); // HTML code var bHTML = '
' + '
' + '' + '
' + '
' + bName + '
' + '
' + bCountry + '
' + '
' + bXID + '
' + '
'; // The buddy is not in our buddy list? if(!exists('#buddy-list .buddy[data-xid=' + escape(bXID) + ']')) bHTML += '' + _e("Add") + ''; // Chat button, if not in welcome/directory mode if(target == 'discovery') bHTML += '' + _e("Chat") + ''; // Close the HTML element bHTML += '
'; $(bPath).append(bHTML); // Click events $(bPath + ' .' + bHash + ' a').click(function() { // Buddy add if($(this).is('.one-add')) { $(this).hide(); addThisContact(bXID, dName); } // Buddy chat if($(this).is('.one-chat')) { if(target == 'discovery') closeDiscovery(); checkChatCreate(bXID , 'chat', '', '', dName); } return false; }); // Get the user's avatar if(bXID) getAvatar(bXID, 'cache', 'true', 'forget'); }); // No result? if(!$(handleXML).find('item').size()) noResultDataForm(pathID); // Previous button buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID); } // Command to complete else if(xElement.attr('xmlns') || ((type == 'subscribe') && xRegister)) { // We display the elements fillDataForm(handleXML, sessionID); // We display the buttons if(bStatus != 'completed') buttonsDataForm(type, 'submit', sessionID, from, bNode, bSession, target, pathID); else buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID); } // Command completed or subscription done else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) { // Display the good text var cNote = $(xCommand).find('note'); // Any note? if(cNote.size()) { cNote.each(function() { $(pathID).append( '
' + $(this).text().htmlEnc() + '
' ); }); } // Default text else $(pathID).append('
' + _e("Your form has been sent.") + '
'); // Display the back button buttonsDataForm(type, 'back', sessionID, from, '', '', target, pathID); // Add the gateway to our roster if subscribed if(type == 'subscribe') addThisContact(from); } // Command canceled else if((bStatus == 'canceled') && (type == 'command')) { if(target == 'discovery') startDiscovery(); else if(target == 'adhoc') dataForm(from, 'command', '', '', 'adhoc'); } // No items for this query else noResultDataForm(pathID); } else if(type == 'command') { if($(handleXML).find('item').attr('jid')) { // We display the elements $(handleXML).find('item').each(function() { // We parse the received xml var itemHost = $(this).attr('jid'); var itemNode = $(this).attr('node'); var itemName = $(this).attr('name'); var itemHash = hex_md5(itemHost); // We display the waiting element $(pathID).prepend( '
' + '
' + itemName + '
' + '
ยป
' + '
' ); }); } // Else, there are no items for this query else noResultDataForm(pathID); } } // Focus on the first input $(document).oneTime(10, function() { $(pathID + ' input:visible:first').focus(); }); // Hide the wait icon $('#' + target + ' .wait').hide(); } // Fills the dataform elements function fillDataForm(xml, id) { /* REF: http://xmpp.org/extensions/xep-0004.html */ // Initialize new vars var target = id.split('-')[0]; var pathID = '#' + target + ' .results[data-session=' + id + ']'; var selector, is_dataform; // Is it a dataform? if($(xml).find('x[xmlns=' + NS_XDATA + ']').size()) is_dataform = true; else is_dataform = false; // Determines the good selector to use if(is_dataform) selector = $(xml).find('x[xmlns=' + NS_XDATA + ']'); else selector = $(xml); // Form title selector.find('title').each(function() { $(pathID).append( '
' + $(this).text().htmlEnc() + '
' ); }); // Form instructions selector.find('instructions').each(function() { $(pathID).append( '
' + $(this).text().htmlEnc() + '
' ); }); // Register? if(!is_dataform) { // Items to detect var reg_names = [_e("Nickname"), _e("Name"), _e("Password"), _e("E-mail")]; var reg_ids = ['username', 'name', 'password', 'email']; // Append these inputs for(a in reg_names) { selector.find(reg_ids[a]).each(function() { $(pathID).append( '
' + '' + '' + '
' ); }); } return false; } // Dataform? selector.find('field').each(function() { // We parse the received xml var type = $(this).attr('type'); var label = $(this).attr('label'); var field = $(this).attr('var'); var value = $(this).find('value:first').text(); var required = ''; // No value? if(!field) return; // Required input? if($(this).find('required').size()) required = ' required=""'; // Compatibility fix if(!label) label = field; if(!type) type = ''; // Generate some values var input; var hideThis = ''; // Fixed field if(type == 'fixed') $(pathID).append('
' + value.htmlEnc() + '
'); else { // Hidden field if(type == 'hidden') { hideThis = ' style="display: none;"'; input = ''; } // Boolean field else if(type == 'boolean') { var checked; if(value == '1') checked = 'checked'; else checked = ''; input = ''; } // List-single/list-multi field else if((type == 'list-single') || (type == 'list-multi')) { var multiple = ''; // Multiple options? if(type == 'list-multi') multiple = ' multiple=""'; // Append the select field input = ''; } // Text-multi field else if(type == 'text-multi') input = ''; // JID-multi field else if(type == 'jid-multi') { // Put the XID into an array var xid_arr = []; $(this).find('value').each(function() { var cValue = $(this).text(); if(!existArrayValue(xid_arr, cValue)) xid_arr.push(cValue); }); // Sort the array xid_arr.sort(); // Create the input var xid_value = ''; if(xid_arr.length) { for(i in xid_arr) { // Any pre-value if(xid_value) xid_value += ', '; // Add the current XID xid_value += xid_arr[i]; } } input = ''; } // Other stuffs that are similar else { // Text-single field var iType = 'text'; // Text-private field if(type == 'text-private') iType = 'password'; // JID-single field else if(type == 'jid-single') iType = 'email'; input = ''; } // Append the HTML markup for this field $(pathID).append( '
' + '' + input + '
' ); } }); return false; } // Gets the dataform type function getDataFormType(host, node, id) { var iq = new JSJaCIQ(); iq.setID(id + '-' + genID()); iq.setTo(host); iq.setType('get'); var iqQuery = iq.setQuery(NS_DISCO_INFO); if(node) iqQuery.setAttribute('node', node); con.send(iq, handleThisBrowse); } // Handles the browse stanza function handleThisBrowse(iq) { /* REF: http://xmpp.org/registrar/disco-categories.html */ var id = iq.getID(); var splitted = id.split('-'); var target = splitted[0]; var sessionID = target + '-' + splitted[1]; var from = fullXID(getStanzaFrom(iq)); var hash = hex_md5(from); var handleXML = iq.getQuery(); var pathID = '#' + target + ' .results[data-session=' + sessionID + ']'; // We first remove the waiting element $(pathID + ' .disco-wait .' + hash).remove(); if($(handleXML).find('identity').attr('type')) { var category = $(handleXML).find('identity').attr('category'); var type = $(handleXML).find('identity').attr('type'); var named = $(handleXML).find('identity').attr('name'); if(named) gName = named; else gName = ''; var one, two, three, four, five; // Get the features that this entity supports var findFeature = $(handleXML).find('feature'); for(i in findFeature) { var current = findFeature.eq(i).attr('var'); switch(current) { case NS_SEARCH: one = 1; break; case NS_MUC: two = 1; break; case NS_REGISTER: three = 1; break; case NS_COMMANDS: four = 1; break; case NS_DISCO_ITEMS: five = 1; break; default: break; } } var buttons = Array(one, two, three, four, five); // We define the toolbox links depending on the supported features var tools = ''; var aTools = Array('search', 'join', 'subscribe', 'command', 'browse'); var bTools = Array(_e("Search"), _e("Join"), _e("Subscribe"), _e("Command"), _e("Browse")); for(i in buttons) { if(buttons[i]) tools += ''; } // As defined in the ref, we detect the type of each category to put an icon switch(category) { case 'account': case 'auth': case 'automation': case 'client': case 'collaboration': case 'component': case 'conference': case 'directory': case 'gateway': case 'headline': case 'hierarchy': case 'proxy': case 'pubsub': case 'server': case 'store': break; default: category = 'others'; } // We display the item we found $(pathID + ' .disco-' + category + ' .disco-category-title').after( '
' + '
' + '
' + from + '
' + '
' + gName + '
' + '
' + tools + '
' + '
' ); // We display the category $(pathID + ' .disco-' + category).show(); } else { $(pathID + ' .disco-others .disco-category-title').after( '
' + '
' + '
' + from + '
' + '
' + _e("Service offline or broken") + '
' + '
' ); // We display the category $(pathID + ' .disco-others').show(); } // We hide the waiting stuffs if there's no remaining loading items if(!$(pathID + ' .disco-wait .' + target + '-oneresult').size()) $(pathID + ' .disco-wait, #' + target + ' .wait').hide(); } // Cleans the current data-form popup function cleanDataForm(target) { if(target == 'discovery') cleanDiscovery(); else $('#' + target + ' div.results').empty(); } // Displays the no result indicator function noResultDataForm(path) { $(path).prepend('

' + _e("Sorry, but the entity didn't return any result!") + '

'); }