Чем могу- помогу

RSS лента
Автор блога: Александр
Рубрики:
Все рубрики (9)
Личные сообщения + Друзья+AJAX
+18
Один мой друг просил сделать отправку личных сообщений на AJAX.
Полностью с ним согласен.

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

В общем к делу.

Реализована отправка личных сообщений и добавление друзей во всплывающих окнах с AJAX отправкой на сервер.

Очень хотелось бы услышать предложения по улучшению или сообщения об ошибках.


Как прикрутить?

1) Качаем АРХИВ. Копируем файлы...

2) В templates\_default_\css\styles.css добавим новые стили всплывающего окна:

Код PHP:
/* Всплывающее окошко */
#popup_container{font-family:Arial, sans-serif;font-size:12px;width: 380px;background:#FFF;border:solid 5px #a5bede;color:#000}
#popup_title{font-size:13px;font-weight:bold;color:white;line-height:1;margin:0;background:#6D84B4 none repeat scroll 0 0;border:1px solid #3B5998;padding:6px;position:relative}
#popup_content{border-left:1px solid #aaa;border-right:1px solid #aaa;border-bottom:1px solid #aaa;padding:0em;margin:0em}
#popup_message{padding:10px 30px 10px 30px}
#popup_panel{text-align:right;background:#f2f2f2;border-top:1px solid #ccc;margin:0;padding:3px;padding-right:10px;}
#popup_prompt{margin: .5em 0em}

3) В шаблоне страницы профиля ищем строки

Код PHP:
{* ==================меню в профиле======== *}
							<div id="usermenu" style="text-align:center;">
                            <div class="usr_profile_menu">
...................
.....................
.........................
....

И правим код до такого состояния:  

Код PHP:
{* ===============================меню в профиле================================================= *}
							<div id="usermenu" style="text-align:center;">
                            <div class="usr_profile_menu">
              <input type="hidden" name="nickname" value="{$usr.nickname}" />             
							<table cellpadding="0" cellspacing="1" align="center" style="margin-left:auto;margin-right:auto"><tr>
							{if !$myprofile}
							<td><a id="newmess" href="/users/{$usr.id}/sendmessage.html" title="{$LANG.WRITE_MESS}"><img src="/components/users/images/profilemenu/message.gif" border="0"/></a></td>
							{/if}
                            {if !$myprofile && $cfg.sw_friends}
                            	{if !$usr.isfriend}
                                	{if !$usr.isfriend_not_add}
                                	<td><a id="friends" href="/users/{$usr.id}/friendship.html" title="{$LANG.ADD_TO_FRIEND}"><img src="/components/users/images/profilemenu/friends.gif" border="0"/></a></td>
                                    {else}
                                    <td><a href="/users/{$usr.id}/nofriends.html" title="{$LANG.STOP_FRIENDLY}"><img src="/components/users/images/profilemenu/nofriends.gif" border="0"/></a></td>
                                	{/if}
                                {else}
                                <td><a href="/users/{$usr.id}/nofriends.html" title="{$LANG.STOP_FRIENDLY}"><img src="/components/users/images/profilemenu/nofriends.gif" border="0"/></a>
                                {/if}
                            {/if}

4) Заключительный маневр.

Вверху в этом же файле подключим скрипт из архива:

Код PHP:
{add_js file="components/users/js/popup.js"}

Чистим кэш.

Проверяем...
Стена пользователя AJAX
+10
Набросал на скорую руку очередную поправку к оф. релизу. Может кому пригодится.
(Возможно уже кто-нибудь описывал такую тему, тогда я извиняюсь.)

Смысл вот в чем:

-при добавлении новой записи на стену пользователя (или клуба) страница полностью обновляется,
что на мой непрофессиональный взгляд не очень красиво и очень не рационально.

-считаю это нужно делать с применением AJAX.

-удаление сообщений тоже доверим ему...




Так. С чего начать?
Нет. Много объяснять... Кому на самом деле интересно - разберется сам.


Вот ССЫЛКА, скопируйте с заменой, и все.
Да предупреждение. Сделайте копии своих файлов которые будем менять. Предъявы не принимаются!!!

И еще. Проверял под ver.1.6.2. и дефолтный шаблон! Если у Вас свой шаблон,
то файлы из папки _default_/components(в архиве)необходимо сверить с Вашими
в одноименной папке (components) и поправить.

Вроде ничего не забыл. А вот! Чистим папку cache.

Жду комментариев.

26 июня 2010
Обновил архив. Суть исправлений в добавлении возможности забубенить на стену сообщение с отключенным JavaScript.
Кстати в стандартной комплектации нет такой возможности!!! А если я с мобилки зашел на сайт?
А если в браузере отключен Java...
Считаю что нужно предусмотреть такой поворот событий, тем более в components\users\frontend.php остались строчки,
отвечающие за добавление сообщений на стену, и они не задействованны.


в файле templates\_default_\components\com_users_profile.tpl найдем строку

Код PHP:
<div id="addwall" style="display:none">{$usr.addwall_html}</div>
и поправим на

Код PHP:
<div id="addwall">{$usr.addwall_html}</div>
и в верху этого же файла
Код PHP:
{literal}
	<script type="text/javascript">
		$(document).ready(function(){
			$("#profiletabs > ul#tabs").tabs();
		});
	</script>
{/literal}
заменим на

Код PHP:
{literal}
	<script type="text/javascript">
		$(document).ready(function(){
			$("#profiletabs > ul#tabs").tabs();
			$("#addwall").css("display", "none");
		});
	</script>
{/literal}
Это нужно для того, чтобы форма ввода сообщения не пряталась при отключенном JavaScript.

Все. Качаем архив, тестим, говорим спасибо.

27.06.10 Изменил архив. Исправлена ошибка, приводящая к удвоению записей на стене. Извиняюсь за причиненные неудобства.
Активные темы
+6
Сегодня на форуме прозвучал вопрос от wmaximum:

Подобные темы уже поднимались, но толкового ответа на вопрос о том, как сделать ссылку кликнув по которой пользователь получал список последних активных тем форума (как это реализовано в форумных движках, либо в форуме от DLE), т.е. тем, где оставлялись сообщения с его последнего визита.

Не стал отвечать на форуме, поскольку лично мое мнение что его читают пару человек. Движухи почти никакой!
А тема интерестная, может еще кому пригодится. Может кто поправит меня...

Вот мое решение данного вопроса...


Пропишем нужную нам ссылку там где надо...(Я для теста прописал в футере шаблона)
Да. Примечание. Она должно появляться только для авторизованных пользователей.
Сделаем... (!!!Листинг для template.php!!!)

Код PHP:
<?php if($inUser->id){ ?>
   <a href="/forum/active.html">Активные темы на форуме</a>
<?php } ?>
В файле   components\forum\router.php добавим в начало после строк

Код PHP:
 function routes_forum(){
новое правило:

Код PHP:
        //RewriteRule ^forum/active.html$ /index.php?view=forum&do=active&id=$1
        $routes[] = array(
                            '_uri'  => '/^forum\/active.html$/i',
                            'do'    => 'active',
                            1       => 'id',
                         );
В файле  components\forum\frontend.php где-нибудь, например после строчек

Код PHP:
///////////////////////////// VIEW FORUMS LIST ////////////////////
if ($do=='view'){
................
.................
....................		
}	
Вставим следующий кодик:

Код PHP:
///////////////////////////// АКТИВНЫЕ ТЕМЫ ////////////////////////
if ($do=='active'){
			$inPage->setTitle('Активные темы форума');
			$inPage->addPathway('Активные темы форума', $_SERVER['REQUEST_URI']);
if(usrCheckAuth()) {
       $id = $inUser->id;
    
    if ($inUser->id){
        $logdate = $_SESSION['user']['logdate'];
    } else {
        $logdate = '9999-01-01 12:00:00';
    }
		$kolvo = 15; //сколько активных тем выводить на странице
		$groupsql = forumUserAuthSQL('f.');
		
		$tsql = "SELECT t.*, COUNT(p.id) as postsnum, f.id as fid, f.title as forum, u.id as uid,
		         u.nickname as starter, u.login as login, f.auth_group as auth_group
						 FROM cms_forum_threads t, cms_forum_posts p, cms_forums f, cms_users u
						 WHERE p.thread_id = t.id AND t.user_id = u.id AND t.forum_id = f.id $groupsql AND (p.editdate > '$logdate')
						 GROUP BY p.thread_id
						 ORDER BY t.pubdate DESC
						 LIMIT $kolvo";
						 
		$result = $inDB->query($tsql) ;
		$threads = array();
		
		if ($inDB->num_rows($result)){
		
				$threads = array();

				while ($t = $inDB->fetch_assoc($result)){
					$next = sizeof($threads);							

					$pages = ceil($t['postsnum'] / $cfg['pp_thread']);				
					$lastmessage = threadLastMessageData($t['id']);							

					$threads[$next]['date']         = strip_tags($lastmessage['date']);
					$threads[$next]['author']       = $lastmessage['user'];
					$threads[$next]['authorhref']   = cmsUser::getProfileURL($lastmessage['login']);
					$threads[$next]['starter']      = $t['starter'];
					$threads[$next]['starterhref']  = cmsUser::getProfileURL($t['login']);
					$threads[$next]['topic']        = ucfirst($t['title']);
					$threads[$next]['topicdesc']    = ucfirst($t['description']);
					$threads[$next]['topichref']    = '/forum/thread'.$t['id'].'-'.$pages.'.html#new';
					$threads[$next]['forum']        = ucfirst($t['forum']);
					$threads[$next]['forumhref']    = '/forum/'.$t['fid'];

                    $threads[$next]['secret']       = 0;
                    if ($t['auth_group']>0) {
                        $threads[$next]['secret']   = 1;
                    }

					if (strlen($lastmessage['msg'])>70) { $lastmessage['msg'] = substr($lastmessage['msg'], 0, 70).'...'; }

                    $msg = $lastmessage['msg'];

                    $threads[$next]['msg'] = $msg;

					if ($t['postsnum']==1) {
						$threads[$next]['act'] = 'начинает тему';
					} else { 
						$threads[$next]['act'] = 'отвечает в теме';
					}										
				}

				$smarty = $inCore->initSmarty('components', 'com_forum_active.tpl');			
				$smarty->assign('threads', $threads);
				$smarty->assign('cfg', $cfg);				
				$smarty->display('com_forum_active.tpl');	
														
		} else { echo '<h2>Нет активных тем на форуме!!!</h2>'; }

} else { usrAccessDenied(); }

}

И наконец, в папку templates\_default_\components нужно создать файл com_forum_active.tpl
со следующим содержанием

Код PHP:
<table width="100%" cellspacing="0" cellpadding="5" border="0" >
{foreach key=tid item=thread from=$threads}
	<tr>
		<td style="font-size: 12px;" align="left" valign="top" width="">
			<div><a href="{$thread.topichref}" style="font-weight:bold">{$thread.topic}</a></div>
			<div class="thread_desc">{$thread.topicdesc}</div>
		</td>
		<td style="font-size: 12px;" class="" valign="top" width="120">
			<div><strong>Автор:</strong><br><a href="{$thread.starterhref}">{$thread.starter}</a>
		</td>		
		<td style="font-size: 12px;" class="" valign="top" width="200">
			<div><strong>Последнее сообщение: </strong></div>
			<div>{$thread.date} от <a href="{$thread.authorhref}">{$thread.author}</a></div>
		</td>
	</tr>
{/foreach}
</table>
А если желаете выводить в стиле WEB 2

Код PHP:
<table width="100%" cellspacing="0" cellpadding="5" border="0" >
    {foreach key=tid item=thread from=$threads}

        <tr>
            <td align="left" class="mod_fweb2_date" width="70"><div style="text-align:center">{$thread.date}</div></td>
            <td width="13">
                {if !$thread.secret}
                    <img src="/modules/mod_forum/user.gif" border="0" />
                {else}
                    <img src="/modules/mod_forum/hidden.gif" border="0" title="Скрытая тема - видна только вашей группе"/>
                {/if}
            </td>
            <td style="padding-left:0px"><a href="{$thread.authorhref}" class="mod_fweb2_userlink">{$thread.author}</a> {$thread.act} «<a href="{$thread.topichref}" class="mod_fweb2_topiclink">{$thread.topic}</a>»
            {if $cfg.showforum neq 0} на форуме «<a href="{$thread.forumhref}">{$thread.forum}</a>»{/if}</td>
        </tr>

        {if $cfg.showtext neq 0}
        <tr>
            <td> </td>
            <td colspan="2"><div class="mod_fweb2_shorttext">{$thread.msg}</div></td>
        </tr>
        {/if}

    {/foreach}
</table>

А если желаете выводить в другом стиле, правим ручками...  laugh


Все. Вот мое видение и решение данной проблемы.
Удаление Профиля пользователя
+2
Наткнулся еще на один мааааленький неприятный момент.
Боюсь называть мелкие недочеты Багами, но считаю мелочи рано или поздно дают о себе знать.

Смысл вот в чем:
При удалении пользователя (не важно, с админки или из профиля) профиль пользователя удаляется. Если теперь перейти по ссылке удаленного пользователя – наблюдаем страницу удаленного пользователя. Тут вроде все нормально. Идем дальше…

Переходим на страницу регистрации и пробуем зарегистрироваться с тем же Логином, как у удаленного пользователя… Трам-тарам, логин-пароль… И о чудо! ”Регистрация прошла успешно!” – пишет Instant!!! Ну подумаешь, что в этом плохого???  Идем дальше…

Пробуем зайти к на страничку пользователя… Хм???

Еще раз попробуем…

Нет! Не то! Авторизация проходит, а в профиле видим все ту страницу удаленного пользователя…

Разбираюсь в чем проблема. Оказывается пару символов лишних в коде поправить надо, а именно:

-в файле core\ajax\registration.php строка
Код PHP:
$sql    = "SELECT id, login FROM cms_users WHERE (login LIKE '$data') AND (is_deleted = 0) LIMIT 1";
Должна быть такой:
Код PHP:
$sql    = "SELECT id, login FROM cms_users WHERE (login LIKE '$data') LIMIT 1";
Открываем components\registration\frontend.php и ищем строки:
Код PHP:
   if ($do=='register'){
…..
…..
…..
        if($msg==''){

            if ($inCore->checkCaptchaCode($code)){
…..
…..
И меняем строку
Код PHP:
$sql = "SELECT id, login, email FROM cms_users WHERE (login LIKE '$login' OR email LIKE '$email') AND (is_deleted = 0)";
На
Код PHP:
$sql = "SELECT id, login, email FROM cms_users WHERE (login LIKE '$login' OR email LIKE '$email') LIMIT 1";
Проверям….
Все нормально. Теперь такой ошибки не наблюдается…
Настойки профиля
+13
Сегодня случайно заметил, что в настройках профиля пользователя есть небольшие неприятности.
- не вижу сообщений об ошибке при смене пароля. А хотелось бы точно знать -  поменялся пароль, или остался старый. Интуитивно догадываюсь, что по функционалу это предусмотрено (стоит только заглянуть в шаблон  com_users_edit_profile.tpl).
- постоянно ”выбрасывает” на страницу профиля, но по идее я должен остаться на странице настроек, если случайно допустил ошибку. Вижу сообщение об ошибке, думаю, исправляю… Если ошибок небыло – меня переносит в профиль, и снова читаю сообщение о удачном сохранении настроек.

Правим файл  components\users\frontend.php
Что именно поменялось нету времени обьяснять, кому интерестно сравните.

Код PHP:
/////////////////////////////// EDIT PROFILE /////////////////////////////////////////////////////////////////////////////////////////
if ($do=='editprofile'){

	$opt = $inCore->request('opt', 'str', 'edit');

	if (usrCheckAuth()){
	
		if ($inUser->id==$id || $inCore->userIsAdmin($inUser->id)){
		    $emsg = '';
				if ($opt == 'save'){
					
					
					$nickname = $inCore->request('nickname', 'str');
                    if (strlen($nickname)<2) {$emsg .= $_LANG['SHORT_NICKNAME'].'<br/>';}

					$gender = $inCore->request('gender', 'str');
					
					$city = $inCore->request('city', 'str');
					if (strlen($city)>20) {$emsg .= $_LANG['LONG_CITY_NAME'].'<br/>';}

					$email = $inCore->request('email', 'str');
					if (!preg_match('/^([a-z0-9\._-]+)@([a-z0-9\._-]+)\.([a-z]{2,4})$/i', $email)) {$emsg .= $_LANG['REALY_ADRESS_EMAIL'].'<br/>';}
					
					$showmail       = $inCore->request('showmail', 'int');
					$email_newmsg   = $inCore->request('email_newmsg', 'int');
					
					$showbirth      = $inCore->request('showbirth', 'int');
					$description    = $inCore->request('description', 'str');
					
					$birthdate      = (int)$_REQUEST['birthdate']['year'].'-'.(int)$_REQUEST['birthdate']['month'].'-'.(int)$_REQUEST['birthdate']['day'];
					$signature      = $inCore->request('signature', 'str');

					$allow_who      = $inCore->request('allow_who', 'str');
                    if (!preg_match('/^([a-zA-Z]+)$/i', $allow_who)) { $emsg .= $_LANG['ACCESS_BLOCK'].'<br/>';}

					$icq            = $inCore->request('icq', 'str');
          $icq            = preg_replace('/([^0-9])/i', '', $icq);
                    
					$showicq        = $inCore->request('showicq', 'int');
					
					$cm_subscribe   = $inCore->request('cm_subscribe', 'str');
					
					if ($inCore->inRequest('field')){
						foreach($_POST['field'] as $k=>$val){
							$_POST['field'][$k] = str_replace('\"', '"', $_POST['field'][$k]);
							$_POST['field'][$k] = str_replace('"', '"', $_POST['field'][$k]);
							$_POST['field'][$k] = str_replace("\'", ''', $_POST['field'][$k]);
							$_POST['field'][$k] = str_replace("'", ''', $_POST['field'][$k]);
							$_POST['field'][$k] = strip_tags($_POST['field'][$k]);
						}					
						$formsdata = $inCore->arrayToYaml($_POST['field']);
						$forms_sql = ", formsdata='$formsdata'";
					} else {
						$forms_sql = '';
					}
					
					if (strlen($emsg)==0){
                       
						$sql = "UPDATE cms_user_profiles 
						 		SET city = '$city',
									description = '$description',
									showmail='$showmail',
									showbirth='$showbirth',
									showicq='$showicq',
									allow_who='$allow_who',
									signature='$signature',
									gender='$gender' $forms_sql,
									email_newmsg='$email_newmsg',
									cm_subscribe='$cm_subscribe'
								WHERE user_id = $id";
						$inDB->query($sql) ;

						$sql = "UPDATE cms_users 
								SET birthdate='$birthdate',
									email='$email',
									icq='$icq',
									nickname='$nickname'
								WHERE id = $id";
						$inDB->query($sql) ;

                        cmsCore::addSessionMessage($_LANG['PROFILE_SAVED'], 'info');
                        $inCore->redirect(cmsUser::getProfileURL($inUser->login));
					}
				}				
				
				if ($opt == 'changepass'){
					$msg = '';
					if ($inUser->password==md5($_POST['oldpass'])){ $oldpass = $inCore->request('oldpass', 'str'); } else { $emsg .= $_LANG['OLD_PASS_WRONG'].'<br/>'; }
					if ($_POST['newpass']==$_POST['newpass2']){ $newpass = $inCore->request('newpass', 'str'); } else { $emsg .= $_LANG['WRONG_PASS'].'<br/>'; }

					if (strlen($emsg)==0){
						$sql = "UPDATE cms_users SET password='".md5($newpass)."' WHERE id = $id AND password='".md5($oldpass)."'";
						$inDB->query($sql);
						$msg = $_LANG['PASS_CHANGED'];
					}
					//$inCore->redirect(cmsUser::getProfileURL($inUser->login));
				}
		
		
			$sql = "SELECT u.*, p.*, u.id as id, 
							DATE_FORMAT(u.regdate, '%d-%m-%Y') as fregdate, 
							DATE_FORMAT(u.logdate, '%d-%m-%Y') as flogdate,
							DATE_FORMAT(u.birthdate, '%d') as bday,
							DATE_FORMAT(u.birthdate, '%m') as bmonth,
							DATE_FORMAT(u.birthdate, '%Y') as byear,
							IFNULL(p.gender, 0) as gender
					FROM cms_users u, cms_user_profiles p
					WHERE u.is_locked = 0 AND p.user_id = u.id AND u.id = $id
					LIMIT 1
					";					
			$result = $inDB->query($sql);
			
			if ($inDB->num_rows($result)){
				$usr = $inDB->fetch_assoc($result);
		
				$inPage->setTitle($_LANG['CONFIG_PROFILE'].' - '.$usr['nickname']);
				$inPage->addPathway($usr['nickname'], cmsUser::getProfileURL($usr['login']));
				$inPage->addPathway($_LANG['CONFIG_PROFILE']);
																				
				if ($opt == 'edit'||$opt=='save'||$opt=='changepass'){
					
					$private_forms = '';
					if(isset($cfg['privforms'])){						
						if (is_array($cfg['privforms'])){
							if ($usr['formsdata']==''){
								$formsdata = array();
							} else {
                                $formsdata = $inCore->yamlToArray($usr['formsdata']);
							}
							foreach($cfg['privforms'] as $num=>$form_id){								
								$private_forms .= usrFormEditor($id, $form_id, $formsdata);								
							}							
						}						
					}				
				
					$inPage->initAutocomplete();
					$autocomplete_js = $inPage->getAutocompleteJS('citysearch', 'city', false);
									
					$smarty = $inCore->initSmarty('components', 'com_users_edit_profile.tpl');
				
					$smarty->assign('opt', $opt);
					$smarty->assign('msg', $msg);
					$smarty->assign('emsg', $emsg);
					$smarty->assign('usr', $usr);			
					$smarty->assign('dateform', $inCore->getDateForm('birthdate', false, $usr['bday'], $usr['bmonth'], $usr['byear']));
					$smarty->assign('private_forms', $private_forms);		
					$smarty->assign('autocomplete_js', $autocomplete_js);
					
					$smarty->display('com_users_edit_profile.tpl');
				}
				
			} else { usrAccessDenied(); }
		
		} else { usrAccessDenied(); }
	
	} else { usrAccessDenied(); }

}

А для того чтобы ошибка отображалась как надо, подправим файл шаблона com_users_edit_profile.tpl. (Где-то с 18 строки)
Удаляем:
Код PHP:
{if $emsg && $opt=='save'} 
	<div style="color:red">{$emsg}</div>
{/if}

{if $msg && $opt=='save'}
	<div style="color:green">{$msg}</div>
{/if}
А вместо этих строк напишем:
Код PHP:
{if $emsg} 
	<div class="sess_messages"><div class="message_error">{$emsg}</div></div>
{/if}

{if $msg}
<div class="sess_messages"><div class="message_success">{$msg}</div></div>
{/if}
Теперь идем вниз и удаляем строки:
Код PHP:
    {if $emsg && $opt=='changepass'}
        <div style="color:red">{$emsg}</div>
    {/if}
    {if $msg && $opt=='changepass'}
        <div style="color:green">{$msg}</div>
    {/if}
- и еще. Ни в регистрации, ни в настройках пользователя нет проверки длины пароля, но это уже другая история… Может она и не нужна? Может кто-то с памятью не дружит и вообще без пароля неплохо себя чувствует...