How to convert table data to array by using selenium+Javascript - javascript

I want to get HTML table data to cover to array by using selenium and Javascript.
I test below code and I can get console.log(lm) in the for loop, but it shows
array each loop.
the wepage is https://www.scoresandodds.com/mlb
and click Game Details-->Line Movement
How I can get array(lm) at the end of the code? why I can not get any
data in my code ?
console.log("Line Movement=================================\n");
driver.findElement(By.xpath('//*[#id="line-movements-tab--65040"]/span')).click(); //Line Movement
await driver.sleep(2500);
let rowC = '';
driver.findElements(By.xpath('//*[#id="line-movements--65040"]/div/table/tbody/tr')).then( function(rows){
console.log("[" + rows.length + "]" + "\n\n");
rowC = rows.length;
});
var lm=[];
for (i=0; i<rowC; i++) {
for (s=1; s<5; s++) {
var addCellText=function(elem, doneCallback){
elem.getText().then(function(textValue){
driver.sleep(1000);
lm.push(textValue);
return doneCallback(null);
});
};
xpath='//*[#id="line-movements--65040"]/div/table/tbody/tr[' + i + ']/td[' + s + ']';
driver.findElements(By.xpath(xpath)).then(function(elem){
async.each(elem, addCellText, function(error){
driver.sleep(1000);
//console.log(lm);
});
});
}
}
console.log("lm");
console.log(lm);
each team has a different code such as 65040, please look at each games code in the html. For example today(5/30) ARI-ATL of the code is 65051.

Related

How to access attributes of NodeList elements in Protractor

I'm trying to read values from a fairly big HTML table in Protractor (about a thousand rows and 5 columns).
Protractor's element.all().getText() method is very slow at this, so I decided to implement a solution using browser.executeScript to read the values directly, like:
async getTextFromHtmlTable(){
try{
var rows = element.all(by.css('table[id^="P"] tr'));
var numRows = await rows.count();
var arrRows = [];
for (var i = 2; i <= numRows; i++){
console.log("********Processing row: " + i);
var css = 'table[id^=\"P\"] tr:nth-child(' + i + ') td div div';
//**Slow solution: var arrRowsText = await element.all(by.css(css)).getText();
//Faster:
var arrRowsText = await browser.executeScript("return document.querySelectorAll('" + css + "')").then(function(elements){
var arrayRes = [];
for (var j=0; j<elements.length; j++){
console.log("****** Element text: " + elements[j].textContent);
arrayRes.push(elements[j].textContent);
}
return arrayRes;
});
arrRows.push(arrRowsText.join(';').replace(/;\s/gm, ";"));
}
return arrRows;
}catch(err){
console.log ('Some error: ' + err)
};
}
However, console output when executing the test is:
********Processing row: 569
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
********Processing row: 570
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
No matter what attribute I read (textContent, innerText, innerHTML...), it always returns 'undefined'. Am I doing anything wrong? Thanks for the help!
I finally found a solution to this, DublinDev pointed me in the right direction when he said that executeScript does not return NodeLists. So I thought about processing the NodeList inside the executeScript method and have it return an array of texts instead of the actual NodeList:
var arrRowsText = await browser.executeScript("return (function(){" +
"var nodes = document.querySelectorAll('" + css + "');" +
"var arrayRes = [];" +
"for (var j=0; j<nodes.length; j++){" +
" arrayRes.push(nodes[j].innerText);" +
"}" +
"return arrayRes;" +
"})();");
Now it works like a charm and element texts are read much faster with innerText than with getText().
It appears that nodelists are returned through the executeScript method as an array of webElements so getText() should work. You also don't need to use .then() when something is already awaited. Can you try the below code?
async getTextFromHtmlTable(){
try{
var rows = element.all(by.css('table[id^="P"] tr'));
var numRows = await rows.count();
var arrRows = [];
for (var i = 2; i <= numRows; i++){
console.log("********Processing row: " + i);
var css = 'table[id^=\"P\"] tr:nth-child(' + i + ') td div div';
//**Slow solution: var arrRowsText = await element.all(by.css(css)).getText();
//Faster:
var arrRowsText = await browser.executeScript("return document.querySelectorAll('" + css + "')");
let allEleText = [];
for(let j = 0; j < arrRowsText.length; j++){
allEleText.push(await arrRowsText[j].getText());
}
arrRows.push(allEleText.join(';').replace(/;\s/gm, ";"));
}
return arrRows;
}catch(err){
console.log ('Some error: ' + err)
};
}

Issues attempting to display data from JSON file

Premise:
I'm playing around with javascript and have been trying to display a populated JSON file with an array of people on the browser. I've managed to display it through ajax, but now I'm trying to perform the same task with jQuery.
Problem:
The problem is that it keeps saying customerdata[i] is undefined and can't seem to figure out why.
$(function() {
console.log('Ready');
let tbody = $("#customertable tbody");
var customerdata = [];
$.getJSON("MOCK_DATA.json", function(data) {
customerdata.push(data);
});
for (var i = 0; i < 200; i++) {
//Cell for name
let nameTD = $('<td>').text(customerdata[i].first_name + ", " + customerdata[i].last_name);
//Cell for birthdate
let mDate = moment(customerdata[i].birthdate);
let formattedmDate = mDate.format('YYYY-MM-DD');
let birthdateTD = $('<td>').text(formattedmDate);
//Cell for Address
let addressTD = $('<td>').html("City: " + customerdata[i].city + '<br>' + "Email: " + customerdata[i].email + '<br>' + '<a href=' + customerdata[i].website + '>Website</a>');
//Cell for Credits
let creditTD = $('<td>').text(customerdata[i].credits);
let row = $('<tr>').append(nameTD).append(birthdateTD).append(addressTD).append(creditTD);
tbody.append(row);
}
})
SAMPLE CONTENT OF MOCK_DATA.json
[
{"id":1,"first_name":"Tracey","last_name":"Jansson","email":"tjansson0#discuz.net","gender":"Female","ip_address":"167.88.183.95","birthdate":"1999-08-25T17:24:23Z","website":"http://hello.com","city":"Medellín","credits":7471},
{"id":2,"first_name":"Elsa","last_name":"Tubbs","email":"etubbs1#uol.com.br","gender":"Female","ip_address":"61.26.221.132","birthdate":"1999-06-28T17:22:47Z","website":"http://hi.com","city":"At Taḩālif","credits":6514}
]
Firstly, you're pushing an array into an array, meaning you're a level deeper than you want to be when iterating over the data.
Secondly, $.getJSON is an asynchronous task. It's not complete, meaning customerdata isn't populated by the time your jQuery is trying to append the data.
You should wait for getJSON to resolve before you append, by chaining a then to your AJAX call.
$.getJSON("MOCK_DATA.json")
.then(function(customerdata){
for(var i = 0; i < 200; i++){
//Cell for name
let nameTD = $('<td>').text(customerdata[i].first_name + ", " + customerdata[i].last_name);
//Cell for birthdate
let mDate = moment(customerdata[i].birthdate);
let formattedmDate = mDate.format('YYYY-MM-DD');
let birthdateTD = $('<td>').text(formattedmDate);
//Cell for Address
let addressTD = $('<td>').html("City: " +
customerdata[i].city + '<br>' + "Email: " +
customerdata[i].email + '<br>' + '<a
href='+customerdata[i].website+'>Website</a>');
//Cell for Credits
let creditTD = $('<td>').text(customerdata[i].credits);
let row = $('<tr>').append(nameTD).append(birthdateTD).append(addressTD).append(creditTD);
tbody.append(row);
}
})
You also won't need to define customerdata as an empty array at all with this approach.
The problem is that data is already an array.
so you should use:
customerdata = data;
otherwhise you are creating an array in the pos 0 with all the data

accessing a specific column in a csv file using javascript

My problem is simple. I would like to know if there is a way to access a specific column from a csv file which is in MS Excel format. There are about 40 fields or columns in the file. I want to access only 3 of these. Please guide me.
Thanks in advance
This is as far as I got. Can we count the number of columns in the file?
$(document).on("click","#bucket_list a",function(evt){
// console.log("ID :: ",evt.target.id);
var bucketID = evt.target.id;
evt.preventDefault();
// alert("Event Fired");
counter = 0;
//lists the bucket objects
s3Client.listObjects(params = {Bucket: bucketID}, function(err, data){
if (err) {
document.getElementById('status').innerHTML = 'Could not load objects from ' + bucketID;
} else {
//document.getElementById('status').innerHTML = 'Loaded ' + data.Contents.length + ' items from ' + bucketID;
var listStart = document.createElement("ul");
document.getElementById('status').appendChild(listStart);
for(var i=0; i<data.Contents.length;i++){
fileKey = data.Contents[i].Key;
if(fileKey.search(str) != -1) {
//var listItems = document.createElement("li");
//listItems.innerHTML = data.Contents[i].Key;
//listStart.appendChild(listItems);
fileList[i] = data.Contents[i].Key;
//alert(fileList[i]);
counter = counter + 1;
}
}
if(counter == 0){
alert("This bucket has no CSV files. Please try another bucket!");
}
// else{
// for(var i = 0; i<fileList.length;i++){
// alert("File: " + fileList[i]);
// }
// }
}
//to read the contents of the files into textviews
var file = fileList[0];
//console.log("Loading:: ", file);
s3Client.getObject(params={Bucket: bucketID, Key: file},function(err,data){
if(err != null){ alert("Failed to load object " + err); }
else{
//alert("Loaded " + data.ContentLength + " bytes");
var allDataLines = data.split(/\r\n|\n/);
var headers = allDataLines[0].split(',');
}
});
});
});
I am unable to figure out how to get only the second column.
Yes. You have to parse the csv file to get the values for a particular column.Refer the following post on how to read a CSV file in Javascript.
[How to read data From *.CSV file using javascript?
To give you a head start the logic is simple . You just have to split based on "," and do a if statement.

Outputting array elements one at a time

Currently I am pushing form data (a single text field) to an empty array so that every time I click 'submit' the data is pushed to the end of the array (and thus, the array gets larger)
What I am experiencing:
I would like to output each element in a table, but I would like to do it one element per row, but right now it outputs like this per row
First row: Data entered and submit pressed once -> enteredData
Second row: More data entered and submit pressed -> enteredData
enteredData1
If I enter another element it does
enteredData
enteredData1
enteredData2
And so forth and so on....
Here's the code block that I have looping:
userInputName.push(userString);
for (arrayIndex = 0; arrayIndex < userInputName.length; arrayIndex++) {
output.innerHTML += "<tr><td>" + userInputName[arrayIndex] + "</td></tr>";
}
I feel like I'm missing some kind of conditional logic inside the for loop, but at this moment (too little sleep) I can't piece it together rationally :|
Any suggestions on what I'm missing?
This is what my full javascript code block looks like--I may reference this to my other thread asking a related question:
//Declare global variable
var userInputName = [];
function displayTableAndTotals() {
// Your code goes in here.
//var totalStrings = [];
var userString;
var arrayIndex;
var output;
var outputTotal;
var form;
form = document.getElementById("userFormId");
output = document.getElementById("userEntriesId");
outputTotal = document.getElementById("testId");
userString = form.string.value;
userInputName.push(userString);
for (arrayIndex = 0; arrayIndex < userInputName.length; arrayIndex++) {
output.innerHTML += "<tr><td>" + userInputName[arrayIndex] + "</td></tr>";
}
form.string.select();
return false;
}
you could just add the pushed element
var table = document.querySelector('#myTable');
document.querySelector('[type="submit"]').addEventListener('click', function(e) {
table.innerHTML += "<tr><td>" + userInputName.reverse()[0] + "</td></tr>";
}, false);
Good grief, of course I solve my own problem AFTER I spent forever agonizing and then consulting.
Basically I needed to do this:
for (arrayIndex = 0; arrayIndex < userInputName.length; arrayIndex++) {
tableData = "<tr><td>" + userInputName[arrayIndex] + "</td></tr>";
totalCount = userInputName.length;
}
output.innerHTML += tableData;
outputTotal.innerHTML = "<h4>Total Number of Strings: " + totalCount + "</h4>";
form.string.select();
return false;
So that the tableData variable would contain a new iteration without constantly resubmitting the entire thing every time. That way I could output tableData outside the loop properly.
I appreciate the feedback I have received.
Thank you!

post data from table row like json format

this is related to my last question(
NOTE: I already got some good answers there). I'm doing a program that will filter. I didn't include this question because i thought that it is easier for me to add text as long as i know how to get the data from the row. But to my dismay, I wasn't able to code a good program til now.
Im currently using this javascript code (thanks to Awea):
$('#out').click(function(){
$('table tr').each(function(){
var td = '';
$(this).find('option:selected').each(function(){
td = td + ' ' + $(this).text();
});
td = td + ' ' + $(this).find('input').val();
alert(td);
});
})
my question is: How to add text before the data from the row? like for example, this code alert
the first row like data1.1 data1.2 data1.3,
then the second row like data2.1 data2.2 data2.3,
I want my output to be displayed like this
[
{"name":"data1.1","comparison":"data1.2", "value":"data1.3"},
{"name":"data2.1","comparison":"data2.2", "value":"data2.3"},
{"name":"data3.1","comparison":"data3.2", "value":"data3.3"}
{.....and so on......}]
but before that happen, i want to check if all the FIRST cell in a row is not empty. if its empty, skip that row then proceed to next row.
is there somebody can help me, please...
Building on my answer to your previous question, see http://jsfiddle.net/evbUa/1/
Once you have your data in a javascript object (dataArray in my example), you can write the JSON yourself, per my example, but you will find it much easier to use a library such as JSON-js (see this also).
// object to hold your data
function dataRow(value1,value2,value3) {
this.name = value1;
this.comparison = value2;
this.value = value3;
}
$('#out').click(function(){
// create array to hold your data
var dataArray = new Array();
// iterate through rows of table
for(var i = 1; i <= $("table tr").length; i++){
// check if first field is used
if($("table tr:nth-child(" + i + ") select[class='field']").val().length > 0) {
// create object and push to array
dataArray.push(
new dataRow(
$("table tr:nth-child(" + i + ") select[class='field']").val(),
$("table tr:nth-child(" + i + ") select[class='comp']").val(),
$("table tr:nth-child(" + i + ") input").val())
);
}
}
// consider using a JSON library to do this for you
for(var i = 0; i < dataArray.length; i++){
var output = "";
output = output + '{"name":"data' + (i + 1) + '.' + dataArray[i].name + '",';
output = output + '"comparison":"data' + (i + 1) + '.' + dataArray[i].comparison + '",';
output = output + '"value":"data' + (i + 1) + '.' + dataArray[i].value + '"}';
alert(output);
}
})
There are two things you need to do here. First get the data into an array of objects, and secondly get the string representation.
I have not tested this, but it should give you a basic idea of what to do.
Edit Please take a look at this JS-Fiddle example I've made. http://jsfiddle.net/4Nr9m/52/
$(document).ready(function() {
var objects = new Array();
$('table tr').each(function(key, value) {
if($(this).find('td:first').not(':empty')) {
//loop over the cells
obj = {};
$(this).find('td').each(function(key, value) {
var label = $(this).parents('table').find('th')[key].innerHTML;
obj[label] = value.innerHTML;
});
objects.push(obj);
}
});
//get JSON.
var json = objects.toSource();
$('#result').append(json);
});
var a = [];
a[0] = "data1.1 data1.2 data1.3"
a[1] = "data1.6 data1.2 data1.3"
var jsonobj = {};
var c = []
for (var i = 0;i
alert(c); //it will give ["{"name":"data1.1","comp...1.2","value":"data1.3"}", "{"name":"data1.6","comp...1.2","value":"data1.3"}"]
u have to include library for function from JSON.stringify from
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
hope this helps

Categories

Resources