]> git.mxchange.org Git - friendica-addons.git/blobdiff - jappixmini/jappix/js/vcard.js
jappixmini: include jappix source
[friendica-addons.git] / jappixmini / jappix / js / vcard.js
diff --git a/jappixmini/jappix/js/vcard.js b/jappixmini/jappix/js/vcard.js
new file mode 100644 (file)
index 0000000..6e0fa09
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+
+Jappix - An open social platform
+These are the vCard JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+// Opens the vCard popup
+function openVCard() {
+       // Popup HTML content
+       var html =
+       '<div class="top">' + _e("Your profile") + '</div>' + 
+       
+       '<div class="tab">' + 
+               '<a href="#" class="tab-active" data-key="1">' + _e("Identity") + '</a>' + 
+               '<a href="#" data-key="2">' + _e("Profile image") + '</a>' + 
+               '<a href="#" data-key="3">' + _e("Others") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="content">' + 
+               '<div id="lap1" class="lap-active one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Personal") + '</legend>' + 
+                               
+                               '<label for="USER-FN">' + _e("Complete name") + '</label>' + 
+                               '<input type="text" id="USER-FN" class="vcard-item" />' + 
+                               
+                               '<label for="USER-NICKNAME">' + _e("Nickname") + '</label>' + 
+                               '<input type="text" id="USER-NICKNAME" class="vcard-item" />' + 
+                               
+                               '<label for="USER-N-GIVEN">' + _e("First name") + '</label>' + 
+                               '<input type="text" id="USER-N-GIVEN" class="vcard-item" />' + 
+                               
+                               '<label for="USER-N-FAMILY">' + _e("Last name") + '</label>' + 
+                               '<input type="text" id="USER-N-FAMILY" class="vcard-item" />' + 
+                               
+                               '<label for="USER-BDAY">' + _e("Date of birth") + '</label>' + 
+                               '<input type="text" id="USER-BDAY" class="vcard-item" />' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Contact") + '</legend>' + 
+                               
+                               '<label for="USER-EMAIL-USERID">' + _e("E-mail") + '</label>' + 
+                               '<input type="text" id="USER-EMAIL-USERID" class="vcard-item" />' + 
+                               
+                               '<label for="USER-TEL-NUMBER">' + _e("Phone") + '</label>' + 
+                               '<input type="text" id="USER-TEL-NUMBER" class="vcard-item" />' + 
+                               
+                               '<label for="USER-URL">' + _e("Website") + '</label>' + 
+                               '<input type="text" id="USER-URL" class="vcard-item" />' + 
+                       '</fieldset>' + 
+               '</div>' + 
+               
+               '<div id="lap2" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("New") + '</legend>' + 
+                               
+                               '<input type="hidden" id="USER-PHOTO-TYPE" class="vcard-item" />' + 
+                               '<input type="hidden" id="USER-PHOTO-BINVAL" class="vcard-item" />' + 
+                               
+                               '<form id="vcard-avatar" action="./php/avatar-upload.php" method="post" enctype="multipart/form-data">' + 
+                                       generateFileShare() + 
+                               '</form>' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Current") + '</legend>' + 
+                               
+                               '<div class="avatar-container"></div>' + 
+                               
+                               '<a href="#" class="one-button avatar-delete talk-images">' + _e("Delete") + '</a>' + 
+                               '<div class="no-avatar">' + _e("What a pity! You have no profile image defined in your identity card!") + '</div>' + 
+                       '</fieldset>' + 
+                       
+                       '<div class="avatar-wait avatar-info">' + _e("Please wait while your avatar is uploaded...") + '</div>' + 
+                       '<div class="avatar-ok avatar-info">' + _e("Here it is! A new beautiful profile image!") + '</div>' + 
+                       '<div class="avatar-error avatar-info">' + _e("The image file is not supported or has a bad size.") + '</div>' + 
+               '</div>' + 
+               
+               '<div id="lap3" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Address") + '</legend>' + 
+                               
+                               '<label for="USER-ADR-STREET">' + _e("Street") + '</label>' + 
+                               '<input type="text" id="USER-ADR-STREET" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-LOCALITY">' + _e("City") + '</label>' + 
+                               '<input type="text" id="USER-ADR-LOCALITY" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-PCODE">' + _e("Postal code") + '</label>' + 
+                               '<input type="text" id="USER-ADR-PCODE" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-CTRY">' + _e("Country") + '</label>' + 
+                               '<input type="text" id="USER-ADR-CTRY" class="vcard-item" />' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Biography") + '</legend>' + 
+                               
+                               '<textarea id="USER-DESC" rows="8" cols="60" class="vcard-item"></textarea>' + 
+                       '</fieldset>' + 
+               '</div>' + 
+               
+               '<div class="infos">' + 
+                       '<p class="infos-title">' + _e("Important notice") + '</p>' + 
+                       
+                       '<p>' + _e("Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to).") + '</p>' + 
+                       '<p>' + _e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '</p>' + 
+                       '<p>' + 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) + '</p>' + 
+                       '<p><a href="https://me.jappix.com/new" target="_blank">' + _e("Enable my public profile") + ' ยป</a></p>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish save disabled">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';
+       
+       // 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)
+               openMe();
+       
+       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('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
+       }
+       
+       // 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('<input id="' + id + '" class="vcard-item" type="hidden" />');
+}
+
+// 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('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
+                                               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 = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
+                                       }
+                                       
+                                       // 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('avatar', iqFrom);
+               
+               // If there were no stored avatar previously
+               if($(XMLFromString(xml)).find('type').text() == 'none') {
+                       xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>');
+                       setPersistent('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('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
+       }
+       
+       else if(type == 'buddy')
+               $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" /></div>');
+       
+       // 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;
+       });
+}