]> git.mxchange.org Git - friendica-addons.git/blob - jappixmini/jappix/js/vcard.js
Removed the word "Settings" from the settings. This information is redundant.
[friendica-addons.git] / jappixmini / jappix / js / vcard.js
1 /*
2
3 Jappix - An open social platform
4 These are the vCard JS scripts for Jappix
5
6 -------------------------------------------------
7
8 License: AGPL
9 Author: Vanaryon
10 Last revision: 16/01/12
11
12 */
13
14 // Opens the vCard popup
15 function openVCard() {
16         // Popup HTML content
17         var html =
18         '<div class="top">' + _e("Your profile") + '</div>' + 
19         
20         '<div class="tab">' + 
21                 '<a href="#" class="tab-active" data-key="1">' + _e("Identity") + '</a>' + 
22                 '<a href="#" data-key="2">' + _e("Profile image") + '</a>' + 
23                 '<a href="#" data-key="3">' + _e("Others") + '</a>' + 
24         '</div>' + 
25         
26         '<div class="content">' + 
27                 '<div id="lap1" class="lap-active one-lap forms">' + 
28                         '<fieldset>' + 
29                                 '<legend>' + _e("Personal") + '</legend>' + 
30                                 
31                                 '<label for="USER-FN">' + _e("Complete name") + '</label>' + 
32                                 '<input type="text" id="USER-FN" class="vcard-item" />' + 
33                                 
34                                 '<label for="USER-NICKNAME">' + _e("Nickname") + '</label>' + 
35                                 '<input type="text" id="USER-NICKNAME" class="vcard-item" />' + 
36                                 
37                                 '<label for="USER-N-GIVEN">' + _e("First name") + '</label>' + 
38                                 '<input type="text" id="USER-N-GIVEN" class="vcard-item" />' + 
39                                 
40                                 '<label for="USER-N-FAMILY">' + _e("Last name") + '</label>' + 
41                                 '<input type="text" id="USER-N-FAMILY" class="vcard-item" />' + 
42                                 
43                                 '<label for="USER-BDAY">' + _e("Date of birth") + '</label>' + 
44                                 '<input type="text" id="USER-BDAY" class="vcard-item" />' + 
45                         '</fieldset>' + 
46                         
47                         '<fieldset>' + 
48                                 '<legend>' + _e("Contact") + '</legend>' + 
49                                 
50                                 '<label for="USER-EMAIL-USERID">' + _e("E-mail") + '</label>' + 
51                                 '<input type="text" id="USER-EMAIL-USERID" class="vcard-item" />' + 
52                                 
53                                 '<label for="USER-TEL-NUMBER">' + _e("Phone") + '</label>' + 
54                                 '<input type="text" id="USER-TEL-NUMBER" class="vcard-item" />' + 
55                                 
56                                 '<label for="USER-URL">' + _e("Website") + '</label>' + 
57                                 '<input type="text" id="USER-URL" class="vcard-item" />' + 
58                         '</fieldset>' + 
59                 '</div>' + 
60                 
61                 '<div id="lap2" class="one-lap forms">' + 
62                         '<fieldset>' + 
63                                 '<legend>' + _e("New") + '</legend>' + 
64                                 
65                                 '<input type="hidden" id="USER-PHOTO-TYPE" class="vcard-item" />' + 
66                                 '<input type="hidden" id="USER-PHOTO-BINVAL" class="vcard-item" />' + 
67                                 
68                                 '<form id="vcard-avatar" action="./php/avatar-upload.php" method="post" enctype="multipart/form-data">' + 
69                                         generateFileShare() + 
70                                 '</form>' + 
71                         '</fieldset>' + 
72                         
73                         '<fieldset>' + 
74                                 '<legend>' + _e("Current") + '</legend>' + 
75                                 
76                                 '<div class="avatar-container"></div>' + 
77                                 
78                                 '<a href="#" class="one-button avatar-delete talk-images">' + _e("Delete") + '</a>' + 
79                                 '<div class="no-avatar">' + _e("What a pity! You have no profile image defined in your identity card!") + '</div>' + 
80                         '</fieldset>' + 
81                         
82                         '<div class="avatar-wait avatar-info">' + _e("Please wait while your avatar is uploaded...") + '</div>' + 
83                         '<div class="avatar-ok avatar-info">' + _e("Here it is! A new beautiful profile image!") + '</div>' + 
84                         '<div class="avatar-error avatar-info">' + _e("The image file is not supported or has a bad size.") + '</div>' + 
85                 '</div>' + 
86                 
87                 '<div id="lap3" class="one-lap forms">' + 
88                         '<fieldset>' + 
89                                 '<legend>' + _e("Address") + '</legend>' + 
90                                 
91                                 '<label for="USER-ADR-STREET">' + _e("Street") + '</label>' + 
92                                 '<input type="text" id="USER-ADR-STREET" class="vcard-item" />' + 
93                                 
94                                 '<label for="USER-ADR-LOCALITY">' + _e("City") + '</label>' + 
95                                 '<input type="text" id="USER-ADR-LOCALITY" class="vcard-item" />' + 
96                                 
97                                 '<label for="USER-ADR-PCODE">' + _e("Postal code") + '</label>' + 
98                                 '<input type="text" id="USER-ADR-PCODE" class="vcard-item" />' + 
99                                 
100                                 '<label for="USER-ADR-CTRY">' + _e("Country") + '</label>' + 
101                                 '<input type="text" id="USER-ADR-CTRY" class="vcard-item" />' + 
102                         '</fieldset>' + 
103                         
104                         '<fieldset>' + 
105                                 '<legend>' + _e("Biography") + '</legend>' + 
106                                 
107                                 '<textarea id="USER-DESC" rows="8" cols="60" class="vcard-item"></textarea>' + 
108                         '</fieldset>' + 
109                 '</div>' + 
110                 
111                 '<div class="infos">' + 
112                         '<p class="infos-title">' + _e("Important notice") + '</p>' + 
113                         
114                         '<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>' + 
115                         '<p>' + _e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '</p>' + 
116                         '<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>' + 
117                         '<p><a href="https://me.jappix.com/new" target="_blank">' + _e("Enable my public profile") + ' ยป</a></p>' + 
118                 '</div>' + 
119         '</div>' + 
120         
121         '<div class="bottom">' + 
122                 '<div class="wait wait-medium"></div>' + 
123                 
124                 '<a href="#" class="finish save disabled">' + _e("Save") + '</a>' + 
125                 '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
126         '</div>';
127         
128         // Create the popup
129         createPopup('vcard', html);
130         
131         // Associate the events
132         launchVCard();
133         
134         // We get the VCard informations
135         getVCard(getXID(), 'user');
136         
137         return false;
138 }
139
140 // Closes the vCard popup
141 function closeVCard() {
142         // Destroy the popup
143         destroyPopup('vcard');
144         
145         // Create the welcome end popup?
146         if(END_WELCOME)
147                 openMe();
148         
149         return false;
150 }
151
152 // Switches the vCard popup tabs
153 function switchVCard(id) {
154         $('#vcard .one-lap').removeClass('lap-active');
155         $('#vcard #lap' + id).addClass('lap-active');
156         $('#vcard .tab a').removeClass('tab-active');
157         $('#vcard .tab a[data-key=' + id + ']').addClass('tab-active');
158         
159         return false;
160 }
161
162 // Waits for the avatar upload reply
163 function waitAvatarUpload() {
164         // Reset the avatar info
165         $('#vcard .avatar-info').hide().stopTime();
166         
167         // Show the wait info
168         $('#vcard .avatar-wait').show();
169 }
170
171 // Handles the avatar upload reply
172 function handleAvatarUpload(responseXML) {
173         // Data selector
174         var dData = $(responseXML).find('jappix');
175         
176         // Not current upload session?
177         if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name=id]').val()))
178                 return;
179         
180         // Reset the avatar info
181         $('#vcard .avatar-info').hide().stopTime();
182         
183         // Process the returned data
184         if(!dData.find('error').size()) {
185                 // Read the values
186                 var aType = dData.find('type').text();
187                 var aBinval = dData.find('binval').text();
188                 
189                 // We remove everything that isn't useful right here
190                 $('#vcard .no-avatar').hide();
191                 $('#vcard .avatar').remove();
192                 
193                 // We display the delete button
194                 $('#vcard .avatar-delete').show();
195                 
196                 // We tell the user it's okay
197                 $('#vcard .avatar-ok').show();
198                 
199                 // Timer
200                 $('#vcard .avatar-info').oneTime('10s', function() {
201                         $(this).hide();
202                 });
203                 
204                 // We put the base64 values in a hidden input to be sent
205                 $('#USER-PHOTO-TYPE').val(aType);
206                 $('#USER-PHOTO-BINVAL').val(aBinval);
207                 
208                 // We display the avatar !
209                 $('#vcard .avatar-container').replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
210         }
211         
212         // Any error?
213         else {
214                 $('#vcard .avatar-error').show();
215                 
216                 // Timer
217                 $('#vcard .avatar-info').oneTime('10s', function() {
218                         $(this).hide();
219                 });
220                 
221                 logThis('Error while uploading the avatar: ' + dData.find('error').text(), 1);
222         }
223 }
224
225 // Deletes the encoded avatar of an user
226 function deleteAvatar() {
227         // We remove the avatar displayed elements
228         $('#vcard .avatar-info').stopTime();
229         $('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide();
230         $('#vcard .avatar').remove();
231         
232         // We reset the input value
233         $('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val('');
234         
235         // We show the avatar-uploading request
236         $('#vcard .no-avatar').show();
237         
238         return false;
239 }
240
241 // Creates a special vCard input
242 function createInputVCard(id, type) {
243         // Generate the new ID
244         id = 'USER-' + id;
245         
246         // Can append the content
247         if((type == 'user') && !exists('#vcard #' + id))
248                 $('#vcard .content').append('<input id="' + id + '" class="vcard-item" type="hidden" />');
249 }
250
251 // Gets the vCard of a XID
252 function getVCard(to, type) {
253         // Generate a special ID
254         var id = genID();
255         
256         // New IQ
257         var iq = new JSJaCIQ();
258         iq.setID(id);
259         iq.setType('get');
260         iq.appendNode('vCard', {'xmlns': NS_VCARD});
261         
262         // Send the IQ to the good user
263         if(type == 'user') {
264                 // Show the wait icon
265                 $('#vcard .wait').show();
266                 
267                 // Apply the session ID
268                 $('#vcard').attr('data-vcard', id);
269                 
270                 // Send the IQ
271                 con.send(iq, handeUVCard);
272         }
273         
274         else {
275                 // Show the wait icon
276                 $('#userinfos .wait').show();
277                 
278                 // Apply the session ID
279                 $('#userinfos').attr('data-vcard', id);
280                 
281                 // Send the IQ
282                 iq.setTo(to);
283                 con.send(iq, handeBVCard);
284         }
285 }
286
287 // Handles the current connected user's vCard
288 function handeUVCard(iq) {
289         handleVCard(iq, 'user');
290 }
291
292 // Handles an external buddy vCard
293 function handeBVCard(iq) {
294         handleVCard(iq, 'buddy');
295 }
296
297 // Handles a vCard stanza
298 function handleVCard(iq, type) {
299         // Extract the data
300         var iqID = iq.getID();
301         var iqFrom = fullXID(getStanzaFrom(iq));
302         var iqNode = iq.getNode();
303         
304         // Define some paths
305         var path_vCard = '#vcard[data-vcard=' + iqID + ']';
306         var path_userInfos = '#userinfos[data-vcard=' + iqID + ']';
307         
308         // End if the session does not exist
309         if(((type == 'user') && !exists(path_vCard)) || ((type == 'buddy') && !exists(path_userInfos)))
310                 return;
311         
312         // We retrieve main values
313         var values_yet = [];
314         
315         $(iqNode).find('vCard').children().each(function() {
316                 // Read the current parent node name
317                 var tokenname = (this).nodeName.toUpperCase();
318                 
319                 // Node with a parent
320                 if($(this).children().size()) {
321                         $(this).children().each(function() {
322                                 // Get the node values
323                                 var currentID = tokenname + '-' + (this).nodeName.toUpperCase();
324                                 var currentText = $(this).text();
325                                 
326                                 // Not yet added?
327                                 if(!existArrayValue(values_yet, currentID)) {
328                                         // Create an input if it does not exist
329                                         createInputVCard(values_yet, type);
330                                         
331                                         // Userinfos viewer popup
332                                         if((type == 'buddy') && currentText) {
333                                                 if(currentID == 'EMAIL-USERID')
334                                                         $(path_userInfos + ' #BUDDY-' + currentID).html('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
335                                                 else
336                                                         $(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc());
337                                         }
338                                         
339                                         // Profile editor popup
340                                         else if(type == 'user')
341                                                 $(path_vCard + ' #USER-' + currentID).val(currentText);
342                                         
343                                         // Avoid duplicating the value
344                                         values_yet.push(currentID);
345                                 }
346                         });
347                 }
348                 
349                 // Node without any parent
350                 else {
351                         // Get the node values
352                         var currentText = $(this).text();
353                         
354                         // Not yet added?
355                         if(!existArrayValue(values_yet, tokenname)) {
356                                 // Create an input if it does not exist
357                                 createInputVCard(tokenname, type);
358                                 
359                                 // Userinfos viewer popup
360                                 if((type == 'buddy') && currentText) {
361                                         // URL modification
362                                         if(tokenname == 'URL') {
363                                                 // No http:// or https:// prefix, we should add it
364                                                 if(!currentText.match(/^https?:\/\/(.+)/))
365                                                         currentText = 'http://' + currentText;
366                                                 
367                                                 currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
368                                         }
369                                         
370                                         // Description modification
371                                         else if(tokenname == 'DESC')
372                                                 currentText = filterThisMessage(currentText, getBuddyName(iqFrom).htmlEnc(), true);
373                                         
374                                         // Other stuffs
375                                         else
376                                                 currentText = currentText.htmlEnc();
377                                         
378                                         $(path_userInfos + ' #BUDDY-' + tokenname).html(currentText);
379                                 }
380                                 
381                                 // Profile editor popup
382                                 else if(type == 'user')
383                                         $(path_vCard + ' #USER-' + tokenname).val(currentText);
384                                 
385                                 // Avoid duplicating the value
386                                 values_yet.push(tokenname);
387                         }
388                 }
389         });
390         
391         // Update the stored avatar
392         if(type == 'buddy') {
393                 // Get the avatar XML
394                 var xml = getPersistent('avatar', iqFrom);
395                 
396                 // If there were no stored avatar previously
397                 if($(XMLFromString(xml)).find('type').text() == 'none') {
398                         xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>');
399                         setPersistent('avatar', iqFrom, xml);
400                 }
401                 
402                 // Handle the user avatar
403                 handleAvatar(iq);
404         }
405         
406         // The avatar values targets
407         var aBinval, aType, aContainer;
408         
409         if(type == 'user') {
410                 aBinval = $('#USER-PHOTO-BINVAL').val();
411                 aType = $('#USER-PHOTO-TYPE').val();
412                 aContainer = path_vCard + ' .avatar-container';
413         }
414         
415         else {
416                 aBinval = $(iqNode).find('BINVAL:first').text();
417                 aType = $(iqNode).find('TYPE:first').text();
418                 aContainer = path_userInfos + ' .avatar-container';
419         }
420         
421         // We display the avatar if retrieved
422         if(aBinval) {
423                 // No type?
424                 if(!aType)
425                         aType = 'image/png';
426                 
427                 if(type == 'user') {
428                         // We move all the things that we don't need in that case
429                         $(path_vCard + ' .no-avatar').hide();
430                         $(path_vCard + ' .avatar-delete').show();
431                         $(path_vCard + ' .avatar').remove();
432                 }
433                 
434                 // We display the avatar we have just received
435                 $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
436         }
437         
438         else if(type == 'buddy')
439                 $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" /></div>');
440         
441         // Do someting depending of the type
442         if(type == 'user') {
443                 $(path_vCard + ' .wait').hide();
444                 $(path_vCard + ' .finish:first').removeClass('disabled');
445         }
446         
447         else
448                 vCardBuddyInfos();
449         
450         logThis('vCard received: ' + iqFrom);
451 }
452
453 // Sends the vCard of the user
454 function sendVCard() {
455         // Initialize the IQ
456         var iq = new JSJaCIQ();
457         iq.setType('set');
458         
459         var vCard = iq.appendNode('vCard', {'xmlns': NS_VCARD});
460         
461         // We send the identity part of the form
462         $('#vcard .vcard-item').each(function() {
463                 var itemID = $(this).attr('id').replace(/^USER-(.+)/, '$1');
464                 var itemVal = $(this).val();
465                 
466                 if(itemVal && itemID) {
467                         if(itemID.indexOf('-') != -1) {
468                                 var tagname = explodeThis('-', itemID, 0);
469                                 var aNode;
470                                 
471                                 if(vCard.getElementsByTagName(tagname).length > 0)
472                                         aNode = vCard.getElementsByTagName(tagname).item(0);
473                                 else
474                                         aNode = vCard.appendChild(iq.buildNode(tagname, {'xmlns': NS_VCARD}));
475                                 
476                                 aNode.appendChild(iq.buildNode(explodeThis('-', itemID, 1), {'xmlns': NS_VCARD}, itemVal));
477                         }
478                         
479                         else
480                                 vCard.appendChild(iq.buildNode(itemID, {'xmlns': NS_VCARD}, itemVal));
481                 }
482         });
483         
484         // Send the IQ
485         con.send(iq);
486         
487         // Send the user nickname & avatar over PEP
488         if(enabledPEP()) {
489                 // Read values
490                 var user_nick = $('#USER-NICKNAME').val();
491                 var photo_bin = $('#USER-PHOTO-BINVAL').val();
492                 var photo_type = $('#USER-PHOTO-TYPE').val();
493                 var photo_data = Base64.decode(photo_bin) || '';
494                 var photo_bytes = photo_data.length || '';
495                 var photo_id = hex_sha1(photo_data) || '';
496                 
497                 // Values array
498                 var read = [
499                         user_nick,
500                         photo_bin,
501                         [photo_type, photo_id, photo_bytes]
502                 ];
503                 
504                 // Nodes array
505                 var node = [
506                         NS_NICK,
507                         NS_URN_ADATA,
508                         NS_URN_AMETA
509                 ];
510                 
511                 // Generate the XML
512                 for(i in read) {
513                         var iq = new JSJaCIQ();
514                         iq.setType('set');
515                         
516                         var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
517                         var publish = pubsub.appendChild(iq.buildNode('publish', {'node': node[i], 'xmlns': NS_PUBSUB}));
518                         
519                         if((i == 0) && read[0]) {
520                                 var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
521                                 
522                                 // Nickname element
523                                 item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, read[i]));
524                         }
525                         
526                         else if(((i == 1) || (i == 2)) && read[1]) {
527                                 var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
528                                 
529                                 // Apply the SHA-1 hash
530                                 if(photo_id)
531                                         item.setAttribute('id', photo_id);
532                                 
533                                 // Avatar data node
534                                 if(i == 1)
535                                         item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, read[i]));
536                                 
537                                 // Avatar metadata node
538                                 else {
539                                         var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA}));
540                                         
541                                         if(read[i]) {
542                                                 var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA}));
543                                                 
544                                                 if(read[i][0])
545                                                         meta_info.setAttribute('type', read[i][0]);
546                                                 if(read[i][1])
547                                                         meta_info.setAttribute('id', read[i][1]);
548                                                 if(read[i][2])
549                                                         meta_info.setAttribute('bytes', read[i][2]);
550                                         }
551                                 }
552                         }
553                         
554                         con.send(iq);
555                 }
556         }
557         
558         // Close the vCard stuffs
559         closeVCard();
560         
561         // Get our new avatar
562         getAvatar(getXID(), 'force', 'true', 'forget');
563         
564         logThis('vCard sent.');
565         
566         return false;
567 }
568
569 // Plugin launcher
570 function launchVCard() {
571         // Focus on the first input
572         $(document).oneTime(10, function() {
573                 $('#vcard input:first').focus();
574         });
575         
576         // Keyboard events
577         $('#vcard input[type=text]').keyup(function(e) {
578                 // Enter pressed: send the vCard
579                 if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled'))
580                         return sendVCard();
581         });
582         
583         // Click events
584         $('#vcard .tab a').click(function() {
585                 // Yet active?
586                 if($(this).hasClass('tab-active'))
587                         return false;
588                 
589                 // Switch to the good tab
590                 var key = parseInt($(this).attr('data-key'));
591                 
592                 return switchVCard(key);
593         });
594         
595         $('#vcard .avatar-delete').click(function() {
596                 return deleteAvatar();
597         });
598         
599         $('#vcard .bottom .finish').click(function() {
600                 if($(this).is('.cancel'))
601                         return closeVCard();
602                 if($(this).is('.save') && !$(this).hasClass('disabled'))
603                         return sendVCard();
604                 
605                 return false;
606         });
607         
608         // Avatar upload vars
609         var avatar_options = {
610                 dataType:       'xml',
611                 beforeSubmit:   waitAvatarUpload,
612                 success:        handleAvatarUpload
613         };
614         
615         // Avatar upload form submit event
616         $('#vcard-avatar').submit(function() {
617                 if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $('#vcard-avatar input[type=file]').val())
618                         $(this).ajaxSubmit(avatar_options);
619                 
620                 return false;
621         });
622         
623         // Avatar upload input change event
624         $('#vcard-avatar input[type=file]').change(function() {
625                 if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $(this).val())
626                         $('#vcard-avatar').ajaxSubmit(avatar_options);
627                 
628                 return false;
629         });
630 }