Кнопка "вставить пользователя" в стандартном редакторе

Возможность вставить ссылку на профиль пользователя в тело топика.


Для начала надо добавить кнопку в щаблон добавления топика:
Файл /templates/skin/new/actions/actionTopic/add.tpl строка 100

<a href="#" onclick="showUserForm(); return false;" class="button">
<img src="{$DIR_STATIC_SKIN}/images/panel/user.png" width="16" height="16" title="{$aLang.panel_user}">
</a>

… и подключить шаблон окна выбора пользователя:
{include file='window_add_user.tpl' sToLoad='topic_text'}


Шаблон окна выбора пользователя:

Создать файл /templates/skin/new/window_add_user.tpl
<div style="display: none;">
<div class="login-popup upload-image" id="winUserAdd">
	<div class="login-popup-top"><a href="#" class="close-block" onclick="return false;"></a></div>
	<div class="content">
		<form method="POST" action="" enctype="multipart/form-data" id="form_user_insert" >
			<h3>{$aLang.insertuser}</h3>
			<p><label for="username">{$aLang.insertuser_username}:</label><br /><input  type="text" name="username" value="" class="w100p"/></p>
			<p>
				<input type="button" value="{$aLang.insertuser_find}" onclick="ajaxFindUsers(this.form.username.value);">
				<a href="#" onclick="return ajaxGetFriends();">{$aLang.insertuser_friends}</a>
			</p>
			<div style="display:none;" id="insertuser_results"><label for="userlist">{$aLang.insertuser_users}:</label><br />				
				<select name="userlist" id="userlist" class="w50p ld" size="10">
				
				</select>
				<div class="w50p rd" style="background:#fff; height:160px;" id="userPreview">
				
				</div>
				<div class="br"></div>
			</div>
			<p style="margin-top:20px;">
				<input type="button" value="{$aLang.insertuser_submit}" onclick="lsPanel.insertUser('topic_text',this.form.userlist.value); return false;">
				<input type="button" value="{$aLang.insertuser_cancel}" onclick="hideUserForm(); return false;">
			</p>
		</form>
	</div>
	<div class="login-popup-bottom"></div>
</div>
</div>


Добавить js-функции для поиска пользователей:
/templates/skin/new/js/other.js

function showUserForm() {	
	if (Browser.Engine.trident) {
		//return true;
	}	
	if (!winUserAdd) {		
		winUserAdd=new StickyWin.Modal({content: $('winUserAdd'), closeClassName: 'close-block', useIframeShim: false});
	}
	winUserAdd.show();
	winUserAdd.pin(true);
	return false;
}

function hideUserForm() {
	winUserAdd.hide();
}

var winUserAdd;

function ajaxFindUsers(search){
	var req = new JsHttpRequest();
	$('userlist').set('html','');			
	req.onreadystatechange = function() {
		if (req.readyState == 4) {
			if (req.responseJS.bStateError) {
				msgErrorBox.alert(req.responseJS.sMsgTitle,req.responseJS.sMsg);				
			} else {	
				req.responseJS.found.each(function(item, index){
					$('userlist').set('html','<option>'+item+'</option>');
				});
				$('insertuser_results').show();
				$('userlist').addEvent('change',ajaxGetUserInfo);
			}
		}
	}
	req.open(null, DIR_WEB_ROOT+'/include/ajax/insertUser.php', true);
	req.send( { search:search } );
	return false;

}

function ajaxGetFriends(){
	var req = new JsHttpRequest();
	$('userlist').set('html','');			
	req.onreadystatechange = function() {
		if (req.readyState == 4) {
			if (req.responseJS.bStateError) {
				msgErrorBox.alert(req.responseJS.sMsgTitle,req.responseJS.sMsg);				
			} else {				
				req.responseJS.found.each(function(item, index){
					$('userlist').set('html','<option value="'+item+'">'+item+'</option>');
				});
				$('insertuser_results').show();
				$('userlist').addEvent('change',ajaxGetUserInfo);
			}
		}
	}
	req.open(null, DIR_WEB_ROOT+'/include/ajax/insertUser.php', true);
	req.send( { task: 'getFriends' } );
	return false;
}

function ajaxGetUserInfo(){
	var req = new JsHttpRequest();
	var login = $('userlist').get('value');
	req.onreadystatechange = function() {
		if (req.readyState == 4) {
			if (req.responseJS.bStateError) {
				msgErrorBox.alert(req.responseJS.sMsgTitle,req.responseJS.sMsg);				
			} else {				
				$('userPreview').set('html',req.responseText);
			}
		}
	}
	req.open(null, DIR_WEB_ROOT+'/include/ajax/insertUser.php', true);
	req.send( { task: 'getInfo',search: login } );
	return false;
}



AJAX-Обработчик:
Создать файл /include/ajax/insertUser.php


<?

set_include_path(get_include_path().PATH_SEPARATOR.dirname(dirname(dirname(__FILE__))));
$sDirRoot=dirname(dirname(dirname(__FILE__)));
require_once($sDirRoot."/config/config.ajax.php");

$found = array();
$bStateError=true;
$sText='';
$sMsg=$oEngine->Lang_Get('system_error');
$sMsgTitle=$oEngine->Lang_Get('error');
$task = @$_REQUEST['task'];
$search = @$_REQUEST['search'];

if ($oEngine->User_IsAuthorization()) {
	switch($task){
		case 'getFriends':
			$oUserCurrent=$oEngine->User_GetUserCurrent();
			$friendList = $oUserCurrent->User_GetUsersFrend($oUserCurrent->getId());
			if(count($friendList)>0){
				foreach($friendList AS $friend){
					$found[] = $friend->getLogin();
				}
				$bStateError=false;
				$sMsgTitle='';
				$sMsg='';		
			}else{
				$sMsgTitle=$oEngine->Lang_Get('error');
				$sMsg=$oEngine->Lang_Get('friends_empty');
			}
		break;
		
		case 'getInfo':
			if(strlen($search)<3){
				$sMsgTitle=$oEngine->Lang_Get('error');
				$sMsg=$oEngine->Lang_Get('registration_login_error');		
			}else{
				$oUserCurrent=$oEngine->User_GetUserCurrent();
				$user = $oUserCurrent->User_GetUserByLogin($search);
				if($user){
					echo '<img src="'.$user->getProfileAvatarPath(100).'">
					
					'.$user->getProfileName().'
					';
					$bStateError=false;
					$sMsgTitle='';
					$sMsg='';		
				}else{
					$sMsgTitle=$oEngine->Lang_Get('error');
					$sMsg=$oEngine->Lang_Get('user_empty');
				}			
			}
		break;
		
		default:
			if(strlen($search)<3){
				$sMsgTitle=$oEngine->Lang_Get('error');
				$sMsg=$oEngine->Lang_Get('registration_login_error');		
			}else{
				$oUserCurrent=$oEngine->User_GetUserCurrent();
				$userList = $oUserCurrent->User_GetUsersByLoginLike($search,30);
				if(count($userList)>0){
					foreach($userList AS $user){
						$found[] = $user->getLogin();
					}
					$bStateError=false;
					$sMsgTitle='';
					$sMsg='';		
				}else{
					$sMsgTitle=$oEngine->Lang_Get('error');
					$sMsg=$oEngine->Lang_Get('user_empty');
				}			
			}
		break;
	}
	
} else {
	$sMsgTitle=$oEngine->Lang_Get('error');
	$sMsg=$oEngine->Lang_Get('need_authorization');
}

$GLOBALS['_RESULT'] = array(
"bStateError"     => $bStateError,
"found"     => $found,
"sMsgTitle"   => $sMsgTitle,
"sMsg"   => $sMsg
);

?>


Вставка тега user в текст:
Файл /templates/skin/new/js/panel.js
Тут надо добавить метод insertUser:
insertUser: function(obj,login){
		obj=$(obj);
		this.putText(obj,'<user>'+login+'</user>');
		hideUserForm();
	}


Правила фильтрации тэгов:
Файл /classes/modules/sys_text/Text.class.php
В разрешенные теги добавить тег «user».
Добавить метод userParser
public function UserParser($sText) {
		return preg_replace("/<user>(.*)<\/user>/Ui","<a href=\"/profile/$1\" class=\"user\" target=_blank>$1</a>",$sText);
	}

и его вызов в методе Parser:
$sResult=$this->UserParser($sResult);


В css для красоты:
a.user {
color: #999; 
padding: 5px 0; 
background: url(../images/icons.gif) no-repeat scroll 0 -101px; padding-left: 12px; 
}

Должно получиться вот так:


В итоге все теги вида
<user>UserName</user>
будут заменяться ссылками на профиль с классом «user».

UPD:
Если необходима проверка на присутствие пользователя в базе, то функция парсера примет вид:
Файл /classes/modules/sys_text/Text.class.php

	public function UserParser($sText) {
		if (preg_match_all("/<user>(.*)<\/user>/Ui",$sText,$aMatch)) {
			$oEngine = Engine::getInstance();
			foreach ($aMatch[1] as $key => $str) {
				$oUser = $oEngine->User_GetUserByLogin($aMatch[1][$key]);
				!$oUser ? $aMatch[1][$key] = '' : $aMatch[1][$key] = '<a href="/profile/'.$aMatch[1][$key].'" class="user" target=_blank>'.$aMatch[1][$key].'</a>';
				$sText=str_replace($aMatch[0][$key],$aMatch[1][$key],$sText);
			}
		}
		return $sText;
	}

76 комментариев

avatar
Не помешала бы перед вставкой проверка на существование юзера в базе. Просмотрел код по диагонали, такого не увидел.
avatar
Согласен, поправлю
avatar
Написал проверку. Правда не уверен, что грамотно :)
avatar
для чего это применимо?, серьезно, не понял…
  • p12
  • 0
avatar
Навеяно редактором на Я.ру
avatar
полезная штука. там, к примеру, можно написать «уважаеиый user», и другие могут посмотреть к кому идет обращение=)
хех.
avatar
Добавить бы еще обработчик при постинге, чтобы пользователю приходило сообщение что о нем написали:)
avatar
Не могу пока сообразить как это сделать. Может кто подскажет?)
avatar
1. Делаем ссылку на пользователя без использования тегов (без символов
< >
напр, [user=benone]
2. Перед постингом топика, цепляем хук (как использовать можно найти, используя поиск)
3. В хуке берем текст топика, ищем в нем регуляркой наши ссылки на пользователей (похожие регулярки есть в модуле sys_text). Имя пользователя не может включать в себя всякие левые теги.
4. Отсылаем пользователям приватки типа «О вас упомянули в топике..»
5. Заменяем нашу ссылку [user=benone] на
<a href="...


Усё
avatar
Отсылаем пользователям приватки

С механизмом отправки я как раз еще не разобрался)
А чем плох тег «user»?
avatar
С механизмом отправки я как раз еще не разобрался)
trac.assembla.com/livestreet/changeset/342
public function SendTalk($sTitle,$sText,$oUserFrom,$aUserTo,$bSendNotify=true) { 

А чем плох тег «user»?
Тем что он будет резаться Jevix'ом
avatar
А почему бы не сделать исключение?
avatar
Можно сделать исключение)
Только в моем случае всё будет реализовано без правки кода livestreet, через хуки.
avatar
Пасиб буду пробовать. Я в список разрешенных тегов добавил user, не режет
avatar
Я бы не стал у себя делать это похожим на html-тег.
Зачем путать :)
avatar
Ну это уже дело вкуса)
avatar
Не будет ли большей путаницей часть тегов делать похожими, а часть — нет? Тот же как, например, использует угловые скобки.

Лично я за единообразие. Тем более, что большая часть пользователей далеки от html и довольствуются тем, что им предоставляет редактор.

По хорошему, лучше вообще скрыть все теги в окне редактирования поста/комментария и показывать сразу их интерпретацию, без предпросмотра. Как на той же респективе, например.
avatar
не как, а кат, разумеется
avatar
Кат — первый и последний пример:)

Вообще, да. Дело вкуса.
avatar
Кстати в стандартном редакторе я не заметил квадратных скобок :)
avatar
Потому что в нем всё кроме ката html
avatar
втч html 5:) (video)
avatar
Видимо, Кирилл — фанат TMCE ;-)
avatar
О ужас ) А зачем такое отслеживать?
avatar
Ну чтобы вапще круто было :)
avatar
Пользователи будут чахнуть от такой «накрутки» Чувства Собственной Значимости. Это же можно выводить цифрой на странице с профайлом.
avatar
С цифрой помойму перебор)
avatar
Двачую, с цифрой тонко же
avatar
Дополню:
Даже не с цифрой, а с вертикальной полоской, которая будет удлиняться, и становиться (по мере увеличения рейтинга «внимания к персоне») золотой и загадочно мерцающей.
avatar
Ето надо поле в БД заводить тогда
avatar
годно! будет, чем померяться
avatar
Полоска непременно должна иметь embed-код и быть рядом с фотографией пользователя.
avatar
)))))
avatar
Мне интересно где и что обо мне пишут:)
avatar
Но ведь этот механизм не будет показывать, где о вас пишут. Он покажет, где на вас поставили ссылку через редактор.
avatar
Ну если при публикации отслеживать, то можно попробовать и адреса топиков в сообщении отправлять
avatar
Логично:)

Но если кнопка будет популярной, в основном, будут перечислины ссылки на профили. Я, например, стараюсь ссылаться.
avatar
*перечислены
avatar
супер, спасибо =)
никто не поблагодарил, афтар молодец )
avatar
Огромное спасибо! То, что доктор прописал :)
Идея с отображением «внимания к персоне» тоже очень понравилась :) Различные пи*ькомерные феньки всегда привлекали внимание юзеров :)
avatar
Файл /classes/modules/sys_txt/Text.class.php

sys_text*
avatar
Спасибо, исправил
avatar
И всё же у меня не получается сделать инсталлятор вашего мода для своей системы :(
avatar
Что не получается? Я вроде все моменты описал.
avatar
Великолепно! Самому этого порой не хватало, но все руки не доходили сделать.
avatar
У меня проблема. Когда подключаю
{include file='window_add_user.tpl' sToLoad='topic_text'}

не грузяться изображения. Пишет «системная ошибка… попробуйте позже»

Как побороть?
avatar
Не грузятся из файла или по ссылке?
avatar
Не грузилось при нажатии кнопки «вставить картинку» в редакторе. Т.е. открывается форма выбора изображения. Изображение выбераю и после нажатия «загрузить». Пишет «системная ошибка....»

Поправил сам. Вроде работает.

Что сделал? В файле /templates/skin/new/window_add_user.tpl
исправил строчку
<form method="POST" action="" enctype="multipart/form-data" id="form_upload_img" >

на

<form method="POST" action="" enctype="multipart/form-data" id="form_user_insert" >

avatar
Дада, я здесь забыл в описании поправить
avatar
Было бы не плохо еще знать что в lang-файл добавить :)
avatar
Что-то вроде:
'insertuser' => 'Вставка пользователя',
	'insertuser_username' => 'Имя пользователя',
	'insertuser_find' => 'Найти',
	'insertuser_friends' => 'Мои друзья',
	'insertuser_users' => 'Пользователи',
	'insertuser_submit' => 'Вставить',
	'insertuser_cancel' => 'Отмена',
avatar
Друзья, простите что не по делу спрашиваю тут.

Вот появляется форма добавления пользователя (аналог добавления картинки в топик), как и где убрать затемнение экрана за этой формой?

Все стили прибивал — не в стилях дело.

avatar
Цвет прописан по дефолту в самом mootools в плагине StickyWin.Modal.js
(по умолчанию фон #333 и прозрачность 0.8)

Чтобы изменить эти настройки нужно открыть файл (по примеру стандартного шаблона)
templates/skin/new/js/other.js и найти в нем строку:

winFormImgUpload=new StickyWin.Modal({content: $('window_load_img'), closeClassName: 'close-block', useIframeShim: false, modalOptions: {modalStyle:{'z-index':900}}});


в конце перед последней закрывающей скобкой вставить переопределяющие свойства, вот так:

winFormImgUpload=new StickyWin.Modal({content: $('window_load_img'), closeClassName: 'close-block', useIframeShim: false, modalOptions: {modalStyle:{'z-index':900}}, maskOptions: {style: {'background-color':'red', opacity:0.7} } });


А именно код
maskOptions: {style: {'background-color':'red', opacity:0.7} }


Где можно задать свойства CSS
avatar
Спасибо, нашлось уже с «01 июля 2009, 12:35» ;-)
avatar
Ну может все равно будет кому-то полезно :)
avatar
может напишите фак для 0.4.2?
avatar
Так это и было для 0.4.2 :)
avatar
В плане всё с начала.
В шапке для 0.3 расписано всё
avatar
Не понял вопроса.

Комментарий валиден для 0.4.2
avatar
Опишите как реализовать добавление пользователей в комментарии. В шапке описано под 0.3, но хочется увидеть под 0.4.2
avatar
Вы читали на какой вопрос был дан мой ответ?
avatar
Еще не хватает стилей:

.w50p {width: 180px;} 
.rd {float: right;}
.ld {float: left;}
.br {clear: both;}
avatar
Сделал вроде все как описано — вставляется только имя пользователя, а не ссылка на профиль. Подскажите куда копать люди.
avatar
В сторону classes/modules/sys_text/Text.class.php
avatar
Спасибо огромное за подсказку, точно забыл добавить в разрешенные теги «user».
avatar
А для того чтобы это дружило с поддоменами парсер становится вот таким

	public function UserParser($sText) {
                if (preg_match_all("/<user>(.*)<\/user>/Ui",$sText,$aMatch)) {
                        $oEngine = Engine::getInstance();
                        foreach ($aMatch[1] as $key => $str) {
                                $oUser = $oEngine->User_GetUserByLogin($aMatch[1][$key]);
                                !$oUser ? $aMatch[1][$key] = '' : $aMatch[1][$key] = '<a href="http://'.$aMatch[1][$key].'.'.SERVER_NAME.'/profile/" class="user" target=_blank>'.$aMatch[1][$key].'</a>';
                                $sText=str_replace($aMatch[0][$key],$aMatch[1][$key],$sText);
                        }
                }
                return $sText;
        }
avatar
ОШИБКА!
Даже если найденных пользователей или друзей несколько в списке выводится один.
Как это поправить?
avatar
Аналогично. Находит всего одного юзера. хотя их много.
+ не работает меню выбора списка друзей.
При нажатии «Мои друзья», пишет — NOT_FOUND_LANG_TEXT — , и нет окошка для выбора.

Как поправить?
  • _et
  • 0
avatar
Ошибка с окошком для вывода друзей глючит- если нет в списке друзей.
Но показывает все равно всего одного человека.
avatar
в языковой файл добавить что-то типа
'friends_empty' => 'У Вас нет друзей...',
avatar
function ajaxFindUsers(search){
        var req = new JsHttpRequest();
        $('userlist').set('html','');
        req.onreadystatechange = function() {
                if (req.readyState == 4) {
                        if (req.responseJS.bStateError) {
                                msgErrorBox.alert(req.responseJS.sMsgTitle,req.responseJS.sMsg);
                        } else {
                        		var _html = '';
                                req.responseJS.found.each(function(item, index){
	                                _html = _html + '<option value="'+item+'">'+item+'</option>';
                                });
                                $('userlist').set('html',_html);
                                $('insertuser_results').show();
                                if (Browser.Engine.trident) 
                                	$('userlist').addEvent('click',ajaxGetUserInfo);
                                else $('userlist').addEvent('change',ajaxGetUserInfo);
                        }
                }
        }
        req.open(null, DIR_WEB_ROOT+'/include/ajax/insertUser.php', true);
        req.send( { search:search } );
        return false;
}
avatar
Спасибо.
avatar
для друзей аналогично
function ajaxGetFriends(){
        var req = new JsHttpRequest();
        $('userlist').set('html','');
        req.onreadystatechange = function() {
                if (req.readyState == 4) {
                        if (req.responseJS.bStateError) {
                                msgErrorBox.alert(req.responseJS.sMsgTitle,req.responseJS.sMsg);
                        } else {
                        		var _html = '';
                                req.responseJS.found.each(function(item, index){
	                                _html = _html + '<option value="'+item+'">'+item+'</option>';
                                        $('userlist').set('html','<option value="'+item+'">'+item+'</option>');
                                });
                                $('userlist').set('html',_html);
                                $('insertuser_results').show();
                                if (Browser.Engine.trident)
                                	$('userlist').addEvent('click',ajaxGetUserInfo);
                                else $('userlist').addEvent('change',ajaxGetUserInfo);
                        }
                }
        }
        req.open(null, DIR_WEB_ROOT+'/include/ajax/insertUser.php', true);
        req.send( { task: 'getFriends' } );
        return false;
}
avatar
А че в SVN не добавили?
avatar
Под 0.4.2 не получается, может кто в плагин уже оформил?
  • dddr
  • 0
avatar
Может кто под 0.4.2 реализовать?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.