Cannot loop through array comparing text values, undefined result with Protractor - javascript

I am new to protractor and JavaScript and struggling trying to compare a delimited string to an array.
What I am trying to do is to find a list of all elements and then from each element, loop through the arrays to compare the text values to the delimited string but the delimited string values are 'undefined'
element.all(by.css('.itemField')).then(function (allFieldItems) {
var toCompare= ["AGO", "9"]
for (var i = 0; i < toCompare.length; i++) {
var valueToCompare = toCompare[i]
allFieldItems[i].getText().then(function (text) {
if(text != valueToCompare[i]){
console.log("Values don't match")
}
}.bind( i))
}
})
The problem is that the line "if(text != valueToCompare[i]) the "valueToCompare[i]" is always 'undefined' and I am looking for help on how to resolve this without using expect statements.

You can call getText() on the result of element.all() directly:
var toCompare = ["AGO", "9"];
element.all(by.css('.itemField')).getText().then(function (texts) {
for (var i = 0; i < toCompare.length; i++) {
if (texts[i] != toCompare[i]) {
console.log("Values don't match");
}
}
});
Or, you may even expect it like this (not sure if this is what you are actually trying to do):
expect($$('.itemField').getText()).toEqual(toCompare);

Related

javascript get only array elements equal to variable

I'm trying to compare the variable determineHour against the array stationRentalsHours, whenever the variable would be equal to a stationRentalsHours element, I'd like to add that element to another Array (stationRentalsHoursTemp), but only the values that match. I tried with simple operators, but that doesn't put anything into the temp array. I also tried using JQuery $.inArray, but that gives me some strange results, Equal to those in the original array. Are there any other methods of comparing a variable with an array for this particular task?
Thank you for any help.
function updateChart() {
if(canvas3){canvas3.destroy();}
var determineHour = selectNumber.options[selectNumber.selectedIndex].innerHTML;
for (var i = 0; i < stationRentalsHours.length; i++) {
/*if(determineHour == stationRentalsHours){
stationRentalsHoursTemp.push(stationRentalsHours[i]);*/
if( $.inArray(determineHour, stationRentalsHours[i])){
stationRentalsHoursTemp.push(stationRentalsHours[i]);
}
}
In this case, instead of using $.inArray, you can simply use the for loop and the index to test the equality. I guess you mixed up two things:
var determineHour = selectNumber.options[selectNumber.selectedIndex].innerHTML;
for (var i = 0; i < stationRentalsHours.length; i++) {
if( determineHour == stationRentalsHours[i]){
stationRentalsHoursTemp.push(stationRentalsHours[i]);
}
}
Better yet, use filter:
var determineHour = selectNumber.options[selectNumber.selectedIndex].innerHTML;
stationRentalsHoursTemp = stationRentalsHours.filter(function(val){return val == determineHour;});
Instead of
if( $.inArray(determineHour, stationRentalsHours[i])){
Try
if( $.inArray(determineHour, stationRentalsHours) != -1){
Your commented out code would do the trick with a slight amendment to the if condition. Your original condition was comparing a string to an array instead of an individual element in that array:
function updateChart() {
if(canvas3){
canvas3.destroy();
}
var determineHour = selectNumber.options[selectNumber.selectedIndex].innerHTML;
for (var i = 0; i < stationRentalsHours.length; i++){
if(determineHour == stationRentalsHours[i]){
stationRentalsHoursTemp.push(stationRentalsHours[i]);
}
}
}

loop through array to find matches and return every possible solution

I have a small input field where this code gets activated everytime a key is pressed inside it. But it now only prints "found something" when the name exacly matches what you type in the input field.
How can change a part that when I type something like "b" it already removes the matches where there is no "b" in the name is and print every possible matches that still have a "b".
My small code to find the match.
Info is my json big array where I can loop through all the names with info[i].name
var textInput = $findperson.find('input').val();
console.log(textInput);
for (i = 1; i < info.length; i++) {
if (textInput === info[i].name) {
console.log('found something');
}
}
Set Flag if found any match and print them, otherwise print found nothing,
for gi g mean search globally and i mean ignore case sothat A will match a and vise verse.
var textInput = $findperson.find('input').val();
console.log(textInput);
found = false
for (i = 1; i < info.length; i++) {
if (info[i].name.match(new RegExp(textInput,"gi")) ) {
console.log(info[i].name);
found = true
}
}
if(!found){
console.log("found nothing")
}
I would use regex like this:
var textInput = $findperson.find('input').val();
var regex = new Regexp(".*("+textInput+").*","i");
var filtered = info.filter(function (current) {
return current.name.match(regex);
});
console.log(filtered);
Just use indexOf to search for one String within another:
if(info[i].name.indexOf(textInput) != -1) {
indexOf will return -1 if String isn't found within the other.
You can try searching for some letters in one of the results 'balloon', 'ball', 'apple' in the example below:
var results = ['balloon', 'ball', 'apple'];
function filterResults() {
var input = document.getElementById('input').value;
var resultsFiltered = results.filter(function(a) {
return a.indexOf(input) != -1;
});
var result = ''; resultsFiltered.map(function(a) {
result += a + '<br/>';
}); document.getElementById('result').innerHTML = result;
}
<input id='input' onkeyup='filterResults();'/>
<div id='result'></div>

remove items from object if value is empty

So I'm taking a form and using serializeArray() to get all the forms data. There are 10 text inputs. What I am trying to do is skip the forms that return a empty result or forms that have "" as value. Here is what I came up with and it returns the index of the forms with "" or empty results correctly.
$("#" + forms).on("submit", function(event) {
var allData = $(this).serializeArray();
event.preventDefault();
for (var key in allData) {
if (allData[key].value === "") {
allData.splice(key, 1);
}
}
});
But when I add allData.splice(key, 1); it doesn't remove all the values with "" as a result. I basically want to remove any input that isn't going to have a value.
Also the structure of the objec is as follows.
[0]
name: "emailone",
value "some#email.com"
[1]
name: "passwordone",
value: "123asd"
[2]
name: "emailtwo",
value "another#email.com"
[3]
name: "passwordtwo",
value: "asd123"
[4]
name: "emailthree",
value ""
[5]
name: "passwordthree",
value: ""
That happens because you are altering the array while traversing it...
When you key is 4 and the value is '' you remove that element (succesfully) but when you splice the array it becomes a smaller one.. so the element at position 5 is now at 4. Your key variable is increased to 5 but now there is no element 5 in your array..
You need to traverse it backwards
$("#" + forms).on("submit", function(event) {
var allData = $(this).serializeArray();
event.preventDefault();
for (var key = allData.length-1; key >= 0 ; key--) {
if (allData[key].value === "") {
allData.splice(key, 1);
}
}
});
By splicing an array as you iterate over it, you can accidentally skip values - in this case, by removing a value at index four, you decrease the index of the following value by one. The loop than increments to five, and the value that started at the fifth index is skipped.
A few other answers have posted reasonable ways to work around this. If you're working with a newer version of JavaScript or with a library like jQuery or underscore, you could alternatively do this:
allData = allData.filter(function(e) {
return e.value !== "";
});
With jQuery, this can be written as
allData = $.grep(allData, function(e) {
return e.value !== "";
});
and in underscore:
allData = _.filter(allData, function(e) {
return e.value !== "";
});
var arrLength = allData.length, i, cleanArray = [], serializedArr;
for(i = 0; i < arrLength; i += 1{
if(allData[i] != ""){
cleanArray.push(allData[i]);
}
}
serializedArr = cleanArray.serializeArray();
You simply use delete to achieve your need,
for (var key in allData) {
if (allData[key].value === "") {
delete allData[key];
}
}
additionally you don't need explicitly get the value by this toallData[key].value, toallData[key] will simply return the value associated with the particular key.
DEMO
Updated:
for (var i=0; i < allData.length ; I++) {
if (allData[i].value === "") {
allData.splice(i, 1);
i--;
}
}
You should decrement the value of the index by one, every time you are removing an object from the array.

javascript not removing undefined objects from array

I've got an in page text search using JS, which is here:
$.fn.eoTextSearch = function(pat) {
var out = []
var textNodes = function(n) {
if (!window['Node']) {
window.Node = new Object();
Node.ELEMENT_NODE = 1;
Node.ATTRIBUTE_NODE = 2;
Node.TEXT_NODE = 3;
Node.CDATA_SECTION_NODE = 4;
Node.ENTITY_REFERENCE_NODE = 5;
Node.ENTITY_NODE = 6;
Node.PROCESSING_INSTRUCTION_NODE = 7;
Node.COMMENT_NODE = 8;
Node.DOCUMENT_NODE = 9;
Node.DOCUMENT_TYPE_NODE = 10;
Node.DOCUMENT_FRAGMENT_NODE = 11;
Node.NOTATION_NODE = 12;
}
if (n.nodeType == Node.TEXT_NODE) {
var t = typeof pat == 'string' ?
n.nodeValue.indexOf(pat) != -1 :
pat.test(n.nodeValue);
if (t) {
out.push(n.parentNode)
}
}
else {
$.each(n.childNodes, function(a, b) {
textNodes(b)
})
}
}
this.each(function() {
textNodes(this)
})
return out
};
And I've got the ability to hide columns and rows in a table. When I submit a search and get the highlighted results, there would be in this case, the array length of the text nodes found would be 6, but there would only be 3 highlighted on the page. When you output the array to the console you get this:
So you get the 3 tags which I was expecting, but you see that the array is actually consisting of a [span,undefined,span,undefined,undefined,span]. Thus giving me the length of 6.
<span>
<span>
<span>
[span, undefined, span, undefined, undefined, span]
I don't know why it's not stripping out all of the undefined text nodes when I do the check for them. Here's what I've got for the function.
performTextSearch = function(currentObj){
if($.trim(currentObj.val()).length > 0){
var n = $("body").eoTextSearch($.trim(currentObj.val())),
recordTitle = "matches",
arrayRecheck = new Array(),
genericElemArray = new Array()
if(n.length == 1){
recordTitle = "match"
}
//check to see if we need to do a recount on the array length.
//if it's more than 0, then they're doing a compare and we need to strip out all of the text nodes that don't have a visible parent.
if($(".rows:checked").length > 0){
$.each(n,function(i,currElem){
if($(currElem).length != 0 && typeof currElem != 'undefined'){
if($(currElem).closest("tr").is(":visible") || $(currElem).is(":visible")){
//remove the element from the array
console.log(currElem)
arrayRecheck[i] = currElem
}
}
})
}
if(arrayRecheck.length > 0){
genericElemArray.push(arrayRecheck)
console.log(arrayRecheck)
}
else{
genericElemArray.push(n)
}
genericElemArray = genericElemArray[0]
$("#recordCount").text(genericElemArray.length + " " +recordTitle)
$(".searchResults").show()
for(var i = 0; i < genericElemArray.length; ++i){
void($(genericElemArray[i]).addClass("yellowBkgd").addClass("highLighted"))
}
}
else{
$(".highLighted").css("background","none")
}
}
If you look at the code below "//check to see if we need to do a recount on the array length. ", you'll see where I'm stripping out the text nodes based off of the display and whether or not the object is defined. I'm checking the length instead of undefined because the typeof == undefined wasn't working at all for some reason. Apparently, things are still slipping by though.
Any idea why I'm still getting undefined objects in the array?
My apologies for such a big post!
Thanks in advance
I've modified your eoTextSearch() function to remove dependencies on global variables in exchange for closures:
$.fn.extend({
// helper function
// recurses into a DOM object and calls a custom function for every descendant
eachDescendant: function (callback) {
for (var i=0, j=this.length; i<j; i++) {
callback.call(this[i]);
$.fn.eachDescendant.call(this[i].childNodes, callback);
}
return this;
},
// your text search function, revised
eoTextSearch: function () {
var text = document.createTextNode("test").textContent
? "textContent" : "innerText";
// the "matches" function uses an out param instead of a return value
var matches = function (pat, outArray) {
var isRe = typeof pat.test == "function";
return function() {
if (this.nodeType != 3) return; // ...text nodes only
if (isRe && pat.test(this[text]) || this[text].indexOf(pat) > -1) {
outArray.push(this.parentNode);
}
}
};
// this is the function that will *actually* become eoTextSearch()
return function (stringOrPattern) {
var result = $(); // start with an empty jQuery object
this.eachDescendant( matches(stringOrPattern, result) );
return result;
}
}() // <- instant calling is important here
});
And then you can do something like this:
$("body").eoTextSearch("foo").filter(function () {
return $(this).closest("tr").is(":visible");
});
To remove unwanted elements from the search result. No "recounting the array length" necessary. Or you use each() directly and decide within what to do.
I cannot entirely get my head around your code, but the most likely issue is that you are removing items from the array, but not shrinking the array afterwards. Simply removing items will return you "undefined", and will not collapse the array.
I would suggest that you do one of the following:
Copy the array to a new array, but only copying those items that are not undefined
Only use those array items that are not undefined.
I hope this is something of a help.
Found the answer in another post.
Remove empty elements from an array in Javascript
Ended up using the answer's second option and it worked alright.

How do I avoid looping through an array to find a partial match?

I am looping through an array of english phrases, and if i find a match, with the current text node, i replace it with it's translation in the non_english array. All of that works 100% for exact matches.
But for partial matches, I need to use the .match command, which allows for partial matches.
My code to search for exact matches is like this:
var found = $.inArray(value,en_lang);
Then if there is a found value, then do replacement of text. This method is fast and I love it.
However to do partial word/phrase matching, I have to use this looping code.
// loop thru language arrays
for (var x = en_count; x > 0; x--) {
// assign current from/to variables for replace
var from = en_lang[x];
var to = other_lang[x];
// if value match do translation
if (value.match(from)) {
content(node, value.replace(from, to));
}
// mark this node as translated
if ($.browser.msie == 'false') {
$(node).data('translated', 'yes');
}
}
This does the job but is pretty slow. After a lot of research, I have found that I can convert the english array to a list-based string via the join command.
But I am unable to come up with a function to search this list for a partial match, and return the position in the list.
I was trying out this old js function created in 2006. But I can't figure out how to get the position back, correctly.
function listfind(list, value, delimiters) {
if (!delimiters) {
var delimiters = ','
}
_TempListSplitArray = list.split(delimiters)
var FoundIdx = 0;
for (i = 0; i < _TempListSplitArray.length; i++) {
if (_TempListSplitArray[i] == value) {
FoundIdx = i + 1;
break
}
if (value.match(_TempListSplitArray[i])) {
FoundIdx = i + 1;
break
}
}
return FoundIdx
}
Thank you for your time.
Javascript has a foreach type of system but its still based on a loop
var array = ['hello', 'world'];
for(var key in array){
alert(array[key]);
}
Thats the best your getting for looping though an array but this way allso works with objects
var obj = {'one':'hello', 'two':'world'];
for(var key in obj){
alert("key: "+key+" value: "+obj[key]);
}
UPDATED for Comments on your question
You can just replace the text you know
var str = "hello World";
str = str.replace("hello", "Bye bye");
alert(str);

Categories

Resources