Урок 1: Создание AJAX запросов, используя MODx API

Задача:
Сдалать отправку данных на сервер получив ответом результат выполнения Ditto с фильтром по данным переданым в _POST

1) Создадим структуру файлов. Наш сниппет назовём mysnip.php

В версии выше 1.0.8:
— прописываем путь к папке snippets/наш код
было — $allowed_dirs = array('assets/snippets/ajaxSearch/','наш путь');
стало — $allowed_dirs = array('assets/snippets/ajaxSearch/','assets/snippets/mysnip/mysnip.php');

В версиях ниже данных действий не надо.

2) создаём файл assets/snippets/mysnip/mysnip.php с кодом:


<?php
define('MODX_API_MODE', true);
include_once 'manager/includes/config.inc.php';
include_once 'manager/includes/document.parser.class.inc.php';
$modx = new DocumentParser;
$modx->db->connect();
$modx->getSettings();
startCMSSession();
$modx->minParserPasses=2;

echo $modx->RunSnippet('Ditto',array('parent'=>$modx->db->escape($_POST['parent'])));
// вот тут мы выполняем сниппет по нашим данным
?>


3) Приём готов, делаем отправку:

На сайте (обьяснять как работать с jQuery не буду думаю уже знакомы просто приведу пример) где требуется на событие клика вешаем отправку $.ajax



<a class="our_link" href="" data-id="4">Получить дочерние документы ресурса №4</a>

<script>
$('.our_link').click(function(){ //вешаем на событие клика по ссылке
    $.ajax({          // $.ajax - jQuery механизм упрощающий построения AJAX запросов
		type:'POST',               //тип данных которые передаём POST
		url: '/index-ajax.php',    // это уже механизм MODx
		cache: false,               // не кешировать результаты
		data:{
			q:'assets/snippets/mysnip/mysnip.php',    //путь к нашему коду 
			parent:$(this).attr('data-id')           //переменая которую передаём
		},
		success:function(data){
			$('блок отображения результатов').html( data );    // data ответ тот сервера
			}
	});
	
	return false;     // блокируем переход по нажатой ссылке дабы не уйти со страницы
});
<script>


4) готово. У нас уже есть код на стороне клиента отправляющий ajax запрос и принимающий его, есть код на стороне сервера. Дальше от вас только желание разобраться и делать свои решения.

P.S.
Если будет востребовано (по количеству плюсиков), будет написан Урок 2: AJAX и парсинг строк и парсинг результатов сниппетов средствами MODx

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

avatar
Очень полезные мануал, будет для меня шпаргалкой по работе с ajax.
avatar
Как обычно, ставлю плюсик :)
avatar
Плюсиков уже на целый сериал :) Так что ждемс
avatar
Завтра будет новая задача и ёе решение )
avatar
а чем принципиально отличается от modx.im/blog/triks/383.html?
вы не подумайте что я с наездами) мне просто интересно!
avatar
1) использую встроенный инструмент специально созданный для AJAX запросов.
2) так как скрипт лежит в файле а не в виде исполняемого ресурса, время выполнения гоооораздо быстрее
3) В уроке дан лишь полезный код. который можно использовать как шаблон

думаю этого достаточно ))
Самое главное что подходы разные
avatar
проглядел что это на EVO. А на REVO имеет смысл подобное, пример кто нибудь может подбросить?
сейчас запускаю через снипет на отдельной странице — отдает где то 190-210 мс и 110-130 из кеша… как по вашему будет прирост с использованием отдельного файла?
avatar
однозначно да
avatar
А чем плох подход c die()?
Ведь если нужно будет получить ID, заголовок TV или еще что-то от документа намного сложнее это сделать.
Интересно было бы цифры услышать на сколько быстрее.
avatar
startCMSSession(); не обязателен в случае вывода ресурсов через Ditto, можно упразднить уровень сессий, а значит прирост к скорости получения ответа.
avatar
добрый день, а не могли бы вы показать код что бы просто вывести ditto через ajax без клика? с modx недавно, прошу сильно не пинать
avatar
А как ваш Ditto должен узнать когда ему выводиться?
avatar
а может быть есть какое то решение? поставить контейнер с id и в этом месте выводит список, статей например…
avatar
Решение, наверняка, есть. Задача не ясна.
Вы хотите «вывести ditto через ajax без клика». Хорошо, а в какой момент?
Аяксом сниппет вызывается при наступлении какого-то события. В данном случае — клик по определенной ссылке. А вы хотите при каком событии?
avatar
наверно на $(document).ready() )))))
avatar
Я тоже, предполагаю этот вариант, но все же интересно узнать чего хочет вопрошающий =)
avatar
в целях оптимизации! хочется что б ajax вывалил список ditto, робот не увидит, а пользователь увидит
avatar


скрипт в нужное для текста место.

ресурс №1 пустой шаблон в контенте:

[[Ditto?parents=`23` &tpl=`row.News`]]
avatar
блин ошибка. приеду напишу
avatar

<script>
$.ajax({
url:'[~10~]',  // 10 - Ditto вывод
cache:true,
type:'get',
success:function(data){
    document.write( $('<div>'+data+'</div>').html() );
}
})
</script>


а в ресурсе №10 просто, шаблон blank, в контенте [[Ditto? .....]]
avatar
сделал по вашему примеру, вроде заработало, но он вывел только этот список на белом фоне, сам сайт пропал
avatar
Вы лучше вот так сделайте
<div id="result"></div>
<script>
$(document).ready(function(){
$.ajax({
url:'[~10~]',  // 10 - Ditto вывод
type:'get',
success:function(data){
   $("#result").html(data);
}
})
})
</script>


и поставьте в то место, где нужен вывод списка в шаблоне.
Комментарий отредактирован 2013-10-23 12:22:46 пользователем webber
avatar
огромное спасибо, чет заработался) заработало!
и спасибо всем кто откликнулся!!!
avatar
а как в таком случае передать переменную parents в ditto? Пробовал таким вот образом, но ни чего не выводит
<div id="result"></div>
<script>
$(document).ready(function(){
$.ajax({
url:'[~228~]',
type:'POST',
data:{
      parent:$(this).attr('data-id')
},
success:function(data){
   $("#result").html(data);
}
})
})
</script>
avatar
а что вы имели в виду или хотели получить введя эту загадочную фразу
parent:$(this).attr('data-id')
в контексте приведенного вами кода?
avatar
хотелось передать в документ 228 id родителя, чтобы вывести дочек
содержимое 228: [!Ditto?tpl=`ajax.tpl` &extenders=`request`!]
структура доков такая
карта // открываем эту страницу
-Москва // на ней выводим area с этими документами
--дилер 1 // нужно вывести вот эти документы
--дилер 2 // при нажатии на Москву

вот пример www.baswool.ru/production/kupit/
Комментарий отредактирован 2014-03-04 04:20:28 пользователем jDeuterium
avatar
А вы указали в какое место документа выводить результат или скопировали предложенный код без изменений?
avatar
вот так сделал
<div id="result"></div>
<script>
$(document).ready(function(){
  $.ajax({
    url:'[~228~]',
    type:'get',
    success:function(data){
      $("#result").html(data);
    }
  })
});
</script>

на 228 [!Ditto?tpl=`ajax.tpl` &extenders=`request`!]
и выводится Записей не найдено
заместо ссылки использую
<area href="[~228~]?ditto_documents=[+id+]" class="our_link" title="[+longtitle+]" alt="" shape="poly" coords="[+coords+]" data-reveal-id="myModal" data-id="[+id+]">
avatar
Есть простейшие решения — создаете ресурс с пустым шаблоном (который выводит только [*content*] — например хоть со встроенным _BLANK) и в этом ресурсе в поле контента ставите вызов дитто [[Ditto? &startID=`` &display=`5`]]. А потом просто через аякс спрашиваете этот ресурс и его ответ вставляете в нужный div. Это если нет желания поупражняться с вырезанием нужных кусков в preg_match()
avatar
Именно для этого способа описывался подход тут preg_match не понадобится, только div в контенте.
avatar
Кстати, что меня смутило как-то в load — он похоже не генерирует запрос как ajax-запрос, т.е если подвешивать на плагин, то не распознается условие
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {}


Хотя, может чего и я накосячил, но добиться от .load ответа аналогичного .ajax не удалось. А .ajax грузит полностью, а не отдельным дивом не получается у него.

С другой стороны так и не ясно, то ли .load грузит всю страницу и потом вырезает сам нужный селектор, то ли он грузит только часть страницы. Есть подозрение, что все-таки грузит и потом вырезает.

Аналогичный функционал можно добиться и в .ajax чтобы взять только то, что лежит внутри дива с классом selector

success: function(data) { 
	var resp=$(data);
        var text=resp.find(".selector").html();
}
avatar
Вы правы, .load грузит и потом вырезает нужный кусок. Это просто обертка, синтаксический сахар.

jquery.page2page.ru/index.php5/Ajax_запрос_HTML-данных

Что касается if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) — я уже давно отказался от его использования. У меня с ним постоянные проблемы. Поэтому я просто добавляю в запрос любую переменную, которая однозначно трактует запрос как аяксовый и делаю проверку на ее наличие. Это заодно позволяет простым запросом в браузере смотреть что именно приходит при аякс запросе с сервера в ответ.
avatar
мне передали шаблон который работает на Ajax — но для части страниц там нужно дописать обработку; я сделал так
<script>
$('.ajax').click(function(){
  $.ajax({
    url:'[~80~]',  // Ditto вывод
    type:'get',
    success:function(data){
       $("#module-text").html(data);
    }
  })
  return false; // блокируем переход по нажатой ссылке
});
</script>

в документе 80 (с пустым шаблоном)
[[Ditto?tpl=`ajax.tpl` &extenders=`request`]] //в шаблоне дитто [+content+]

для урл
<a href="?ditto_documents=67" class="ajax">текст</a>

* но он переходит по ссылке…
avatar
Смотрите консоль возможно какая то ошибка там
avatar
чисто; а если писать
<code><a href="[~80~]?ditto_documents=67" class="ajax">текст</a></code>
то видно, что Дитто работает; думаю дело в побочном коде сайта ertesalon.ru/

p.s. может дело в CMS — и для этого надо брать «index-ajax»?
Комментарий отредактирован 2013-11-14 21:29:57 пользователем doc555
avatar
Сколько еще плюсов осталось до следующего урока?))
avatar
Товарищи ХЕЛП!!!
Вызываю Дитто через аякс, все нормально, товары выходят. Но пагинация работает неправильно, точнее вообще не работает, появляется только строка паганации, и при нажатии на переход другой страницы все исчезает. Как быть в таком случае?
Вот код вызова Дитто через апи:
$date_filter = 'price,'.$ot_do.',6|price,'.$do_ot.',5';

$pop_tovary = $modx->runSnippet('Ditto',
array(
'parents' => $id_cat,
'tpl' => 'tovary-tpl',
'orderBy' => 'pagetitle ASC',
'hideFolders' => '1',
'display' => $disp,
'paginate' => '1',
//'tplPaginatePage' => '@CODE:[+page+]',
'paginateAlwaysShowLinks' => '1',
'depth' => '2',
'filter' => $date_filter
)
);
$pop_tovary = str_replace('[!', '[[', $pop_tovary);
$pop_tovary = str_replace('!]', ']]', $pop_tovary);
$pop_tovary = $modx->parseDocumentSource($pop_tovary);
$pop_tovary = $modx->evalSnippets($pop_tovary);
//$pop_tovary.='[+previous+] [+pages+] [+next+] ';
echo $pop_tovary. '[+previous+] [+pages+] [+next+] ';
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.