简体   繁体   English

jQuery 循环表单并仅检索可见输入的字段标签和值

[英]jQuery loop through form and retrieve field labels and values of visible inputs only

I have the following markup where I have a holder div <div data-name="holder"></div> for dynamic content.我有以下标记,其中我有一个用于动态内容的持有者 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>
  • The holder can have multiple child divs which has a class called child conveniently.持有人可以有多个子 div,其中有一个 class 方便地称为child
  • Each child div can contain multiple divs with a class called area .每个子 div 可以包含多个 div,其中 class 称为area
  • Each div with a class called area can contain a single div with a class called section每个带有 class 称为area的 div 可以包含一个带有 class 称为section的 div
  • Each div with a class called section can contain multiple form input widgets that sit inside a div with a data-type attribute.每个具有 class 称为section的 div 可以包含多个表单输入小部件,这些小部件位于具有数据类型属性的 div 内。

visibility of a div with class area , section or data-type attribute can be toggled by including a hidden class.可以通过包含hidden的 class 来切换具有 class areasectiondata-type属性的 div 的可见性。

visibility of each of these divs can also be restricted by including a data-access attribute with a value of either agent or guest - this works by adding either agent or guest class to the #main div.每个 div 的可见性也可以通过包含值为 agent 或 guest 的data-access属性来限制 - 这可以通过将 agent 或 guest class 添加到#main div 来实现。

So if a guest user is accessing the site, div with #main will have the guest class injected and if its an agent it will have a agent class and then the following CSS is used to toggle visibility of each div.因此,如果来宾用户正在访问该站点,带有#main 的 div 将注入guest class,如果它是代理,它将有一个agent class,然后使用以下 CSS 来切换每个 div 的可见性。

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

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

I need to retrieve the field labels and values for all form inputs whose visibility is not hidden, either by the hidden class or the data-access attributes and then re-display them on another page eg.我需要通过隐藏的 class 或数据访问属性检索所有未隐藏可见性的表单输入的字段标签和值,然后在另一个页面上重新显示它们,例如。 summary page.摘要页面。

So in the above example if the #main div has class of agent then only the gender and school fields have been displayed to user so function would retrieve the field label and value of those fields only because the full name widget is hidden and the date of birth area is hidden因此,在上面的示例中,如果#main div 具有代理的 class 则仅向用户显示性别和学校字段,因此 function 将检索字段 label 和这些字段的值,因为这些字段的全名和值是隐藏的出生区是隐藏的

If the #main div had class of guest then only the gender field would have been displayed because the full name widget is hidden, the date of birth area is hidden and school section div has data-access of agent only.如果#main div 有访客的 class 则只会显示性别字段,因为隐藏了全名小部件,隐藏了出生日期区域,并且学校部分 div 仅具有代理的数据访问权限。

So in short I need to check three divs which have either class area, section or data-type attr to see if they are not hidden.所以简而言之,我需要检查三个具有 class 区域、部分或数据类型 attr 的 div 以查看它们是否未隐藏。 I also have to check the same divs to see if they contain a data-access attribute and ensure visibility has not been hidden by that.我还必须检查相同的 div 以查看它们是否包含数据访问属性并确保可见性未被隐藏。

so really if the area div has either a hidden class or data-access attribute value that does not match the class in <div id="main" class="agent"> there is no need to traverse any deeper as the input field will have been hidden所以真的,如果区域 div 有一个隐藏的 class 或数据访问属性值与<div id="main" class="agent">中的 class 不匹配,则无需遍历更深,因为输入字段将被隐藏了

similarly would be the case with the div with section class and finally the div with data-type attr.具有 class 部分的 div 和最后具有数据类型 attr 的 div 也是如此。

How do I loop through such markup to pull out field labels and values of only those form element that have been displayed?如何循环遍历此类标记以仅提取那些已显示的表单元素的字段标签和值?

This is what I have so far:这是我到目前为止所拥有的:

 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 

      });
 }

Struggling to transform the pseudo code into jQuery.努力将伪代码转换为 jQuery。 any help appreciated.任何帮助表示赞赏。

*** UPDATE *** *** 更新 ***

The holder div can appear on multiple pages inside <div class="page"> div and as user steps through the form, the previous pages visibility is hidden.持有人 div 可以出现在<div class="page"> div 内的多个页面上,并且当用户逐步浏览表单时,先前页面的可见性被隐藏。 So simply using jQuery's:visible pseudo class wont work as items on previous pages will be hidden but still need to be presented on summary page as they will have been presented to user.因此,简单地使用 jQuery's:visible pseudo class 将无法工作,因为先前页面上的项目将被隐藏,但仍需要在摘要页面上显示,因为它们已呈现给用户。

If the classes (eg: agent, guest) are fixed and you know what are all the possible combination you can do the selecting like this如果类(例如:代理,客人)是固定的,并且您知道所有可能的组合是什么,您可以像这样进行选择

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

or, do it in one big swoop like:或者,一口气完成,例如:

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

Or if you really wan't to do the selecting based on the main div having a class (eg: agent, guest) and checking the exact same, you could try或者,如果您真的不想根据具有 class 的主 div 进行选择(例如:代理、访客)并检查完全相同,您可以尝试

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

but here, to write everything in one big swoop, you would have to use 8 different combination但是在这里,要一口气写完所有内容,您必须使用 8 种不同的组合

eg:例如:

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

so it would be best to use the nested loop itself.所以最好使用嵌套循环本身。

Example例子

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

jQuery's :visible pseudo class will filter only the [data-type] elements visible to the user. jQuery 的:visible伪 class 将仅过滤用户可见的[data-type]元素。

So using it on the selector should suffice per your description:因此,根据您的描述,在选择器上使用它就足够了:

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


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM