JQuery: Get all elements of a class that are not decomment for an element with the same class name?

Problem . Given the specific element of the container container (window, div, set of fields, etc.), find all the elements of the class (.FormWidget) inside this DOM element, recursively search through everything from these container descendants. Include, but do not look inside , elements with the corresponding class (.FormWidget). Elements can be nested in n levels.

For example, given this HTML:

<fieldset id="MyFieldset" class="FormWidget FieldSetMultiplier"> <legend>My Legend</legend> <div> <label for="Field1">Field1</label> <input type="text" name="Field1" value="" id="Field1" class="BasicInput FormWidget"> </div> <div id="SomeWidget" class="FormWidget"> <label for="Field2">Field2</label> <div name="Field2" id="Field2" class="FormWidget RestrictedComboBox"></div> <input type="text"> </div> </fieldset> <div> <label for="Field3">Field3</label> <input type="text" name="Field3" value="" id="Field3" class="BasicInput FormWidget"> </div> 

Example 1:

Let the pseudo Jquery function “.findButNotInside ()” represent the functionality I'm looking for.

 $(document).findButNotInside('.FormWidget'); 

Should return only #MyFieldset and # Field3. Starting from the window, fields 1 and 2 and #SomeWidget are FormWidgets, but they cannot be enabled because the function cannot look through other .FormWidgets to find FormWidgets. Everything inside the .FormWidget field is disabled.

Example 2:

 $('#MyFieldset').findButNotInside('.FormWidget'); 

Only #Field1 and #SomeWidget should be returned. It should search for .FormWidget inside the target field, #MyFieldset , but should not return # Field2 because it is not allowed to search inside .FormWidget (in this case #SomeWidget) to find other .FormWidgets.

I think this can be done with the correct function and selector, but I'm not sure how this selector should be constructed?

+3
javascript jquery
source share
5 answers
 $.fn.findButNotInside = function(selector) { var origElement = $(this); return origElement.find(selector).filter(function() { var nearestMatch = $(this).parent().closest(selector); return nearestMatch.length == 0 || origElement.find(nearestMatch).length == 0; }); }; 

Fiddle The trick is to verify that nearestMatch indeed within our search context.

And note that this is not true:

 $('window').findButNotInside('.FormWidget'); 

... because there is no <window> . Do you want to:

 $(document).findButNotInside('.FormWidget'); 
+5
source share
 $("container-selector").find(".class").not(".class .class"); 
+1
source share

This solution is based on known information about the HTML structure:

 $('body .FormWidget').filter(function(){ return $(this).parents('.FormWidget').length == 0; }).css("border", "solid 3px red");​ $('#MyFieldset .FormWidget').filter(function(){ return $(this).parents('.FormWidget').length == 1; }).css("border", "solid 3px blue"); 

http://jsfiddle.net/dwgZu/

0
source share

Could not come up with a more elegant jqueryish solution. But this can be done recursively.

http://jsfiddle.net/zzBMq/

 function findIt($elements){ $elements.children().each(function(i){ var $this = $(this); if($this.is(".FormWidget")){ // do something with the matched element $this.css("border","1px solid red"); }else{ // make the recursive call findIt($this); } }); } findIt($("#MyFieldset")); 

You could turn this into a plugin.

0
source share
 (function($){ $.fn.findButNotInside = function(selector){ var _n,_o,elemArr=[]; this.find('.FormWidget').each(function(){ _o = _n; _n = $(this); try{ if(_o&&_o.find(_n).length){ _n = _o; if(elemArr.indexOf(_o)==-1) throw _o; }else throw _n; }catch(e){ elemArr.push(e); } }); return $().add(elemArr); } })(jQuery); 

script: http://jsfiddle.net/guerilla/p9fMX/

0
source share

All Articles