/* Jappix - An open social platform These are the vCard JS scripts for Jappix ------------------------------------------------- License: AGPL Author: Valérian Saliou, Maranda Last revision: 20/02/12 */ // Opens the vCard popup function openVCard() { // Popup HTML content var html = '
' + _e("Your profile") + '
' + '
' + '' + _e("Identity") + '' + '' + _e("Profile image") + '' + '' + _e("Others") + '' + '
' + '
' + '
' + '
' + '' + _e("Personal") + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
' + '
' + '' + _e("Contact") + '' + '' + '' + '' + '' + '' + '' + '
' + '
' + '
' + '
' + '' + _e("New") + '' + '' + '' + '
' + generateFileShare() + '
' + '
' + '
' + '' + _e("Current") + '' + '
' + '' + _e("Delete") + '' + '
' + _e("What a pity! You have no profile image defined in your identity card!") + '
' + '
' + '
' + _e("Please wait while your avatar is uploaded...") + '
' + '
' + _e("Here it is! A new beautiful profile image!") + '
' + '
' + _e("The image file is not supported or has a bad size.") + '
' + '
' + '
' + '
' + '' + _e("Address") + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
' + '
' + '' + _e("Biography") + '' + '' + '
' + '
' + '
' + '

' + _e("Important notice") + '

' + '

' + _e("Be careful with the information you store into your profile, because it might be accessible by everyone (even someone you don't want to).") + '

' + '

' + _e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '

' + '

' + printf(_e("It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."), JAPPIX_MAX_UPLOAD) + '

' + '

' + _e("Enable my public profile") + ' »

' + '
' + '
' + '
' + '
' + '' + _e("Save") + '' + '' + _e("Cancel") + '' + '
'; // Create the popup createPopup('vcard', html); // Associate the events launchVCard(); // We get the VCard informations getVCard(getXID(), 'user'); return false; } // Closes the vCard popup function closeVCard() { // Destroy the popup destroyPopup('vcard'); // Create the welcome end popup? if(END_WELCOME) { // Open popup openMe(); // Unavoidable popup $('#me').addClass('unavoidable'); } return false; } // Switches the vCard popup tabs function switchVCard(id) { $('#vcard .one-lap').removeClass('lap-active'); $('#vcard #lap' + id).addClass('lap-active'); $('#vcard .tab a').removeClass('tab-active'); $('#vcard .tab a[data-key="' + id + '"]').addClass('tab-active'); return false; } // Waits for the avatar upload reply function waitAvatarUpload() { // Reset the avatar info $('#vcard .avatar-info').hide().stopTime(); // Show the wait info $('#vcard .avatar-wait').show(); } // Handles the avatar upload reply function handleAvatarUpload(responseXML) { // Data selector var dData = $(responseXML).find('jappix'); // Not current upload session? if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name="id"]').val())) return; // Reset the avatar info $('#vcard .avatar-info').hide().stopTime(); // Process the returned data if(!dData.find('error').size()) { // Read the values var aType = dData.find('type').text(); var aBinval = dData.find('binval').text(); // We remove everything that isn't useful right here $('#vcard .no-avatar').hide(); $('#vcard .avatar').remove(); // We display the delete button $('#vcard .avatar-delete').show(); // We tell the user it's okay $('#vcard .avatar-ok').show(); // Timer $('#vcard .avatar-info').oneTime('10s', function() { $(this).hide(); }); // We put the base64 values in a hidden input to be sent $('#USER-PHOTO-TYPE').val(aType); $('#USER-PHOTO-BINVAL').val(aBinval); // We display the avatar ! $('#vcard .avatar-container').replaceWith('
'); } // Any error? else { $('#vcard .avatar-error').show(); // Timer $('#vcard .avatar-info').oneTime('10s', function() { $(this).hide(); }); logThis('Error while uploading the avatar: ' + dData.find('error').text(), 1); } } // Deletes the encoded avatar of an user function deleteAvatar() { // We remove the avatar displayed elements $('#vcard .avatar-info').stopTime(); $('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide(); $('#vcard .avatar').remove(); // We reset the input value $('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val(''); // We show the avatar-uploading request $('#vcard .no-avatar').show(); return false; } // Creates a special vCard input function createInputVCard(id, type) { // Generate the new ID id = 'USER-' + id; // Can append the content if((type == 'user') && !exists('#vcard #' + id)) $('#vcard .content').append(''); } // Gets the vCard of a XID function getVCard(to, type) { // Generate a special ID var id = genID(); // New IQ var iq = new JSJaCIQ(); iq.setID(id); iq.setType('get'); iq.appendNode('vCard', {'xmlns': NS_VCARD}); // Send the IQ to the good user if(type == 'user') { // Show the wait icon $('#vcard .wait').show(); // Apply the session ID $('#vcard').attr('data-vcard', id); // Send the IQ con.send(iq, handeUVCard); } else { // Show the wait icon $('#userinfos .wait').show(); // Apply the session ID $('#userinfos').attr('data-vcard', id); // Send the IQ iq.setTo(to); con.send(iq, handeBVCard); } } // Handles the current connected user's vCard function handeUVCard(iq) { handleVCard(iq, 'user'); } // Handles an external buddy vCard function handeBVCard(iq) { handleVCard(iq, 'buddy'); } // Handles a vCard stanza function handleVCard(iq, type) { // Extract the data var iqID = iq.getID(); var iqFrom = fullXID(getStanzaFrom(iq)); var iqNode = iq.getNode(); // Define some paths var path_vCard = '#vcard[data-vcard="' + iqID + '"]'; var path_userInfos = '#userinfos[data-vcard="' + iqID + '"]'; // End if the session does not exist if(((type == 'user') && !exists(path_vCard)) || ((type == 'buddy') && !exists(path_userInfos))) return; // We retrieve main values var values_yet = []; $(iqNode).find('vCard').children().each(function() { // Read the current parent node name var tokenname = (this).nodeName.toUpperCase(); // Node with a parent if($(this).children().size()) { $(this).children().each(function() { // Get the node values var currentID = tokenname + '-' + (this).nodeName.toUpperCase(); var currentText = $(this).text(); // Not yet added? if(!existArrayValue(values_yet, currentID)) { // Create an input if it does not exist createInputVCard(values_yet, type); // Userinfos viewer popup if((type == 'buddy') && currentText) { if(currentID == 'EMAIL-USERID') $(path_userInfos + ' #BUDDY-' + currentID).html('' + currentText.htmlEnc() + ''); else $(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc()); } // Profile editor popup else if(type == 'user') $(path_vCard + ' #USER-' + currentID).val(currentText); // Avoid duplicating the value values_yet.push(currentID); } }); } // Node without any parent else { // Get the node values var currentText = $(this).text(); // Not yet added? if(!existArrayValue(values_yet, tokenname)) { // Create an input if it does not exist createInputVCard(tokenname, type); // Userinfos viewer popup if((type == 'buddy') && currentText) { // URL modification if(tokenname == 'URL') { // No http:// or https:// prefix, we should add it if(!currentText.match(/^https?:\/\/(.+)/)) currentText = 'http://' + currentText; currentText = '' + currentText.htmlEnc() + ''; } // Description modification else if(tokenname == 'DESC') currentText = filterThisMessage(currentText, getBuddyName(iqFrom).htmlEnc(), true); // Other stuffs else currentText = currentText.htmlEnc(); $(path_userInfos + ' #BUDDY-' + tokenname).html(currentText); } // Profile editor popup else if(type == 'user') $(path_vCard + ' #USER-' + tokenname).val(currentText); // Avoid duplicating the value values_yet.push(tokenname); } } }); // Update the stored avatar if(type == 'buddy') { // Get the avatar XML var xml = getPersistent('global', 'avatar', iqFrom); // If there were no stored avatar previously if($(XMLFromString(xml)).find('type').text() == 'none') { xml = xml.replace(/false<\/forced>/gi, 'true'); setPersistent(getXID(), 'avatar', iqFrom, xml); } // Handle the user avatar handleAvatar(iq); } // The avatar values targets var aBinval, aType, aContainer; if(type == 'user') { aBinval = $('#USER-PHOTO-BINVAL').val(); aType = $('#USER-PHOTO-TYPE').val(); aContainer = path_vCard + ' .avatar-container'; } else { aBinval = $(iqNode).find('BINVAL:first').text(); aType = $(iqNode).find('TYPE:first').text(); aContainer = path_userInfos + ' .avatar-container'; } // We display the avatar if retrieved if(aBinval) { // No type? if(!aType) aType = 'image/png'; if(type == 'user') { // We move all the things that we don't need in that case $(path_vCard + ' .no-avatar').hide(); $(path_vCard + ' .avatar-delete').show(); $(path_vCard + ' .avatar').remove(); } // We display the avatar we have just received $(aContainer).replaceWith('
'); } else if(type == 'buddy') $(aContainer).replaceWith('
'); // Do someting depending of the type if(type == 'user') { $(path_vCard + ' .wait').hide(); $(path_vCard + ' .finish:first').removeClass('disabled'); } else vCardBuddyInfos(); logThis('vCard received: ' + iqFrom); } // Sends the vCard of the user function sendVCard() { // Initialize the IQ var iq = new JSJaCIQ(); iq.setType('set'); var vCard = iq.appendNode('vCard', {'xmlns': NS_VCARD}); // We send the identity part of the form $('#vcard .vcard-item').each(function() { var itemID = $(this).attr('id').replace(/^USER-(.+)/, '$1'); var itemVal = $(this).val(); if(itemVal && itemID) { if(itemID.indexOf('-') != -1) { var tagname = explodeThis('-', itemID, 0); var aNode; if(vCard.getElementsByTagName(tagname).length > 0) aNode = vCard.getElementsByTagName(tagname).item(0); else aNode = vCard.appendChild(iq.buildNode(tagname, {'xmlns': NS_VCARD})); aNode.appendChild(iq.buildNode(explodeThis('-', itemID, 1), {'xmlns': NS_VCARD}, itemVal)); } else vCard.appendChild(iq.buildNode(itemID, {'xmlns': NS_VCARD}, itemVal)); } }); // Send the IQ con.send(iq); // Send the user nickname & avatar over PEP if(enabledPEP()) { // Read values var user_nick = $('#USER-NICKNAME').val(); var photo_bin = $('#USER-PHOTO-BINVAL').val(); var photo_type = $('#USER-PHOTO-TYPE').val(); var photo_data = Base64.decode(photo_bin) || ''; var photo_bytes = photo_data.length || ''; var photo_id = hex_sha1(photo_data) || ''; // Values array var read = [ user_nick, photo_bin, [photo_type, photo_id, photo_bytes] ]; // Nodes array var node = [ NS_NICK, NS_URN_ADATA, NS_URN_AMETA ]; // Generate the XML for(i in read) { var iq = new JSJaCIQ(); iq.setType('set'); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': node[i], 'xmlns': NS_PUBSUB})); if((i == 0) && read[0]) { var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); // Nickname element item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, read[i])); } else if(((i == 1) || (i == 2)) && read[1]) { var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); // Apply the SHA-1 hash if(photo_id) item.setAttribute('id', photo_id); // Avatar data node if(i == 1) item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, read[i])); // Avatar metadata node else { var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA})); if(read[i]) { var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA})); if(read[i][0]) meta_info.setAttribute('type', read[i][0]); if(read[i][1]) meta_info.setAttribute('id', read[i][1]); if(read[i][2]) meta_info.setAttribute('bytes', read[i][2]); } } } con.send(iq); } } // Close the vCard stuffs closeVCard(); // Get our new avatar getAvatar(getXID(), 'force', 'true', 'forget'); logThis('vCard sent.'); return false; } // Plugin launcher function launchVCard() { // Focus on the first input $(document).oneTime(10, function() { $('#vcard input:first').focus(); }); // Keyboard events $('#vcard input[type="text"]').keyup(function(e) { // Enter pressed: send the vCard if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled')) return sendVCard(); }); // Click events $('#vcard .tab a').click(function() { // Yet active? if($(this).hasClass('tab-active')) return false; // Switch to the good tab var key = parseInt($(this).attr('data-key')); return switchVCard(key); }); $('#vcard .avatar-delete').click(function() { return deleteAvatar(); }); $('#vcard .bottom .finish').click(function() { if($(this).is('.cancel')) return closeVCard(); if($(this).is('.save') && !$(this).hasClass('disabled')) return sendVCard(); return false; }); // Avatar upload vars var avatar_options = { dataType: 'xml', beforeSubmit: waitAvatarUpload, success: handleAvatarUpload }; // Avatar upload form submit event $('#vcard-avatar').submit(function() { if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $('#vcard-avatar input[type="file"]').val()) $(this).ajaxSubmit(avatar_options); return false; }); // Avatar upload input change event $('#vcard-avatar input[type="file"]').change(function() { if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $(this).val()) $('#vcard-avatar').ajaxSubmit(avatar_options); return false; }); // Placeholders $('#vcard-avatar input[type="text"]').placeholder(); }