jQuery if div contains multiple text strings - javascript

I had a quick script to search for some text (a unique code) in a div and hide a different element if it exists:
var itemCode = ["000001"];
if( $(".itemCode").text().indexOf(itemCode) >= 0) {
$(".codeBox").addClass("hideElement");
}
however I wanted to expand this so it finds one of multiple texts (codes) and if any of them exist then hide the element:
var itemCode = ["000001", "000003", "000008"];
if( $(".itemCode").text().indexOf(itemCode) >= 0) {
$(".codeBox").addClass("hideElement");
}
and this isn't working. I'm sure It's probably something simple and I'm supposed to add a .each() somewhere but I'm just not getting it working when I experiment trying things, what am I missing?

Might be slighty quicker if you have a few item codes in your array
var itemCode = ["000001", "000003", "000008"];
var regExpPattern = itemCode.join('|');
if($(".itemCode").text().match(new RegExp(regExpPattern, 'i'))) {
$(".codeBox").addClass("hideElement");
}
});

indexOf takes only one (mandatory) argument, so you'll have to iterate over your list to find element(s) matching your condition :
var itemCode = ["000001", "000003", "000008"];
var contains = itemCode.some(function(code) {
return $(".itemCode").text().indexOf(code) >= 0;
});
if (contains) {
$(".codeBox").addClass("hideElement");
}

Related

Using Jquery Filter as a way to filter links on a page

I have a list of links on a page and a set of checkboxes that should filter the links so that only the ones that have the specific criteria will be active. My rudimentary attempt to do this involves creating an array of all the filter options that are active and running a .filter(Array) to make those active and a .not(Array) to disable the other links.
The problem is that if more than one filter options is selected any link that matches either filter option will be active. When in reality what i want is only the links that match ALL the filter options to be active.
Here is my stripped down version in jsFiddle
var filterAll = ["filter-F_0", "filter-F_1", "filter-F_2", "filter-F_3", "filter-F_4", "filter-P_0", "filter-P_1", "filter-P_2", "filter-P_3", ]
var filterActive = [];
function filterApps(){
if(filterActive.length == 0)
{
filterReset();
return;
}
var arrActive = $.map(filterActive, function (val) {
return '[' + val + ']'
}).join(",")
addToLog("arr = " + arrActive);
$(".appLink").filter(arrActive).css(activeAppCSS).addClass("active").removeClass("disable");
$(".appLink").not(arrActive).css(disabledAPPCSS).addClass("disable").removeClass("active");}
You have complicated many things here, using attribute's name for filtering the elements is a terrible idea (sorry), you could use data-* attributes that store the filtering criteria in an array. If I have understood the question correctly something like the following should work, this solution reads the attributes' name using attributes property, it should be noted that it's not the most efficient way of doing the task and as Array object's .filter() method is used it doesn't work in older browsers that don't support ES5, for supporting those browsers you can use a shim.
var $links = $('.appLink');
var $checkboxes = $('input[type=checkbox]').on('change', function () {
// Creating an array of values
var checked = $checkboxes.filter(':checked').map(function () {
return this.value.toLowerCase();
}).get();
// Filtering the .appLink elements by reading the attributes
// and comparing the filtered array's length with the checked one
$links.removeClass('matched').filter(function () {
return [].slice.call(this.attributes).filter(function (a) {
return a.name.indexOf('filter') === 0;
}).filter(function(f) {
return $.inArray(f.name.replace('filter-', ''), checked) > -1;
}).length === checked.length;
}).addClass('matched');
});
http://jsfiddle.net/85tTp/
In case that you want to use data-* properties, you can define an attribute like data-filter='["f1", "f2", ""]' for the elements and use jQuery .data() method for reading them:
$links.removeClass('matched').filter(function () {
return $(this).data('filter').filter(function(f) {
return $.inArray(f, checked) > -1;
}).length === checked.length;
}).addClass('matched');

Jquery Search - Case insensitive

I have had some help on a Jquery script which creates a searchable, toggleable FAQ. The code can be seen here:
http://jsfiddle.net/pT6dB/62/
The trouble is, if there is the word “How” with an upper case “H” and I search “h”, it wont find it. How can I make this script case insensitive?
Update
Alternatively, you could reduce the amount of code significantly using regular expression. jsFiddle demo
$('#search').keyup(function(e) {
// create the regular expression
var regEx = new RegExp($.map($(this).val().trim().split(' '), function(v) {
return '(?=.*?' + v + ')';
}).join(''), 'i');
// select all list items, hide and filter by the regex then show
$('#result li').hide().filter(function() {
return regEx.exec($(this).text());
}).show();
});​
Original
Based on your current algorithm for determining relative elements, you could use the jQuery filter method to filter your results based on the keywords array. Here's a rough idea:
// select the keywords as an array of lower case strings
var keywords = $(this).val().trim().toLowerCase().split(' ');
// select all list items, hide and filter then show
$('#result li').hide().filter(function() {
// get the lower case text for the list element
var text = $(this).text().toLowerCase();
// determine if any keyword matches, return true on first success
for (var i = 0; i < keywords.length; i++) {
if (text.indexOf(keywords[i]) >= 0) {
return true;
}
}
}).show();
Change this line
$('#result LI:not(:contains('+keywords[i]+'))').hide();
to
$('#result LI').each(function()
{
if(this.innerHTML.toLowerCase().indexOf(keywords[i].toLowerCase()) === -1)
{
$(this).hide();
}
});
// split the search into words
var keywords = s.toLowerCase().split(' ');
// loop over the keywords and if it's not in a LI, hide it
for(var i=0; i<keywords.length; i++) {
$('#result LI').each(function (index, element) {
if ($(element).text().toLowerCase().indexOf(keywords) != -1) {
$(element).show();
} else {
$(element).hide();
}
});
}

Build a switch based on array

I want to create a Javascript switch based on an array I'm creating from a query string. I'm not sure how to proceed.
Let's say I have an array like this :
var myArray = ("#general","#controlpanel","#database");
I want to create this...
switch(target){
case "#general":
$("#general").show();
$("#controlpanel, #database").hide();
break;
case "#controlpanel":
$("#controlpanel").show();
$("#general, #database").hide();
break;
case "#database":
$("#database").show();
$("#general, #controlpanel").hide();
break;
}
myArray could contain any amount of elements so I want the switch to be created dynamically based on length of the array. The default case would always be the first option.
The array is created from a location.href with a regex to extract only what I need.
Thanks alot!
#Michael has the correct general answer, but here's a far simpler way to accomplish the same goal:
// Once, at startup
var $items = $("#general,#controlpanel,#database");
// When it's time to show a target
$items.hide(); // Hide 'em all, even the one to show
$(target).show(); // OK, now show just that one
If you really only have an array of selectors then you can create a jQuery collection of them via:
var items = ["#general","#controlpanel","#database"];
var $items = $(items.join(','));
Oh, and "Thanks, Alot!" :)
I think you want an object. Just define keys with the names of your elements to match, and functions as the values. e.g.
var switchObj = {
"#general": function () {
$("#general").show();
$("#controlpanel, #database").hide();
},
"#controlpanel": function () {
$("#controlpanel").show();
$("#general, #database").hide();
},
"#database": function () {
$("#database").show();
$("#general, #controlpanel").hide();
}
}
Then you can just call the one you want with
switchObj[target]();
Granted: this solution is better if you need to do explicitly different things with each element, and unlike the other answers it focused on what the explicit subject of the question was, rather than what the OP was trying to accomplish with said data structure.
Rather than a switch, you need two statements: first, to show the selected target, and second to hide all others.
// Array as a jQuery object instead of a regular array of strings
var myArray = $("#general,#controlpanel,#database");
$(target).show();
// Loop over jQuery list and unless the id of the current
// list node matches the value of target, hide it.
myArray.each(function() {
// Test if the current node's doesn't matche #target
if ('#' + $(this).prop('id') !== target) {
$(this).hide();
}
});
In fact, the first statement can be incorporated into the loop.
var myArray = $("#general,#controlpanel,#database");
myArray.each(function() {
if ('#' + $(this).prop('id') !== target) {
$(this).hide();
}
else {
$(this).show();
}
});
Perhaps you're looking for something like this? Populate myArray with the elements you're using.
var myArray = ["#general","#controlpanel","#database"];
var clone = myArray.slice(0); // Clone the array
var test;
if ((test = clone.indexOf(target)) !== -1) {
$(target).show();
clone.splice(test,1); // Remove the one we've picked up
$(clone.join(',')).hide(); // Hide the remaining array elements
}
here you dont need to explicitly list all the cases, just let the array define them. make sure though, that target exists in the array, otherwise you'll need an if statement.
var target = "#controlpanel";
var items = ["#general","#controlpanel","#database"];
items.splice($.inArray(target, items), 1);
$(target).show();
$(items.join(",")).hide();
items.push(target);

Javascript getElementById based on a partial string

I need to get the ID of an element but the value is dynamic with only the beginning of it is the same always.
Heres a snippet of the code.
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite">
The ID always starts with poll- then the numbers are dynamic.
How can I get the ID using just JavaScript and not jQuery?
You can use the querySelector for that:
document.querySelector('[id^="poll-"]').id;
The selector means: get an element where the attribute [id] begins with the string "poll-".
^ matches the start
* matches any position
$ matches the end
jsfiddle
Try this.
function getElementsByIdStartsWith(container, selectorTag, prefix) {
var items = [];
var myPosts = document.getElementById(container).getElementsByTagName(selectorTag);
for (var i = 0; i < myPosts.length; i++) {
//omitting undefined null check for brevity
if (myPosts[i].id.lastIndexOf(prefix, 0) === 0) {
items.push(myPosts[i]);
}
}
return items;
}
Sample HTML Markup.
<div id="posts">
<div id="post-1">post 1</div>
<div id="post-12">post 12</div>
<div id="post-123">post 123</div>
<div id="pst-123">post 123</div>
</div>
Call it like
var postedOnes = getElementsByIdStartsWith("posts", "div", "post-");
Demo here: http://jsfiddle.net/naveen/P4cFu/
querySelectorAll with modern enumeration
polls = document.querySelectorAll('[id ^= "poll-"]');
Array.prototype.forEach.call(polls, callback);
function callback(element, iterator) {
console.log(iterator, element.id);
}
The first line selects all elements in which id starts ^= with the string poll-.
The second line evokes the enumeration and a callback function.
Given that what you want is to determine the full id of the element based upon just the prefix, you're going to have to do a search of the entire DOM (or at least, a search of an entire subtree if you know of some element that is always guaranteed to contain your target element). You can do this with something like:
function findChildWithIdLike(node, prefix) {
if (node && node.id && node.id.indexOf(prefix) == 0) {
//match found
return node;
}
//no match, check child nodes
for (var index = 0; index < node.childNodes.length; index++) {
var child = node.childNodes[index];
var childResult = findChildWithIdLike(child, prefix);
if (childResult) {
return childResult;
}
}
};
Here is an example: http://jsfiddle.net/xwqKh/
Be aware that dynamic element ids like the ones you are working with are typically used to guarantee uniqueness of element ids on a single page. Meaning that it is likely that there are multiple elements that share the same prefix. Probably you want to find them all.
If you want to find all of the elements that have a given prefix, instead of just the first one, you can use something like what is demonstrated here: http://jsfiddle.net/xwqKh/1/
I'm not entirely sure I know what you're asking about, but you can use string functions to create the actual ID that you're looking for.
var base = "common";
var num = 3;
var o = document.getElementById(base + num); // will find id="common3"
If you don't know the actual ID, then you can't look up the object with getElementById, you'd have to find it some other way (by class name, by tag type, by attribute, by parent, by child, etc...).
Now that you've finally given us some of the HTML, you could use this plain JS to find all form elements that have an ID that starts with "poll-":
// get a list of all form objects that have the right type of ID
function findPollForms() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
results.push(list[i]);
}
}
return(results);
}
// return the ID of the first form object that has the right type of ID
function findFirstPollFormID() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
return(id);
}
}
return(null);
}
You'll probably have to either give it a constant class and call getElementsByClassName, or maybe just use getElementsByTagName, and loop through your results, checking the name.
I'd suggest looking at your underlying problem and figure out a way where you can know the ID in advance.
Maybe if you posted a little more about why you're getting this, we could find a better alternative.
You use the id property to the get the id, then the substr method to remove the first part of it, then optionally parseInt to turn it into a number:
var id = theElement.id.substr(5);
or:
var id = parseInt(theElement.id.substr(5));
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite" target="_blank">
The ID always starts with 'post-' then the numbers are dynamic.
Please check your id names, "poll" and "post" are very different.
As already answered, you can use querySelector:
var selectors = '[id^="poll-"]';
element = document.querySelector(selectors).id;
but querySelector will not find "poll" if you keep querying for "post": '[id^="post-"]'
If you need last id, you can do that:
var id_list = document.querySelectorAll('[id^="image-"]')
var last_id = id_list.length
alert(last_id)

Javascript Insert Row

I have an HTML Table consisting of several rows. I am trying to insert rows at a specific position in the table. For example if I mark an already existing row and click insert a new row should be inserted below. At the moment adding rows at the bottom of the table works. What I need is to insert the already build row at a certain position.
Here is my code:
function addLine(lineNumberGlobal,columnnumber,insertion)
{
var newrow = document.createElement("tr");
newrow.setAttribute('id', globalObj.lineNumberGlobal);
newrow.setAttribute('onmousedown', "setCurIdG(getAttribute(\"id\"))");
for (j = 1; j <= globalObj.monthdays + 1; j++)
{
//build row cells with content
}
if (insertion == true)
{
var newrowinsert = globalObj.bodyGlobal.insertRow(globalObj.currenIdGlobal);
//this actually inserts a new empty row but I want to append my existing row "newrow"
}
else if (insertion == false)
{
globalObj.bodyGlobal.appendChild(newrow);
}
}
Any help would be appreciated ...
You can use the insertBefore DOM method. If you want to insert after the row that you have marked, you would need to use that row's nextSibling to find the row after it, and then insert before that.
If I assume that globalObj.currenIdGlobal is the ID of the row you want to insert after, that would look like this:
var refElement = document.getElementById(globalObj.currenIdGlobal);
if (refElement) { // Being defensive here, you probably know it _does_ exist
globalObj.bodyGlobal.insertBefore(newrow, refElement.nextSibling);
}
That assumes that your HTML is structured with no whitespace or similar between rows (since nextSibling will return the next node after the row, which can be a text node rather than an element). If you need to be more defensive:
function findNextSiblingElement(elm, tagName) {
do {
elm = elm.nextSibling;
} while (elm && (elm.nodeType != 1 || elm.tagName != tagName));
return elm;
}
and then change the above to:
var refElement = document.getElementById(globalObj.currenIdGlobal);
if (refElement) { // Being defensive here, you probably know it _does_ exist
globalObj.bodyGlobal.insertBefore(newrow, findNextSiblingElement(refElement, 'TR'));
}
Note that if you pass null as the second argument to insertBefore, it appends to the end.
FWIW, operations like these can be made a bit easier if you use a library like Prototype, jQuery, Closure, or any of several others.
Use insertRow to create the row.
Also: Don't use setAttribute, it's broken in IE. And an event handler requires a function reference and not a string.
function addLine(lineNumberGlobal,columnnumber,insertion)
{
var newrow = globalObj.bodyGlobal.insertRow(insertion ? globalObj.currenIdGlobal : -1);
newrow.id = globalObj.lineNumberGlobal;
newrow.onmousedown = function() { setCurIdG(this.id); };
for (j = 1; j <= globalObj.monthdays + 1; j++)
{
//build row cells with content
}
}
BTW, you seem to be using the id to "re-find" the table rows. Consider keeping a reference to the row instead.

Categories

Resources