Загрузка поля cck ajax-запросом.

Аватар пользователя Mufanu Mufanu 30 июля 2011 в 12:55

На главной странице есть лента новостей. Она состоит из:
1. Дата новости;
2. Анонс новости;
3. Ссылка на саму новость.

Захотелось мне реализовать ajax-загрузку основного текста новости на место ссылки.
Изучив "как создать свой модуль", основы javascript, jquery и вспомнив основы php-программирования я все таки реализовал свою идею. Возможно для профи это 5 минутное дело, у меня ушло около 5 дней в совокупности. Работу модуля можете посмотреть на www.appri.ru.
Модуль назвал loadnews. Здесь обноленный код.
Файл loadnews.module:

<?php
/*
 * Implementing hook_init
 */

function loadnews_init() {
    
drupal_add_css(drupal_get_path('module''loadnews') . "/loadnews.css");
  
drupal_add_js(drupal_get_path('module''loadnews') ."/loadnews.js");
}

/*
 * Implementation hook_perm
 */
function loadnews_perm() {
  return array(
'access onthisdate content');
}

/**
 * Implementation hook_menu()
 */
function loadnews_menu() {
  
// Элемент меню с соответствующим путем
  
$items['loadnews'] = array (
    
// Функция, которая будет "обрабатывать" путь
    
'page callback' => 'loadnews_ajax',
    
// Права на доступ к пути
    
'access arguments' => array('access content'),
    
// Элемент не будет отображаться в меню сайта
    
'type' => MENU_CALLBACK,
  );
  return 
$items;
}

/* Функция обработки запроса */
function loadnews_ajax() {
    
/*
     * Ссылка на на новость передается методом GET в переменной 'url'
     * В БД алисы адресов хранятся без первого слеша, поэтом удаляем его
    */
    
$url substr($_GET['url'], 1);
    
// По полученному алиасу ищем в таблице url_alias соответствующий системный адрес
    
$sys_url db_result(db_query("SELECT n.src FROM {url_alias} n WHERE dst = '%s'"$url));
    
/* Адрес получаем в виде "node/nid". Нам нужно получить параметр nid.
     * Для этого разбиваем строку на массив из 2-х элементов, второй который наш nid
    */
    
$sys_url_array explode('/',$sys_url);
    
// Сохраняем наш nid в переменную
    
$nid $sys_url_array['1'];
    
// Выбираем поле основного текста новости "field_news_text_value" из таблицы "content_type_news"
    
$result db_result(db_query("SELECT n.field_news_text_value FROM {content_type_news} n WHERE n.nid = '%d'"$nid));
    
// Наш ответ клиенту
    
drupal_json(array('status' => 1'data' => $result));
}
?>

Файл loadnews.js:

Drupal.behaviors.loadnews = function(context) {
        // Добавляем для всех ссылок в блоке новостей class =loadnews
  $('#block-views-news-block_news', context).find('a').addClass('loadnews')
  // Реагируем на клик
  .bind('click', function() {
        // Передаем с методом get адрес ссылки
        var href = $(this).attr('href');
        // Переменная, это куда мы будем выводить ответ
        var target = $(this).parents(".field-content");
                // Прячем ссылку
        $(this).hide();
        // Вместо нее выводим анимацию
        $(target).append("<div class=loading></div>");
        // Получаем данные с сервера
        $.get(Drupal.settings.basePath + 'loadnews', {url:href} , function(response) {
                // Сохраняем ответ в переменной
                var result = Drupal.parseJson(response);
                // Прячем анимацию
                $(target).find(".loading").hide();
                // Вместо нее ставим "Свернуть"
                $(target).append("<span class=hidenews>Свернуть</span>");
                $(target).append("<span class=shownews>Подробнее...</span>");
                $(target).find(".shownews").hide();
                // Создаем блок для вывода текста новости
                $(target).append("<div class='newstext'></div>");
                // Изначально блок будет скрыт, чтобы потом красиво его развернуть
                $(target).find("div.newstext").hide();
                // Загружаем текст из переменной в блок
                $(target).find("div.newstext").html(result.data);
                // Красиво раскрываем наш блок
                $(target).find("div.newstext").slideDown("fast").addClass("active");
                // Реализация скрытия и раскрытия блока (нужно оптимизировать код)
                $(target).find(".hidenews").click(function() {
                        $(target).find(".hidenews").hide();
                        $(target).find("div.newstext").slideUp("fast").removeClass("active");
                        $(target).find(".shownews").show();
                });
                $(target).find(".shownews").click(function() {
                        $(target).find(".shownews").hide();
                        $(target).find("div.newstext").slideDown("fast").addClass("active");
                        $(target).find(".hidenews").show();
                });
        });
        return false;
  });
}

Хотелось бы услышать мнения и замечания профи по коду. Спасибо за внимание.

ВложениеРазмер
Иконка пакета loadnews_v6.x-1.6.zip3.62 КБ
0 Thanks

Комментарии

Аватар пользователя xxandeadxx xxandeadxx 30 июля 2011 в 22:43

статус должен быть true, раз результат удачный

<?php
drupal_json
(array('status' => 1'data' => $result));
?>

не забывайте про контекст:

Drupal.behaviors.loadnews = function(context) {
  $('#block-views-news-block_news', context).find('a').addClass('loadnews')

и про basePath

$.get(Drupal.settings.basePath + 'loadnews'
Аватар пользователя Mufanu Mufanu 2 августа 2011 в 7:48

Учел все замечания. Про сворачивание - занимаюсь этим. Насчет получения системных путей - тоже занимаюсь. Сделать универсальный модуль - для меня это пока сложновато, но возможно в будущем ))))

Аватар пользователя iNFerNo iNFerNo 30 июля 2011 в 20:35

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

Аватар пользователя Lotar Lotar 30 июля 2011 в 22:26

Для сворачивания нужно добавить css. Я так понимаю выгрузить сск поле не получиться да и смысла нет.

Аватар пользователя Arturus Arturus 1 августа 2011 в 14:24

Я так понял, что модуль из таблицы content_type_news выводит поле field_news_text_value. Может можно сделать модуль более универсальным, к примеру после установки модуля отмечаем тип материала и поле для скрытия на основе этих данных создается вьюз для вывода, который можно оптимизировать и изменить?

Аватар пользователя seaji seaji 1 августа 2011 в 11:54

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

Аватар пользователя NikaDevs NikaDevs 1 августа 2011 в 15:19

Не забываем про права доступа :)

<?php
function loadnews_init() {
  if (
user_access('access onthisdate content')) {
    
drupal_add_css(drupal_get_path('module''loadnews') . "/loadnews.css");
    
drupal_add_js(drupal_get_path('module''loadnews') ."/loadnews.js");
  }
}

/**
 * Implementation hook_menu()
 */
function loadnews_menu() {
  
// Элемент меню с соответствующим путем
  
$items['loadnews'] = array (
    
// Функция, которая будет "обрабатывать" путь
    
'page callback' => 'loadnews_ajax',
    
// Права на доступ к пути
   
'access arguments' => array('access onthisdate content'),
    
// Элемент не будет отображаться в меню сайта
    
'type' => MENU_CALLBACK,
  );
  return 
$items;
}
?>
Аватар пользователя Mufanu Mufanu 2 августа 2011 в 7:43
4elove4ek wrote:

Не забываем про права доступа :)

<?php
function loadnews_init() {
  if (
user_access('access onthisdate content')) {
    
drupal_add_css(drupal_get_path('module''loadnews') . "/loadnews.css");
    
drupal_add_js(drupal_get_path('module''loadnews') ."/loadnews.js");
  }
}

/**
 * Implementation hook_menu()
 */
function loadnews_menu() {
  
// Элемент меню с соответствующим путем
  
$items['loadnews'] = array (
    
// Функция, которая будет "обрабатывать" путь
    
'page callback' => 'loadnews_ajax',
    
// Права на доступ к пути
   
'access arguments' => array('access onthisdate content'),
    
// Элемент не будет отображаться в меню сайта
    
'type' => MENU_CALLBACK,
  );
  return 
$items;
}
?>

А этого не достаточно будет?:

<?php/*
 * Implementation hook_perm
 */
function loadnews_perm() {
  return array(
'access onthisdate content');
}
?>
Аватар пользователя Mufanu Mufanu 2 августа 2011 в 10:55

Обновил код модуля с учетом ваших замечаний. Добавил "Свернуть/Развернуть".

Аватар пользователя iNFerNo iNFerNo 2 августа 2011 в 13:15

у вас получается что тизер отдельно прописан продолжение отдельно и тизер прилипает... к содержанию .

а если тизер свой текст а содержание по своему... я это к тому что... у вас что грузиться после нажатия???

реально ли грузить вместо тизера все содержание ? а не тизер + содержание?

Аватар пользователя Mufanu Mufanu 2 августа 2011 в 13:17

Не совсем понял ваш вопрос. Грузится только содержание конкретного cck-поля, в моем случаем это основной текст новости.

Аватар пользователя iNFerNo iNFerNo 2 августа 2011 в 14:00

ясно. а вариант гружения не только содержания а всей ноды вместо тизера и содержания в случае если тизер отличается от всей ноды.

Аватар пользователя iNFerNo iNFerNo 2 августа 2011 в 14:01

а если юзеру запрещено просматривать содержание ноды. он увидит в вашем случае информацию полностью при клике ?

Аватар пользователя Mufanu Mufanu 2 августа 2011 в 14:13

Для полной загрузки ноды можно использовать
<?php$("#somediv').load(url);?>

В моем случае тип контента "Новость" разрешен для просмотра пользователям, а сск-поле текста является частью контента "Новость", поэтому разрешен(по крайней мере я так думаю)))).

Аватар пользователя Dan Dan 7 августа 2011 в 14:27
"Mufanu" wrote:

А этого не достаточно будет?

Нет. Этот хук только добавляет кастомные разрешения, а их ещё и проверять где-то нужно.

Аватар пользователя Dan Dan 7 августа 2011 в 19:45

Если модуль так популярен, думаю надо его сделать более универсальным. А именно:

- добавить настройки, для какогог типа контента показывать ссылку
- добавлять ссылку "подробнее" черех хук hook_links, т.к. $('#block-views-news-block_news', context).find('a') делать неправильно - будут обработаны все ссылки, а не только нужная. Это также избавит от необходмости получать путь ноды.
- показывать тизер, а подгружать полную ноду, избавившись ССК-поля и хардкорных запросов к БД
- подгружать скрипт и стили через hook_nodeapi ($op == 'load')

Аватар пользователя Mufanu Mufanu 7 августа 2011 в 21:46
"Dan" wrote:

Нет. Этот хук только добавляет кастомные разрешения, а их ещё и проверять где-то нужно.

Надо будет поизучать, спасибо.

"Dan" wrote:

Если модуль так популярен, думаю надо его сделать более универсальным. А именно:
- добавить настройки, для какогог типа контента показывать ссылку
- добавлять ссылку "подробнее" черех хук hook_links, т.к. $('#block-views-news-block_news', context).find('a') делать неправильно - будут обработаны все ссылки, а не только нужная. Это также избавит от необходмости получать путь ноды.
- показывать тизер, а подгружать полную ноду, избавившись ССК-поля и хардкорных запросов к БД
- подгружать скрипт и стили через hook_nodeapi ($op == 'load')

Я в начале статьи забыл указать, что вывод ленты новостей осуществляется с помощью views. Это мой первый модуль, сделать его универсальным для меня пока проблематично. Возможно лучше будет выполнить модуль в виде плагина для views, например как views accordion

"VasyOK" wrote:

Добавил, ничего не происходит. Автор ответь плз.

Нужно изменить код под себя.
loadnews.module:

<?php
// Выбираем поле основного текста новости "field_news_text_value" из таблицы "content_type_news"
$result db_result(db_query("SELECT n.field_news_text_value FROM {content_type_news} n WHERE n.nid = '%d'"$nid));
?>

Здесь нужно указать свой тип контента и поле cck (у меня это content_type_news и field_news_text_value соответственно).
loadnews.js:

// Добавляем для всех ссылок в блоке новостей class =loadnews
$('#block-views-news-block_news', context).find('a').addClass('loadnews')

Здесь нужно указать свой селектор, у меня это #block-views-news-block_news.

Аватар пользователя Dan Dan 7 августа 2011 в 21:51
"Mufanu" wrote:

Я в начале статьи забыл указать, что вывод ленты новостей осуществляется с помощью views. Это мой первый модуль, сделать его универсальным для меня пока проблематично. Возможно лучше будет выполнить модуль в виде плагина для views, например как views accordion

Если вы не будете привязываться к полям ССК, то модуль для views писать не придётся.
Делаем выборку тизеров и отмечаем "показывать ссылки". И всё будет :)

Аватар пользователя VasyOK VasyOK 9 августа 2011 в 11:12
"Mufanu" wrote:

Здесь нужно указать свой тип контента и поле cck (у меня это content_type_news и field_news_text_value соответственно).

1. А с обычным текстовым полем, т.е. тем которое по умолчанию в типе материала оно работает?

"Mufanu" wrote:

Здесь нужно указать свой селектор, у меня это #block-views-news-block_news.

2. Т.е. нужно предварительно создать блок в котором выводить материалы и только в этом блоке будет наблюдаться "раскрытие"?

Обновл.
3. А если надо несколько каких блоков данный модуль, как я понимаю, нужно еще больше дописать.

Аватар пользователя _viktor_ _viktor_ 23 ноября 2011 в 10:48

Mufanu, а вы не могли-бы написать как настраивать ваш модуль? Модуль очень полезный.

Аватар пользователя lipinart lipinart 16 января 2016 в 9:37

Интересное решение. Если получиться порт на семерку с настройками (без лазанья в код) модуль стал бы популярным.