6
\$\begingroup\$

I need to return True if a page contains any of a list of element types. This code works.

var elements = 0;
var content = $('.TestModule');
if (content !== null && typeof (content) !== "undefined") {
 elements += content.first().find('.btn').length;
 elements += content.first().find('.textbox').length;
 elements += content.first().find('.ui-jqgrid').length;
 elements += content.first().find('.flexboxdiv').length;
 elements += content.first().find('.headerlabel').length;
}
return elements > 0;

But always runs every test which is obviously inefficient so I changed to;

var valid = false;
var content = $('.TestModule');
if (content !== null && typeof (content) !== "undefined") {
 var elementTypes = ['btn', 'textbox', 'ui-jqgrid', 'flexboxdiv', 'headerlabel'];
 for (i = 0; i < elementTypes.length; i++) {
 var num = content.first().find('.' + elementTypes[i]).length;
 if (num > 0) {
 valid = true;
 break;
 }
 }
}
return valid;

Which also works and runs the minimum number of tests. But it looks pretty clunky to me. Can you suggest a better loop/structure/test, please? I don't need a count of element types, just to know whether one or more of any type exists.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Nov 24, 2015 at 11:07
\$\endgroup\$
2
  • \$\begingroup\$ @Kyll I wouldn't say "More strict", just different and strongly enforced. \$\endgroup\$ Commented Nov 24, 2015 at 11:26
  • \$\begingroup\$ @Zak I always say it to encourage users to actually read them =p \$\endgroup\$ Commented Nov 24, 2015 at 11:27

2 Answers 2

5
\$\begingroup\$

Join the string to create a jQuery selector

var elementTypes = ['btn', 'textbox', 'ui-jqgrid', 'flexboxdiv', 'headerlabel'];
var selector = '.' + elementTypes.join(', .');
return $('.TestModule').first().find(selector).length > 0;

The variable selector will return the string '.btn, .textbox, .ui-jqgrid, .flexboxdiv, .headerlabel' which can be used in the jQuery selector.

The statement

return $('.TestModule').first().find(selector).length > 0;

is equivalent to

return $('.TestModule').first().find('.btn, .textbox, .ui-jqgrid, .flexboxdiv, .headerlabel').length > 0;

after the string substitution.


To make it more dynamic, store complete selector in the array and join the array by ,-comma.

var elementTypes = ['.btn', '.textbox', '.ui-jqgrid', '.flexboxdiv', '.headerlabel', '#myId', 'input', 'input[name="firstname"]'];
var selector = elementTypes.join(', ');
answered Nov 24, 2015 at 11:11
\$\endgroup\$
1
  • 2
    \$\begingroup\$ That's exactly the sort of cleverness I was looking for. Thanks a lot! \$\endgroup\$ Commented Nov 24, 2015 at 11:33
1
\$\begingroup\$

You can utilize Array.prototype.reduce to calculate the sum of length.

var $testModuleFirst = $('.TestModule').first();
var selectors = ['.btn', '.textbox', '.ui-jqgrid', '.flexboxdiv', '.headerlabel'];
var elements = selectors.reduce(function(a, b) {
 return a + $testModuleFirst.find(b).length;
}, 0);
return elements > 0;
answered Nov 24, 2015 at 11:12
\$\endgroup\$
1
  • \$\begingroup\$ That is interesting. I was wondering about using an array function but didn't know how to go about it, so thanks for the example. \$\endgroup\$ Commented Nov 24, 2015 at 11:36

You must log in to answer this question.