1 /** @fileoverview <pre>Widget social para o Tela Social/Janelas Virtuais 2 Baseado no widget Twitter Social by Taboca 3 </pre> 4 @version 1.1 5 @author Matheus Martins Teixeira <a href="mailto:mteixeira@grad.icmc.usp.br"><mteixeira@grad.icmc.usp.br></a> 6 */ 7 /* ***** BEGIN LICENSE BLOCK ***** 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 9 * 10 * The contents of this file are subject to the Mozilla Public License Version 11 * 1.1 (the "License"); you may not use this file except in compliance with 12 * the License. You may obtain a copy of the License at 13 * http://www.mozilla.org/MPL/ 14 * 15 * Software distributed under the License is distributed on an "AS IS" basis, 16 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 17 * for the specific language governing rights and limitations under the 18 * License. 19 * 20 * The Original Code is TelaSocial 21 * 22 * The Initial Developer of the Original Code is Taboca TelaSocial. 23 * Portions created by the Initial Developer are Copyright (C) 2010 24 * the Initial Developer. All Rights Reserved. 25 * 26 * Contributor(s): 27 * Matheus Teixeira <teixeira.mdk@gmail.com> 28 * 29 * Alternatively, the contents of this file may be used under the terms of 30 * either the GNU General Public License Version 2 or later (the "GPL"), or 31 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 32 * in which case the provisions of the GPL or the LGPL are applicable instead 33 * of those above. If you wish to allow use of your version of this file only 34 * under the terms of either the GPL or the LGPL, and not to allow others to 35 * use your version of this file under the terms of the MPL, indicate your 36 * decision by deleting the provisions above and replace them with the notice 37 * and other provisions required by the GPL or the LGPL. If you do not delete 38 * the provisions above, a recipient may use your version of this file under 39 * the terms of any one of the MPL, the GPL or the LGPL. 40 * 41 * ***** END LICENSE BLOCK ***** */ 42 43 44 /** 45 Objeto com as funções para o widget social 46 @class 47 @name social 48 */ 49 var social = { 50 /** 51 URL para requisição dos posts do grupo social do ICMC 52 @type String 53 */ 54 URL : ICMC_FACEBOOK, 55 /** 56 Array com os comentários do grupo 57 @type array 58 */ 59 comments : null, 60 /** 61 Div container do widget. 62 @type DOM Object 63 */ 64 container : null, 65 /** 66 Lista com os posts do Grupo em formato DOM 67 @type DOM Object 68 */ 69 listObj : null, 70 /** 71 Numero máximo de posts. 72 @type int 73 @default 5 74 */ 75 numberPosts : 5, 76 /** 77 Inicializa o widget 78 @param {DOM Object} obj Container dos posts 79 @public 80 @function 81 */ 82 init : function(obj) { 83 social.comments = new Array(); 84 social.container = $(obj); 85 social.listObj = $('<ul>').appendTo(social.container); 86 }, 87 /** 88 Inicia o widget 89 @public 90 @function 91 */ 92 start : function() { 93 $('<img>').attr('src', 'f_logo.png').addClass('facebookLogo').appendTo(social.container); 94 $('<input>').attr('type', 'hidden').attr('id', 'hascontent').attr('id', 'hascontent').appendTo(social.container); 95 social.loadComments(); 96 }, 97 /** 98 Carrega os posts do grupo 99 @private 100 @function 101 */ 102 loadComments : function() { 103 $.getJSON(social.URL, function(e) { 104 social.__storeComments(e); 105 }); 106 }, 107 /** 108 Armazena os posts na memoria do widget 109 @param {DOM Object} e Objeto JSON com os posts 110 @private 111 @function 112 */ 113 __storeComments : function(e) { 114 social.createQueue(e.data); 115 }, 116 /** 117 Cria o array de posts em {@link social.comments} 118 @param {DOM Object} e Objeto JSON com os posts 119 @private 120 @function 121 */ 122 createQueue : function(e) { 123 var i = 0; 124 for( i = 0; i < e.length && i < social.numberPosts; i++) { 125 var reply = new social.prepareComment(e[i]); 126 social.comments.push(reply); 127 } 128 129 social.listObj.html(''); 130 setTimeout(function() { 131 social.render(); 132 }, 100); 133 }, 134 /** 135 Renderiza os posts na div {@link social.container} 136 @private 137 @function 138 */ 139 render : function() { 140 if(social.comments.length > 0) { 141 $('#hascontent').attr('value', '1'); 142 var post = social.comments.pop(); 143 social.postFormat(post); 144 setTimeout(function() { 145 social.render(); 146 }, 100); 147 } else { 148 setTimeout(function() { 149 $('#hascontent').attr('value', '0'); 150 social.loadComments(); 151 }, 45000); 152 } 153 }, 154 /** 155 Formata o post com os códigos HTML para exibição 156 @param {DOM Object} e Post a ser formatado 157 @private 158 @function 159 */ 160 postFormat : function(e) { 161 var storyContent = $('<div>').addClass('storyContent').appendTo($("<li>").prependTo(social.listObj)); 162 var clearfix = $('<div>').addClass('clearfix').appendTo(storyContent); 163 $('<div>').append($('<img>').attr('src', 'http://graph.facebook.com/' + e.user_id + '/picture?type=normal')).addClass('actorPhoto').appendTo(clearfix); 164 var mainWrapper = $('<div>').addClass('mainWrapper').appendTo($('<div>').addClass('storyInnerContent').appendTo(clearfix)); 165 $('<div>').addClass('actorName').html(e.from).appendTo(mainWrapper); 166 if(e.type == 'link') { 167 $('<div>').addClass('messageBody').html(e.message.replace(/(https?:\/\/)?(www\.)?([a-zA-Z0-9_\-]+)+\.([a-zA-Z]{2,4})(?:\.([a-zA-Z]{2,4}))?\/?(.*)/, '<a href="' + e.link + '">' + e.link + '</a>')).appendTo(mainWrapper); 168 if(e.picture != null) 169 $('<div>').addClass('links').addClass('clearfix').html('<img src="' + e.picture + '"/><div class="linkData"><strong>' + e.name + '</strong>' + ((e.caption != null) ? '<span class=caption>' + e.caption + '</span>' : "") + '<div class=description>' + e.description + '</div></div>').appendTo(mainWrapper); 170 else 171 $('<div>').addClass('links').addClass('clearfix').html('<div class="linkData"><strong>' + e.name + '</strong>' + ((e.caption != null) ? '<span class=caption>' + e.caption + '</span>' : "") + '<div class=description>' + e.description + '</div></div>').appendTo(mainWrapper); 172 } else { 173 $('<div>').addClass('messageBody').html(e.message).appendTo(mainWrapper); 174 } 175 $('<abbr>').addClass('messageFooter').append(social.calcDate(e.updated_time)).appendTo(mainWrapper); 176 var listReplies = $('<ul>').addClass('listReplies').appendTo($('<div>').appendTo(mainWrapper)); 177 178 if(e.likes == 1) 179 $('<div>').addClass('clearfix').append($('<img>').attr('src', 'like-50.png').addClass('commentLike')).append($('<span>').html(e.likes + ' pessoa curtiu isso')).appendTo($('<li>').appendTo(listReplies)); 180 else if(e.likes > 1) 181 $('<div>').addClass('clearfix').append($('<img>').attr('src', 'like-50.png').addClass('commentLike')).append($('<span>').html(e.likes + ' pessoas curtiram isso')).appendTo($('<li>').appendTo(listReplies)); 182 var i = 0; 183 for(; i < e.comments.length; i++) { 184 var comment = $('<div>').addClass('clearfix').appendTo($('<li>').appendTo(listReplies)); 185 $('<img>').addClass('actorPhoto').attr('src', 'http://graph.facebook.com/' + e.comments[i].user_id + '/picture?type=square').appendTo(comment); 186 var commentContent = $('<div>').addClass('commentContent').appendTo(comment); 187 $('<span>').addClass('actorName').html(e.comments[i].from).appendTo(commentContent); 188 $('<span>').addClass('commentBody').html(e.comments[i].message).appendTo(commentContent); 189 var commentFooter = $('<div>').addClass('commentFooter').appendTo(commentContent); 190 $('<abbr>').append(social.calcDate(e.comments[i].updated_time)).appendTo(commentFooter); 191 192 if(e.comments[i].likes > 0) { 193 commentFooter.append(' · '); 194 $('<span>').append($('<img>').attr('src', 'like-50.png').addClass('likeIcon')).addClass('replyLikes').append(e.comments[i].likes).appendTo(commentFooter); 195 } 196 } 197 }, 198 /** 199 Calcula o tempo que se passou após o post. 200 @param {Date} date Objeto data 201 @private 202 @function 203 */ 204 calcDate : function(date) { 205 var now = new Date(); 206 var seconds = Math.floor((now.getTime() - date.getTime()) / 1000) % 60; 207 var minutes = Math.floor((now.getTime() - date.getTime()) / 1000 / 60) % 60; 208 var hours = Math.floor((now.getTime() - date.getTime()) / 1000 / 60 / 60) % 60; 209 var days = Math.floor((now.getTime() - date.getTime()) / 1000 / 60 / 60 / 24) % 24; 210 var months = Math.floor((now.getTime() - date.getTime()) / 1000 / 60 / 60 / 24 / 30) % 30; 211 if(months > 0) { 212 return months + ' meses atrás'; 213 } else if(days > 0) { 214 if(days == 1) { 215 var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()); 216 var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()); 217 return 'Ontem ás ' + h + ':' + m + ' horas'; 218 } else 219 return days + ' dias atrás'; 220 } else if(hours > 0) { 221 return hours + ' horas atrás'; 222 } else if(minutes > 0) { 223 return 'á ' + minutes + ' minutos'; 224 } else { 225 return 'á ' + seconds + ' segundos'; 226 } 227 }, 228 /** 229 Prepara o comentário para ser trabalhado pelo widget. 230 @param {JSON Object} postData Objeto JSON com o post do Facebook 231 @private 232 @function 233 */ 234 prepareComment:function(postData) { 235 this.id = postData.id; 236 this.user_id = postData.from.id; 237 this.from = postData.from.name; 238 this.message = (postData.message != null) ? postData.message.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "<br />") : this.name = (postData.name != null) ? postData.name : null; 239 this.message_tags = (postData.message_tags != null) ? postData.message_tags : null; 240 if(this.picture != null && new String(this.picture).search(/(https?:\/\/)?(www\.)?([a-zA-Z0-9_\-]+)+\.([a-zA-Z]{2,4})(?:\.([a-zA-Z]{2,4}))?\/?(.*)/) > 0) { 241 this.picture = "http://facebook.com" + this.picture; 242 } 243 this.link = (postData.link != null) ? postData.link : null; 244 this.name = postData.name; 245 this.caption = (postData.caption != null) ? postData.caption : null; 246 this.source = (postData.source != null) ? postData.source : null; 247 this.icon = (postData.icon != null) ? postData.icon : null; 248 this.proprieties = (postData.proprieties != null) ? postData.proprieties : null; 249 this.description = (postData.description != null) ? postData.description : ""; 250 this.type = postData.type; 251 this.likes = (postData.likes != null) ? ((postData.likes.count != null) ? postData.likes.count : postData.likes) : 0; 252 this.place = (postData.place != null) ? postData.place : null; 253 254 if(postData.updatedTime != null) { 255 var date = (postData.updated_time.split('T')[0]).split('-'); 256 var time = ((postData.updated_time.split('T')[1]).split('+')[0]).split(':'); 257 } else { 258 var date = (postData.created_time.split('T')[0]).split('-'); 259 var time = ((postData.created_time.split('T')[1]).split('+')[0]).split(':'); 260 } 261 this.updated_time = new Date(date[0], date[1] - 1, date[2], time[0], time[1], time[2], 0); 262 this.updated_time = new Date((this.updated_time.getTime() - (this.updated_time.getTimezoneOffset() * 60 * 1000))); 263 264 /* create coment queue for this post */ 265 this.comments = new Array(); 266 if(postData.comments != null && postData.comments.count > 0) { 267 for( i = 0; i < postData.comments.count; i++) { 268 var reply = new social.prepareComment(postData.comments.data[i]); 269 this.comments.push(reply); 270 } 271 } 272 } 273 }