View file js/mail/main.js

File size: 11.87Kb
var SCRIPTS_URL = '/ajax/mail/', 
	SEND_MSG_URL = SCRIPTS_URL + 'send_message.php', 
	GET_MESSAGES_URL = SCRIPTS_URL + 'get_messages.php', 
	CHECK_READ_URL = SCRIPTS_URL + 'check_read.php', 
	CHECK_TYPING_URL = SCRIPTS_URL + 'check_typing.php', 
	UPDATE_TYPING_URL = SCRIPTS_URL + 'update_typing.php';

var GET_MESSAGES_TIMEOUT = 2000, 
	CHECK_READ_TIMEOUT = 2000, 
	CHECK_TYPING_TIMEOUT = 2000;

var window_focus = true;
$(window).focus(function () {
	window_focus = true;
}).blur(function () {
	window_focus = false;
});

function handleJsonErrors(json) {
	if (json == undefined || json.error != undefined) {
		showError(json == undefined ? 'Произошла ошибка' : json.error);
		return true;
	}

	return false;
}

function showError(error) {
	alert(error);
}

var Mail = function (id_user) {0;
	var self = this;
	var $btnSend, $inputMsg, $loading, $messages, $typingElement, $typingDotsElement;

	// handlers
	var typingHandler, dotsHandler;
	var getMessagesTimeout, checkReadTimeout, checkTypingTimeout;

	// jqXHR
	var checkReadXHR, sendMessageXHR, longPollingXHR, checkTypingXHR, typingXHR;

	var isTyping = false, 
		isUserTyping = false;

	$(document).ready(function () {
		$btnSend = $('#btnSend');
		$inputMsg = $('#inputMsg');
		// for altername_post_form.php
		if ($inputMsg.length == 0)
			$inputMsg = $('textarea[name="msg"]');
		$loading = $('#loading');
		$messages = $('#messages');
		$typingElement = $('#typing');
		$typingDotsElement = $('#typingDots');

		self.initListeners();

	});

	this.initListeners = function () {
		$btnSend.on('click', function (e) {
			e.preventDefault();

			if (sendMessageXHR != undefined) {
				// showError('Не так быстро...');
				return;
			}

			var msg = $inputMsg.val().trim();
			if (msg.length == 0) {
				showError('Введите сообщение');
				return;
			}

			self.sendMessage(msg);
		});

		$inputMsg.on('input', function () {
			if (!isTyping) {
				isTyping = true;
				if (typingXHR != undefined)
					typingXHR.abort();

				self.updateTyping();
			}

			if (typingHandler != undefined)
				clearInterval(typingHandler);

			typingHandler = setTimeout(function () {
				isTyping = false;

				if (typingXHR != undefined)
					typingXHR.abort();

				self.updateTyping();
			}, 1000);
		});

		self.setCheckTypingTimeout();
		self.setGetMessagesTimeout(function () {
			self.setCheckReadTimeout();
		});
		self.reloadNavigationOnClicks();
	}

	this.setGetMessagesTimeout = function (completeCallback) {
		self.abortGetMessages();

		getMessagesTimeout = setTimeout(function () {
			self.startLongPollingMessages(function () {
				if ($.isFunction(completeCallback)) {
					completeCallback();
					completeCallback = undefined;
				}
				self.setGetMessagesTimeout();
			});
		}, GET_MESSAGES_TIMEOUT);
	}

	this.abortGetMessages = function () {
		if (getMessagesTimeout != undefined)
			clearInterval(getMessagesTimeout);

		if (longPollingXHR != undefined)
			longPollingXHR.abort();
	}

	this.setCheckReadTimeout = function (completeCallback) {
		self.abortCheckRead();

		checkReadTimeout = setTimeout(function () {
			self.checkRead(function () {
				self.setCheckReadTimeout();
			});
		}, CHECK_READ_TIMEOUT);
	}

	this.abortCheckRead = function () {
		if (checkReadTimeout != undefined)
			clearInterval(checkReadTimeout);

		if (checkReadXHR != undefined)
			checkReadXHR.abort();
	}

	this.setCheckTypingTimeout = function () {
		self.abortCheckTyping();

		checkTypingTimeout = setTimeout(function () {
			self.checkTyping(function () {
				self.setCheckTypingTimeout();
			});
		}, CHECK_TYPING_TIMEOUT);
	}

	this.abortCheckTyping = function () {
		if (checkTypingTimeout != undefined)
			clearInterval(checkTypingTimeout);

		if (checkTypingXHR != undefined)
			checkTypingXHR.abort();
	}

	this.updateTyping = function () {
		typingXHR = $.ajax({
			url: UPDATE_TYPING_URL, 
			type: 'post', 
			data: {
				id_user: id_user, 
				is_typing: isTyping
			},  
			success: function (json) {
				handleJsonErrors(json);
			}
		});
	}

	this.checkTyping = function (completeCallback) {
		checkTypingXHR = $.ajax({
			url: CHECK_TYPING_URL, 
			type: 'post', 
			data: {
				id_user: id_user, 
				is_typing: isUserTyping
			}, 
			success: function (json) {
				if (handleJsonErrors(json))
					return;

				isUserTyping = json.is_typing;

				if (dotsHandler != undefined)
					clearInterval(dotsHandler);

				if (isUserTyping) {
					dotsHandler = setInterval(function () {
						self.updateDots();
					}, 200);
					$typingElement.show(100);
				}
				else
					$typingElement.hide(100);
			}, 
			complete: function () {
				if ($.isFunction(completeCallback))
					completeCallback();
			}
		});
	}


	self.updateDots = function () {
		var dots = $typingDotsElement.text();
		var objs = {'': '.', '.': '..', '..': '...', '...': ''};
		$typingDotsElement.text(objs[dots]);
	}

	this.reloadNavigationOnClicks = function() {
		var $navigationElement = $('#navigation .c2');
		$('a', $navigationElement).on('click', function (e) {
			e.preventDefault();

			var href = $(this).attr('href');
			self.goToPage(href.match(/page=end$/) ? count_pages : parseInt($(this).text()));
		});
	}

	this.buildNavigation = function () {
		var $navigationElement = $('#navigation');
		var $c2Element = $('.c2', $navigationElement);
		if (count_pages == 1) {
			if ($c2Element.length) {
				$c2Element.remove();
				return;
			}
		} else if ($c2Element.length == 0)
			$c2Element = $('<div>', {class: 'c2'}).appendTo($navigationElement);

		$c2Element.empty();
		if (current_page != 1)
			$c2Element.append("<span class='page'><a href=\"" + navigation_link + "page=1\" title='Первая страница'>&lt;</a></span> ");
		if (current_page != 1)
			$c2Element.append("<span class='page'><a href=\"" + navigation_link + "page=1\" title='Страница №1'>1</a></span>");
		else
			$c2Element.append(" <span class='str'><b>1</b></span>");

		for (var ot =- 3; ot<=3; ot++) {

			if (current_page + ot > 1 && current_page + ot < count_pages) {
				if (ot == -3 && current_page+ot>2)
					$c2Element.append("<span class='page'> ..");
				if (ot != 0)
					$c2Element.append(" <span class='page'><a href=\"" + navigation_link + "page=" + (current_page + ot) + "\" title='Страница №" + (current_page + ot) + "'>" + (current_page + ot) + "</a></span>");
				else
					$c2Element.append(" <span class='str'><b>" + (current_page + ot) + "</b></span>");
				if (ot == 3 && current_page + ot < count_pages - 1)
					$c2Element.append("<span class='page'> ..");
			}
		}

		if (current_page != count_pages)
			$c2Element.append(" <span class='page'><a href=\"" + navigation_link + "page=end\" title='Страница №" + count_pages + "'>" + count_pages + "</a></span>");
		else if (count_pages > 1)
			$c2Element.append(" <span class='str'><b>" + count_pages + "</b></span>");
		if (current_page != count_pages)
			$c2Element.append(" <span class='page'><a href=\"" + navigation_link + "page=end\" title='Последняя страница'>&gt;</a></span>");

		self.reloadNavigationOnClicks();
	}

	this.startLongPollingMessages = function (completeCallback, successCallback) {
		var existing = [];
		var $allMessages = $('.message', $messages);
		$.each($allMessages, function (k, v) {
			var m_id = $(v).attr('data-id');
			if ($.inArray(m_id, existing) == -1)
				existing.push(m_id);
		});

		longPollingXHR = $.ajax({
			url: GET_MESSAGES_URL, 
			type: 'post', 
			data: {
				id_user: id_user, 
				existing: existing.join(','), 
				page: current_page
			}, 
			timeout: 0, 
			success: function (json) {
				if ($.isFunction(successCallback)) {
					successCallback();
				}

				if (handleJsonErrors(json))
					return;

				count_pages = json.count_pages;
				self.removeMessages(json.removed);
				self.showMessages(json.messages);
			}, 
			complete: function () {
				longPollingXHR = undefined;

				if ($.isFunction(completeCallback))
					completeCallback();
			}
		});
	}

	this.removeMessages = function (removed_ids) {
		$.each(removed_ids, function (k, v) {
			$message = $('[data-id=' + v + ']', $messages);
			$message.remove();
		});
	}

	this.showMessages = function (messages) {
		var countMessages = getKeyCount(messages);

		$.each(messages, function (k, message) {
			self.showMessage(message);
		});

		self.updateMessages();
		self.buildNavigation();
	}

	this.showMessage = function (message) {
		var $message = $('<div>', {class: 'nav1 message', 'data-id': message.id});
		if (message.read == 0 && message.id_kont == id_user)
			 $message.addClass('unread');
		$message.append(message.user.nick_form);
		$message.append("(" + message.time + ")<br>");
		
		var $ur_word = $('<span>', {class: 'ur_word'}).appendTo($message);
		$ur_word.append("(не прочитано)<br>");
		
		$message.append(message.msg);
		
		var $right = $('<div>', {style: 'text-align:right'}).appendTo($message);
		if (message.id_user == id_user)
			$right.append("<a href='/mail.php?id=" + id_user + "&spam=" + message.id + "'><img src='/style/icons/blicon.gif'></a>");
		$right.append("<a href='/mail.php?id=" + id_user + "&delete=" + message.id + "'><img src='/style/icons/delete.gif'></a>");
		
		if (message.id_after != undefined && message.id_after != false) {
			var $af = $('[data-id=' + message.id_after + ']', $messages);
			console.log($af);
			$af.after($message);
		}
		else
			$message.prependTo($messages);
	}

	this.updateMessages = function () {
		var $allMessages = $('.message', $messages);
		if ($allMessages.length == 0) {
			$('#empty').removeClass('hidden');
			return;
		}
		$('#empty').addClass('hidden');

		var num = 0;
		var c_messages = 0;
		$.each($allMessages, function (k, v) {
			var $messageElement = $(v);
			if (c_messages >= results_on_page)
				$messageElement.remove();
			$messageElement.removeClass('nav1');
			$messageElement.removeClass('nav2');

			$messageElement.addClass('nav' + (num++ % 2 ? 2 : 1));
			c_messages++;
		});
	}

	this.sendMessage = function (msg) {
		self.showLoading();

		sendMessageXHR = $.ajax({
			url: SEND_MSG_URL, 
			type: 'post', 
			data: {
				id_user: id_user, 
				msg: msg
			}, 
			success: function (json) {
				$inputMsg.val('');
			}, 
			error: function (error) {
				showError('Произошла ошибка');
			}, 
			complete: function () {
				self.hideLoading();
				sendMessageXHR = undefined;
			}
		});
	}

	this.showLoading = function () {
		$loading.show(100);
	}

	this.hideLoading = function () {
		$loading.hide(100);
	}

	this.checkRead = function (completeCallback) {
		var $unread = $('.unread', $messages);
		if ($unread.length == 0 || checkReadXHR != undefined) {
			if ($.isFunction(completeCallback))
				completeCallback();
			return;
		}

		var from_id = parseInt($($unread[0]).attr('data-id'));

		checkReadXHR = $.ajax({
			url: CHECK_READ_URL, 
			type: 'post', 
			data: {
				id_user: id_user, 
				from_id: from_id
			}, 
			success: function (json) {
				if (handleJsonErrors(json))
					return;

				if (json.read == 0)
					return;

				self.setRead();
			}, 
			complete: function () {
				checkReadXHR = undefined;
				if ($.isFunction(completeCallback))
					completeCallback();
			}
		});
	}

	this.setRead = function () {
		var $unread = $('.unread', $messages);
		if ($unread.length == 0)
			return;

		$.each($unread, function (k, value) {
			var $value = $(value);
			$value.removeClass('unread');
		});
	}

	this.goToPage = function (page) {
		current_page = page;

		self.abortGetMessages();
		self.startLongPollingMessages(function () {
			self.setGetMessagesTimeout();
		}, function () {
			$messages.empty();
			moveToTop();
		});

	}
}