/*
Jappix - An open social platform
These are the PEP JS scripts for Jappix
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var PEP = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/**
* Stores the PEP items
* @public
* @param {string} xid
* @param {string} type
* @param {string} value1
* @param {string} value2
* @param {string} value3
* @param {string} value4
* @return {undefined}
*/
self.store = function(xid, type, value1, value2, value3, value4) {
try {
// Handle the correct values
if(!value1)
value1 = '';
if(!value2)
value2 = '';
if(!value3)
value3 = '';
if(!value4)
value4 = '';
// If one value
if(value1 || value2 || value3 || value4) {
// Define the XML variable
var xml = '
' + fText + '
'); // Apply the text to the buddy chat if(Common.exists('#' + hash)) { // Selector var bc_pep = $('#' + hash + ' .bc-pep'); // We remove the old PEP item bc_pep.find('a.bi-' + type).remove(); // If the new PEP item is not null, create a new one if(fText != Common._e("unknown")) bc_pep.prepend( '' ); // Process the new status position Presence.adaptChat(hash); } // If this is the PEP values of the logged in user if(xid == Common.getXID()) { // Change the icon/value of the target element if((type == 'mood') || (type == 'activity')) { // Change the input value var dVal = ''; var dAttr = pepValue; // Must apply default values? if(pepValue == 'none') { if(type == 'mood') dAttr = 'happy'; else dAttr = 'exercising'; } // No text? if(dText != Common._e("unknown")) dVal = dText; // Store this user event in our database DataStore.setDB(Connection.desktop_hash, type + '-value', 1, dAttr); DataStore.setDB(Connection.desktop_hash, type + '-text', 1, dVal); // Apply this PEP event $('#my-infos .f-' + type + ' a.picker').attr('data-value', dAttr); $('#my-infos .f-' + type + ' input').val(dVal); $('#my-infos .f-' + type + ' input').placeholder(); } else if((type == 'tune') || (type == 'geoloc')) { // Reset the values $('#my-infos .f-others a.' + type).remove(); // Not empty? if(dText != Common._e("unknown")) { // Specific stuffs var href, title, icon_class; if(type == 'tune') { href = fURI; title = dText; icon_class = 'tune-note'; } else { href = 'http://maps.google.com/?q=' + Common.encodeQuotes(tLat) + ',' + Common.encodeQuotes(tLon); title = Common._e("Where are you?") + ' (' + dText + ')'; icon_class = 'location-world'; } // Must create the container? if(!Common.exists('#my-infos .f-others')) $('#my-infos .content').append(''); // Create the element $('#my-infos .f-others').prepend( '' + '' + '' ); } // Empty? else if(!Common.exists('#my-infos .f-others a.icon')) $('#my-infos .f-others').remove(); // Process the roster height again Roster.adapt(); } } } } catch(e) { Console.error('PEP.display', e); } }; /** * Changes the mood icon * @public * @param {string} value * @return {string} */ self.moodIcon = function(value) { try { // The main var var icon; // Switch the values switch(value) { case 'angry': case 'cranky': case 'hot': case 'invincible': case 'mean': case 'restless': case 'serious': case 'strong': icon = 'mood-one'; break; case 'contemplative': case 'happy': case 'playful': icon = 'mood-two'; break; case 'aroused': case 'envious': case 'excited': case 'interested': case 'lucky': case 'proud': case 'relieved': case 'satisfied': case 'shy': icon = 'mood-three'; break; case 'calm': case 'cautious': case 'contented': case 'creative': case 'humbled': case 'lonely': case 'undefined': case 'none': icon = 'mood-four'; break; case 'afraid': case 'amazed': case 'confused': case 'dismayed': case 'hungry': case 'in_awe': case 'indignant': case 'jealous': case 'lost': case 'offended': case 'outraged': case 'shocked': case 'surprised': case 'embarrassed': case 'impressed': icon = 'mood-five'; break; case 'crazy': case 'distracted': case 'neutral': case 'relaxed': case 'thirsty': icon = 'mood-six'; break; case 'amorous': case 'curious': case 'in_love': case 'nervous': case 'sarcastic': icon = 'mood-eight'; break; case 'brave': case 'confident': case 'hopeful': case 'grateful': case 'spontaneous': case 'thankful': icon = 'mood-nine'; break; default: icon = 'mood-seven'; break; } // Return the good icon name return icon; } catch(e) { Console.error('PEP.moodIcon', e); } }; /** * Changes the activity icon * @public * @param {string} value * @return {string} */ self.activityIcon = function(value) { try { // The main var var icon; // Switch the values switch(value) { case 'doing_chores': icon = 'activity-doing_chores'; break; case 'drinking': icon = 'activity-drinking'; break; case 'eating': icon = 'activity-eating'; break; case 'grooming': icon = 'activity-grooming'; break; case 'having_appointment': icon = 'activity-having_appointment'; break; case 'inactive': icon = 'activity-inactive'; break; case 'relaxing': icon = 'activity-relaxing'; break; case 'talking': icon = 'activity-talking'; break; case 'traveling': icon = 'activity-traveling'; break; case 'working': icon = 'activity-working'; break; default: icon = 'activity-exercising'; break; } // Return the good icon name return icon; } catch(e) { Console.error('PEP.activityIcon', e); } }; /** * Sends the user's mood * @public * @param {string} value * @param {string} text * @return {undefined} */ self.sendMood = function(value, text) { /* REF: http://xmpp.org/extensions/xep-0107.html */ try { // We propagate the mood on the xmpp network var iq = new JSJaCIQ(); iq.setType('set'); // We create the XML document var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_MOOD, 'xmlns': NS_PUBSUB})); var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); var mood = item.appendChild(iq.buildNode('mood', {'xmlns': NS_MOOD})); if(value != 'none') { mood.appendChild(iq.buildNode(value, {'xmlns': NS_MOOD})); mood.appendChild(iq.buildNode('text', {'xmlns': NS_MOOD}, text)); } // And finally we send the mood that is set con.send(iq); Console.info('New mood sent: ' + value + ' (' + text + ')'); } catch(e) { Console.error('PEP.sendMood', e); } }; /** * Sends the user's activity * @public * @param {string} main * @param {string} sub * @param {string} text * @return {undefined} */ self.sendActivity = function(main, sub, text) { try { // We propagate the mood on the xmpp network var iq = new JSJaCIQ(); iq.setType('set'); // We create the XML document var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_ACTIVITY, 'xmlns': NS_PUBSUB})); var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); var activity = item.appendChild(iq.buildNode('activity', {'xmlns': NS_ACTIVITY})); if(main != 'none') { var mainType = activity.appendChild(iq.buildNode(main, {'xmlns': NS_ACTIVITY})); // Child nodes if(sub) mainType.appendChild(iq.buildNode(sub, {'xmlns': NS_ACTIVITY})); if(text) activity.appendChild(iq.buildNode('text', {'xmlns': NS_ACTIVITY}, text)); } // And finally we send the mood that is set con.send(iq); Console.info('New activity sent: ' + main + ' (' + text + ')'); } catch(e) { Console.error('PEP.sendActivity', e); } }; /** * Sends the user's geographic position * @public * @param {string} vLat * @param {string} vLon * @param {string} vAlt * @param {string} vCountry * @param {string} vCountrycode * @param {string} vRegion * @param {string} vPostalcode * @param {string} vLocality * @param {string} vStreet * @param {string} vBuilding * @param {string} vText * @param {string} vURI * @return {undefined} */ self.sendPosition = function(vLat, vLon, vAlt, vCountry, vCountrycode, vRegion, vPostalcode, vLocality, vStreet, vBuilding, vText, vURI) { /* REF: http://xmpp.org/extensions/xep-0080.html */ try { // We propagate the position on pubsub var iq = new JSJaCIQ(); iq.setType('set'); // We create the XML document var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_GEOLOC, 'xmlns': NS_PUBSUB})); var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); var geoloc = item.appendChild(iq.buildNode('geoloc', {'xmlns': NS_GEOLOC})); // Create two position arrays var pos_names = ['lat', 'lon', 'alt', 'country', 'countrycode', 'region', 'postalcode', 'locality', 'street', 'building', 'text', 'uri', 'timestamp']; var pos_values = [ vLat, vLon, vAlt, vCountry, vCountrycode, vRegion, vPostalcode, vLocality, vStreet, vBuilding, vText, vURI, DateUtils.getXMPPTime('utc')]; for(var i = 0; i < pos_names.length; i++) { if(pos_names[i] && pos_values[i]) geoloc.appendChild(iq.buildNode(pos_names[i], {'xmlns': NS_GEOLOC}, pos_values[i])); } // And finally we send the XML con.send(iq); // For logger if(vLat && vLon) { Console.info('Geolocated.'); } else { Console.warn('Not geolocated.'); } } catch(e) { Console.error('PEP.sendPosition', e); } }; /** * Parses the user's geographic position * @public * @param {string} data * @return {object} */ self.parsePosition = function(data) { try { var result = $(data).find('result:first'); // Get latitude and longitude var lat = result.find('geometry:first location:first lat').text(); var lng = result.find('geometry:first location:first lng').text(); var array = [ lat, lng, result.find('address_component:has(type:contains("country")):first long_name').text(), result.find('address_component:has(type:contains("country")):first short_name').text(), result.find('address_component:has(type:contains("administrative_area_level_1")):first long_name').text(), result.find('address_component:has(type:contains("postal_code")):first long_name').text(), result.find('address_component:has(type:contains("locality")):first long_name').text(), result.find('address_component:has(type:contains("route")):first long_name').text(), result.find('address_component:has(type:contains("street_number")):first long_name').text(), result.find('formatted_address:first').text(), 'http://maps.google.com/?q=' + Common.encodeQuotes(lat) + ',' + Common.encodeQuotes(lng) ]; return array; } catch(e) { Console.error('PEP.parsePosition', e); } }; /** * Converts a position into an human-readable one * @public * @param {string} tLocality * @param {string} tRegion * @param {string} tCountry * @return {string} */ self.humanPosition = function(tLocality, tRegion, tCountry) { try { var tHuman = ''; // Any locality? if(tLocality) { tHuman += tLocality; if(tRegion) tHuman += ', ' + tRegion; if(tCountry) tHuman += ', ' + tCountry; } // Any region? else if(tRegion) { tHuman += tRegion; if(tCountry) tHuman += ', ' + tCountry; } // Any country? else if(tCountry) tHuman += tCountry; return tHuman; } catch(e) { Console.error('PEP.humanPosition', e); } }; /** * Gets the user's geographic position * @public * @param {object} position * @return {undefined} */ self.getPosition = function(position) { try { // Convert integers to strings var vLat = '' + position.coords.latitude; var vLon = '' + position.coords.longitude; var vAlt = '' + position.coords.altitude; // Get full position (from Google Maps API) $.get('./server/geolocation.php', {latitude: vLat, longitude: vLon, language: XML_LANG}, function(data) { // Parse data! var results = self.parsePosition(data); // Handled! self.sendPosition( Utils.isNumber(vLat) ? vLat : null, Utils.isNumber(vLon) ? vLon : null, Utils.isNumber(vAlt) ? vAlt : null, results[2], results[3], results[4], results[5], results[6], results[7], results[8], results[9], results[10] ); // Store data DataStore.setDB(Connection.desktop_hash, 'geolocation', 'now', Common.xmlToString(data)); Console.log('Position details got from Google Maps API.'); }); Console.log('Position got: latitude > ' + vLat + ' / longitude > ' + vLon + ' / altitude > ' + vAlt); } catch(e) { Console.error('PEP.getPosition', e); } }; /** * Geolocates the user * @public * @return {undefined} */ self.geolocate = function() { try { // Don't fire it until options & features are not retrieved! if(!DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') || (DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '0') || !Features.enabledPEP()) { return; } // We publish the user location if allowed if(navigator.geolocation) { // Wait a bit... (to fix a bug) $('#my-infos').stopTime().oneTime('1s', function() { navigator.geolocation.getCurrentPosition(self.getPosition); }); Console.info('Geolocating...'); } else { Console.error('Not geolocated: browser does not support it.'); } } catch(e) { Console.error('PEP.geolocate', e); } }; /** * Gets the user's geolocation to check it exists * @public * @return {undefined} */ self.getInitGeoloc = function() { try { var iq = new JSJaCIQ(); iq.setType('get'); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var ps_items = pubsub.appendChild(iq.buildNode('items', {'node': NS_GEOLOC, 'xmlns': NS_PUBSUB})); ps_items.setAttribute('max_items', '0'); con.send(iq, self.handleInitGeoloc); } catch(e) { Console.error('PEP.getInitGeoloc', e); } }; /** * Handles the user's geolocation to create note in case of error * @public * @param {object} iq * @return {undefined} */ self.handleInitGeoloc = function(iq) { try { // Any error? if((iq.getType() == 'error') && $(iq.getNode()).find('item-not-found').size()) { // The node may not exist, create it! Pubsub.setup('', NS_GEOLOC, '1', '1', '', '', true); Console.warn('Error while getting geoloc, trying to reconfigure the PubSub node!'); } } catch(e) { Console.error('PEP.handleInitGeoloc', e); } }; /** * Displays all the supported PEP events for a given XID * @public * @return {undefined} */ self.displayAll = function() { try { self.display(xid, 'mood'); self.display(xid, 'activity'); self.display(xid, 'tune'); self.display(xid, 'geoloc'); } catch(e) { Console.error('PEP.displayAll', e); } }; /** * Plugin launcher * @public * @return {undefined} */ self.instance = function() { try { // Apply empty values to the PEP database DataStore.setDB(Connection.desktop_hash, 'mood-value', 1, ''); DataStore.setDB(Connection.desktop_hash, 'mood-text', 1, ''); DataStore.setDB(Connection.desktop_hash, 'activity-value', 1, ''); DataStore.setDB(Connection.desktop_hash, 'activity-text', 1, ''); // Click event for user mood $('#my-infos .f-mood a.picker').click(function() { // Initialize some vars var path = '#my-infos .f-mood div.bubble'; var mood_id = ['crazy', 'excited', 'playful', 'happy', 'shocked', 'hot', 'sad', 'amorous', 'confident']; var mood_lang = [Common._e("Crazy"), Common._e("Excited"), Common._e("Playful"), Common._e("Happy"), Common._e("Shocked"), Common._e("Hot"), Common._e("Sad"), Common._e("Amorous"), Common._e("Confident")]; var mood_val = $('#my-infos .f-mood a.picker').attr('data-value'); // Yet displayed? var can_append = true; if(Common.exists(path)) can_append = false; // Add this bubble! Bubble.show(path); if(!can_append) return false; // Generate the HTML code var html = ''; // Append the HTML code $('#my-infos .f-mood').append(html); // Click event $(path + ' a').click(function() { // Update the mood marker $('#my-infos .f-mood a.picker').attr('data-value', $(this).attr('data-value')); // Close the bubble Bubble.close(); // Focus on the status input $(document).oneTime(10, function() { $('#mood-text').focus(); }); return false; }); return false; }); // Click event for user activity $('#my-infos .f-activity a.picker').click(function() { // Initialize some vars var path = '#my-infos .f-activity div.bubble'; var activity_id = ['doing_chores', 'drinking', 'eating', 'exercising', 'grooming', 'having_appointment', 'inactive', 'relaxing', 'talking', 'traveling', 'working']; var activity_lang = [Common._e("Chores"), Common._e("Drinking"), Common._e("Eating"), Common._e("Exercising"), Common._e("Grooming"), Common._e("Appointment"), Common._e("Inactive"), Common._e("Relaxing"), Common._e("Talking"), Common._e("Traveling"), Common._e("Working")]; var activity_val = $('#my-infos .f-activity a.picker').attr('data-value'); // Yet displayed? var can_append = true; if(Common.exists(path)) can_append = false; // Add this bubble! Bubble.show(path); if(!can_append) return false; // Generate the HTML code var html = ''; // Append the HTML code $('#my-infos .f-activity').append(html); // Click event $(path + ' a').click(function() { // Update the activity marker $('#my-infos .f-activity a.picker').attr('data-value', $(this).attr('data-value')); // Close the bubble Bubble.close(); // Focus on the status input $(document).oneTime(10, function() { $('#activity-text').focus(); }); return false; }); return false; }); // Submit events for PEP inputs $('#mood-text, #activity-text').placeholder() .keyup(function(e) { if(e.keyCode == 13) { $(this).blur(); return false; } }); // Input blur handler $('#mood-text').blur(function() { // Read the parameters var value = $('#my-infos .f-mood a.picker').attr('data-value'); var text = $(this).val(); // Must send the mood? if((value != DataStore.getDB(Connection.desktop_hash, 'mood-value', 1)) || (text != DataStore.getDB(Connection.desktop_hash, 'mood-text', 1))) { // Update the local stored values DataStore.setDB(Connection.desktop_hash, 'mood-value', 1, value); DataStore.setDB(Connection.desktop_hash, 'mood-text', 1, text); // Send it! self.sendMood(value, text); } }) // Input focus handler .focus(function() { Bubble.close(); }); // Input blur handler $('#activity-text').blur(function() { // Read the parameters var value = $('#my-infos .f-activity a.picker').attr('data-value'); var text = $(this).val(); // Must send the activity? if((value != DataStore.getDB(Connection.desktop_hash, 'activity-value', 1)) || (text != DataStore.getDB(Connection.desktop_hash, 'activity-text', 1))) { // Update the local stored values DataStore.setDB(Connection.desktop_hash, 'activity-value', 1, value); DataStore.setDB(Connection.desktop_hash, 'activity-text', 1, text); // Send it! self.sendActivity(value, '', text); } }) // Input focus handler .focus(function() { Bubble.close(); }); } catch(e) { Console.error('PEP.instance', e); } }; /** * Return class scope */ return self; })();