jQuery перебирает форму и извлекает метки полей и значения только видимых входных данных

#javascript #html #jquery #css

#javascript #HTML #jquery #css

Вопрос:

У меня есть следующая разметка, в которой у меня есть div-держатель <div data-name="holder"></div> для динамического содержимого.

 <div id="main" class="agent">
  <div class="page">
  <div data-name="holder">

    <div class="child">
        <div class="area" >
           <div class="box">
              <div  class="section" >
                 <div data-type="text" class="widget_type_text hidden" >
                     <div>
                         <label for="child0name">Full name</label>
                     </div>
                     <div>
                        <div class="validationMessage">
                           Enter Name
                        </div>
                         <input id="child0name" type="text" name="child[0][name]" required="" title="Enter full name">
                     </div>
                 </div>
                 <div data-type="radio" class="widget_type_radio" >
                     <div>
                        <fieldset>
                            <legend>Gender</legend>
                            <span data-value="male"><input id="child0genderMale" type="radio" name="child[0][gender]" value="male"><label for="child0genderMale">Male</label></span>
                            <span data-value="female"><input id="child0genderFemale" type="radio" name="child[0][gender]" value="female"><label for="child0genderFemale">Female</label></span>
                        </fieldset>
                     </div>
                 </div>
             </div>
          </div>
        </div>
        <div class="area hidden">
          <div class="box">
             <div class="section">
                <div data-type="date" class="widget_type_date">
                    <div>
                       <label for="child0dob">Date of Birth</label>
                    </div>
                    <div>
                       <div class="validationMessage">
                           Enter Date of Birth
                       </div>
                       <input id="child0dob" type="date" name="child[0][dob]" required="" title="Enter date of Birth">
                    </div>
                </div>
             </div>
          </div>
        </div>
        <div class="area ">
          <div class="box">
             <div class="section" data-access="agent">
                <div data-type="text" class="widget_type_text">
                    <div>
                       <label for="child0school">School</label>
                    </div>
                    <div>
                       <div class="validationMessage">
                           Enter School
                       </div>
                       <input id="child0school" type="text" name="child[0][school]" required="" title="Enter school">
                    </div>
                </div>
             </div>
          </div>
        </div>
     </div>

  </div>
 </div>
</div>
 
  • У владельца может быть несколько дочерних подразделений, у которых есть класс, называемый
    child удобно.
  • Каждый дочерний div может содержать несколько divs с вызываемым классом area .
  • Каждый div с вызываемым классом area может содержать один div с вызываемым классом section
  • Каждый div с вызываемым классом section может содержать несколько виджетов ввода формы, которые находятся внутри div с атрибутом типа данных.

видимость div с классом area section или data-type атрибутом можно переключать, включая hidden класс.

видимость каждого из этих divs также может быть ограничена путем включения data-access атрибута со значением либо agent, либо guest — это работает путем добавления класса agent или guest в #main div.

Таким образом, если гостевой пользователь получает доступ к сайту, в div с #main будет введен guest класс, и если это агент, у него будет agent класс, а затем следующий CSS используется для переключения видимости каждого div.

 #main.guest [data-access="agent"] {
    display: none;
}

#main.agent [data-access="guest"] {
    display: none;
}
 

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

Итак, в приведенном выше примере, если #main div имеет класс agent, пользователю отображаются только поля gender и school, поэтому функция будет извлекать метку поля и значение этих полей только потому, что виджет полного имени скрыт, а область даты рождения скрыта

Если бы у #main div был класс guest, то отображалось бы только поле gender, потому что виджет full name скрыт, область date of birth скрыта, а раздел школы div имеет доступ к данным только для агента.

Короче говоря, мне нужно проверить три divs, которые имеют либо класс area, section, либо тип данных attr, чтобы увидеть, не скрыты ли они. Я также должен проверить те же divs, чтобы увидеть, содержат ли они атрибут доступа к данным, и убедиться, что видимость не была скрыта этим.

так что на самом деле, если область div имеет либо скрытый класс, либо значение атрибута доступа к данным, которое не соответствует классу, <div id="main" class="agent"> нет необходимости проходить глубже, поскольку поле ввода будет скрыто

аналогично было бы в случае с div с классом раздела и, наконец, с div с типом данных attr.

Как мне выполнить цикл через такую разметку, чтобы извлекать метки полей и значения только тех элементов формы, которые были отображены?

Это то, что у меня есть до сих пор:

  if ($("[data-name='holder']").children().length > 0 ) {
 
      $('.child').each(function(index, element) {

          //pseudo code
          for each div with class area 
             if div does not have class hidden or if div has data-access attribute and $( "#main" ) has class with same value then
                   if div with class section does not have class hidden or if div has data-access attribute and $( "#main" ) has class with same value then
                         for each div with data-type attribute 
                              if div does not have class hidden or if div has data-access attribute and $( "#main" ) has class with same value then
                                   save the field label and field value in array
                              end if

                         end for 
                   end if

             end if

          endfor 

      });
 }
 

Изо всех сил пытаюсь преобразовать псевдокод в jQuery. любая помощь приветствуется.

*** ОБНОВЛЕНИЕ ***

Держатель div может отображаться на нескольких страницах внутри <div class="page"> div, и по мере прохождения пользователем формы видимость предыдущих страниц скрывается. Таким образом, простое использование псевдокласса jQuery:visible не будет работать, поскольку элементы на предыдущих страницах будут скрыты, но все равно должны быть представлены на странице сводки, поскольку они будут представлены пользователю.

Ответ №1:

Если классы (например: агент, гость) исправлены, и вы знаете, каковы все возможные комбинации, вы можете выполнить выбор следующим образом

 var $main = $('#main');
    
// filter all the class that are not in the main
var aClasses = ['agent', 'guest'].filter(function(cl) {
    return !$main.hasClass(cl)
});

// build the selector
var selector = ':not(.hidden)';
aClasses.forEach(function(cl) {
    selector  = ':not([data-access="'   cl   '"])'
})

$('div.area'   selector).each(function(i, el) {
    $('div.section'   selector, el).each(function(_i, _el) {
        $('div[data-type]'   selector, _el).each(function(__i, __el) {
            // you are inside the visible 'div[data-type]' here; do your stuff
        });
    });
});
 

или сделайте это одним большим махом, например:

 $(
    'div.area'   selector 
      ' div.section'   selector 
      ' div[data-type]'   selector
).each( function(i, el) {
    // your stuff
}
 

Или, если вы действительно не хотите выполнять выбор на основе основного div, имеющего класс (например: agent, guest) и проверяющего то же самое, вы могли бы попробовать

 var $main = $('#main');
    
// get the main div's class
var sClass = (['agent', 'guest'].filter(function(cl) {
    return $main.hasClass(cl)
})[0];

// make the two selector combination
var s1 = ':not(.hidden):not([data-access])';
    s2 = '[data-access="'   sClass   '"]:not(.hidden)';
    
$('div.area'   s1   ',div.area'   s2).each(function(i, el) {
    $('div.section'   s1   ',div.section'   s2, el).each(function(_i, _el) {
        $('div[data-type]'   s1   ',div[data-type]'   s2, el).each(function(__i, __el) {
            // your stuff
        });
    });
});
 

но здесь, чтобы написать все одним махом, вам пришлось бы использовать 8 разных комбинаций

например:

 // area-s1 sect-s1 div-s1, 
// area-s1 sect-s1 div-s2, 
// area-s1 sect-s2 div-s1,
// area-s1 sect-s2 div-s2,
// area-s2 sect-s1 div-s1,
// area-s2 sect-s1 div-s2, 
// area-s2 sect-s2 div-s1,
// area-s2 sect-s2 div-s2,

// ie:

$(
    'div.area'   s1   ' div.section'   s1   ' div[data-type]'   s1
      ',div.area'   s1   ' div.section'   s1   ' div[data-type]'   s2
      ',div.area'   s1   ' div.section'   s2   ' div[data-type]'   s1
      ',div.area'   s1   ' div.section'   s2   ' div[data-type]'   s2
      ',div.area'   s2   ' div.section'   s1   ' div[data-type]'   s1
      ',div.area'   s2   ' div.section'   s1   ' div[data-type]'   s2
      ',div.area'   s2   ' div.section'   s2   ' div[data-type]'   s1
      ',div.area'   s2   ' div.section'   s2   ' div[data-type]'   s2
).each(function(i, el) {
    // your stuff
})
 

поэтому было бы лучше использовать сам вложенный цикл.

Пример

 // assume the classes are (agent, guest) and main div is having class 'agent' then

/* First approch */
$('div.area:not(.hidden):not([data-access="guest"] div.section:not(.hidden):not([data-access="guest"] div[data-type]:not(.hidden):not([data-access="guest"]').each(function(index, elem) {
    //your stuff
})

// using nested loops
$('div.area:not(.hidden):not([data-access="guest"]').each(function(i, el) {
    $('div.section:not(.hidden):not([data-access="guest"'], el).each(function(_i, _el) {
        $('div[data-type]:not(.hidden):not([data-access="guest"'], _el).each(function(__i, __el) {
            // you are inside the visible 'div[data-type]' here; do your stuff
        });
    });
});


/* Second approch */
$(
    'div.area:not(.hidden):not([data-access]) div.section:not(.hidden):not([data-access]) div[data-type]:not(.hidden):not([data-access]), '
      'div.area:not(.hidden):not([data-access]) div.section:not(.hidden):not([data-access]) div[data-type][data-access="agent"]:not(.hidden), '
      ...
).each(function(i, el) {
    //your stuff
})

// using nested loops
$('div.area:not(.hidden):not([data-access]), div.area[data-access="agent"]:not(.hidden)').each(function(i, el) {
    $('div.section:not(.hidden):not([data-access]), div.section[data-access="agent"]:not(.hidden)', el).each(function(_i, _el) {
        $('div[data-type]:not(.hidden):not([data-access]), div[data-type][data-access="agent"]:not(.hidden)', _el).each(function(__i, __el) {
            // your stuff
        });
    });
});
 

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

1. у вас есть пример без использования ES6, поскольку мой jquery очень простой.?

2. @adam78 также добавил примеры.

3. означает ли следующее его условие и И $('div.area:not(.hidden):not([data-access="guest"] , т.Е. Область не скрыта, А доступ к данным не является гостевым? Как вы делаете это условием ИЛИ, т.Е. Область не скрыта или доступ к данным не является гостевым?

4. С помощью запятой. Смотрите второй подход. например: $('div.area:not(.hidden), div.area:not([data-access="guest"])

5. второй подход работает, но я столкнулся с другой проблемой: что, если у меня есть другие <div class="area"><div class="section"><div data-type="text"></div></div></div> вложенные внутри родительского раздела div. Я заметил, что в этом случае второй подход дублирует результаты, т.Е. Повторяет один и тот же div несколько раз?

Ответ №2:

:visible Псевдокласс jQuery будет фильтровать только [data-type] элементы, видимые пользователю.

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

 <script>
$(function () {
    function fetchFormData() {
        var result = [];

        $('[data-name=holder] [data-type]:visible').each(function (idx, elem) {
            var $elem = $(elem);
            var type = $elem.data('type');
            var label, value;

            // specific case: radio input
            if (type === 'radio') {
                label = $elem.find('legend').text();
                value = $elem.find('input[type=radio]:checked').val();

                result.push({label: label, value: value});

                // done with this item, skip to next one
                return true; // continue;
            }

            // generic case, works with most inputs
            label = $elem.find('label').text();
            value = $elem.find('input').val();

            result.push({label: label, value: value});
        });

        return resu<
    }


    // add this to an event handler
    console.log(fetchFormData());
});
</script>
 

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

1. это не сработает. Смотрите Мой обновленный пост, так как разделы-владельцы содержатся внутри раздела страниц, видимость которого скрыта как страницы пользователя через форму.