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;
		}
	});

});

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

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

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

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

Метки: ,

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

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

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

  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. Александр

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

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

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

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

Ваш 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