Scraping <td> values on table generate by Javascript to Python - javascript

I've run with a problem with my web app.
Here's my code:
#app.route('/addrec',methods = ['POST', 'GET'])
def addrec():
if g.user:
if request.method == 'POST':
#UPPER PANE
payor = request.form['payor']
receiptno = request.form['OR']
paymentmethod = request.form['paymentmethod']
naive_dt = time.strftime("%m/%d/%Y")
collectiondate = naive_dt = datetime.now()
message = request.form['message']
#LOWER PANE
url_to_scrape = 'http://localhost:5000/form'
r = requests.get(url_to_scrape)
soup = BeautifulSoup(r.text)
nature = []
for table_row in soup.select("table.inmatesList tr"):
cells = table_row.findAll('td')
if len(cells) > 0:
nature = cells[0].text.strip()
natureamt = cells[1].text.strip()
nature = {'nature': nature, 'nature': natureamt}
nature_list.append(nature)
ent = Entry(receiptno, payor,officer, paymentmethod, collectiondate,message, nature_list)
add_entry(ent)
actions="Applied"
return redirect(url_for('form'))
return redirect(url_for('home'))
As you can see I am getting each of the values from my forms and is scraping the values in my table using beautifulsoup. However after I click the submit button, it loads forever. I am getting the valeus from the upper pane but not in the table.
By the way I am generating my cells from a javascript function onClick. Just in case my javascript might be the problem. or maybe there's an easy way to extract these values from the javascrip functions -> python. Here's my javascript code and HTML
<script type="text/javascript">
function deleteRow(o){
var p=o.parentNode.parentNode;
p.parentNode.removeChild(p);
}
function addRow()
{
var table = document.getElementById("datatable"),
newRow = table.insertRow(table.length),
cell1 = newRow.insertCell(0),
cell2 = newRow.insertCell(1),
cell3 = newRow.insertCell(2),
name = document.getElementById("form").value,
amount = document.getElementById("amount").value;
delete1 = delete1 = '<input type="button" class="btn btn-danger" class="glyphicon glyphicon-trash"id="delete" value="Delete" onclick="deleteRow(this)">';
cell1.innerHTML = name;
cell2.innerHTML = amount;
cell3.innerHTML = delete1;
findTotal();
}
function findTotal(){
var arr = document.querySelectorAll("#datatable td:nth-child(2)");
var tot=0;
for(var i=0;i<arr.length;i++){
var enter_value = Number(arr[i].textContent)
if(enter_value)
tot += Number(arr[i].textContent);
}
document.getElementById('total').value = tot;
}
</script>
HTML:
<form name="noc">
<input class="form-control input-lg" id="form" list="languages" placeholder="Search" type="text" required>
<br>
<input class="form-control input-lg" id="amount" list="languages" placeholder="Amount" type="number" required>
<br>
<button onclick="addRow(); return false;">Add Item</button>
</form>
<table id="datatable" class="table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>Nature of Collection</th>
<th>Amount</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
The data of these scraped values, I expect them to be saved to my database. On a cell. If possible I would like the list to be inserted in a column so I can get them later.
Or is there a way I can get the lists on a cleaner and better way to my database? Any help is appreciated. Thank you!

So it looks like you're using requests to try and get data generated by JS. Well this isn't going to work, unless you know some magic a lot of people don't. Requests can't deal with the JS, so it never runs. You should be able to get the data using selenium or something to automate a browser. Otherwise, I don't think you're going to be able to scrape it like this. But if someone knows a way to get JS generated data with requests, please post it.

Related

setValues from HTML dynamic table to SheetByName

I am building an automated solution on Google Apps Scripts for my job that is testing my basic knowledge of HTML and JS. I would appreciate some guidance.
Context:
I am building a tool to automate certain tasks on Google Sheets through formulas and scripts
The task I'm having issues with begins with the user clicking on a button that opens a getUi() Modal Dialog
The main challenge is to extract data out of an HTLM table where the user makes inputs
JS code triggering the popup (just for context):
function openbrief() {
//pull necessary values
var supp_main = SpreadsheetApp.getActive().getSheetByName('supp_main')
//projects
var projrng = supp_main.getRange(2, 64, 1000);
var projval = projrng.getValues();
var projname = projval.filter(String)
//content_category
var catrng = supp_main.getRange(2, 65, 1000);
var catval = catrng.getValues();
var catname = catval.filter(String)
//content_type
var typerng = supp_main.getRange(2, 66, 1000);
var typeval = typerng.getValues();
var typename = typeval.filter(String)
//format
var formatrng = supp_main.getRange(2, 67, 1000);
var formatval = formatrng.getValues();
var formatname = formatval.filter(String)
//channel
var chanrng = supp_main.getRange(2, 68, 1000);
var chanval = chanrng.getValues();
var channame = chanval.filter(String)
var widget = HtmlService.createTemplateFromFile('briefs');
widget.projdata = projname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.catdata = catname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.typedata = typename.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.formatdata = formatname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.chandata = channame.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
SpreadsheetApp.getUi().showModalDialog(widget.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(5000).setWidth(5000), 'Briefs');
}
Questions:
I have a GS/JS script within the HTML that is supposed to run through the table values, push them to an array and paste them to a gSheet. However it does not do that. I'm not experience with for loops and arrays on JS, and I can't tell what's not working.
Will this type of script pull the values from the dropdown menus? I suspect it won't as they seem to be sitting on top of the cell. But I'm unsure (see screenshot for more context)
Any other improvements or suggestions based on both code or screenshot is very welcome
References:
The script is "inspired" by this: Getting value from table cell in JavaScript...not jQuery
Here's another case I've been browsing but I fail to understand the solution provided: extract value from dynamic html table
HTML code
<table id="brief_table">
<thead>
<tr>
<th>Content category</th>
<th>Description</th>
<th>Content type</th>
<th>Format</th>
<th>Channel</th>
<th>Assets</th>
<th>Start date</th>
<th>End date</th>
<th>Relevant links</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select id="catname" style="Border: none;"><?!= catdata ?></select>
</td>
<td contenteditable='true'>Test</td>
<td>
<select id="typename" style="Border: none;"><?!= typedata ?></select>
</td>
<td>
<select id="formatname" style="Border: none;"><?!= formatdata ?></select>
</td>
<td>
<select id="channame" style="Border: none;"><?!= chandata ?></select>
</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
</tr>
</tbody>
</table>
<script>
function pasteBrief() {
var table = document.getElementById("brief_table");
var tablevalues = [];
for (var r = 0, n = table.rows.length; r < n; r++) {
for (var c = 0, m = table.rows[r].cells.length; c < m; c++) {
tablevalues.push(table.rows[r].cells[c].innerHTML);
}
}
alert(tablevalues);
google.script.run.pasteBriefVal(tablevalues);
}
</script>
GS SERVER CODE
function pasteBriefVal(tablevalues){
SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1:cb').setValues(tablevalues);
}
Screenshots:
Additional info:
I have managed to stringify the array, which in return allow me to paste it as a value in one single cell. This enable me to take a closer look to it (see img below)
Link to copy of the spreadsheet: link - to trigger the popup "briefs.html" you want to go to "[SOW] #2-Project & deliverables" and click on the icon that says "PLAN" around D24
Edits:
Moved setValues out of HTML file back to GS side. Called the new GS function out from HTML via google.script.run.pasteBriefVal(tablevalues)
Added more information on what the array look like
Added the link to a copy of the original spreadsheet should anyone want to take a deeper look
Server side GS and Client side JS
The below server side code does not run in a browser:
SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1').setValues(tablevalues);
If you wish to run server side code the use google.script.run

Retrieve input values in td from table without id

I need to retrieve date from the generic input field. The number of how many date (input field) user can create in form is unknown by me, so I count them by rowCount.
I'm not enable to extract the value of field (Syntax error maybe).
N.B when I lunch my code I get: Cannot set property '0' of undefined
html code:
<div>
<table id='dynamic_field_edit'>
<tbody>
<tr>
<td>Date</td>
<td><input type="text" placeholder="Enter date" /></td>
</tr>
<tr>
<td>Date:</td>
<td><input type="text" placeholder="Enter date" /></td>
</tr>
</tbody>
</table>
</div>
JS code :
var arrayDate = [];
var rowCount = document.getElementById('dynamic_field_edit').rows.length;
console.log(rowCount);
var allInputs = document.querySelectorAll('input');
for (let i = 0; i < allInputs.length; i++) {
arrayDate.push(allInputs[i].value);
}
console.log(arrayDate);
Edit:
After all suggested change it works, but it retrieve all values from input in document.
You just need to initialize your array:
var arrayDate = [];
EDIT:
Seems to work in this sample, can you compare to your code?
https://jsfiddle.net/emeLdecm/1/
(I added a button to fire off your JS, just to demonstrate)
Y you use jQuery syntax in plain javascript?
Select your table via:
table = document.getElementById('dynamic_field_edit');
and that iterate:
for (var i = 0, row; row = table.rows[i]; i++) {
// do your stuff
};
I find a way to achieve what I wanted to do by doing this.
#proggrock solution is also good for retrieving all input values in the document.
var arrayDate = [];
var rowCount = document.getElementById('dynamic_field_edit').rows.length;
console.log(rowCount);
$("#dynamic_field_edit").find('input:text')
.each(function() {
arrayDate.push($(this).val());
});
console.log(arrayDate);

Log Solutions In Table

I need help please.I created a calculator and wondering how i can make it to show the result both on the textbox and create a log on a column.
One for the question and another column for the answer./*
Fiddle link
<input type="button" value="="
onClick="document.calculator.ans.value=eval
(document.calculator.ans.value); addlog();" />
</form>
<br>
<table id="myTable">
<tr>
</tr>
<script>
function addlog()
{
var table = document.getElementById("myTable");
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = "Question";
cell2.innerHTML = "solution";
}
</script>
First problem, your table seems to be broken. Complete the table tag perhaps like this:
<table id="myTable">
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</table>
Next you could change from "onLoad" to "No wrap - (inhead)"
Then define the function like this with a global variable on top - question:
var question;
function addlog () {
var table = document.getElementById("myTable");
var row = table.insertRow(1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = question;
cell2.innerHTML = document.calculator.ans.value;
}
Finally in your calling method set the question and call addlog:
<input type="button" value="=" onclick="
question = document.calculator.ans.value;document.calculator.ans.value=eval(document.calculator.ans.value); addlog();" />
Here is a JSFiddle that seems to run fine JSFiddle
When I check the javascript console in your fiddle, it tells me addlog() is not defined. This is because it is defined in an onLoad event, which means it is defined within another function and therefore will not be visible to your window-level elements. Look for information on lexical closures to understand why.
The solution is simple: explicitly define your function as part of the window object:
window.addlog = function() {
//the same code here
}
There are other solutions, but this is a "best practice". In fact, all global variables should be explicit to make debugging easier. I hope this was helpful.

How to get the values from dynamically created row of textboxes in JSON

I am trying to create a row of text boxes dynamically through Javascript and read the values of the textbox in JSON. Later,I have to read JSON and display the values in textarea and this should achieved only though jquery and javascript.
I am able to create the text boxes dynamically but I am unable to read the values in JSON. When I use the jQuery part(mentioned below),the javascript to dynamically create textboxes is not working.Any suggestions please.
<table id="myTable">
<th>Name</th>
<th>Age</th>
<th>Gender</th>
<th>Occupation and Employer</th>
<th>Add</th>
<tr>
<td><input type="text" id="txtName" /></td>
<td><input type="text" id="txtAge" /></td>
<td><input type="text" id="txtGender" /></td>
<td><input type="text" id="txtOccupation" /></td>
<td><input type="button" id="btnAdd" class="button-add" onClick="insertRow()" value="add"></input></td>
<td><input type="button" id="btnSave" class="button-add" value="Save"></input> </td>
</tr>
</table>
<script>
var index = 1;
function insertRow()
{
var table=document.getElementById("myTable");
var row=table.insertRow(table.rows.length);
var cell1=row.insertCell(0);
var t1=document.createElement("input");
t1.id = "txtName"+index;
cell1.appendChild(t1);
var cell2=row.insertCell(1);
var t2=document.createElement("input");
t2.id = "txtAge"+index;
cell2.appendChild(t2);
var cell3=row.insertCell(2);
var t3=document.createElement("input");
t3.id = "txtGender"+index;
cell3.appendChild(t3);
var cell4=row.insertCell(3);
var t4=document.createElement("input");
t4.id = "txtOccupation"+index;
cell4.appendChild(t4);
index++;
}
$(document).ready(function(){
$("#btnsave").click(function ()
{
alert("Hi");
var dataToSend={
'Name':[],
'Age':[]};
dataToSend.Name.push({$("txtName").val().trim()});
dataToSend.Age.push({$("txtAge").val().trim()});
localStorage.setItem('DataToSend', JSON.stringify(DataToSend));
var restoredSession = JSON.parse(localStorage.getItem('dataToSend'));
// Now restoredSession variable contains the object that was saved
// in localStorage
console.log(restoredSession);
alert(restoredSession);
});
});
JSFIddle:http://jsfiddle.net/S7c88/
Since you are using jQuery you can greatly simplify the whole process by using methods like clone().
Here's a working example where I created one array of row objects. Since you aren't doing this in a form, I removed the ID's and just used data-name.
var $row;
function insertRow() {
$('#myTable').append($row.clone());
}
$(function () {
$row = $('tr').eq(1).clone(); /* clone first row for re-use*/
$('#myTable').on('click', '.btnSave', function () {
var dataToSend = [];
$('tr:gt(0)').each(function () {
var data = {};
$(this).find('input').each(function () {
data[$(this).data('name')] = this.value
});
dataToSend.push(data);
});
/* display data in textarea*/
$('#output').val(JSON.stringify(dataToSend, null, '\t'))
});
}) ;
I changed your input type=button to button to take advantage of using input selector while looping rows to create data and not have to filter out the buttons
Your demo has invalid html, missing <tr> for top set of <th>
DEMO
Some areas where you were going wrong:
$("txtName") Invalid selector
No row references in attempt to gather data

Accessing row element of table in Javascript

This is my first attempt in Javascript, so may be this is fairly easy question.
I need to access row element of a table, each row contains checkbox and two other column. If checkbox is checked, i need to get the id of checkbox.
I made following attempt but element_table.rows returns undefined, therefore i could not proceed. I debugged using Inspect element tool of eclipse and found element_table contains the rows.
Please suggest where I am making a mistake.
Javascript code:
function myfunction3(){
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table.rows;
var selectedTr = new Array();
var data = "";
for(var i =0 ; element_tableRows.length;i++)
{
var checkerbox = element_tableRows[i].getElementsByName('checkmark');
if(checkerbox.checked){
selectedTr[selectedTr.length] = element_tableRows[i].getAttribute("name");
data = data + element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
}
html code:
<table name="collection" border="1px">
<tr name="1">
<td><input type="checkbox" name="checkmark"></td>
<td>Tum hi ho</td>
<td>Arjit singh</td>
</tr>
<tr name="2">
<td><input type="checkbox" name="checkmark"></td>
<td>Manjha</td>
<td>Somesh</td>
</tr>
<tr name="3">
<td><input type="checkbox" name="checkmark"></td>
<td>Ranjhana</td>
<td>A.R Rehman</td>
</tr>
</table>
<input type="button" value="Check" onclick="myfunction3()">
here's a working version
function myfunction3(){
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table[0].rows;
var selectedTr = new Array();
var data = "";
for(var i =0 ; i < element_tableRows.length;i++)
{
var checkerbox = element_tableRows[i].cells[0].firstChild;
if(checkerbox.checked){
//selectedTr[selectedTr.length] = element_tableRows[i].getAttribute("name"); //not sure what you want with this
data = data + element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
alert(data);
}
http://jsfiddle.net/eZmwy/
jsfiddle for your example, your problem is mainly at when you getElementsByName you need to specify the index, also not that not all getElement methods are available in the table
i would also suggest you learn jQuery, this makes life easier, also not sure why you want to display the data as 1,2,3 the name on the tr... seems pretty strange to me
Actually this line
var element_table = document.getElementsByName('collection');
will return collection of elements. If you are sure that you have exactly one table with the specified name, try this approach:
var element_table = document.getElementsByName('collection')[0];
actually if you are using jQuery (very recommanded )
you can do something like
var idsArray = [];
$("[name=collection] tr td [type=checkbox]:checked").parent().each(function() {
idsArray .push($(this).attr('name'))
});
this answer related only to jQuery use (which is same as javascript only more compiled.)

Categories

Resources