Не важно AJAX или нет — Notify как весьма полезная библиотека для вывода пользовательских уведомлений (UPD: 20.05.13)

Fork me on GitHub

Как вы выводите сообщения пользователю в своих приложениях на Codeigniter?

Я использую для вывода сообщений форм как через ajax, так и при обычных post-запросах собственный хелпер Notify, перекочевавший из другого проекта на чистом PHP.

Любое действие пользователя (в том числе и отправка формы, нажатие на кнопку) имеет результат. Не зависимо от того какой этот результат, пользователь хочет видеть его. В более, чем 50% случаев результат этот будет нести какое-то сообщение, как-то «Новость добавлена» или «Комментарий удален».

Возьмем допустим последний пример с удалением комментария. Редко сейчас где увидишь ситуацию, когда после удаления комментария, сообщение об этом выскакивает на следующей странице (как например после нажатия «Спасибо» на форуме Рутрекера). Чаще всего мы стараемся вернуть пользователя на ту же страницу, самые тщательные программисты — еще и к анкору элемента, к которому относился комментарий.

При этом сообщение о результате удаления выводится где-нибудь в блоке сообщений в верху страницы, или приклеенное к краю экрана.

Для этого, господа программисты, я думаю вы скорее всего используете следующие конструкции в функции удаления вашего контроллера комментариев:

function delete_comment($id)
{

   if ($this->db_model->deleteComment($id))
      $this->session->set_flashdata('message','<div class="success">Комментарий удален</div>');
   else
      $this->session->set_flashdata('message','<div class="error">Ошибка удаления</div>');

   redirect($_SERVER['HTTP_REFERER']);
}

Если же потом вам захочется немного ajax’a с собственным блекджеком и шлюхами, вы скорее всего будете возвращать результат операции в json_encode. Но для этого вам придется определять AJAX и в зависимости от того AJAX это или нет, перенаправлять пользователя или просто отправлять кодированный ответ для разбора в javascript.

Если вы представили эту муторную операцию для каждого контроллера, и вздрогнули, или просто заинтересовались, то следующие инструкции для вас.

  1. Сам CI_helper под гордым названием CI_Notify, скачайте его отсюда -> ci_notify_helper.php.zip (notify.class.php.zip), и распакуйте в папку хелперов (по умолчанию /application/helpers/)
  2. Потребуется константа определения AJAX.
  3. Добавьте Notify в /application/config/autoload.php в массив хелперов
  1. Теперь Notify — библиотека, скачайте её отсюда -> https://github.com/antongorodezkiy/notify-library/archive/master.zip, распакуйте, перенесите библиотеку в папку библиотек (по умолчанию /application/libraries/), а файл конфигурации соответсвенно в /application/config/.
  2. Добавьте Notify в /application/config/autoload.php в массив библиотек
    $autoload['libraries'] = array('session','notify');
  3. Вот так изменится функция нашего контроллера с использованием Notify (пояснения я приведу ниже):
    function delete_comment($id)
    {
       if ($this->db_model->deleteComment($id))
          $this->notify->returnSuccess('Комментарий удален');
       else
          $this->notify->returnError('Ошибка удаления');
    }
  4. Notify использует jQuery в режиме noConflict(), без него javascript часть работать не будет
  5. Следующие изменения необходимо внести в View для инициализации и вывода, лучше всего сделать это где-нибудь наподобие head_view.php, т.е. в файле, включаемом во всех страницах, но лишь один раз:
    <html>
    <head>
      <script type="text/javascript" src="<?=base_url()?>js/jquery.js"></script>
      <?=$this->NOTIFY->initJs()?><!--здесь происходит инициализация javascript части Notify-->
      <script type="text/javascript">
      // удаление
      $("a.delete_activator").live("click",function()
        {
            var a = $(this);
                $.post(a.attr("href"),{},function(data)
                {
                    var json = JSON.parse(data);
                    // или
                    var json = $.parseJSON(data);
    
                    notify(json); // эта функция выведет ответ Notify, если запрос был выполнен с помощью AJAX
    
                    return false;
                });
    
                return false;
            }
    
        });
    </script>
    </head>
    
    <body>
      <div class="notify">
          <?=$this->notify->getMessages()?><!--Здесь будет происходить вывод сообщений, как загруженных из сессии так и из ajax-ответов-->
      </div>

На этом собственно все уже должно работать.

Метод

$this->notify->returnSuccess

Принимает один аргумент — текстовое сообщение, которое будет отображено функцией

$this->notify->getMessages() // обычный метод, php
// или 
notify(json); // ajax, javascript

Т.е. вы не задумываетесь о методе вызова, вы просто пишете тот ответ, который будет видеть пользователь. Если в браузере пользователя включен javascript, то сообщения через некоторое время скроются с экрана последовательно.

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

   $this->notify->success('Удален пост'); // если эти методы вызваны до загрузки 
$this->notify->getMessages(), то они будут отображены без перезагрузки
   $this->notify->success('Удален комментарий');
   $this->notify->error('Не удалось удалить комментарий №'.$number);

   // notify автоматически перенаправит пользователя на страницу реферера $_SERVER['HTTP_REFERER']
   // если вы хотите изменить адрес перенаправления, то используйте следующий метод, передав ему желаемый адрес
   $this->notify->setComeback('return/controller/method'); // адрес для переадресации
   $this->notify->returnNotify(); // весь код ниже этой строчки выполняться не будет

Говоря о зависимостях скажу, что хелпер использует функцию redirect(), и библиотеку Session из codeigniter, а также фреймворк jQuery.

Чтобы разукрасить сообщения Notify, вы можете подключить во view в head документа вызов этой функции:

$this->notify->initCss()

Либо использовать следующий css в одно из ваших css файлов:

/** Notification **/
		.notify.default
		{
			display:block;
			position:fixed;
			top:20px;
			right:20px;
			z-index: 50;
		}

		.notify.default .notice{
		  position: relative;
		  padding: 15px 15px;
		  margin-bottom: 18px;
		  color: #404040;
		  background-color: #eedc94;
		  background-repeat: repeat-x;
		  background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));
		  background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
		  background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
		  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));
		  background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
		  background-image: -o-linear-gradient(top, #fceec1, #eedc94);
		  background-image: linear-gradient(top, #fceec1, #eedc94);
		  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);
		  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
		  border-color: #eedc94 #eedc94 #e4c652;
		  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
		  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
		  border-width: 1px;
		  border-style: solid;
		  -webkit-border-radius: 4px;
		  -moz-border-radius: 4px;
		  border-radius: 4px;
		  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
		  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
		  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
		}

		.notify.default .notice
		{
			margin-bottom: 10px;
		}

		.notify.default .notice .close
		{
			font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
			float: right;
			color: #000000;
			font-size: 20px;
			font-weight: bold;
			line-height: 13.5px;
			text-shadow: 0 1px 0 #ffffff;
			filter: alpha(opacity=20);
			-khtml-opacity: 0.2;
			-moz-opacity: 0.2;
			opacity: 0.2;
			text-decoration: none;
		}

		.notify.default .notice .close:hover
		{
		  color: #000000;
		  text-decoration: none;
		  filter: alpha(opacity=40);
		  -khtml-opacity: 0.4;
		  -moz-opacity: 0.4;
		  opacity: 0.4;
		}

		.notify.default .notice strong
		{
			font-weight: bold;
			color:inherit;
		}

		.notify.default .notice.success{
			background-color: #57a957;
			background-repeat: repeat-x;
			background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
			background-image: -moz-linear-gradient(top, #62c462, #57a957);
			background-image: -ms-linear-gradient(top, #62c462, #57a957);
			background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
			background-image: -webkit-linear-gradient(top, #62c462, #57a957);
			background-image: -o-linear-gradient(top, #62c462, #57a957);
			background-image: linear-gradient(top, #62c462, #57a957);
			filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
			text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
			border-color: #57a957 #57a957 #3d773d;
			border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
			color:#FFF;
		}

		.notify.default .notice.error
		{
			background-color: #c43c35;
			background-repeat: repeat-x;
			background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
			background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
			background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
			background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
			background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
			background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
			background-image: linear-gradient(top, #ee5f5b, #c43c35);
			filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
			text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
			border-color: #c43c35 #c43c35 #882a25;
			border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
			color: #FFF!important;
		}

		.notify.default .notice.info
		{
			background-color: #339bb9;
			background-repeat: repeat-x;
			background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
			background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
			background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
			background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
			background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
			background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
			background-image: linear-gradient(top, #5bc0de, #339bb9);
			filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
			text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
			border-color: #339bb9 #339bb9 #22697d;
			border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
			color:#FFF;
		}

Самую свежу информацию вы как всегда можете найти на Github: https://github.com/antongorodezkiy/notify-library

Полезно(0)Бесполезно(0)

Добавить комментарий

16 Responses to “ Не важно AJAX или нет — Notify как весьма полезная библиотека для вывода пользовательских уведомлений (UPD: 20.05.13) ”

  1. Александр

    Статья вроде неплохая. Сделал всё как написано в инструкции, в итоге выдаёт вот такую ошибку:
    A PHP Error was encountered

    Severity: Notice

    Message: Undefined property: CI_Loader::$NOTIFY

    Filename: blocks/titolo_view.php

    Line Number: 17

    Fatal error: Call to a member function initJs() on a non-object

    Что я сделал не так?

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Александр, вы подключили notify в autoload или через $this->load->library() ?
      Какая у вас версия CI?

      Полезно(0)Бесполезно(0)
  2. Александр

    Версия 2.1.3 - самая последняя.
    Файл констант мой выглядит следующим образом:
    //константа определения AJAX
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')
    define('AJAXED',true);
    else
    define('AJAXED',false);

    Файс автолоад: $autoload['helper'] = array('url','html', 'form', 'notify');

    Суть, ошибки, как я понимаю, в том, что в скрипте у меня написано так, как в вашей инструкции: NOTIFY->initJs();?>

    говорит о том, что в этой строке происходит попытка обратиться к неопределённому свойству, помимо того, производиться попытка обращения к неизвестному объекту. Вывод: initJs(); - неопределённый объект JavaScript. Тогда возникает вопрос, где его определить? Понятное дело определение объектов на php, но тут что-то я недопонимаю как это сделать. Потом ещё такой вопрос, в инструкции предлагается скачать файлы. Куда загружать notify.class.php ??? Может в этом дело? Про этот файл в инструкции ничего не написано!

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      notify - не хелпер, а библиотека. Соответственно пропишите ее в $autoload['library'].
      По поводу файлов вы обратили мое внимание очень кстати. ВНИМАНИЕ: там была ссылка на устаревший архив. Я поменял ссылку в статье, и продублирую ее сейчас: https://github.com/antongorodezkiy/notify-library/archive/master.zip Пожалуйста, перекачайте библиотеку.

      Полезно(0)Бесполезно(0)
  3. Александр

    И вопрос, не относящийся к данному посту. Честно говоря, я искал в сети ответ совсем на другой вопрос, натолкнулся в итоге на эту статью. Данная реализация всплывающих окон меня очень заинтриговала. Если я правильно понимаю, это реализация всплывающих уведомлений, потипу, как в контакте? Решил попробовать этот пример в действии. Ладно если бы реализация была на чисто на php, – я бы сам разобрался во всём и ещё кому что помог подсказками. Другое дело же обстоит с JavaScript, который я изучаю недавно, поэтому не совсем понимаю, что и куда, возможно из-за этого недопонимания или недостатка определённых знаний и тем более опыта не могу реализовать кажущиеся элементарные вещи. Думаю, с таким сталкивается каждый начинающий какое-то изучение чего-либо. Собственно к сути вопроса. Хочу реализовать на сайте последовательный выбор меню select стран, городов и населённых пунктов (собственно ответ на этот вопрос я изначально и искал, натолкнувшись впоследствии на эту статью). Так вот, как всё это реализовать на codeigniter? Есть несколько sql запросов выводящих из БД страны, города и нас.пункты. Вывожу список, например стран в цикле foreach. Дальше возникает вопрос, как при выборе, например из этого списка «Россия» во втором списке появлялись все области России и т.д. Алгоритм понятен. Но как действовать с ООП, как передать в тот же вид результат, как отправить запрос на сервер… Вообщем одни вопросы. Может быть, что подскажете по этому поводу?

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Кажется это похоже на то, что вы ищете http://webersoft.ru/svyazannye-s-pomoschyu-ajax-selecty-jquery/

      Запрос на сервер отправляется ajax-ом с помощью jquery.
      Результат вы с сервера передаете в json, почти всегда.

      Полезно(0)Бесполезно(0)
  4. Александр

    Перечитал статью два раза, нигде не нашёл записи про подключение какой-то библиотеки. notify.class.php - нужно кидать в aplication/libraries ??? или что с ним делать?

    Полезно(0)Бесполезно(0)
  5. Александр

    Скачал библиотеку. Добавил в автозагрузку. Теперь уже пишет такую ошибку Fatal error: Cannot redeclare class Notify in D:\OpenServer\domains\weldnum.ru\application\libraries\notify.php on line 24

    Как быть дальше?

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Проверьте не осталось ли старого файла в helpers? Если остался - удалите его и удалите из автозагрузки.
      Попробуйте также еще одну инструкцию, теперь уже с гитхаба, может быть там я объяснил более понятно: https://github.com/antongorodezkiy/notify-library/blob/master/README

      Полезно(0)Бесполезно(0)
  6. Александр

    Извините за отнятое время, спасибо за помощь. Но ваш пример не работает. Подключил библиотеки поставив её на автозагрузку, в конструкторе определил методы для библиотеки. В виде создал блок для вывода всплывающих сообщений. В функциях прописал $this->NOTIFY = new Notify($this->session); В итоге ошибок не выдаёт, с объектами всё в порядке, но никаких всплывающих сообщений в помине не появляется. Вы конечно меня извините, ну Вы хоть сами пробывали работоспособность данной библиотеки, кто её написал? Есть ли рабочий пример того, что она работает? Зачем тогда выкладывать посты на то, что не работает и отнимать у людей время и надежды в решении вопросов веб ? Мне, извините, непонятно!

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Александр, библиотека работает на десятке проектов. Рабочий пример пожалуйста - http://splitcss.com

      Полезно(0)Бесполезно(0)
  7. Александр

    Вот такие примеры и в книжках и на блогах и на форумах и в интернете. Мы их берём, вот по таким материалам мы и учимся, а в итоге ничего не работает. А оказывается ссылка на файл не та, оказывается это нужно уже не хелпер загружать, а библиотеку... Нет слов одни слюни... Вот поэтому код берёшь один в один копируешь а ничего не пашет, потому, что, кто этот код писал сам ошибок больше нас сделал.

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Александр, не нужно ждать, что кто-то сделает всё за вас. Нельзя просто взять и скопировать, это вообще исходя из собственного опыта слишком опасно.
      Изначальная статья была актуальна для Notify версии 1.0. Многое изменилось с тех пор. За всем к сожалению не уследишь.
      Самые последние сведения в github, я уже говорил вам, возможно там написано понятнее. Если вы все еще заинтересованы, попробуйте по инструкции на странице репозитория https://github.com/antongorodezkiy/notify-library

      Полезно(0)Бесполезно(0)
  8. Александр

    Цит. Александр, не нужно ждать, что кто-то сделает всё за вас.

    А я никогда этого не ждал и не собираюсь ни от кого ждать и не жду. Если я говорю, что не работает, значит не работает. Вот пример, по поводу выбора городов на AJAX, его реализовал за пол часа. Полностью запросы переделал под движок и свою БД. Во всём разобрался от и до. Потому что без косяков всё сделано.
    Что я имею тут. Скинул конфиг в папку, закинул библиотеку куда нужно, поставил библиотеку на загрузку. JQuery подключена, версии 1.9.2. В хедере всё прописал, как в инструкции. Где нужно выводить сообщение, сделал тестовую функцию, туда скопировал пример в точности как в статье. В итоге никаких сообщений на экране в виде текста, не говоря уже про всплывающие сообщения. Пробовал переделывать по несколько раз. В итоге тишина. Вы хотите сказать, что я дятел, и не понимаю, как библиотеку скинуть в папку с библиотеками и поставить её на автозагрузку?

    Полезно(0)Бесполезно(0)
    • Городецкий

      Городецкий

      Все, что я хотел сказать, я сказал вам прямо.
      И я уже говорил, что библиотека сейчас работает на десятке сайтов под управлением как CI, так и Kohana, и Yii.
      Если вам нужна моя помощь, то я рад буду вам подсказать. Только тогда мне понадобиться от вас чуть больше информации о том, что и как вы сделали.
      А если ваш комментарий просто повествовательный, тогда мне правда жаль, что я непонятно пояснил все моменты.

      Полезно(0)Бесполезно(0)
  9. Александр

    Спасибо за понимание! Соглашусь, может быть я и правда что-то не так делаю, не буду спорить и настаивать на своём мнении. Если вам нужна информация о том, что как я пытался сделать, я могу вам её предоставить. И если Вы в свою очередь изъявите желание в разрешении ситуации я буду только рад и очень вам благодарен, тем более если всё получится.

    Полезно(0)Бесполезно(0)