Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как вернуть div и все вложенные в него элементы в первоначальное состояние? (https://javascript.ru/forum/misc/53950-kak-vernut-div-i-vse-vlozhennye-v-nego-ehlementy-v-pervonachalnoe-sostoyanie.html)

lucky89 25.02.2015 12:26

Как вернуть div и все вложенные в него элементы в первоначальное состояние?
 
Здравствуйте!
Помогите найти хорошее решение. Пишу на jquery ajax приложение. Есть формы для заполнения данными, они обернуты в div. Он сразу есть на странице, просто скрыт (display: none). Внутри его есть самые разные элементы (select, radio, text, checkbox, textarea, div и еще всякие). Когда оператор первый раз кликает по заказу, ему показывается этот блок со всем содержимым в начальном состоянии. Пока оператор заполняет поля, работает js, кое что считает, кое какие поля заполняет сам, создает дополнительные элементы и тд. Оператор нажимает Сохранить, данные улетают на сервер, div с формами опять скрывается, оператору снова доступна таблица для выбора заказа. Если этот div с формами не почистить перед скрытием, то при следующих отображениях он уже частично заполнен старыми данными, в нем уже созданы какие-то элементы, а скрипт умеет работать только с пустым (с первоначальным состоянием), появляются ошибки. Вопрос: как можно сохранить первоначальное состояние этого большого div'а и всех формам и прочих элементов в него вложенных и возвращаться к нему каждый раз, как только форма закрывается? Так сказать, чтобы каждый заказ заполнялся с чистого листа. Сейчас чищу каждое поле по отдельности, но это плохо, так как их уже под сотню и дальше разрабатывать становится тяжело. Перезагружать страницу тоже нельзя, так как это ajax приложение (теряется смысл).
Пробовал в переменную записать .html() этого блока, и при закрытии вставить его обратно, но тогда формы-то восстанавливают первоначальный вид, но сбрасываются все переменные к которым были привязаны DOM элементы, получается такой манипуляцией я создаю как бы такие же но новые DOM элементы и все переменные надо снова переопределять, что тоже плохо и не подходит.
Какие есть варианты?

Erolast 25.02.2015 13:11

Поизучай MVC-фреймворки и возьми какой-нибудь на вооружение. Оно не решит проблему очистки персонально, но решит в том числе. Распространенные варианты:

React.js в связке с https://babeljs.io/docs/usage/jsx/
Backbone.js в связке с Marionette.js или Chaplin.js (+, опционально, какой-нибудь http://rivetsjs.com/ для дата-байндинга)
AngularJS. Имхо, дарк сайд - философию JS курочит, хотя весьма удобен.

+ переходи на ES6.

ksa 25.02.2015 13:44

Цитата:

Сообщение от lucky89
Внутри его есть самые разные элементы (select, radio, text, checkbox, textarea, div и еще всякие).
...
Вопрос: как можно сохранить первоначальное состояние этого большого div'а и всех формам и прочих элементов в него вложенных и возвращаться к нему каждый раз, как только форма закрывается?

Если это все в форме - у формы есть метод reset()! ;)

lucky89 25.02.2015 14:58

более подробно про код внутри div
 
Цитата:

Сообщение от ksa (Сообщение 358344)
Если это все в форме - у формы есть метод reset()! ;)

Нет, не в форме. Тег <form> вообще не используется. Там JS всем рулит, через элементы DOM.
Для наглядности:
Код "чистого div'а":
Код:

<div id="ffcDiv" class="form dn">

    <div class="divTitle">Менеджер:</div>
    <div id="ffcManagerName" class="divString">E-mail менеджера</div>
    <input id="ffcClientName" class="inputStringLong" name="clientName" type="text" placeholder="ФИО"/><br/>
    <input id="ffcClientAddress" class="inputStringLong" type="text" placeholder="Адрес"/><br/>
    <div id="ffcPostIndex" class="divString">Почтовый индекс (появится сам)</div>
    <input id="ffcClientPhone1" class="inputStringWithBtn" type="text" placeholder="Телефон"/>
    <button id="ffcBtnCall1" class="inputStringBtn" type="button">▶</button><br/>
    <input id="ffcClientPhone2" class="inputStringWithBtn" type="text" placeholder="Дополнительный телефон (только цифры)"/>
    <button id="ffcBtnCall2" class="inputStringBtn" type="button">▶</button><br/>
    <div class="divTitle">Комментарии к звонку (если были):</div>
    <div id="ffcCallCommentBlock"></div>
    <select id="ffcCallResult" class="inputStringLong"></select><br/>
    <textarea id="ffcCallComment" class="commentBlock" placeholder="Комментарий к звонку"></textarea>
    <div class="divTitle">Доставка:</div>
    <div id="ffcDelivery" class="divBlock">
        <div id="ffcDeliveryLeft" class="ffcDeliveryLeft">
            <input id="ffcBtnPost" name="delivery" value="post" type="radio" checked/>Почта<br/>
            <input id="ffcBtnCourier" name="delivery" value="courier" type="radio"/>Курьер<br/>
            <input id="ffcBtnPickup" name="delivery" value="pickup" type="radio"/>Самовывоз<br/>
        </div>
        <div id="ffcDeliveryPrice" class="ffcDeliveryPrice">400</div>
        <div style=" width:100%; height:1px; clear:both;"></div>
    </div>

    <div id="ffcCourierDiv" class="divBlock dn">
        <div id="ffcCourierCity">Город клиента (заполняется автоматически)</div>
        <input id="ffcCourierMetro" class="inputStringWithBtn dn" type="text" placeholder="Станция метро"/>
        <input id="ffcCourierDate" type="date" /><br />
        <select id="ffcCourierTime">
            <option value="10:00 - 15:00">10:00 - 15:00</option>
            <option value="10:00 - 18:00">10:00 - 18:00</option>
            <option value="10:00 - 22:00">10:00 - 22:00</option>
            <option value="15:00 - 20:00">15:00 - 20:00</option>
            <option value="18:00 - 22:00">18:00 - 22:00</option>
        </select>
    </div>

    <div id="ffcPickupDiv" class="divBlock dn">
        Рязанский проспект 52А<br/>
        Метро- Рязанский Проспект<br/>
        С понедельника по пятницу с 11:00 до 21:00<br/>
        В субботу с 12:00 до 17:00<br/>
        Воскресенье – выходной<br/>
        <input id="ffcPickupDate" type="date"/><br />
        <select id="ffcPickupTime">
            <option value="10:00 - 15:00">10:00 - 15:00</option>
            <option value="10:00 - 18:00">10:00 - 18:00</option>
            <option value="10:00 - 22:00">10:00 - 22:00</option>
            <option value="15:00 - 20:00">15:00 - 20:00</option>
            <option value="18:00 - 22:00">18:00 - 22:00</option>
        </select>
    </div>

    <!--Сюда скрипт вставит список групп товаров и блоки с товарами-->
    <div id="ffcGood">
        <select id="ffcGoodFamily" class="inputStringLong"></select>
    </div>

    <input id="ffcSale" class="inputStringLong" type="text" placeholder="Скидка (целое число)"/><br/>
    <b>Итого:</b>&#160&#160<input id="ffcBtnCalculatePrice" type="button" value="Посчитать"/>
    <div id="ffcTotalPrise" class="divString">Пока считается по кнопке "Посчитать"</div>
    <input id="ffcBtnSave" type="button" value="Сохранить"/>
    <input id="ffcBtnCancel" type="button" value="Отмена"/>

</div>

Код после заполнения и отработки всех скриптов:
Код:

<div id="ffcDiv" class="form dn" style="display: block;">

    <div class="divTitle">Менеджер:</div>
    <div id="ffcManagerName" class="divString">CallCenter_01</div>
    <input id="ffcClientName" class="inputStringLong suggestions-input" name="clientName" type="text" placeholder="ФИО" autocomplete="off" style="box-sizing: border-box; padding-right: 1px;"><div class="suggestions-wrapper"><div class="suggestions-suggestions" style="position: absolute; left: -499px; top: 20px; width: 499px; display: none;"></div><span class="suggestions-addon" data-addon-type="spinner" style="left: -20px; top: 2px; height: 18px; width: 18px; display: none; opacity: 0;"></span><ul class="suggestions-constraints" style="left: -496px; top: 11px;"></ul></div><br>
    <input id="ffcClientAddress" class="inputStringLong suggestions-input" type="text" placeholder="Адрес" autocomplete="off" style="box-sizing: border-box; padding-right: 1px;"><div class="suggestions-wrapper"><div class="suggestions-suggestions" style="position: absolute; left: -499px; top: 20px; width: 499px; display: none;"></div><span class="suggestions-addon" data-addon-type="spinner" style="left: -20px; top: 2px; height: 18px; width: 18px; display: none; opacity: 0;"></span><ul class="suggestions-constraints" style="left: -496px; top: 11px;"></ul></div><br>
    <div id="ffcPostIndex" class="divString">633454</div>
    <input id="ffcClientPhone1" class="inputStringWithBtn" type="text" placeholder="Телефон">
    <button id="ffcBtnCall1" class="inputStringBtn" type="button">▶</button><br>
    <input id="ffcClientPhone2" class="inputStringWithBtn" type="text" placeholder="Дополнительный телефон (только цифры)">
    <button id="ffcBtnCall2" class="inputStringBtn" type="button">▶</button><br>
    <div class="divTitle">Комментарии к звонку (если были):</div>
    <div id="ffcCallCommentBlock">Пока нет ни одного комментария</div>
    <select id="ffcCallResult" class="inputStringLong"><option value="-1">Результат звонка</option><option value="10">Подтвержден</option><option value="30">Перезвонить в ...</option><option value="31">Недозвон: занято</option><option

... Все не влезло кусок убрал ...

    <div id="ffcPickupDiv" class="divBlock dn" style="display: none;">
        Рязанский проспект 52А<br>
        Метро- Рязанский Проспект<br>
        С понедельника по пятницу с 11:00 до 21:00<br>
        В субботу с 12:00 до 17:00<br>
        Воскресенье – выходной<br>
        <input id="ffcPickupDate" type="date"><br>
        <select id="ffcPickupTime">
            <option value="10:00 - 15:00">10:00 - 15:00</option>
            <option value="10:00 - 18:00">10:00 - 18:00</option>
            <option value="10:00 - 22:00">10:00 - 22:00</option>
            <option value="15:00 - 20:00">15:00 - 20:00</option>
            <option value="18:00 - 22:00">18:00 - 22:00</option>
        </select>
    </div>

    <!--Сюда скрипт вставит список групп товаров и блоки с товарами-->
    <div id="ffcGood">
        <select id="ffcGoodFamily" class="inputStringLong"><option value="Desire_Pheromone">Desire_Pheromone</option><option value="Valgus_Pro">Valgus_Pro</option></select>
    <div id="Desire_Pheromone" class="divBlock" style="display: block;"><input type="checkbox" name="Desire_Pheromone" value="Desire_Pheromone_5_ml_990" goodid="0"><span>5 мл цена 990<br></span><input type="checkbox" name="Desire_Pheromone" value="Desire_Pheromone_10_ml_1290" goodid="1"><span>10 мл цена 1290<br></span><input type="checkbox" name="Desire_Pheromone" value="Desire_Pheromone_10_ml_2970" goodid="2"><span>10 мл цена 2970<br></span><input type="checkbox" name="Desire_Pheromone" value="Desire_Pheromone_20_ml_3960" goodid="3"><span>20 мл цена 3960<br></span><input type="checkbox" name="Desire_Pheromone" value="Desire_Pheromone_5_+_5_ml_1980" goodid="4"><span>5 + 5 мл цена 1980<br></span></div><div id="Valgus_Pro" class="divBlock" style="display: none;"><input type="checkbox" name="Valgus_Pro" value="Valgus_Pro_1_pcs_990" goodid="0"><span>1 шт цена 990<br></span><input type="checkbox" name="Valgus_Pro" value="Valgus_Pro_2_pcs_1980" goodid="1"><span>2 шт цена 1980<br></span><input type="checkbox" name="Valgus_Pro" value="Valgus_Pro_3_pcs_2780" goodid="2"><span>3 шт цена 2780<br></span><input type="checkbox" name="Valgus_Pro" value="Valgus_Pro_4_pcs_3580" goodid="3"><span>4 шт цена 3580<br></span></div></div>

    <input id="ffcSale" class="inputStringLong" type="text" placeholder="Скидка (целое число)"><br>
    <b>Итого:</b>&nbsp;&nbsp;<input id="ffcBtnCalculatePrice" type="button" value="Посчитать">
    <div id="ffcTotalPrise" class="divString">1290 + 300 - 120 = 1470</div>
    <input id="ffcBtnSave" type="button" value="Сохранить">
    <input id="ffcBtnCancel" type="button" value="Отмена">

</div>

Как видно и радиобаттоны переставлены и селекты не первоначальные и спрятанные поля отображены и штук 100 новых элементов DOM создано. Вот это все надо как-то по умному почистить и вернуть к "чистому виду" :)

Erolast 25.02.2015 15:01

Цитата:

Там JS всем рулит, через элементы DOM.
Поэтому нужно использовать MVC-фреймворк. На чистом JS такие вещи не делаются.

Цитата:

React.js в связке с https://babeljs.io/docs/usage/jsx/
Backbone.js в связке с Marionette.js или Chaplin.js (+, опционально, какой-нибудь http://rivetsjs.com/ для дата-байндинга)
AngularJS. Имхо, дарк сайд - философию JS курочит, хотя весьма удобен.

+ переходи на ES6.

ksa 25.02.2015 15:03

Цитата:

Сообщение от lucky89
и штук 100 новых элементов DOM создано

Тогда простым ресетом конечно не обойтись... :no:

Запасной вариант!
Иметь некий див-заготовку. Его внутренности просто клонировать в твой див-форму. Причем делать это всякий раз при его открытии. Прибил внутренности у дива-формы, клонировал внутренности из дива-заготовки - вот тебе и девственная форма заказа. ;)

ksa 25.02.2015 15:03

Цитата:

Сообщение от Erolast
На чистом JS такие вещи не делаются.

Экий ты пессимист! :D Все бы вам фремворки подавай... :nono:

Erolast 25.02.2015 15:05

Что-то не так? Ты поощряешь велосипеды?
Цитата:

Иметь некий див-заготовку. Его внутренности просто клонировать в твой див-форму. Причем делать это всякий раз при его открытии. Прибил внутренности у дива-формы, клонировал внутренности из дива-заготовки - вот тебе и девственная форма заказа.
Это как раз концепция V в MVC лол.

ksa 25.02.2015 15:09

Цитата:

Сообщение от Erolast
Что-то не так?

Чем провинился JS? :cray: Почему вдруг стало невозможным его использование?

ksa 25.02.2015 15:11

Цитата:

Сообщение от Erolast
Это как раз концепция V в MVC лол.

Не совсем понял что смешного в этом подходе? То, что его еще кто-от использует? :D
И только поэтому его использовать запрещено? А разрешено только с подключением некоего фреймворка? :blink:

Erolast 25.02.2015 15:29

Цитата:

Чем провинился JS? Почему вдруг стало невозможным его использование?
Не будь занудой. Я имел в виду "без сторонних модулей".

Цитата:

Не совсем понял что смешного в этом подходе? То, что его еще кто-от использует?
Абсолютно ничего смешного. Тот же реакт можно использовать только для V.
Вот только ты предлагаешь велосипедить все самому, когда уже есть готовые решения.

ksa 25.02.2015 19:47

Цитата:

Сообщение от Erolast
Не будь занудой.

Я еще и зануда... :D Самое главное в споре это обозвать оппонента. :yes:

Цитата:

Сообщение от Erolast
Вот только ты предлагаешь велосипедить все самому, когда уже есть готовые решения.

А ты предлагаешь начать присоединять сторонние фреймворки! :D И это ради нескольких строк кода...

lucky89 26.02.2015 06:52

так не работает
 
Цитата:

Сообщение от ksa (Сообщение 358369)
Запасной вариант!
Иметь некий див-заготовку. Его внутренности просто клонировать в твой див-форму. Причем делать это всякий раз при его открытии. Прибил внутренности у дива-формы, клонировал внутренности из дива-заготовки - вот тебе и девственная форма заказа

Может я не правильно понял, но вроде я так пробовал и написал в начале, что не получилось. Делал так:
var tmp = div.html(); //Сохранил в переменную чистый код
программа отработала...
div.html(tmp); //Вставил чистый код на место
Итог: формы чистые, но дальше ничего не работает, так как слетели все ранее определенные переменные, а именно все что было связано с DOM внутри div:
var $ffcDiv = $('#ffcDiv');
var $ffcManagerName = $('#ffcManagerName');
var $ffcClientName = $('#ffcClientName');
и т.д.
Можно, конечно, при чистке их каждый раз переопределять, но если я так подойду к созданию всех необходимых в будущем подобных div'ов, то боюсь получить лагающий портал...

Erolast 26.02.2015 08:56

Цитата:

Самое главное в споре это обозвать оппонента.
А? Это "обозвал" теперь называется? :blink:
Цитата:

А ты предлагаешь начать присоединять сторонние фреймворки! И это ради нескольких строк кода...
Я что-то не уверен, что на этих нескольких строках дело закончится.
Цитата:

Можно, конечно, при чистке их каждый раз переопределять, но если я так подойду к созданию всех необходимых в будущем подобных div'ов, то боюсь получить лагающий портал...
Вот именно поэтому и следует использовать бэкбон/реакт - они за тебя позаботятся, что надо перерисовывать и что нет (реакт особенно).
http://facebook.github.io/react/
https://babeljs.io/docs/usage/jsx/

ksa 26.02.2015 09:03

Цитата:

Сообщение от lucky89
не получилось

При клонировании "внутренностей" использование ИД недопустимо. :nono: Т.к. ИД должно быть уникально на странице.

В итоге у тебя должна быть такая структура

<div id='box-form'>
   <!-- тут будет работать пользователь -->
</div>
<div id='box-template'>
   <!-- тут размещаются пустые элементы -->
</div>

У ключевых элементов должен быть свой "уникальный" класс. И обращаться к ним нужно будет "через призму" родителя, т.е. так

var $ffcDiv = $('#box-form .ffcDiv');
var $ffcManagerName = $('#box-form .ffcManagerName');
var $ffcClientName = $('#box-form .ffcClientName');

ksa 26.02.2015 09:04

Erolast, делай как знаешь... :D Зануда. :p

lucky89 26.02.2015 18:24

Цитата:

ИД должно быть уникально на странице
Это конечно. Так он у меня был и есть уникальный.
div.html(tmp); - ничего не дублирует. Она совсем удаляет старое содержимое из div и вставляет туда код из переменной. Получается элементы со старыми ИД пропадают, а на их местах новые "пустые" элементы с такими же ИД. Я так понимаю, что с точки зрения DOM это абсолютно другие элементы и, по этому, ранее определенные всякие $ffcClientName = $('#ffcClientName'); слетают. Если определить по новой, то все работает.
И вот вопрос: что с точки зрения производительности лучше, все множество вложенных элементов поштучно вернуть к начальному состоянию или же обнулить html в div'e вышеуказанным способом и переопределить все переменные? Или как-то иначе?
PS: сторонние тяжеленные фреймверки для таких задач использовать не буду, так как очевидно, что даже поштучное восстановление элементов средствами jquery менее затратно по вычислительным ресурсам и объему кода. Я и jquery не хотел применять, но решил, что не осилю все нюансы кросбраузерности средствами голого js, так что пусть будет - спасет от множества недочетов.

ksa 26.02.2015 18:41

Цитата:

Сообщение от lucky89
ранее определенные всякие $ffcClientName = $('#ffcClientName'); слетают. Если определить по новой, то все работает.

Используй делегирование...
http://api.jquery.com/on/


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