главная

Теги:


AJAX веб чат с использованием PHP, MySQL и jQuery (Часть 2 из 2-х)

Во второй части урока мы разберем клиентскую часть AJAX веб чата, созданную с использованием jQuery и CSS. В первой части рассматривалась серверная часть с использованием PHP и MySQL.

CSS

Стили чата содержатся в файле chat.css. Стили не зависят от остальной страницы и их легко встроить в уже существующий сайт. Нужно только включить разметку HTML, стили и файлы JavaScript.
 

chat.css – Часть 1

/* Основной контейнер чата */

#chatContainer{
	width:510px;
	margin:100px auto;
	position:relative;
}


/* Верхняя панель */


#chatTopBar{
	height:40px;
	background:url('../img/solid_gray.jpg') repeat-x #d0d0d0;
	border:1px solid #fff;
	margin-bottom:15px;
	position:relative;
	
	color:#777;
	text-shadow:1px 1px 0 #FFFFFF;
}

#chatTopBar .name{
	position:absolute;
	top:10px;
	left:40px;
}

#chatTopBar img{
	left:9px;
	position:absolute;
	top:8px;
}


/* Чат */


#chatLineHolder{
	height:360px;
	width:350px;
	margin-bottom:20px;
}

.chat{
	background:url('../img/chat_line_bg.jpg') repeat-x #d5d5d5;
	min-height:24px;
	padding:6px;
	border:1px solid #FFFFFF;
	
	padding:8px 6px 4px 37px;
	position:relative;
	margin:0 10px 10px 0;
}

.chat:last-child{
	margin-bottom:0;
}

.chat span{
	color:#777777;
	text-shadow:1px 1px 0 #FFFFFF;
	font-size:12px;
}

.chat .text{
	color:#444444;
	display:inline-block;
	font-size:15px;
	overflow:hidden;
	vertical-align:top;
	width:190px;
}

.chat .gravatar{
	background:url('http://www.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?size=23') no-repeat;
	left:7px;
	position:absolute;
	top:7px;
}

.chat img{
	display:block;
	visibility:hidden;
}

.chat .time{
	position:absolute;
	right:10px;
	top:12px;
	font-size:11px;
}

.chat .author{
	margin-right:6px;
	font-size:11px;
}

Начинается все с задания стилей для div #chatContainer. Он центрируется горизонтально с помощью свойства margin:100px auto; . Данный div разделяется на верхнюю панель, область чата, область пользователей и нижнюю панель.

Верхняя панель выводит информацию о зарегистрированном пользователе. Она получает относительное позиционирование, так что аватар, имя и кнопка "выйти" располагаются соответственно.

Затем следует div, который содержит все строки чата – #chatLineHolder. Данный div имеет фиксированную высоту и ширину, а в части данного урока, которая посвящена jQuery, мы используем плагин jScrollPane для превращения его в область с прокруткой контента с боковым слайдером.

chat.css – Часть 2

/* Область пользователя */


#chatUsers{
	background-color:#202020;
	border:1px solid #111111;
	height:360px;
	position:absolute;
	right:0;
	top:56px;
	width:150px;
}

#chatUsers .user{
	background:url('http://www.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?size=30') no-repeat 1px 1px #444444;
	border:1px solid #111111;
	float:left;
	height:32px;
	margin:10px 0 0 10px;
	width:32px;
}

#chatUsers .user img{
	border:1px solid #444444;
	display:block;
	visibility:hidden;
}


/* Нижняя панель */


#chatBottomBar{
	background:url('../img/solid_gray.jpg') repeat-x #d0d0d0;
	position:relative;
	padding:10px;
	border:1px solid #fff;
}

#chatBottomBar .tip{
	position:absolute;
	width:0;
	height:0;
	border:10px solid transparent;
	border-bottom-color:#eeeeee;
	top:-20px;
	left:20px;
}

#chatContainer input{
	background:url('../img/input_bg.jpg') repeat-x #dcdcdc;
	height:26px;
	font:13px/26px Calibri,Arial,sans-serif;
	color:#777;
	border:1px solid;
	border-color:#c1c1c1 #eee #eee #c1c1c1;
	text-shadow:1px 1px 0 #E4E4E4;
	padding:0 5px;
	margin-right:5px;
	width:185px;
	outline:none;
}


#submitForm{
	display:none;
}

Во второй части файла стилей мы оформляем контейнер #chatUsers и элементы div для пользователя. Каждый активный пользователь чата представлен изображением gravatar размером 32 на 32 пикселя. Изображение по умолчанию используется в качестве фона, и когда реальное изображение загружается с сервера gravatar.com, оно выводится сверху. Так предотвращается раздражающее мерцание, которое обычно появляется в момент загрузки изображения.

Остальная часть кода связана с нижней панелью и формой отправки. Элемент div .tip становится треугольником, сделанным с использованием CSS, за счет установки нулевой высоты и ширины, при этом ширина обводки устанавливается большой.

chat.css – Часть 3

/* Изменение стилей по умолчанию для jScrollPane */


.jspVerticalBar{
	background:none;
	width:20px;
}

.jspTrack{
	background-color:#202020;
	border:1px solid #111111;
	width:3px;
	right:-10px;
}

.jspDrag {
	background:url('../img/slider.png') no-repeat;
	width:20px;
	left:-9px;
	height:20px !important;
	margin-top:-5px;
}

.jspDrag:hover{
	background-position:left bottom;
}

/* Дополнительные стили */


a.logoutButton{
	background-color:#bbb;
	border:1px solid #eee !important;
	color:#FFFFFF !important;
	font-size:12px;
	padding:5px 9px;
	position:absolute;
	right:10px;
	text-shadow:1px 1px 0 #888;
	top:7px;
	
	-moz-box-shadow:0 0 7px #888 inset;
	-webkit-box-shadow:0 0 7px #888 inset;
	box-shadow:0 0 7px #888 inset;
}

a.logoutButton:hover{
	text-shadow:1px 1px 0 #888;
	
	-moz-box-shadow:0 0 7px #666 inset;
	-webkit-box-shadow:0 0 7px #666 inset;
	box-shadow:0 0 7px #666 inset;
}

#chatContainer .blueButton{
	background:url('../img/button_blue.png') no-repeat;
	border:none !important;
	color:#516D7F !important;
	display:inline-block;
	font-size:13px;
	height:29px;
	text-align:center;
	text-shadow:1px 1px 0 rgba(255, 255, 255, 0.4);
	width:75px;
	margin:0;
	cursor:pointer;
}

#chatContainer .blueButton:hover{
	background-position:left bottom;
}

p.noChats,
#chatUsers .count{
	clear:both;
	font-size:12px;
	padding:10px;
	text-align:center;
	text-shadow:1px 1px 0 #111111;
}

#chatUsers .count{
	font-size:11px;
}

.rounded{
	-moz-border-radius:4px;
	-webkit-border-radius:4px;
	border-radius:4px;
}

#chatErrorMessage{
	width:100%;
	top:0;
	left:0;
	position:fixed;
	background-color:#ab0909;
	border-bottom:1px solid #d32a2a;
	font-size:23px;
	padding:16px;
	text-align:center;
	color:#fff;
	
	text-shadow:1px 1px 0 #940f0f;
}


В последней части кода мы изменяем стили по умолчанию для элементов div плагина jScrollPane. По умолчанию плагин выводит панель прокрутки в алом цвете, что плохо сочетается с дизайном нашей страницы. Вместо написания собственных стилей с нуля, мы просто включаем стили по умолчанию и изменяем некоторые правила.

jQuery

Перейдем к последней части нашего урока - коду jQuery. Чат работает, получая события от форм регистрации и отправки сообщения, а также от кнопки "Выйти", а также по расписанию отправляются запросы AJAX к серверу для проверки наличия новых сообщений и пользователей.

PHP часть обрабатывает запросы AJAX в файле ajax.php. jQuery генерирует следующие запросы AJAX:

* Вход пользователя в систему: один запрос POST;
* Выход пользователя из системы: один запрос POST;
* Проверка пользователей, которые находятся в режиме онлайн: выполняется каждые 15 секунд;
* Проверка новых записей: запрос GET генерируется каждую секунду. Такое функционирование может привести к очень высокой нагрузке на веб сервер, поэтому скрипт оптимизирован, и в зависимости от активности чата, период генерации запроса может быть увеличен до 15 секунд.

Мы определили пользовательские функции-обертки для функций AJAX jQuery $.get и $.post, которые помогают заполнять длинные параметры для генерации запроса.

Также весь код чата организован в один объект chat. Он содержит несколько удобных методов.

script.js – Часть 1

$(document).ready(function(){
	
	// Запускаем метод init, когда документ будет готов:
	chat.init();
	
});

var chat = {
	
	// data содержит переменные для использования в классах:
	
	data : {
		lastID 		: 0,
		noActivity	: 0
	},
	
	// Init привязывает обработчики событий и устанавливает таймеры:
	
	init : function(){
		
		// Используем плагин jQuery defaultText, включенный внизу:
		$('#name').defaultText('Псевдоним');
		$('#email').defaultText('Email (используется Gravatar)');
		
		// Конвертируем div #chatLineHolder в jScrollPane,
		// сохраняем API плагина в chat.data:
		
		chat.data.jspAPI = $('#chatLineHolder').jScrollPane({
			verticalDragMinHeight: 12,
			verticalDragMaxHeight: 12
		}).data('jsp');
		
		// Используем переменную working для предотвращения
		// множественных отправок формы:
		
		var working = false;
		
		// Регистрируем персону в чате:
		
		$('#loginForm').submit(function(){
			
			if(working) return false;
			working = true;
			
			// Используем нашу функцию tzPOST
			// (определяется внизу):
			
			$.tzPOST('login',$(this).serialize(),function(r){
				working = false;
				
				if(r.error){
					chat.displayError(r.error);
				}
				else chat.login(r.name,r.gravatar);
			});
			
			return false;
		});

Метод init() предназначен для привязки обработчиков событий к чату и запуску функций таймера, которые используются для проверки по расписанию наличия новых записей в чате и списка пользователей в режиме онлайн. Мы используем собственные функции-обертки – $.tzGET и $.tzPOST. Они принимают на себя всю тяжесть работы по заданию длинного списка параметров для запросов AJAX.

script.js – Часть 2

	// Отправляем данные новой строки чата:
	
	$('#submitForm').submit(function(){
		
		var text = $('#chatText').val();
		
		if(text.length == 0){
			return false;
		}
		
		if(working) return false;
		working = true;
		
		// Генерируем временный ID для чата:
		var tempID = 't'+Math.round(Math.random()*1000000),
			params = {
				id			: tempID,
				author		: chat.data.name,
				gravatar	: chat.data.gravatar,
				text		: text.replace(//g,'>')
			};

		// Используем метод addChatLine, чтобы добавить чат на экран 
		// немедленно, не ожидая завершения запроса AJAX:
		
		chat.addChatLine($.extend({},params));
		
		// Используем метод tzPOST, чтобы отправить чат
		// через запрос POST AJAX:
		
		$.tzPOST('submitChat',$(this).serialize(),function(r){
			working = false;
			
			$('#chatText').val('');
			$('div.chat-'+tempID).remove();
			
			params['id'] = r.insertID;
			chat.addChatLine($.extend({},params));
		});
		
		return false;
	});
	
	// Отключаем пользователя:
	
	$('a.logoutButton').live('click',function(){
		
		$('#chatTopBar > span').fadeOut(function(){
			$(this).remove();
		});
		
		$('#submitForm').fadeOut(function(){
			$('#loginForm').fadeIn();
		});
		
		$.tzPOST('logout');
		
		return false;
	});
	
	// Проверяем состояние подключения пользователя (обновление браузера)
	
	$.tzGET('checkLogged',function(r){
		if(r.logged){
			chat.login(r.loggedAs.name,r.loggedAs.gravatar);
		}
	});
	
	// Самовыполняющиеся функции таймаута
	
	(function getChatsTimeoutFunction(){
		chat.getChats(getChatsTimeoutFunction);
	})();
	
	(function getUsersTimeoutFunction(){
		chat.getUsers(getUsersTimeoutFunction);
	})();
	
},

Во второй части скрипта мы продолжаем привязку обработчиков событий. В функции отправки формы можно заметить, что когда пользователь создает новую запись в чате, создается временная строка, которая выводится немедленно в окно чата, без ожидания завершения запроса AJAX. Как только запись будет завершена, временная строка удаляется с экрана. Так пользователь получает ощущения, что чат работает молниеносно, в то время как реальная запись происходит в фоновом режиме.

В конце данного куска кода запускаются две именованные самовыполняющиеся функции. Данные функции будут передаваться как параметры методам chat.getChats() или chat.getUsers() соответственно, таким образом, могут быть установлены дополнительные таймауты.

script.js – Часть 3

// Метод login скрывает данные регистрации пользователя
// и выводит форму ввода сообщения

login : function(name,gravatar){
	
	chat.data.name = name;
	chat.data.gravatar = gravatar;
	$('#chatTopBar').html(chat.render('loginTopBar',chat.data));
	
	$('#loginForm').fadeOut(function(){
		$('#submitForm').fadeIn();
		$('#chatText').focus();
	});
	
},

// Метод render генерирует разметку HTML, 
// которая нужна для других методов:

render : function(template,params){
	
	var arr = [];
	switch(template){
		case 'loginTopBar':
			arr = [
			'',
			'',params.name,
			'Выйти'];
		break;
		
		case 'chatLine':
			arr = [
				'
','',params.author, ':',params.text,'',params.time,'
']; break; case 'user': arr = [ '
' ]; break; } // Единственный метод join для массива выполняется // быстрее, чем множественные слияния строк return arr.join(''); },

В данной части кода внимания требует метод render(). Он собирает шаблон в зависимости от параметра template. Метод затем создает и возвращает запрашиваемый код HTML, встраивая в него значения второго параметра объекта params.

script.js – Часть 4

// Метод addChatLine добавляет строку чата на страницу

addChatLine : function(params){
	
	// Все показания времени выводятся в формате временного пояса пользователя
	
	var d = new Date();
	if(params.time) {
		
		// PHP возвращает время в формате UTC (GMT). Мы используем его для формирования объекта date
		// и дальнейшего вывода в формате временного пояса пользователя. 
		// JavaScript конвертирует его для нас.
		
		d.setUTCHours(params.time.hours,params.time.minutes);
	}
	
	params.time = (d.getHours() < 10 ? '0' : '' ) + d.getHours()+':'+
				  (d.getMinutes() < 10 ? '0':'') + d.getMinutes();
	
	var markup = chat.render('chatLine',params),
		exists = $('#chatLineHolder .chat-'+params.id);

	if(exists.length){
		exists.remove();
	}
	
	if(!chat.data.lastID){
		// Если это первая запись в чате, удаляем 
		// параграф с сообщением о том, что еще ничего не написано:
		
		$('#chatLineHolder p').remove();
	}
	
	// Если это не временная строка чата:
	if(params.id.toString().charAt(0) != 't'){
		var previous = $('#chatLineHolder .chat-'+(+params.id - 1));
		if(previous.length){
			previous.after(markup);
		}
		else chat.data.jspAPI.getContentPane().append(markup);
	}
	else chat.data.jspAPI.getContentPane().append(markup);
	
	// Так как мы добавили новый контент, нужно
	// снова инициализировать плагин jScrollPane:
	
	chat.data.jspAPI.reinitialise();
	chat.data.jspAPI.scrollToBottom(true);
	
},

Метод addChat() получает в качестве параметра объект, который содержит строку чата, имя автора и gravatar, и вставляет строку чата в соответствующее место в контейнере div #chatContainer. Каждая строка чата (если она не является временной) имеет уникальный ID, который назначается MySQL. Данный id как имя класса для строки чата в формате chat-123.

Когда метод addChat() выполняется, он проверяет существование предыдущей строки (для chat-123 будет проверяться наличие chat-122). Если она существует, метод вставляет новую строку после нее. Если нет, то просто добавляет новую строку к div. Такая простая техника управляет вставкой строк в правильном порядке и поддерживает его на протяжении всей работы чата.

script.js – Часть 5

 

// Данный метод запрашивает последнюю запись в чате
// (начиная с lastID), и добавляет ее на страницу.

getChats : function(callback){
	$.tzGET('getChats',{lastID: chat.data.lastID},function(r){
		
		for(var i=0;i< r.chats.length;i++)
        {
			chat.addChatLine(r.chats[i]);
		}
		
		if(r.chats.length){
			chat.data.noActivity = 0;
			chat.data.lastID = r.chats[i-1].id;
		}
		else{
			// Если нет записей в чате, увеличиваем 
			// счетчик noActivity.
			
			chat.data.noActivity++;
		}
		
		if(!chat.data.lastID){
			chat.data.jspAPI.getContentPane().html('

Ничего еще не написано

'); } // Устанавливаем таймаут для следующего запроса // в зависимости активности чата: var nextRequest = 1000; // 2 секунды if(chat.data.noActivity > 3){ nextRequest = 2000; } if(chat.data.noActivity > 10){ nextRequest = 5000; } // 15 секунд if(chat.data.noActivity > 20){ nextRequest = 15000; } setTimeout(callback,nextRequest); }); }, // Запрос списка всех пользователей. getUsers : function(callback){ $.tzGET('getUsers',function(r){ var users = []; for(var i=0; i< r.users.length;i++){ if(r.users[i]){ users.push(chat.render('user',r.users[i])); } } var message = ''; if(r.total<1){ message = 'Никого нет в онлайне'; } else { message = 'В онлайне: ' + r.total; } users.push('

'+message+'

'); $('#chatUsers').html(users.join('')); setTimeout(callback,15000); }); },

 

В данной части кода происходит управление запросами AJAX. В методе getChats() определяется, когда будет снова выполняться функция в зависимости от свойства noActivity локального объекта данных. При каждом запросе, который не возвращает новых строк чата, мы увеличиваем счетчик. Если он достигает определенного порога, следующий запрос будет генерироваться с задержкой.

script.js – Часть 6

 

	// Данный метод выводит сообщение об ошибке наверху страницы:
	
	displayError : function(msg){
		var elem = $('
',{ id : 'chatErrorMessage', html : msg }); elem.click(function(){ $(this).fadeOut(function(){ $(this).remove(); }); }); setTimeout(function(){ elem.click(); },5000); elem.hide().appendTo('body').slideDown(); } }; // Формирование GET & POST: $.tzPOST = function(action,data,callback){ $.post('php/ajax.php?action='+action,data,callback,'json'); } $.tzGET = function(action,data,callback){ $.get('php/ajax.php?action='+action,data,callback,'json'); } // Метод jQuery для замещающего текста: $.fn.defaultText = function(value){ var element = this.eq(0); element.data('defaultText',value); element.focus(function(){ if(element.val() == value){ element.val('').removeClass('defaultText'); } }).blur(function(){ if(element.val() == '' || element.val() == value){ element.addClass('defaultText').val(value); } }); return element.blur(); }

В последней части кода определяются вспомогательные функции и методы. Метод displayError() показывает красную строку вверху экрана, если происходит ошибка. Затем определяются функции-обертки $.tzGET и $.tzPOST, и плагин defaultText, который выводит заполняющий текст для полей ввода текста.

Готово!

Заключение

В данном уроке из двух частей мы сделали решение на основе классов PHP, базы данных MySQL и jQuery. Чат можно использовать для обеспечения клиентского сервиса или просто для развлечения посетителей веб сайта. Это отличное решение для маленьких и средних размеров чата (меньше 20 человек одновременно).

Источник урока: tutorialzine.com/2010/10/ajax-web-chat-css-jquery/

 

 

 

Урок Создан:2011-02-10 Просмотров:4553

Добавить комментарий:


Copyright© 2009 Hosted by Zhost