Разделы

Рейтинг
+6.83
голосов:
6
avatar

Быстрые решения  

[REVO] getResources и tvFilters и операторы '==', '!=', '<=', '>=', '<>', '>', '<', '='

Вчера вечером, был пост, где человек хочет отфильтровать по оператору '<>'. Казалось, всё просто, но система втыка, не дала свой результат. Меня стала мучить мысля… что, не так, вскрыв getResources, я заметил, что в tvFilters '==' — это не оператор, а разделитель.

( Читать дальше )

Заставляем eForm исполнять сниппеты в шаблоне формы

Ситуации, когда требуется вывести какой-либо select в шаблон формы eForm заполнив его данными из базы нередки. Стандартный способ, описанный в документации к eForm — использование &eformOnBeforeFormParse и последующие пляски с бубном.
Если просто вставить вызов сниппета в код формы, то сниппет будет интерпретирован уже после того, как eForm разберет шаблон, и он не будет учтен.

Мне совершенно неочевидно, почему разработчики eForm не позволили использовать шаблонизатор modx для создания формы, но, как оказалось, мы легко можем сделать это сами.


( Читать дальше )

PlusCatalog - микро-каталог "на коленке" [Evo]

1. Постановка задачи.

Для одного из сайтов понадобилось создавать ресурсы из 2-3 строк текста + фото. Количество таких ресурсов может в перспективе стать запредельным. Использовать для хранения этих данных таблицу в БД modx я посчитал слишком расточительным, да и дерево документов — не резиновое.

Единственно возможным вариантом является хранить эти записи в отдельной таблице в БД. Структуру таблицы можно задать именно такую, которая нужна. Для записи данных в таблицу, а также для их правки/удаления, можно использовать модуль.

Однако, сам по себе сайт для редактора получился достаточно простым и логичным. Я ощутил, что не имею морального права заставлять пользователя часть материалов добавлять через модуль, а часть — через документы modx. Следовательно, нужен интерфейс для работы с внешней таблицей, причем этот интерфейс должен разместиться прямо в дереве документов.



( Читать дальше )

Определения браузера

Иногда, (в данной ситуации у меня возникла необходимость) нужно вывесть картинку или любой тег в зависимости от версии браузера. В данный момент мне нужно было вывести в IE6 картинку без тени. Можно было имено для ослика 6 написать, но написал более расширенный снипет, может кому пригодиться.
Допустим хотим вывести картинку logo.png, а если IE6 то logo_ie6.png. Демо. — логотип

( Читать дальше )

Поиск в AjaxSearch по словосочетанию

Есть на сайте небольшой каталог, реализованных в виде документов.
Требовалось сделать поиск, чтобы по фразе «стол 7 футов» он действительно искал только столы 7 футов.
При уменьшении минимальной длины слова с 3 до 1 и режиме поиска allwords выводит очень много не релевантных данных, например «Стол / пирамида „Grace“ 12 футов (орех пекан)», а цифра 7 в цене нашлась или еще где (поиск идет по pagetitle и content).
Т.е. в данном случае слово «футов» это специальных случай и при встрече в поиске нужно заставить AjaxSearch воспринимать часть строки "%размер% футов" как одно слово, а не 2.

Решение простое. Нужно сделать динамический фильтр, если в поиске встречается слово «футов» (например 7 футов), то исключить все документы, где в pagetitle не встречается «7 футов». Для этого создадим сниппет ASFilter:

<?php
$SearchString = isset($_REQUEST['search'])?$_REQUEST['search']:'';
$result = '';
if ($SearchString!='') {
  $SearchString = mb_strtolower($SearchString,$modx->config['modx_charset']);
  $matches = array();
  if (preg_match('/\S+\s+футов/',$SearchString,$matches)) {
    $SizeString = $matches[0];
    $result='pagetitle,'.$SizeString.',9';
  }
}
return $result;
?>


И вставить его в вызов AjaxSearch в параметр filter

[!AjaxSearch? .... &filter=`[!ASFilter!]`!]


Теперь при поиске «стол 7 футов» ищет только столы 7 футов. Таким способом можно добавить и другие специальные слова.

"Мне нравится" для фотографий

Создаем сниппет imagevote
<?php
global $modx;
$modx->db->connect();
$pid = $modx->documentIdentifier;;
      $ip=$_SERVER['REMOTE_ADDR'];
      if($_GET['id'])
      {
      if((is_numeric($_GET['id'])) and ($_GET['id'] > 0)){
      $id=$_GET['id'];
      $ip_sql=mysql_query("SELECT ip_add FROM image_IP WHERE img_id_fk='$id' AND ip_add='$ip'");
      $count=mysql_num_rows($ip_sql);
      if($count==0)
      {
      $sql = "UPDATE modx_maxigallery SET love=love+1 WHERE id='$id'";
      mysql_query( $sql);
      $sqlin = "insert into image_IP (ip_add,img_id_fk) values ('$ip','$id')";
      mysql_query( $sqlin);
       $modx->webAlert('Спасибо за Ваш голос','[~'.$pid.'~]');
      }
      else
      {
      $modx->webAlert('Вы уже голосовали за это Фото','[~'.$pid.'~]');
      }
}
else
{
      $modx->webAlert('Что то Вы запрос ручками поменяли!','[~'.$pid.'~]');
}
}
?>

Делаем запрос SQL
CREATE TABLE image_IP(
ip_id INT PRIMARY KEY AUTO_INCREMENT,
img_id_fk INT,
ip_add VARCHAR(40),
FOREIGN KEY(img_id_fk)
REFERENCES modx_maxigallery(id));

Правим в файле gallerypicturetpl.html это
[+maxigallery.embedtype:is=``:then=`
<a href="[+maxigallery.picture_link_url+]">
`+]
<img src="[(base_url)][+maxigallery.path_to_gal+]tn_[+maxigallery.picture.filename+]" class="thumbnail" title="[+maxigallery.picture.title:htmlent+] [+maxigallery.strings.click_to_zoom+]" alt="[+maxigallery.picture.title:htmlent+] [+maxigallery.strings.click_to_zoom+]" />
</a>

На это
[+maxigallery.embedtype:is=``:then=`
<div>
<div class="box" align="left">
<a href="[~[*id*]~]?id=[+maxigallery.picture.id+]" class="love" id="[+maxigallery.picture.id+]">
<span class="on_img" align="left"> [+maxigallery.picture.love+] </span>
</a>
</div>
`+]
<img src="[(base_url)][+maxigallery.path_to_gal+]tn_[+maxigallery.picture.filename+]" class="thumbnail" />
</div>

И наконец добавим стили
.box
{
background-color:#303030; padding:6px;
height:17px;
}
.on_img
{
background-image:url(http://test.finessco.hdd1.ru/on.gif);
background-repeat:no-repeat;
padding-left:35px;
cursor:pointer;
width:60px;
}
.over_img
{
background-image:url(http://test.finessco.hdd1.ru/over.gif);
background-repeat:no-repeat;
padding-left:35px;
cursor:pointer;
width:60px;
}

Теперь добавим TV gallereya
||[!MaxiGallery? &display=`normal` &pics_per_row=`2` &max_thumb_size=`310` &max_pic_size=`0` &thumb_use_dropshadow=`1` &pic_use_watermark=`0` ?=`ru` !][!imagevote!]


P.S. И снова я выкладываю сниппет без использования API. Пример работы
В этом сниппете пользователь может добавить свой голос к понравившейся фотографии один раз, думаю сделать, чтобы голос этот можно было забрать назад. Но это вроде бы пока никому не надо)
Если найдете ошибки или уязвимости, сообщите пожалуйста мне.

P.P.S. И еще добавил голосование за каждую страницу, где можно отдать голос и его забрать.

Redirect Revo

Вот решил поделиться, может кому пригодиться.
Сниппет ( я назвал redirectId)
//redirect the user to the dutch pages
  $sl = 0;
  $ssl = 'full';
  if($http)$ssl = $$http;
  if($sleep)$sl = $sleep;
  header('Refresh: '.$sl.'; URL='.$modx->makeUrl($id, '', '', $ssl));



( Читать дальше )

Личные сообщения

Вот сниппет PM:
<?php
$modx->db->connect();
if ( !isset( $_GET['action'] ) ) $_GET['action'] = 'showInBox';
$actions = array( 'showInBox',
                             'showOutBox',
		             'sendMsgForm' );
if ( !in_array( $_GET['action'], $actions ) ) $_GET['action'] = 'showInBox';
switch ( $_GET['action'] )
{
  case 'showInBox':  
    $content = showInBox( $pageTitle );
	break;
  case 'showOutBox':     
    $content = showOutBox( $pageTitle );
	break;
  case 'sendMsgForm':     
    $content = sendMsgForm( $pageTitle );
	break;
    default:
    $content = showInBox();   
}
$menu = getMainMenu();
$html = file_get_contents( 'p.html' );
$html = str_replace( '{menu}', $menu, $html );
$html = str_replace( '{content}', $content, $html );
echo $html;
function getMainMenu()
{
  $html = '<table>'."\n";
  $html = $html.'<tr valign="left">'."\n";
  $html = $html.'<td width="100px"><a class="header" href="?action=showInBox">Входящие</a>  </td>'."\n";
  $html = $html.'<td width="100px"><a class="header" href="?action=showOutBox">Исходящие</a></td>'."\n";
  $html = $html.'<td width="200px"><a class="header" href="?action=sendMsgForm">Отправить сообщение</a></td>'."\n";
  $html = $html.'</tr>'."\n";
  $html = $html.'</table>'."\n";
  echo $html;
}
function showInBox()
{
global $modx;
  $toUser =  $modx->getLoginUserName();
  $toUserid = $modx->getLoginUserID();
  $res=mysql_query("SELECT * FROM `messages` WHERE to_user = '".$toUser."' AND id_rmv!='".$toUserid."'  ");
  echo "<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\">
  <tr style=\'border: solid 1px #000\'>
  <td><b>Кому</b></td>
  <td align=\"center\"><b>От кого</b></td>
  <td align=\"center\"  width=\"80px\"><b>Когда</b></td>
  <td align=\"center\"><b>Тема сообщения</b></td>
  <td align=\"center\"><b>Сообщение</b></td>
  <td align=\"center\"><b>Статус</b></td>
  <td align=\"center\"><b>Удалить</b></td>
  </tr>";
    while($row=mysql_fetch_array($res))
   {
if ($row['viewed'] == 0)
{
$stat = 'Новое';
}else{
$stat = 'Прочитанное';
}
    $html = $html. "<tr>\n";
    $html = $html. "<td width='80px'>".$row['to_user']."</td>\n";
    $html = $html. '<td width="80px"><a href="'.'?action=sendMsgForm&toUser='.$row['from_user'].'&subject='.$row['subject'].'">'.$row['from_user'].'</a></td>'."\n";
    $html = $html. "<td width='140px'>".$row['sendtime']."</td>\n";
    $html = $html. '<td width="115px"><a href="'.'?idMs='.$row['id_msg'].'" >'.$row['subject'].'</a></td>'."\n";
    $html = $html. "<td width='405px'>".$row['message']."</td>\n";
    $html = $html. "<td width='80px'>".$stat."</td>\n";
$html = $html.'<td align="center"><a href="?action=showInBox&deleteMsg&idMsg='.$row['id_msg'].'">Удалить</a></td>'."\n";
$idMsg = $_GET['idMsg'];
if ( $row['id_rmv'] == 0 ) 
$query1 = "UPDATE `messages` SET id_rmv=".$toUserid." WHERE id_msg=".$idMsg;
 else   
$query1 = "DELETE FROM `messages` WHERE id_msg=".$idMsg;
$res1 = mysql_query( $query1 );
}
    $html = $html. ("</table>\n");
$idM = $_GET['idMs'];
  if ( $row['viewed'] != 1 ) {
    $query = "UPDATE `messages` SET viewed=1 WHERE id_msg=".$idM;
	mysql_query( $query );
}
echo $html;
}
function showOutBox()
{
global $modx;
$fromUser =   $modx->getLoginUserName();
$fromUserid = $modx->getLoginUserID();
$res = mysql_query("SELECT * FROM `messages` WHERE from_user = '".$fromUser."' AND id_rmv!='".$fromUserid."'  ");
   echo "<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\">
  <tr style=\'border: solid 1px #000\'>
  <td align=\"center\"><b>От кого</b></td>
  <td><b>Кому</b></td>
  <td align=\"center\"><b>Когда</b></td>
  <td align=\"center\"><b>Тема сообщения</b></td>
  <td align=\"center\"><b>Сообщение</b></td>
  <td align=\"center\"><b>Статус</b></td>
  <td align=\"center\"><b>Удалить</b></td>
  </tr>";
    while($row = mysql_fetch_array($res))
   {
if ($row['viewed'] == 0)
{
$stat = 'Ожидает';
}else{
$stat = 'Прочитанно';
}
    $html = $html. "<tr>\n";
    $html = $html. "<td width='80px'>".$row['from_user']."</td>\n";
    $html = $html. "<td width='80px'>".$row['to_user']."</td>\n";
    $html = $html."<td width='140px'>".$row['sendtime']."</td>\n";
    $html = $html. "<td width='115px'>".$row['subject']."</td>\n";
    $html = $html."<td width='405px'>".$row['message']."</td>\n";
    $html = $html. "<td width='80px'>".$stat."</td>\n";
$html = $html.'<td align="center"><a href="?action=showOutBox&deleteMsg&idMsg='.$row['id_msg'].'">Удалить</a></td>'."\n";

$idMsg = $_GET['idMsg'];
 if ( $row['id_rmv'] == 0 ) 
$query2 = "UPDATE `messages` SET id_rmv=".$fromUserid." WHERE id_msg=".$idMsg;
 else   
$query2 = "DELETE FROM `messages` WHERE id_msg=".$idMsg;
$res2 = mysql_query( $query2 );
}
    $html = $html. ("</table>\n");

echo $html;

}
function sendMsgForm()
{
global $modx;
$from =  $modx->getLoginUserName();
$fromid = $modx->getLoginUserID();
$to = $_POST[toUser];
$subject = $_POST[subject];
$message = $_POST[message];
  if ( empty( $_POST['toUser'] ) or
       empty( $_POST['subject'] ) or
       empty( $_POST['message'] ) )
  {
$text = ($_GET['toUser']);
$text1 = ($_GET['subject']);
echo '<form action="" method="POST" name="sendMessageForm" id="sendMessageForm">
<table class="showTable">
<tr>
<td colspan="2"><b>Отправить личное сообщение</b></td>
</tr>
<tr>
<td>Для пользователя:</td>
<td><input style="width: 300px;" maxlength="60" name="toUser" type="text" value="'.$text.'" /></td>
</tr>
<tr>
<td>От пользователя:</td>
<td>
'.$from.'
</td>
</tr>
<tr>
<td>Заголовок сообщения:</td>
<td><input type="text" name="subject" maxlength="60" value="'.$text1.'" style="width:300px" /></td>
</tr>
<tr>
<td>Сообщение</td>
<td>
<textarea name="message" cols="40" rows="5" ></textarea>

<input type="submit" name="submitForm" value="Отправить" /> 
</td>
</tr>
</table>
</form>';
  }
  else
  {
  $query = "INSERT INTO messages (to_user, from_user, sendtime, subject, message, id_rmv, viewed) VALUES ('$to', '$from', NOW(), '$subject', '$message', '0', '0')";
  $res = mysql_query( $query );
  echo "Сообщение успешно отправленно!";
  }
}
?>

Все сообщения будут в отдельной таблице messages
CREATE TABLE IF NOT EXISTS `messages` (
  `id_msg` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `to_user` varchar(50) NOT NULL,
  `from_user` varchar(50) NOT NULL,
  `sendtime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `subject` varchar(255) NOT NULL DEFAULT '',
  `message` text NOT NULL,
  `id_rmv` int(10) NOT NULL DEFAULT '0',
  `viewed` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id_msg`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=1 ;


Ну и шаблон должен быть:
<div align="left">
{menu}
</div>


<div align="left">	
{content}
</div>

Это пока что черновая версия. (Часть форума для modx)

Аудио для сайтов (mp3)

Была задача сделать сайт для одной певицы. И нужно было сделать загрузку песен в альбомы как можно проще. Для этих целей был написан сниппет: [!myz!]
<?php
if (!isset($id)) $id = $modx->documentIdentifier;
if (!is_dir($modx->config['base_path'].'assets/mp3/'.$id)) {return false;}
$i=0;
foreach (glob($modx->config['base_path']."assets/mp3/$id/*.{mp3}", GLOB_BRACE) as $sTmp1) {
$aRow1[] = '<div id="audioplayer'.($i+1).'"></div> '.basename($sTmp1).'
<script type="text/javascript">
var flashvars = {"uid":"audioplayer'.($i+1).'","st":"audio12-837.txt","file":"[(base_url)]assets/mp3/'.$id.'/'.basename($sTmp1).'"};
var params = {id:"audioplayer'.($i+1).'",allowScriptAccess:"always"}; 
new swfobject.embedSWF("uppod.swf", "audioplayer'.($i+1).'", "400", "35", "9.0.115", false, flashvars, params);
</script>
';
$i++;
}
if (is_array($aRow1)) {
echo 'Альбом: ';
echo '<strong>';
echo '[*pagetitle*]    |    ';
echo '</strong>';
echo 'Песен в альбоме: ';
echo '<strong>';
echo  count($aRow1) ;
echo '</strong>';
echo ' штук';
echo '
';
echo '<hr>';
return implode('', $aRow1);
}
?>


в шаблоне страниц, где будут выводиться альбомы прописать
<script language="JavaScript" src="js/uppod_player.js"></script>
<script language="JavaScript" src="js/swfobject.js"></script>


Для заполнения альбома надо создать папку в директории assets/mp3
с названием по номеру документа, где выводится этот сниппет. Все песни из этой папки будут выведены на страницу.

При завершении одной композиции начинает играть следующая.

В архиве все необходимые скрипты.
Файлы для аудио

Простая галерея для больших каталогов

Была задача заполнить каталог недвижимости, и к каждому объекту порядка 20 фото. С учетом того, что объектов более 2000, было очень лень заполнять руками всю эту прорву. Родилась идея, написать сниппет, который будет сканировать определенную директорию и выводить фотографии из нее. Исходя из того, что директорий должно быть несколько, но в одной родительской, имена внутренним директориям должны быть присвоены такие же, как id страниц, на которых нужно вывести фото.
И вот он сниппет Gallery:
<?php
if (!isset($id)) $id = $modx->documentIdentifier;
if (!is_dir($modx->config['base_path'].'assets/images/'.$id)) {return false;}
// получаем список файлов


foreach (glob($modx->config['base_path']."assets/images/$id/*.{jpeg,jpg,gif,png}", GLOB_BRACE) as $sTmp) {
        $aRow[] = '<li><a href="[(base_url)]assets/images/'.$id.'/'.basename($sTmp).'"><img src="[(base_url)]assets/images/'.$id.'/'.basename($sTmp).'"></a><span>'.basename($sTmp).'</span></li>';
}

if (is_array($aRow)) {
        return implode('', $aRow);
}
?>

Но это все хотелось бы оформить, и я прикрутил pikachoose.com/demo/ к сниппету.
Вот это между head
<link type="text/css" href="gallery.css" rel="stylesheet" />

		<script type='text/javascript' src='js/jquery.js'></script>
		<script type="text/javascript" src="js/jquery.pikachoose.js"></script>
		<script type="text/javascript" src="js/jquery.jcarousel.min.js"></script>
		<script language="javascript">
			<!--
			$(document).ready(
				function (){
					$("#pikame").PikaChoose();

					$("#pikame").jcarousel({scroll:4,					
						initCallback: function(carousel) 
						{
					        $(carousel.list).find('img').click(function() {
					        	//console.log($(this).parents('.jcarousel-item').attr('jcarouselindex'));
					            carousel.scroll(parseInt($(this).parents('.jcarousel-item').attr('jcarouselindex')));
					        });
					    }
				    });

				});
				
			-->
</script>

а сам вывод результатов:
<div class="pikachoose">
<ul id="pikame" class="jcarousel-skin-pika">
[!Gallery!]
</ul>
</div>

К сожалению пока что не разобрался как ресайзить фотографии при выводе, поэтому просто подготавливаю фото перед заливкой по ftp. По умолчанию тут 413px × 310px
Вот все файлы:Файлы для галереи
Огромная благодарность: makis83

Если вдруг будут предложения по ресайзу, пишите тут. Будем совместными усилиями дорабатывать.