Eduardo Lucio
Eduardo Lucio

Reputation: 2487

JQuery - Perform a "find()" excluding certain elements and their descendants

QUESTION:

Perform a "find()" excluding certain elements and their descendants.

REAL CASE:

Code Sample

The purpose of the code below is try to select all elements within $("#lbr_placehld"), but exclude all those that have the attribute lbr_mval_placehld and its descendants.

$("#lbr_placehld").find(":not([lbr_mval_placehld])");

HTML sample

<span id="lbr_placehld" lbr_mval_placehld="" lbr_mval_phld_grp_path="mg_bases_n_forms#1">
  <div class="form-group">
    <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome da Base</label>
    <div class="col-xs-10">
      <div class="clearfix">
        <input lbr_mval_fld_nm="str_id_base" name="mg_bases_n_forms#1.str_id_base" type="hidden">
        <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome da Base" lbr_mval_fld_nm="str_nm_base" name="mg_bases_n_forms#1.str_nm_base" type="text" autocomplete="off" lbr_fdly_nm="Nome da Base 2">
        <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
        <i class="fa fa-remove red field-border-icon"></i>
        </a>
        <div lbr_mval_container="" class="widget-box transparent">
          <div class="widget-header widget-header-small">
            <h6 class="smaller"></h6>
            <div class="widget-toolbar">
              <a href="#" title="Remover último item" class="lbr-tooltip" lbr_mval_op="rmlast" onclick="lbrad_MultivaluedManipulate(this);return false;" style="display: inline;">
              <i class="fa fa-remove red border-icon"></i>
              </a>
              <a href="#" class="lbr-tooltip" lbr_mval_op="add" onclick="lbrad_MultivaluedManipulate(this);return false;" title="Adicionar item">
              <i class="fa fa-plus blue border-icon"></i>
              </a>
              <a href="#" title="Remover todos itens" class="lbr-tooltip" lbr_mval_op="rmall" onclick="lbrad_MultivaluedManipulate(this);return false;" style="display:none;">
              <i class="fa fa-remove red border-icon"></i>
              </a>
            </div>
          </div>
          <div class="widget-body">
            <div class="widget-main">
              <span lbr_mval_grp_path="mg_forms" lbr_mval_last_idx="3">
                <div class="form-group">
                  <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome do Form</label>
                  <div class="col-xs-10">
                    <div class="clearfix">
                      <input lbr_mval_fld_nm="str_id_form" name="mg_bases_n_forms#1.str_id_form" type="hidden">
                      <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome do Form" lbr_mval_fld_nm="str_nm_form" name="mg_bases_n_forms#1.str_nm_form" type="text" autocomplete="off" lbr_fdly_nm="Nome do Form 2">
                      <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
                      <i class="fa fa-remove red field-border-icon"></i>
                      </a>
                    </div>
                  </div>
                </div>
                <hr>
              </span>
              <span lbr_mval_placehld="" lbr_mval_phld_grp_path="mg_forms#0">
                <div class="form-group">
                  <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome do Form</label>
                  <div class="col-xs-10">
                    <div class="clearfix">
                      <input lbr_mval_fld_nm="str_id_form" name="mg_forms#0.str_id_form" type="hidden">
                      <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome do Form" lbr_mval_fld_nm="str_nm_form" name="mg_forms#0.str_nm_form" type="text" autocomplete="off" lbr_fdly_nm="Nome do Form 1">
                      <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
                      <i class="fa fa-remove red field-border-icon"></i>
                      </a>
                    </div>
                  </div>
                </div>
                <hr>
              </span>
              <span lbr_mval_placehld="" lbr_mval_phld_grp_path="mg_forms#1">
                <div class="form-group">
                  <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome do Form</label>
                  <div class="col-xs-10">
                    <div class="clearfix">
                      <input lbr_mval_fld_nm="str_id_form" name="mg_forms#1.str_id_form" type="hidden">
                      <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome do Form" lbr_mval_fld_nm="str_nm_form" name="mg_forms#1.str_nm_form" type="text" autocomplete="off" lbr_fdly_nm="Nome do Form 2">
                      <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
                      <i class="fa fa-remove red field-border-icon"></i>
                      </a>
                    </div>
                  </div>
                </div>
                <hr>
              </span>
              <span lbr_mval_placehld="" lbr_mval_phld_grp_path="mg_forms#2">
                <div class="form-group">
                  <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome do Form</label>
                  <div class="col-xs-10">
                    <div class="clearfix">
                      <input lbr_mval_fld_nm="str_id_form" name="mg_forms#2.str_id_form" type="hidden">
                      <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome do Form" lbr_mval_fld_nm="str_nm_form" name="mg_forms#2.str_nm_form" type="text" autocomplete="off" lbr_fdly_nm="Nome do Form 3">
                      <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
                      <i class="fa fa-remove red field-border-icon"></i>
                      </a>
                    </div>
                  </div>
                </div>
                <hr>
              </span>
              <span lbr_mval_placehld="" lbr_mval_phld_grp_path="mg_forms#3">
                <div class="form-group">
                  <label class="col-xs-2 control-label no-padding-right" for="for_str_nm_base">Nome do Form</label>
                  <div class="col-xs-10">
                    <div class="clearfix">
                      <input lbr_mval_fld_nm="str_id_form" name="mg_forms#3.str_id_form" type="hidden">
                      <input class="col-xs-5" lbr_invalidat_msg="" lbr_mval_fld_fdly_nm="Nome do Form" lbr_mval_fld_nm="str_nm_form" name="mg_forms#3.str_nm_form" type="text" autocomplete="off" lbr_fdly_nm="Nome do Form 4">
                      <a href="#" title="Remover este item" class="lbr-tooltip" lbr_mval_op="rmthis" onclick="lbrad_MultivaluedManipulate(this);return false;">
                      <i class="fa fa-remove red field-border-icon"></i>
                      </a>
                    </div>
                  </div>
                </div>
                <hr>
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <hr>
</span>

Upvotes: 0

Views: 377

Answers (2)

Eduardo Lucio
Eduardo Lucio

Reputation: 2487

A more elaborate approach using @Taplar's "core" ideia.

For more explanation see the code notes below...

// NOTE: Make a JQuery find excluding certain elements and their descendants. By Questor
// . jqPntElOrPntQry - Ancestor over which a ".find()" will be executed using the
// "string" in jqFind. If it is a string then execute it as a JQuery query to define
// the ancestor. Not being a string and not being undefined then it will be the defined
// ancestor (resulting from a JQuery query). If it is undefined then execute the string
// in jqFind as a JQuery query to define the ancestor;
// . jqFind - Perform as a JQuery query on a ".find()" on the ancestor jqPntElOrPntQry.
// When jqPntElOrPntQry is undefined then, simplistically, execute the string in jqFind
// as a JQuery query for the elements you want to find excluding the elements that
// match jqExcl JQuery query and their descendants;
// . jqExcl - A JQuery query that matches the elements you want to exclude along with
// their descendants.
function findExclElmtsNDesc(jqPntElOrPntQry, jqFind, jqExcl){

    // NOTE: The approach below makes a filter excluding all elements found in jqExcl
    // JQuery query and their children, but excludes from that filter the "parent"
    // element (jqElInst/jqFind) if it is also found in jqExcl jqExcl query. By Questor
    // [Ref.: https://stackoverflow.com/a/58402312/3223785 ]

    var fExclElmtsNDescRtn;
    if (typeof jqPntElOrPntQry === "string" || 
            jqPntElOrPntQry instanceof String) {
    // [Ref.: https://stackoverflow.com/a/9436948/3223785 ]

        jqPntElOrPntQry = $(jqPntElOrPntQry);
        fExclElmtsNDescRtn = jqPntElOrPntQry.find(jqFind);
    } else if (typeof jqPntElOrPntQry !== "undefined") {
        fExclElmtsNDescRtn = jqPntElOrPntQry.find(jqFind);
    } else {
    // [Ref.: https://stackoverflow.com/a/16975373/3223785 ]

        fExclElmtsNDescRtn = jqPntElOrPntQry = $(jqFind);
    }

    // NOTE: Find every nested element. By Taplar
    fExclElmtsNDescRtn = fExclElmtsNDescRtn

       // NOTE: Filter out any element that has the attribute, or is a descendant
       // of an element that has the attribute. EXCLUDE the target element from the
       // check. By Taplar and Questor
       .filter(function(){
           return $(this).closest(jqExcl).not(jqPntElOrPntQry).length === 0;
       });

    return fExclElmtsNDescRtn;
}

Thanks! =D

Upvotes: 0

Taplar
Taplar

Reputation: 24965

var $topElement = $("#lbr_placehld");

   // find every nested element
$topElement.find('*')
   // filter out any element that has the attribute,
   // or is a descendant of an element that has the attribute.
   // EXCLUDE the top element from the attribute check
   .filter(function(){
       return $(this).closest('[lbr_mval_placehld]').not($topElement).length === 0;
   });

Upvotes: 1

Related Questions