Understanding simple sorting script , that compares values - javascript

I was just searching for a simple jquery sorting script and found this online:
$(function() {
$('ol').each(function() {
var matches = $('li', this).filter(function() { // Each item
var text = $(this).text();
return $('ul.three li').filter(function() { // Are there matches in .three?
return $(this).text() == text;
}).length > 0;
}).length;
$('li:last', this).text((matches * 10) + ' Points');
});
});
FIDDLE HERE
Notice how the values of the first 2 tables are compared with that of the values of the third table. now my question is about how matches is incremented, i went through the whole script, but don't quite understand how matches gets a value of 4 and 2 for the first and second table respectively(displayed in the respective table as 40 and 20). I understand the usage of the filter function, but don't quite understand how matches gets its value, I know the length property is involved, i see it at the end of the return statement, But still don't quite understand how is matches incremented ?

$(function() {
$('ol').each(function() {
var matches = $('li', this).filter(function() { // Each item
Here it will iterate over every li item that ins contained inside the ol element that is currently being iterated
var text = $(this).text();
return $('ul.three li').filter(function() { // Are there matches in .three?
return $(this).text() == text;
}).length > 0;
Here it will search in the ul with the class three if there is any li that has the same text as the one li that is being iterated. The filter function will return every element that matches the search, of course if all texts are different, it will return one element or none. Therefore, when it checks for it length > 0 what is doing is checking if there was at least one element that matched (aka: if this text was in .three. So here if it returns true, it will we counter for the previous filter.
}).length;
Here, the same as before, but with the outer filter, to check how many where found. Therefore, for the first one, the value is 4.
$('li:last', this).text((matches * 10) + ' Points');
});
});

Related

The problem of changing multiple of 3 to red using jquery on the presented screen

Only jquery script should be used to mark the number of multiples of 3 in red.
Each number is made up of <table>.
I made the code below, but there's an error.
$(function(){
$("#Q2_1").find(function(){
var num = $("#Q2_1").val();
num = Number(num) + 1;
return num % 3 == 0;
});
.css({"color":"#f00"});
});
Please advise me what the problem is.
Or can you give me a similar but simple example?
Use a selector that returns all the td elements in the table.
Use filter() to restrict this based on a condition.
The condition should get the text of the element; value is for user inputs.
Get rid of the ; after the call, so you can append .css().
$(function() {
$("#tableid td").filter(function() {
let num = Number(this.innerText);
return num % 3 == 0;
}).css("color", "red");
});

How does the matching JS code using indexOf work?

I've managed to copy some JS over into my doc, and I've got it working. But I don't entirely understand how its doing it.
It's a search function to match with data in a table and hide any rows that don't match.
But I don't understand the active line of code that actually searches and matches. Would someone explain it?
$('#searchBar').keyup(function() {
searchFunction($(this).val());
});
function searchFunction(value) {
$('#results tr').each(function() {
var found = 'false';
$(this).each(function() {
if ($(this).text().toLowerCase().indexOf(value.toLowerCase()) >= 0) {
found = 'true';
}
});
if (found === 'true') {
$(this).show();
} else {
$(this).hide();
}
})
};
It's this line I can't get my head around:
if ($(this).text().toLowerCase().indexOf(value.toLowerCase()) >= 0) {
found = 'true';
}
I understand how it changes the variable to true, but I don't understand how it matches the data in the Table row with the Value fed in.
It converts the value you sent to the function to lowercase, and then looks at the data in the row. It converts that to lowercase too, and sees if there is a match using indexof, which is covered here: How to use IndexOf in JQuery
Basically, the indexOf() method returns the position of the first occurrence of a specified value in a string. It returns -1 if the value to search does not occur.
Consider searching for "test"
var str = "Hello this is a test";
var n = str.indexOf("test");
The result of n will be: 16, ergo, as in your script, larger than 0... and "found"
What it does is
For each rows in my table "result"
If one of all these values, that I look in lowercase, is equal to what I typed in the "searchBar" in lower case, more than one time, then I found it, and so found = "true"
From search bar key press event will be triggered and value of search bar will passed to search function
$("#searchBar").keyup(function() {
searchFunction($(this).val());
});
function searchFunction(value) {
//value will contain the value of search bar
$("#results tr").each(function() {
//assuming value is not there in tr
var found = "false";
//now searching for each tr for value
$(this).each(function() {
//converting to lower case and comparing each value with searchbar value
if (
$(this)
.text()
.toLowerCase()
.indexOf(value.toLowerCase()) >= 0
) {
found = "true";
}
});
//actual showing/hiding row
if (found === "true") {
$(this).show();
} else {
$(this).hide();
}
});
}
if need more info about index of
https://www.w3schools.com/jsref/jsref_indexof.asp
#MattCouthon let me know if you need anything else

How to verify the sorting(ascending and descending) functionality in casperjs

I am new to this framework and also not getting any idea how to test the sorting functionality with CasperJS.
The scenario is, I need to verify the search results with sorting functionality.
When i search with any keyword it displays all the possible matching results.
You will have to define your own comparison functions. Here for example one that compares the lexicographical string ordering in a case insensitive manner:
function cmpLexiInsAsc(a, b) {
return a.toLowerCase() < b.toLowerCase();
}
function cmpLexiInsDesc(a, b) {
return a.toLowerCase() > b.toLowerCase();
}
The difficulty will be to retrieve the proper elements that you can compare. For example, you will probably need to split the price and the currency, parse the price as number and compare those.
I will assume for the rest of the answer that you have a default <table> and use column-wise ordering.
You can define a function that takes the column index (beginning at 1), the additional selector to find the element in a cell and the comparison function for that column. It internally defines the CSS selectors or XPath expressions to access the table cells. Keep in mind that to do this, you need to know how many rows there are and possibly adjust this if there is a header/footer row.
function compare(colIndex, cellSelector, cmpFunc){
function rowSelector(rowIndex) {
return "table#tableId tr:nth-child(" + rowIndex + ") > td:nth-child(" + colIndex + ")" + cellSelector;
}
var count = this.getElementsInfo("table#tableId tr");
if (count < 2) {
return true;
}
var previous = this.getElementInfo(rowSelector(i)).text,
current;
for(var i = 2; i <= count; i++) {
current = this.getElementInfo(rowSelector(i)).text;
if (!cmpFunc(previous, current)) {
return false;
}
previous = current;
}
return true;
}
You can then run this compare() function for multiple columns depending on your criteria. For example:
casper.then(function(){
casper.test.assert(compare.call(this, 1, " > span > span.info", cmpLexiInsAsc), "Column 1 ascending");
this.click("some selector to change ordering");
});
casper.then(function(){
casper.test.assert(compare.call(this, 2, " > div > span.info", cmpLexiInsDesc), "Column 2 descending");
});
There is a rare bug in PhantomJS 1.x for :nth-child() CSS selectors. You may try to use XPath selectors which are supported in CasperJS through the helper function:
var x = require('casper').selectXPath;
...
casper.getElementsInfo(x("//table[#id='tableId']//tr["+rowIndex+"]/td["+colIndex+"]/span/span"));
Note that CasperJS is built on top of PhantomJS and has the same limitations. You cannot directly work on DOM elements outside of the page context (casper.evaluate()). You will need to get a representation of such an element beforehand. I do this by accessing the text property on the object returned from getElementsInfo().

jquery filter values according to specific character at specific position

I am trying to filter a table of part numbers according to a user-defined value at a specific position.
see jsFiddle --> http://jsfiddle.net/bagofmilk/wx9F3/12/
The problem is that I'm allowing multiple conditions - not just ONE character at ONE position.
If you take a look at the fiddle you will see I use Table Sorter 2.0 Plugin which works great. But I also created a small table above that with 7 textboxes. Each of these textboxes represents a value of a part number in the table below.
'data-log' = if the textbox is null the value is 0, else the value will be 1.
'data-val' = the character position in the part number string.
Example: If the user types "07" into item# 2, then the script will need to filter the table where the part number has a "0" at character position 2 in the string, and "7" at character position 3 in the string
Most filters will search the ENTIRE string for a "07", but I need this to be specific to its position.
I also need it so that when the user also types in "L" into item#7 that the script will filter the part numbers where "07" are at char positions 2,3 AND where "L" is at char position 11 in the string.
Here's the main function I'm trying to deal with:
$('.modx').keyup(function() {
//I emtpy the "values" array and "position" array
arrval = [];
arrpos = [];
//Whatever textbox the user types in must indicate there is a value
$(this).attr('data-log', '1');
//I create an array of user input values and their positions
$('.modx').each(function() {
if ($(this).attr('data-log') == 1) {
arrval.push($(this).val());
arrpos.push($(this).attr('data-val'));
} else {}
});
/* THIS IS WHERE IM STUCK...Using the "values" array and "position" array,
check each part number where all values and positions are true.
I CANNOT COME UP WITH THE LOGIC HERE... */
});
I might be approaching this completely the wrong way. If so, I'd love to hear any other methods, or if you can think of the logic I could apply at the end of this keyup function that would be awesome too.
It is a regex bases solution
Add an additional data-* attribute data-length to the second and 5th modx text fields as shown below
<input type='text' data-log='0' data-val='1' tabindex='2' placeholder='03' class='size2 modx' id='item2' data-length="2"/>
....
<input type='text' data-log='0' data-val='7' tabindex='6' placeholder='53'class='size2 modx' id='item6' data-length="2"/>
then
var $modxs = $('.modx').keyup(function () {
var string = $modxs.map(function () {
var value = $.trim(this.value),
length = $(this).data('length') || 1;
while (value.length < length) {
value += '.';
}
return value;
}).get().join('');
string = string.replace(/(.{3})(.{5})(.{1})/, '$1-$2-$3');
var regex = new RegExp(string, 'i');
$('#partNumbers tbody tr').hide().filter(function () {
return regex.test($.trim($(this).children().first().text()))
}).show()
});
$('#clearBtn').click(function(){
$modxs.val('');
$('#partNumbers tbody tr').show()
})
Demo: Fiddle
First, let's see the logic. jQuery's filter() function, which seems to be the most practical to use here, works by running a filter function for every result element. When this function returns true, the element will be included in the filtered set.
So, in the filter function we need to check whether the value for the actual row (the text value of the first cell in the row in this case) satisfies all the requirements stored in your arrays.
For this, we iterate on arrpos. For every value we use substr() to extract the relevant part of the examined string (position is the current one from arrpos, length is the length of the current arrval element) and then compare it to the current value from arrval. If they are not equal, the check already failed, so we return false. If the for loop finishes running, we are certain we can return true (every check was successful).
A simple implementation (not thoroughly tested, just an illustration):
$('#partNumbers tbody tr') //get the rows
.hide() //hide all of them
.filter(function () {
var tValue = $(this).find('td:first').text();
for (var i = 0, l = arrpos.length; i < l; i++) {
if (tValue.substr(arrpos[i], arrval[i].length) !== arrval[i]) {
return false;
}
}
return true;
})
.show(); //show only the filtered ones (for which true was returned)
jsFiddle Demo

Check if any tags have a certain inner HTML

How would i write a jquery function that returns true if any spans within a div with id 'word' have an inner HTML of value v? For the selector, I have:
$('#word span').html()
I'm confused as to the correct way to iterate through them, and return a boolean value because currently i have 5 span tags within that div.
You could use :contains as in $("#word span:contains(v)"), but that selects spans that contain 'v' rather than have it as an exact value. .html only returns the html string of the first element selected, so you probably want to iterate with .each and do an exact comparison:
var count = 0;
$("#word span").each(function () {
if ($.trim($(this).text()) === 'v') {
count++;
}
});
You can use filter method:
$("#word span").filter(function () {
return this.innerHTML === v; // in case that v is a variable
// return $(this).text() === 'v';
}).length;
The contains selector
Since you are alread using jQuery, you can take advantage of its .contains method or the ':contains' pseudo-selector:
$("#word span").contains("word")
OR
$("#word span:contains(word)")
This would not return true for each span that contains the word, but rather the elements that contain that word. You would be left with a list of matched elements, that can be manipulated like so:
var $matched = $("word span").contains("word");
$matched.each(function (i, el) {
// do something with the el
});
Reference
http://api.jquery.com/jQuery.contains/

Categories