Contenteditable — редактирование контента «на лету». Урок 2

Contenteditable - редактирование контента на лету

От автора: в этом мы продолжим работу с атрибутом HTML5 contenteditable. При изменении значения редактируемого поля, скрипт будет отправлять асинхронным запросом (средствами AJAX) новое значение, и сохранять его в БД.

 

скачать исходникискачать урок

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

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

После этого нам нужно получить новое значение поля и обязательно сравнить его с предыдущим (тем, которое взяли при получении элементом фокуса). Если эти значения будут отличаться, то это значит, что пользователь изменил значение, и мы можем отправлять новое значение на сервер для его сохранения. Если же значения будут идентичны, то никакого запроса отправлять не нужно, поскольку пользователь ничего не изменил в поле.

Итак, обратимся к событию blur, получим новое значение и сравним его с прежним:

$('.edit').focus(function(){
 oldVal = $(this).text();
 id = $(this).data('id');
}).blur(function(){
 newVal = $(this).text();
 if(newVal != oldVal){
  console.log("Отправляем запрос");
 }
});

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

Теперь напишем сам асинхронный запрос, обратившись к методу ajax():

blur(function(){
 newVal = $(this).text();
 if(newVal != oldVal){
  $.ajax({
 url: 'index.php',
 type: 'POST',
 data: {new_val: newVal, id: id},
 success: function(res){
 console.log(res);
 },
 error: function(){
 alert('Error!');
 }
  });
 }
});

Итак, мы отправляем данные асинхронно методом POST в файл index.php. В случае успеха мы готовы принять некий ответ в переменную res и вывести ее содержимое в консоль. Теперь давайте примем эти данные и вернем какой-нибудь ответ, чтобы убедиться, что все работает.

В индексном файле после подключения файла функций добавим пару строк кода:

if( isset($_POST['new_val']) ){
 print_r($_POST);
 exit("Настройка сохранена");
}

В качестве теста мы просто распечатаем содержимое массива POST. Теперь попробуем изменить значение. Если все сделано верно, то в консоли мы должны в качестве ответа увидеть распечатанный массив POST, в котором будут новое значение и ID изменяемой опции.

Теперь вместо распечатки массива давайте будем вызывать функцию, сохраняющую данные. Если функция будет возвращать ИСТИНУ, тогда вернем в ответе строку об успехе, иначе – сообщение об ошибке сохранения.

if( isset($_POST['new_val']) ){
 if( update_option() ){
  exit("Настройка сохранена");
 }else{
  exit("Ошибка сохранения");
 }
}

И опишем функцию update_option() в файле functions.php:

/**
* обновление настройки
**/
function update_option(){
 global $db;
 $value = mysqli_real_escape_string($db, $_POST['new_val']);
 $id = (int)$_POST['id'];
 $query = "UPDATE options SET value = '$value' WHERE id = $id";
 $res = mysqli_query($db, $query);
 if( mysqli_affected_rows($db) ) return true;
  else return false;
}

Здесь все предельно просто. Запрос UPDATE пытается обновить значение по ID поля. В случае успеха возвращаем TRUE, иначе – FALSE.

Вот практически и все. Если мы нигде не ошиблись, то опция должна сохраняться, а сообщение об успешном сохранении мы должны увидеть в консоли. Конечно же, хотелось бы видеть это сообщение не в консоли, а непосредственно на странице. Давайте это сделаем.

Для этого давайте добавим после таблицы несколько элементов верстки:

<div id="loader"><span></span></div>
<div id="mes-edit"></div>

И опишем стили для них:

#loader{
 position:fixed;
 display:none;
 top:0;
 left:0;
 height:100%;
 width:100%;
 background:#f2f2f2;
 opacity:.9;
 z-index: 30;
}
#loader span{
 display: block;
 background: url(../img/loader.gif);
 width: 128px;
 height: 15px;
 position: absolute;
 left: 50%;
 top: 50%;
 margin: -7px 0 0 -56px;
}
#mes-edit{
 display: none;
 color: #000;
 font-size: 15px;
 border: 1px solid #ccc;
 box-shadow: 0 0 10px #ccc;
 padding: 10px;
 text-align: center;
 width: 400px;
 position: fixed;
 left: 50%;
 top: 50%;
 margin: -20px 0 0 -200px;
 font-weight: bold;
 background: #fff;
}

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

blur(function(){
 newVal = $(this).text();
 if(newVal != oldVal){
  $.ajax({
 url: 'index.php',
 type: 'POST',
 data: {new_val: newVal, id: id},
 beforeSend: function(){
 $('#loader').fadeIn();
 },
 success: function(res){
 $('#mes-edit').text(res).delay(500).fadeIn(1000, function(){
 $('#mes-edit').delay(1000).fadeOut();
 });
 },
 error: function(){
 alert('Error!');
 },
 complete: function(){
 $('#loader').delay(500).fadeOut();
 }
  });
 }
});

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

Ну и напоследок. Если вы решите обновлять опцию не по событию blur, а по нажатию клавиши Enter (на мой взгляд это гораздо удобнее), то все, что нужно сделать, это описанный код использовать для клавиши Enter (ее код у нас уже есть). В таком случае итоговый код будет таким:

$(function(){

 var oldVal, newVal, id;
 $('.edit').focus(function(){
  oldVal = $(this).text();
  id = $(this).data('id');
 });

 $('.edit').keypress(function(e){
  if(e.which == 13){
 newVal = $(this).text();
 if(newVal != oldVal){
 $.ajax({
 url: 'index.php',
 type: 'POST',
 data: {new_val: newVal, id: id},
 beforeSend: function(){
 $('#loader').fadeIn();
 },
 success: function(res){
 $('#mes-edit').text(res).delay(500).fadeIn(1000, function(){
 $('#mes-edit').delay(1000).fadeOut();
 });
 },
 error: function(){
 alert('Error!');
 },
 complete: function(){
 $('#loader').delay(500).fadeOut();
 }
 });
 }
 return false;
  }
 });

});

На этом мы завершим текущий урок. Удачи и до новых встреч!

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее
Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки: ,

Похожие статьи:

Комментарии Вконтакте:

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

Комментарии (21)

  1. masik

    тема — супер, подача материала — супер, но, к сожалению, сама идея без авторизации не прокатит (imho)
    С уважением…

    • Андрей Кудлай

      Ну да, конечно же, это только момент, который можно реализовать, скажем, в админке)

  2. Анатолий

    Доброго дня!
    Андрей, может подскажите, я вот решил дальше пойти, и как раз тэг textarea не срабатывает на .blur(function()

    то есть, когда вот ставишь <textarea data-id="» class=»description» contenteditable>

    как только заменяешь textarea на div все ок. Но мне как раз нужно что бы был что бы видит html код.
    Спасибо за помощь!

    • Андрей Кудлай

      Здравствуйте, Анатолий.
      У меня сразу же возник вопрос: зачем использовать атрибут contenteditable для текстовой области формы, если она итак доступна для редактирования? Относительно вопроса, то здесь нужно только смотреть код, возможно неверно обращаетесь к текстовой области или есть ошибки в верстке или скрипте. Посмотрите нет ли ошибок в консоли. Если не получится разобраться, тогда создайте тему на нашем форуме, прикрепите в архиве ваш код, попробую посмотреть.

  3. Владимир

    Доброго дня!
    Андрей, может подскажите, я вместо div поставил input type=»text» и ajax не срабатывает вобше не пойму почему !

    • Андрей Кудлай

      Здравствуйте.
      Нужно только смотреть консоль на предмет ошибок и производить отладку кода, по другому никак.

      • Владимир

        бееда в том сто в консоль вобше не че не приходит

        • Андрей Кудлай

          В консоли проверяется не только то, что приходит, но и то, что отправляется. Если ничего не приходит, значит запрос AJAX не отправляется и, опять-таки, приходим к необходимости отладки кода.

  4. Wiktor

    здравствуйте
    а как связаться автором?

  5. Екатерина

    Андрей здравствуйте статья пригодилась, а как быть если я не одно поле хочу редактировать а несколько, где указать какой столбец изменять? Запрос update.. переделать можно, не соображу, как передать имя поля для редактирования.

    • Андрей Кудлай

      Здравствуйте, Екатерина.
      Как вариант, можно использовать title (или ID) опции. Получаете его, передаете вместе с прочими данными на сервер и обновляете ту опцию, title (или ID) которой передан.

      • Екатерина

        Никак не получается:(
        Вот так обращаюсь к переменной, POST передает пустое pole
        if ($(this).title = «Emes») {pole = «message»}
        C web-программированием знакома совсем мало, может что то не так делаю…

        • Андрей Кудлай

          Если с программированием знакомы мало, то реализовать задачу, к сожалению, будет довольно проблематично. Имя поля можно поместить, скажем, в атрибут data-name (как это делаем с ID) и получать его оттуда. Соответственно, в запросе update это поле будет подставлено в качестве имени поля таблицы. Также нужно не забывать о безопасности.

  6. Екатерина

    Все получилось, спасибо!!!

  7. Александр

    Здравствуйте Андрей. В уроке Вы применили данный метод только для одного столбца. А как это можно реализовать для нескольких столбцов? Попробовал осуществить изменение столбца с заголовком(тот, что в Вашем примере), но когда я изменяю значение в первом столбце, стирается значение во втором. И наоборот. Не могли Вы показать на практике какие изменения нужно внести чтоб получить данный результат. Надеюсь на Вашу помощь. Спасибо.

    • Андрей Кудлай

      Здравствуйте, Александр. Чуть выше в комментариях аналогичный вопрос задавала Екатерина, и я давал советы, как можно реализовать такую возможность. Возможно в дальнейшем запишу продолжение и покажу реализацию в уроке.

  8. Вероника

    Андрей, спасибо Вам за очень полезный урок! Скажите, а возможно ли таким способом редактировать комментарии, которые Вы добавляете аяксом в курсе Создание каталога. Имею в виду комментарии, которые выведены без перезагрузки страницы. Можно ли их тут же отредактировать? Я пробую, но не получается пока. Редактируются только если обновить страницу.

    • Андрей Кудлай

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

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree