Modify existing match code to exclude matches - javascript

I have some existing jQuery code I need to modify but it is beyond my JS capability (I was never a JS coder).
Currently I have...
jQuery(document).ready(function($) {
function doFilters() {
// Show all rows
$("tr:hidden").show();
// Chemistry
if ($("#filter_chemistry").val() != "") {
var chemFilter = $("#filter_chemistry").val().toLowerCase().split(',');
$("td.polymerTypel").each(function(){
var texts = $(this).text().split(',');
var match = chemFilter.every(function(v) { return texts.indexOf(v) != -1; });
$(this).parent().toggle(!!match);
});
}
};
});
This is not all of the filters but it is the relevant one. Basically it shows all rows in a table and then hides rows that don't match certain criteria.
The table has a hidden column with the class "polymerTypel" which could contain "st,ac" for example and then is someone puts "st" into the filter_chemistry field it will hide any row not containing st.
I need to modify this so that if someone enters "ac,-st" it will exclude those with st.
I have played with it but with literally 0 success.
A working copy is available here...
http://products.dunwood.co.uk/?range=all

Related

filter a table, highlight and hide the content of double words

I have a question !
I'm trying to create a filter in a table with mark.js, where found words are highlighted and non-highlighted content is hidden, so far so good
this is the code:
$(function() {
var $input = $("input[name='test']")
$context = $("table tbody tr");
$input.on("input", function() {
var term = $("#test").val();
$context.show().unmark();
if (term) {
$context.mark(term, {
done: function() {
$context.not(":has(mark)").hide();
}
});
}
});
});
the problem arises when I want to search for more words on the same line, the code will find the matches searched for type OR, while I would like to filter the search type AND and exclude all the other lines that do not have the double match.
How could I solve in your opinion?
this is what I need: jsfiddle.net/julmot/buh9h2r8/
adapting it to the code above, also because I would like to create a checkbox that allows me to search both type OR and type AND!
Thanks for your help

How to add all containers in a selection to an array

I am trying to get all the containers in a selection and add them into an array. So far, I have been able to get only the first container using the following code:
function getSelectedNode()
{
var containers = [];//need to add containers here so we can later loop on it and do the transformations
if (document.selection)
return document.selection.createRange().parentElement();
else
{
var selection = window.getSelection();
if (selection.rangeCount > 0)
return selection.getRangeAt(0).startContainer.parentNode;
}
}
So if I had:
<p>
<b>Here's some more content</b>.
<span style="background-color: #ffcccc">Highlight some</span>
and press the button. Press the other button to remove all highlights
</p>
and I selected this part of the text:
"Here's some more content Highlight"
Once I use the container returned by getSelectedNode() and do some transformation on it only "Here's some more content" gets affected correctly and not "Highlight". So is there a way to make it get all containers and not just the first one?
Note: I was also previously looking at this link:
How can I get the DOM element which contains the current selection?
and someone even commented:
"This solution doesn't work for all cases. If you try to select more than one tag, all the subsequent tags except the first one will be ignored."
Use Range.commonAncestorContainer and Selection.containsNode:
function getSelectedNode()
{
var containers = [];//need to add containers here so we can later loop on it and do the transformations
if (document.selection)
return document.selection.createRange().parentElement();
else
{
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
if (range.startContainer === range.endContainer) {
containers.push(range.startContainer);
} else {
var children = range.commonAncestorContainer.children;
containers = Array.from(children || []).filter(node => selection.containsNode(node, true));
}
}
}
return containers;
}
In your case, all possible "containers" are siblings that have no children, and we are selecting using a mouse or keyboard. In this case, we only have to consider two possibilities: you've selected a single node, or you've selected sibling nodes.
However, if your HTML were more complicated and you considered the possibility of scripts creating multiple selections, we'd have need a different solution. You would have to go through each node in the DOM, looking for ones that were part of something selection.
Maybee i am blondie and old school but if i have to fill a array i use a for next loop and something called push to fill the array. That might not be cool but usually works. I can not see any loop or pushing. So there will be only one element.`
other code
...
if (selection.rangeCount > 0)
for (var i;i<selection.rangeCount;i++){
var x= selection.getRangeAt(i).startContainer.parentNode ; //make a var
containers.push(x);//push var to array
}
return containers ;
}`
It seems that you wan't to unhighlight the selected text, it seems easer to go through the highlighted portions and see if they are part of the selection, here is an example:
document.addEventListener('mouseup', event => {
const sel = document.getSelection();
if (!sel.isCollapsed) {
const elms = [...document.querySelectorAll('.highlighted')];
const selectedElms = elms.filter(e => sel.containsNode(e, true));
if (selectedElms.length) {
selectedElms.forEach(e => {
let prev = e.nextSibling;
[...e.childNodes].forEach(child => e.parentElement.insertBefore(child, e));
e.remove();
});
sel.empty();
}
}
});
.highlighted {
background-color: #ffcccc
}
<p>
<b>Here's <span class="highlighted">Highlight <b>some</b></span> some more content</b>.
<span class="highlighted">Highlight some</span>
and press the button. Press the <span class="highlighted">Highlight some</span> other button to remove all highlights
</p>
Because I've used true as the second parameter to containsNode(...), this example will unhighlight the elements that are only partially selected.

Bootstrap form group checkboxes doesn't get checked in between nav pills

Here's the JSFiddle of my work: https://jsfiddle.net/pb23Ljd8/5/
I use Bootstrap nav-pills to show all products and categorized too like this:
And I based my checkboxes from here: http://bootsnipp.com/snippets/featured/fancy-bootstrap-checkboxes
I count the number of products checked in between the tabs like this:
jQuery(document).ready(function($) {
jQuery(".select-product").change(function() {
jQuery(".counter").text(jQuery("[type='checkbox']:checked").length);
});
});
But the glyphicon check icons doesn't appear on the second and third tabs for some reason. But when I click the products on the second and third, it increases the counter and also when I view it on the first tab, it is checked.
I just need the products to also be visibly checked on the second and third tabs and not only on the first one so it's not confusing for the user.
Ideas, anyone?
Edit: I fetch the list of products from CMS so it's dynamic. I now understand that the duplication of IDs is causing the problem.
Before we try and resolve this issues, we should break it down and see what the actual problem is.
First, let's check if we remove the content from tab 1b is the issue still present?
Nope, if we remove the checkboxes from the first tab, the checkboxes function normally on the second and third.
Fiddle #1
What if we change the id of the checkboxes (remember ids should be unique).
Notice how Book #1 now works if we change the first checkbox's id to 1a.
Fiddle #2
So now we "know" the issue is likely due to the fact that we are using checkboxes with the same id value (ref). The "issue" is now:
How do we check multiple checkboxes if one is checked
(or something like that)
Here's what I would do:
assign all "like" checkboxes the same class (ex. Book #1 checkboxes will have class b1)
use jQuery/javascript to make sure all that all "like" checkboxes, check and uncheck in unison
Working Example
EDIT
Dynamic values for the classes can be achieved by putting the IDs as classes so the similar products would match. These can be passed to JS like this assuming that $products_id_array is a PHP array that contains all the classes needed.
var productIDs = <?php echo json_encode($products_id_array) ?>;
and then creating the snippet of jQuery code on the fiddle like this
productIDs.forEach(function(val, key) {
jQuery('.' + val).on('change', function(){
jQuery('.' + val).prop('checked',this.checked);
});
})
Try this JS, This will work
jQuery(".select-product").change(function() {
var checkValue = jQuery(this).prop('checked');
$('.select-product#' + jQuery(this)[0].id).each(function() {
if (checkValue == true) {
jQuery(this).prop('checked', true)
} else {
jQuery(this).prop('checked', false);
}
});
var uniqueId = [];
jQuery("[type='checkbox']:checked").each(function() {
uniqueId.push(jQuery(this)[0].id);
});
Array.prototype.getUnique = function() {
var u = {},
a = [];
for (var i = 0, l = this.length; i < l; ++i) {
if (u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
jQuery(".counter").text(uniqueId.getUnique().length);
});

Checkboxes that display results with jQuery

I am trying to have the user check the boxes they are interested in getting resources for and then click the button to get a list of those resources that are hyperlinked to those resources. The hyperlinks (ul id="results” in HTML) are hidden until they called upon by the button “Get Resources”.
Plus I would like to add text to it before results saying “You have indicated an interest in:” (line break) then a listing the hyperlinks (line break) “Please click on the links to learn more”. If no check box is selected the div id=“alert” displays, which I got to work.
I think I am very close, I just can’t seem to get the list of resources.
Here is a link to my coding:
JSFiddle Code sample
$(document).ready(function() {
$('#alert').hide();
$('#results > li').hide();
/* Get the checkboxes values based on the parent div id */
$("#resourcesButton").click(function() {
getValue();
});
});
function getValue(){
var chkArray = [];
/* look for all checkboxes that have a parent id called 'checkboxlist' attached to it and check if it was checked */
$("#checkBoxes input:checked").each(function() {
chkArray.push($(this).val());
});
/* we join the array separated by the comma */
var selected;
selected = chkArray.join(',') + ",";
/* check if there is selected checkboxes, by default the length is 1 as it contains one single comma */
if(selected.length > 1){
// Would like it to say something before and after what is displayed
$('#results > li.' + $(this).attr('value')).show();
} else {
$('#alert').show();
}
}
I'd ditch the selected variable and just check the chkArray contents against the list item classes like:
function getValue() {
var chkArray = [];
/* look for all checkboxes that have a parent id called 'checkboxlist' attached to it and check if it was checked */
$("#checkBoxes input:checked").each(function () {
chkArray.push($(this).val());
});
$('#results li').each(function () {
if ($.inArray($(this).attr('class'), chkArray) > -1) $(this).show()
else($(this).hide())
})
/* check if there is selected checkboxes, by default the length is 1 as it contains one single comma */
if (!chkArray.length) {
$('#alert').show();
//alert("Please at least one of the checkbox");
}
}
jsFiddle example
I found a straightforward way of achieving what you want. DEMO: https://jsfiddle.net/erkaner/oagc50gy/8/
Here is my approach: I looped through all checkboxes. This way I could get the index of the current item in the original list, i, and use this index to display the corresponding item in the second list. I filter the checked items by using .is(':checked') condition, and then added them item to the array:
function getValue() {
var chkArray = [];
$("#checkBoxes input").each(function (i) {//now we can get the original index anytime
if($(this).is(':checked')){//is the item checked?
chkArray.push($(this).val());//if so add it to the array
var selected;
selected = chkArray.join(", ");
if (selected.length) {
$('#results').find('li').eq(i).show();//show the corresponding link by using `i`
} else {
$('#alert').show();
}
}
});
}
Last thing in your $(document).ready function, add:
$("#checkBoxes input:checkbox").click(function() {
$('li.' + $(this).val().replace(/ /g, '.')).show()
});
JSFiddle
Explanation:
On document ready, add a click handler to the checkboxes that shows the corresponding hidden list item below. The tricky thing here is the spaces in the list names. This makes each word a separate classname, so simply combine the list names with a dot . which results in a sequential classname call in jQuery.
By using <li class="Fitness & Recreation"> as a list item classname, you are giving this item 3 classnames: Fitness, &, and Recreation. In jQuery you select elements with multiple classnames by including each name preceded by a dot .. For example, selecting a list item element with the classnames foo, bar, and baz:
$('li.foo.bar.baz').show()
In the case of <li class="Fitness & Recreation">:
$('li.Fitness.&.Recreation').show()
Since these values are stored in the value attribute of the checkboxes we use jQuery to pull these values: $(this).val(), replace the spaces with dots: .replace(/ /g, '.'), and concatenate the result to the li. portion to access the appropriate list item.

Hide/show div acting on keyup filter input

I have a script that works with a filter to display the current view of tr's in a table. Pretty simple...when you type in the filter, the table updates based on that query and returns the corresponding amount: Displaying 25 results for Search: ________ (the number changes). I then have a div included at the end of that statement that just reflects the text put into the filter: Displaying 25 results for Search: _______ and Filter "blah". I am looking to be able to hide that div when the filter text is deleted from the filter...the filter is deactivated. As of now, it will clear the actual text blah but leave the rest of the div and Filter " ".
Why is this happening? It should be activated/deactivated by the "keyup" of the filter, right? I have tried creating a separate function and adding an if else statement...no dice. I've also tried jQuery's hide() and show() methods as is used for the $('tbody.searchable').hide(); without luck. I'd like it to remain within the same "keyup" function.
$(document).ready(function(){
(function($) {
$('#filter').keyup(function() {
var rex = new RegExp($(this).val(), 'i');
$('tbody.searchable').hide();
$('tbody.searchable').filter(function() {
return rex.test($(this).text());
}).show();
var x = $('tbody.searchable:visible').length;
document.getElementById("filterUpdate").innerHTML = x;
//NEED TO HIDE THIS AFTER TEXT IN THE FILTER IS BACKSPACED (FILTER IS DEACTIVATED)
$('#filterText').html('and Filter = "' + $('#filter').val()+'"');
})
$('tbody').on("click", function() {
if($(this).data('href') !== undefined){
document.location = $(this).data('href');
}
});
}(jQuery));
});
You just need to check whether the input value is empty or not:
$('#filterText').html($(this).val() ? 'and Filter = "' + $('#filter').val()+'"' : '');
JSFiddle

Categories