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 }