I can only assume I'm doing something wrong, because when I step through the javascript it can't find the object at all.
What I'm trying to do is dynamically add rows of combo boxes to the table. The combo box code is more-or-less irrelevant, because trying to find the newly-generated inputs in the DOM by going through the form doesn't seem to work. I'm not sure if they even exist.
First, I have the form itself:
<form name="WEB070EDIT" action="WEB070" method="POST">
Then lower, there's the table that will contain the generated cells:
<table id='Form2Section2' width="100%" border=0 cellspacing=0 cellpadding=2>
<tr class="woborder">
<th >5. Material or Process Name</th>
<th >6. Specification Number</th>
<th >7. Code</th>
<th >8. Special Process Supplier Code</th>
<th >9. Customer Approval Verification</th>
<th >10. Certificate of Conformance Number</th>
</tr>
</table>
A bit above, there is my heinous script function that populates the table:
<script type="text/javascript">
function addForm1(itemId)
{
if (typeof addForm1.counter == 'undefined') {
addForm1.counter = 1;
}
var object = document.getElementById(itemId);
var curRow = object.insertRow(-1);
curRow.className = "woborder";
curRow.style.backgroundColor = "#D0D0D0";
var curCell = curRow.insertCell(-1);
var cellElem = document.createElement("text");
cellElem.size = 25
cellElem.value = ""
cellElem.name = "V_P2_MATERIAL_" + addForm1.counter;
cellElem.id = "V_P2_MATERIAL_"+ addForm1.counter;
var newAttr = document.createAttribute("onKeyUp");
newAttr.nodeValue = "...[some lengthy script stuff trimmed for readability]...";
cellElem.setAttributeNode(newAttr);
curCell.appendChild(cellElem);
curCell.appendChild(document.createElement("br"));
cellElem = document.createElement("hidden");
cellElem.name = "P2_MATERIAL_" + addForm1.counter;
cellElem.id = "P2_MATERIAL_" + addForm1.counter;
cellElem.value = "";
curCell.appendChild(cellElem);
cellElem = document.createElement("select");
cellElem.name = "MYSELECT_P2_MATERIAL_" + addForm1.counter;
cellElem.id = "MYSELECT_P2_MATERIAL_" + addForm1.counter;
cellElem.size = 10;
newAttr = document.createAttribute("onClick");
newAttr.nodeValue = "...[more script stuff here we don't care about]...";
eval("document.getElementById('V_P2_MATERIAL_" + addForm1.counter + "').focus();");
eval("combohandleKeyUp('WEB070EDIT','MYSELECT_P2_MATERIAL_" + addForm1.counter + "','V_P2_MATERIAL_" + addForm1.counter + "','P2_MATERIAL_" + addForm1.counter + "',MYLIST_P2_MATERIAL,MYDESCLIST_P2_MATERIAL,9999999);");
}
</script>
The reason we don't care about the onClick and onKeyUp is because we never get to that point. What's supposed to happen is that the eval() is supposed to run some javascript that populates the combo boxes with some predefined variables. It works perfectly, as long as the inputs are static. However, when I hit the button that runs this script, it pukes on that combohandleKeyUp right near the beginning, where it is supposed to find the following object:
document.forms['WEB070EDIT'].elements["P2_MATERIAL_1"]
Obviously this is all variables inside the script itself, but that's what it parses out to according to the debugger.
When I use Firebug's DOM inspector, I can find the forms, I can find WEB070EDIT, but I can't find the hidden input P2_MATERIAL_1. The static stuff's all in there, but nothing that's getting dynamically generated. Does this simply not work with dynamic objects? Am I missing something? Am I building it completely wrong?
I see various issues in here.
I don't understand why you're using eval(). The things that you're eval-ing could be just called as plain old JavaScript. The first eval() can be dropped and replaced by a simple .focus() call on the element as soon as it is added to the DOM.
What do you expect this to do?
document.createElement("text");
That creates a <text> tag in the HTML but that's not a valid tag. Are you trying to do something like this?
document.createElement("input");
cellElem.type = 'text';
//...
You're setting a size attribute so I'm guessing that you're trying to produce <input type="text" .../>.
You are initializing addForm1.counter but you never increment it. You'll end up with duplicate IDs that way and that leads to the gnashing of teeth and sundry sorts of confusion.
You create a <select>:
cellElem = document.createElement("select");
and then throw it away as you neglect to add it to the DOM. You also create an onClick attribute right after the <select> but you didn't add it to anything.
I stripped your code down a bit and added some things you were missing, seems to work just fine: http://jsfiddle.net/ambiguous/3v6R3/
Related
Overview:
I am creating a web page using Python and generating both html as well as javascript in my code. Additionally, I am parsing through csv files and converting their table data to html. I want to be able to click on a line of text and the associated table data for that text would then be loaded into an iframe on the currently active web page. The problem I am having, is that my javascript function is not recognizing the key I send it to retrieve the corresponding table data. If I manually enter the key to return the table data, the correct data is returned - though the table doesn't load. However, if I generate the key programmatically, it returns as 'undefined' even though the strings appear to be identical.
Goal:
I need to figure out if there is something wrong with either the syntax, or the format of the key I am using to try and retrieve the table data. Secondly, I need to figure out why the table data is not being correctly loaded into my iframe.
Example:
import pandas
opening_html = """<!DOCTYPE html><h1> Test</h1><div style="float:left">"""
table_html = pandas.DataFrame({'Col_1':['this', 'is', 'a', 'test']}).to_html()
tables_dict = {'test-1 00': table_html}
java_variables = "%s" % json.dumps(tables_dict)
table_frame = """<iframe name="table_frame" style="position:fixed; top:100px; width:750; height:450"></iframe>"""
test_link_text = """ test-1<br>"""
java = """<script type='text/javascript'>
var table_filename = """ + java_variables + ";"
java += """function send_table_data(obj) {
var t = obj.text + ' 00';
alert(t)
//This line below will not work
var table_data = table_filename[t];
//But this line will return the correct value
var table_data = table_filename['test-1 00'];
alert(table_data);
//This line should load the data, but does nothing
document.getElementsByName('table_frame').src = table_data;
}
</script>"""
html_text = """<head>
<link rel="stylesheet" href="style.css">
</head>""" + test_link_text + table_frame + """<body>""" + "</div>" + java + '</body>'
with open('test_table_load.html', 'w') as w:
w.write(html_text)
EDIT: I did just figure out that for some reason there was a default space at the beginning of the var t - so using trim() seemed to fix that. Now, the only issue left is why the data doesn't load into the table.
It looks like you figured out your typo with the space that was messing with your key, so this is for your second question.
Your code
So to get your table to populate in the iframe you need to fix three things:
To edit the HTML contents of your iframe you should be setting the .srcdoc element, not .src
The document.getElementsByName() function will return an array of HTML elements so in order to get the element you want you should do one of the following:
(recommended) switch to using document.getElementById and use id='table_frame' in your iframe tags
select the first element of the array by using document.getElementsByName('table_frame')[0]
The anchor tag that you're using as the trigger for your function is redirecting you back to the original HTML page, stopping you from seeing any of the changes your javascript function is making. A simple solution to this is to switch to using a <button> element in place of <a>.
Here is what your code looks like with the fixes:
import pandas
import json
opening_html = """<!DOCTYPE html><h1>Test</h1><div style="float:left">"""
table_html = pandas.DataFrame({'Col_1':['this', 'is', 'a', 'test']}).to_html()
tables_dict = {'test-1 00': table_html}
java_variables = "%s" % json.dumps(tables_dict)
table_frame = """<iframe id="table_frame" style="position:fixed; top:100px; width:750; height:450"></iframe>"""
test_link_text = """<button href='' onclick="send_table_data(this);"> test-1</button><br>"""
java = """<script type='text/javascript'>
var table_filename = """ + java_variables + ";"
#for the button, innerText needs to be used to get the button text
java += """function send_table_data(obj) {
var t = obj.innerText + ' 00';
alert(t)
//This line below will not work
var table_data = table_filename[t];
//But this line will return the correct value
var table_data = table_filename['test-1 00'];
alert(table_data);
//This line should load the data, but does nothing
document.getElementById('table_frame').srcdoc = table_data;
}
</script>"""
html_text = """<head>
<link rel="stylesheet" href="style.css">
</head>""" + test_link_text + table_frame + """<body>""" + "</div>" + java + '</body>'
with open('test_table_load.html', 'w') as w:
w.write(html_text)
Other Recommendations
I strongly suggest looking into some python frameworks that can assist you in generating your website, either using HTML templates like Flask, or a library that can assist in generating HTML using Python. (I would recommend Dash for your current use case)
I am newbie to google apps script. I am trying to write a google apps script that will take a table from gmail and put the data into google sheets.
The email body is somewhat like the following
CONFIRMATION CODE GUEST'S NAME GUEST'S EMAIL GUEST'S PHONE
A1 Name someone#gmail 012377777
So far I have tried the following the code to get the data in the email and push it to spreadsheet.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("[Gmail]/test");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
//ss.appendRow([msg, sub, dat])
}
// threads[i].removeLabel(label);
}
}
messages[j].getBody() gives me the following html
<u></u>
<div>
<table cellpadding="3" style="font-size:.9em">
<thead>
<tr>
<th>CONFIRMATION CODE</th>
<th>GUEST'S NAME</th>
<th>GUEST'S EMAIL</th>
<th>GUEST'S PHONE</th>
</tr>
</thead>
<tbody>
<tr>
<td>
A1
</td>
<td>
Name
</td>
<td>
someone#gmail
</td>
<td>
012377777
</td>
</tr>
</tbody>
</table>
</div>
Next I am trying to parse this using the following
var msg = threads[0].getMessages();
var rows = Xml.parse(msg[0].getBody(),true).getElement()
.getElement("div")
.getElement("table")
.getElement("tbody")
.getElements("tr");
But this throwing me the error "TypeError: Cannot call method "getElement" of null. " I do not have much experience with XML so please can you tell me what I am doing wrong here.
Thanks :)
It looks like you're calling .getElement() without specifying the element you want it to get. Looking at the docs, XmlService seems to be the current implementation of the api so you might want to use the functions provided for it rather than the deprecated versions in the XML object. https://developers.google.com/apps-script/reference/xml-service/
It looks like you could do something along the lines of:
var document = XmlService.parse(xml);
var content = document.getAllContent();
which will return an array of elements.
You could use what Anders has suggested, but since the content of the email does not have root elements which is something XMLService mandates as part of parsing.
You will have to append root elements on both ends of the email content.
I would recommend doing always writing line 1 before sending it to the parse method
var xml = "<root>" + messageBody + "</root>"
var document = XmlService.parse(xml);
var content = document.getAllContent();
I have created a Google form that is linked to a Google spreadsheet containing two sheets. I have also created a function in Google Scripts, called "handleFormSubmission", that when triggered (on submission of the linked form):
creates a variable containing the values of this submission from sheet one: var s0Row = s0.getRange("A"+(s0Last)+":J"+(s0Last)).getValues();
then, if a matching ID condition is met on both sheets, sets those values from sheet one into the appropriate range on sheet two: s1Row.setValues(s0Row);
There's probably a better way to do this, but for now the function works fine when run from Google Scripts and the form is returning submissions to sheet one.
The problem I'm having is getting this function to trigger when the linked form has been submitted. I've attempted to set this trigger up as you'll see in the screen shot below.
Code
function handleFormSubmission() {
var ss = SpreadsheetApp.openById("1FmArzo50IV2Wmykgsa89l_EARjzkiyeFDoPaCjGyBZM");
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActive();
var s0 = sheet.getSheets()[0];
var s0Last = s0.getLastRow();
var s1 = sheet.getSheets()[1];
var s1Last = s1.getLastRow();
var s0Bid = s0.getRange(s0Last, 10).getValue();
var s0Row = s0.getRange("A"+(s0Last)+":J"+(s0Last)).getValues();
for (var i = 2; i < s1Last + 1; i++) {
var s1Bid = s1.getRange(i, 10).getValue();
var s1First = s1.getRange(i, 2).getValue();
var s1LastName = s1.getRange(i, 3).getValue();
var s1Row = s1.getRange("A"+(i)+":J"+(i));
if (s0Bid === s1Bid) {
Logger.log(i + " " + s1First + s1LastName);
Logger.log("s0: " + s0Bid);
Logger.log("s1: " + s1Bid);
Logger.log("Match!");
s1Row.setValues(s0Row);
Logger.log("----------------------");
break;
} else {
Logger.log(i + " " + s1First + s1LastName);
Logger.log("s0: " + s0Bid);
Logger.log("s1: " + s1Bid);
Logger.log("Nope...");
Logger.log("----------------------");
}
};
};`
Current Project's Triggers
It's definitely an event on the spreadsheet that you're intercepting, although that may seem counter-intuitive.
I had the same problem & solved it by deleting the trigger, creating a new version of the script, then recreating the trigger. Don't know why it works -- perhaps a GAppsScript expert could explain it to us.
Also, why not get your form submission values out of the event object? So, instead of hunting down the last row of sheet[0] (which could, in an extreme case, not be the submission you're looking for, but the next one), you can access the field you want from the event object using either of:
e.values (an array of the form values in the order they appear in the spreadsheet)
e.namedValues (a dictionary/hash of the form values)
I think the event should be "From form" not "From spreadsheet". That is because you are working on script editor opened from the spreadsheet. It populates when you open the script editor from the form and write the function in that editor. Hope that helps!
I created an html 5 table with a single column that holds a variety of strings which are YouTube video URLs. I am able to insert strings into the table but the issue is that I am trying to use a JavaScript function to get a link(string) and insert it into my iframe YouTube player. Here is what I have:
Here is my table:
Link: <input id="link" type="link" name="link">
<button onClick="appendRow()" > Add Song </button>
<table id = "my_table" table border = "5">
<tr>
<th>Link</th>
</tr>
<tr>
<td>http://www.youtube.com/embed/evuSpI2Genw</td>
</tr>
</table>
Here is where I call my JavaScript function to insert the URL to the YouTube player:
<iframe width="888" height="420"
src="getURL()">
</iframe>
Here is my javascript function for grabbing the URL:
var counter = 0;
var songURL = "http://www.youtube.com/embed/evuSpI2Genw";
function getNextSong()
{
if(counter != 0)
{
var tbl = document.getElementById('my_table'), // table reference
songURL = tbl.rows[counter];
counter++;
return;
}
songURL = tbl.rows[0];
counter++;
return;
}
function getURL()
{
return songURL;
}
Please keep in mind that I am new to both JavaScript and HTML5.
A few things you need to consider
tbl.rows[counter] will grab the table row as an object, which will contain a collection of cells. You need to get the content of your cell using tbl.rows[counter].cells[0].innerHTML
Also you are never setting the iframe src. Give it an ID then you can access it via javascript.
Here is rough, and I do mean rough, working sample.
HTML
Link: <input id="link" type="url" name="link">
<button onClick="appendRow()" > Add Song </button><button onClick="getNextSong()" > Play Next </button>
<table id = "my_table" table border = "5">
<tr>
<th>Link</th>
</tr>
<tr>
<td>http://www.youtube.com/embed/evuSpI2Genw</td>
</tr>
</table>
<iframe width="888" height="420" id="player"
src="">
</iframe>
Javascript
var counter = 1;//The Header Row will be row 0
var songURL = "http://www.youtube.com/embed/evuSpI2Genw";
function getNextSong()
{
var tbl = document.getElementById('my_table'); // table reference
if(counter != 0)
{
songURL = tbl.rows[++counter].cells[0].innerHTML
document.getElementById('player').src=songURL;
return;
}
songURL = tbl.rows[1].cells[0].innerHTML;
counter++;
document.getElementById('player').src=songURL;
alert(songURL);
return;
}
function getURL()
{
return songURL;
}
function appendRow()
{
var tbl = document.getElementById('my_table');
var rowCount = tbl.rows.length;
var row = tbl.insertRow(rowCount);
var cell = row.insertCell(0);
cell.innerHTML = document.getElementById("link").value;
}
window.onload=function(){
document.getElementById('player').src=getURL();
};
I've made other adjustment to your script but it still could do with some tidying up.
Example: http://jsfiddle.net/HGKgn/
I think this is what you're trying to do, but only changing the src of one iframe on the page.
http://jsbin.com/orinas/2/
Works on IE9+, FF, Chrome, and Safari. Best viewed in Chrome, Safari or IE10.
I created this demo to show you what you could possibly do, while the JS is advanced, there are a lot of core concepts added in that could help you out. Not everything is commented in, because I threw it together quickly, but it is a very good demo that can help you organize your concept.
Notice as well, I do not use the table element =) I use standard elements that you would see on modern web pages today, as well as new CSS3 features.
Instead of having a table full of strings, you should store data like that on JavaScript's side in an Array []. The links array in my demo stores all the links that will show up on page load, and afterwards a user can add more links by clicking +Add and inserting a valid Youtube embed URL (something like http://youtube.com/embed/randomString).
I will be updating this answer later on.
I am trying to build a very simple tool for use at my work. I work for eBay and currently the tools available are cumbersome for the task. We are asked to compare text and images to check that sellers aren't stealing each others content. I am using the eBay Trading API and the sample HTML/CSS/Javascript code given when the developer account was created. Ultimately what I hope to achieve is a simple page that displays two items' photo and description next to each other. However, right now I am simply trying to edit the sample code given to display the start date of the auction.
My question is this: I am trying add a variable who's value is determined by a response from the API. some of these are provided in the sample however, when I add my own var starttime = items.listingInfo.startTime to the function and add the variable to the HTML table none of the data displays including those that displayed prior to my addition. Unfortunately I don't have more than a rudimentary understanding of javascript and so am unsure if I am even properly phrasing this question, let alone getting the syntax of my addition correct. What am I doing wrong?
below is the sample text with my addition of one declared variable (starttime) and one addition to the HTML table
<html>
<head>
<title>eBay Search Results</title>
<style type="text/css">body { font-family: arial,sans-serif;} </style>
</head>
<body>
<h1>eBay Search Results</h1>
<div id="results"></div>
<script>
function _cb_findItemsByKeywords(root)
{
var items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
var html = [];
html.push('<table width="100%" border="0" cellspacing="0" cellpadding="3"><tbody>');
for (var i = 0; i < items.length; ++i)
{
var item = items[i];
var title = item.title;
var viewitem = item.viewItemURL;
var starttime = items.listingInfo.startTime;
if (null != title && null != viewitem)
{
html.push('<tr><td>' + '<img src="' + pic + '" border="0">' + '</td>' +
'<td>' + title + '' + starttime + '</td></tr>');
}
}
html.push('</tbody></table>');
document.getElementById("results").innerHTML = html.join("");
}
</script>
<!--
Use the value of your appid for the appid parameter below.
-->
<script src=http://svcs.ebay.com/services/search/FindingService/v1?SECURITY-APPNAME=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&OPERATION-NAME=findItemsByKeywords&SERVICE-VERSION=1.0.0&RESPONSE-DATA-FORMAT=JSON&callback=_cb_findItemsByKeywords&REST-PAYLOAD&keywords=iphone%203g&paginationInput.entriesPerPage=3>
</script>
</body>
</html>"
If you believe listingInfo is an property of individual items, and that it is an object that has the property startTime, then the proper syntax is:
var item = items[i];
var title = item.title;
var viewitem = item.viewItemURL;
var starttime = item.listingInfo.startTime;
You are currently referencing items which is the array of items, not an individual item.
Update
I looked into this via the URL you put in the comments. The solution to this particular problem is this:
var starttime = item.listingInfo[0].startTime;
I hope that helps. Please review the FAQ; Imho this question falls outside the scope of this site (the question is really quite narrow, and not likely to help anyone else). I recommend Mozilla Developer Network as a source for learning more about JavaScript.