четверг, 8 ноября 2012 г.

Делаем информационный виджет для Drupal сайта


Недавно передо мной возникла задача - сделать информационный виджет для одного сервиса, что бы размещать его на сторонних сайтах.
Коротко о сервисе - Сайт "Умное слово на каждый день" - это первый образовательный ресурс подобного рода. Неизвестные широким массам слова появляются каждый день и составляют крупнейший в рунете словарь "умных" слов. Заходи на Everydayword.ru каждое утро и повышай словарный запас.


Перед созданием виджета передо мной встал вопрос, каким образом мне получать данные и в каком формате. Мой выбор пал на AJAX в связке с JSON.

Приступим

PHP

Первым делом нужно создать страницу на которую  будет идти ajax запрос. Поэтому в файле модуля объявляем hook_menu() и функцию в которой мы будем возвращать данные :
function mymodule_menu() {
$items['output'] = array(
  'page callback' => 'mymodule_output', //функция для вывода данных
  'access arguments' => array('access content'),
);
return $items;
}

function mymodule_output() {
$data = array(
  'title' => t('Your title'),
  'body' => t('Your body'),
);
drupal_json_output($data);
}
Чистим кэш с помощью инструмента Drush "Drush cc all", переходим на страницу http://yoursite.ru/output
Вы должны увидеть вот такой текст и ничего кроме {"title":"Your title","body":"Your body"}

JS

Ну вроде json формируется и отдается по определенному url, все хорошо, можно и js начинать писать.
$(document).ready(function () {
  $.ajax({
    url: 'http://yoursite.ru/output',
    dataType: "json",
    success: function(data) {
      console.log(data)
    }
  });
});

Разбор ошибок и временные правки

К сожалению, вместо наших данных в консоли нас поджидает вот такая вот ошибка:
XMLHttpRequest cannot load http://yoursite.ru/output. Origin http://your-test-site.ru is not allowed by Access-Control-Allow-Origin.
Можно конечно просто  разрешить ajax для домена yoursite.ru, но это же не будет делать каждый кто хочет установить наш виджет.
Однако у метода .ajax есть такая настройка как crossDomain, но работает она только с типом данных jsonp (dataType: 'jsonp')
Модернизируем наш скрипт:
$(document).ready(function() {
  $.ajax({
    url: 'http://yoursite.ru/output',
    crossDomain: true,
    dataType: 'jsonp',
    success: function(data) {
      console.log(data)
    }
  });
});
На этом дело не заканчивается и мы встречаем новую ошибку:
Uncaught SyntaxError: Unexpected token :
Оказывается браузер подключает нашу страницу как JS и пытается её исполнить. Немого изучив теорию jQuery.ajax() модернизируем наш код.

Итоговый, рабочий вариант

JS

  $.ajax({
    url: 'http://yoursite.ru/output?callback=?',
    crossDomain: true,
    dataType: 'jsonp',
    success: function(data) {
      var code = '<div class="widget-title">' + data.title + '</div>'
      code += '<div class="widget-body">"' + data.body + '"</div>'
      $('#widget-content').html(code)
    }
  });
});

PHP

function mymodule_output() {
  drupal_add_http_header('Content-Type', 'application/x-javascript');
  $data = array(
    'title' => t('Your title'),
    'body' => t('Your body'),
  );
  $json = drupal_json_encode($data);
  echo $_GET['callback'] . "($json);";
  drupal_exit();
}

Размещение виджета

Для того, что бы разместить виджет  необохдимо:


  •   Подключить js файл <script src="http://yoursite.ru/path/to/file/widget.js"></script>
  •   По желанию подключить css файл с некоторыми готовыми стилями <link rel="stylesheet" type="text/css" href="http://yoursite.ru/path/to/file/widget.css">
  •   В месте где необходимо отображать виджет создать div с определенным id <div id="content-widget"></div>


Итог

everydayword.ru
UPD.
Если кого заинтересовал мой виджет, то

  • <script src="http://everydayword.ru/sites/all/themes/edw/scripts/output-word.js"></script>
  • <link rel="stylesheet" type="text/css" href="http://everydayword.ru/sites/all/themes/edw/css/output-word.css">
  • <div id="content-word">

Комментариев нет:

Отправить комментарий