Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Сохранение значения между вызовами функции (https://javascript.ru/forum/dom-window/18768-sokhranenie-znacheniya-mezhdu-vyzovami-funkcii.html)

PanJavkin 14.07.2011 19:09

[Решено] Сохранение значения между вызовами функции
 
День добрый, не так давно изучаю js и ради тренировки пишу простую записную книжку для себя. Принцип простой - в окне есть div с текстом, по нажатию кнопки он превращается в textarea, редактируется, и по нажатию другой кнопки сохраняется.
Возникла проблема с реализацией кнопки отмены (у меня "Редактировать" и "Отменить" это одна функция). В идеале, если внесены изменения и нажата кнопка отмены, то все изменения должны отбрасываться и див возвращается в первоначальное состояние. Пока что я это реализовал через глобальный объект, записывая в него изначальный текст, но по моему это далеко не самый лучший и красивый вариант.

Собственно сам код:
// Объекст для сохранения изначального текста дива
var notesSave = new Object();

// id - номер выбранного дива. save - сохранение изменений, 0 - нет, 1 - да.
function editText(id, save)
	{
	var oldTag = document.getElementById('id'+id);

	// Проверяем, был ли уже сохранен изначальный текст, если нет, сохраняем
	if (notesSave[id] === undefined)notesSave[id] = oldTag.innerHTML;

	//Определяем направление замены div-textarea
	if (oldTag.localName === 'DIV') // Из div в textarea
		{
		var newTag = document.createElement('textarea');
		newTag.value = oldTag.innerHTML.replace(/<br>/gm, '\n');
		document.getElementById('edit'+id).innerText = 'Отменить';
		var url = '/notes/edit/id'+id;

		}else if (oldTag.localName === 'TEXTAREA') // Из textarea в div
			{
			var newTag = document.createElement('div');

			// Если выбранно сохранение, то вернуть в див новый текст
			if(save)newTag.innerHTML = oldTag.value.replace(/\n/gm, '<br>');
			// Иначе оставить старый
			else
			newTag.innerHTML = notesSave[id];
			document.getElementById('edit'+id).innerText = 'Редактировать';
			var url = '';
			}
	newTag.id = oldTag.id;
	newTag.className = oldTag.className;
	document.getElementById('base'+id).replaceChild(newTag, oldTag);
	history.pushState(null, null, url);
	}

Да, безопасность и оптимизация пока что не на высоте, ими буду потом заниматься, сначала хочу все это сделать рабочим.


Хтмл, все значения (текст заметки, даты, номера после id, в данном случае "2") подставляются в php.
<div id="status2">&nbsp;</div>
	<div id="base2">
	id: 2<br>
	<div id="id2" class="note-box">Текст заметки</div><br>
	Дата создания: 2011-07-14 00:47:50<br>
	Дата редактирования: <span id="update2">2011-07-14 18:14:08</span><br>
	<input type="submit" onclick="editText('2')" value="Редактировать" id="edit2">
	<input type="submit" onclick="saveNote(2, 1)" value="Сохранить">
	<input type="submit" onclick="deleteNote('2')" value="Удалить">
	<hr>
	</div>

Смотрел в сторону замыканий, но не срослось, то ли я что-то не так делаю, то ли одно из двух.

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

Заранее благодарю.


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

kobezzza 15.07.2011 01:14

Особо не вникал в код, но вообще принцип такой и есть, только я бы не создавал новую глобальную переменную, а дал бы свойство для editText (editText.tmp = "тут мы храним наш темповый текст)").

Или можно не заменять div на textarea, а создать сразу оба и просто менять свойство display (none/block) и тогда вообще ничего не придётся никуда записывать)

PanJavkin 15.07.2011 01:44

kobezzza
О! Избавиться от глобальных переменных и было целью, спасибо огромное =)

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

kobezzza 15.07.2011 01:51

Функция - это объект, а у любого объекта могут быть свойства, главное не путайте с примитивами (числа, строки, логические, undefined, null (хотя почему то typeof null == "object" Оо)), они хоть и могут трактоваться как объект, но свойства иметь не могут (пользовательские).
var a = new String("Вася");
a.prop = "Свойство"; // Всё ок
var b = "Вася";
b.prop = "Свойство"; // Ошибочка


Но, как я говорил выше, что примитивы могут трактоваться как объекты, то такая запись вполне справедлива:
var a = "Вася";
a.replace("а", "о"); // используем метод для примитива

или даже так:
var a = "Вася".replace("a", "о");

PanJavkin 15.07.2011 02:40

Ага, как-то потратил пару дней на изучение типизации, но из-за того что у функций есть свой специальный синтаксис, отличный от объектов, то и воспринимал их отдельно, теперь буду внимательнее, еще раз спасибо.

И кстати, примитивы не трактуются как объекты, а просто создается временный объект-обертка, свойства и методы которого используются.

kobezzza 15.07.2011 02:42

Цитата:

И кстати, примитивы не трактуются как объекты, а просто создается временный объект-обертка, свойства и методы которого используются.
Я это и имел ввиду, просто мне нравится термин "трактоваться", кстати я его запомнил из книжки по JS, не помню автора.

Всегда пожалуйста)


Часовой пояс GMT +3, время: 23:51.