I'm trying to find a way of dynamically loading a Google visualisation API table, populated from a dynamic query onto a Google spreadsheet into a Blogger blogpost.
Unfortunately, the blog style sheet seems to trash the style of the table, so I thought I'd try to inject the dynamically loaded table into an iframe and isolate it from the host page:
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.3.2");
google.setOnLoadCallback(f1dj_iframeloader);
function f1dj_iframeloader(){
$(function() {var $frame = $('iframe');
setTimeout( function() {
var doc = $frame[0].contentWindow.document;
var $body = $('body',doc);
$body.html("<script type='text/javascript' src='http://www.google.com/jsapi'></script><script type='text/javascript'>var f1dj_sskey="tQQIIA7x9VuyVKE7UVdrytg";var f1dj_sheet=8;var f1dj_authkey='CITwr80K';google.load('visualization', '1', {'packages':['table']});function f1dj_getData(){var url='http://spreadsheets.google.com/tq?tq=select%20*&key='+f1dj_sskey+'&authkey='+f1dj_authkey+'&gid='+f1dj_sheet;var query = new google.visualization.Query(url); query.send(f1dj_displayTable);} function f1dj_displayTable(response){if (response.isError()) return;var data = response.getDataTable(); visualization = new google.visualization.Table(document.getElementById('f1dj__table'));visualization.draw(data, null);} google.setOnLoadCallback(f1dj_getData)</script><div id='f1dj__table'></div>");}, 1 );
});
}</script>
This seems to work okay in a simple HTML text page EXCEPT that:
1) in the test page, ");}, 1 );});} is also rendered on the page (so something's obviously not right...)
2) the Blogger HTML editor/parses throws a parse error and blocks the saving of the page (maybe same issue as in 1)
Any ideas how to fix this? Is there maybe something obvious I've missed?:-(
Your quotes don't match up - the double quotes for fldj_sskey=... are closing the string being passed to $body.html.
And then you've got "</script>" unencoded in the strings within your script tag, so the HTML parser thinks the script tag ends there.
You have to be careful with inline js and should really html encode it all...
This line is your problem:
$body.html("<script type='text/javascript' src='http://www.google.com/jsapi'></script><script type='text/javascript'>var f1dj_sskey="tQQIIA7x9VuyVKE7UVdrytg";var f1dj_sheet=8;var f1dj_authkey='CITwr80K';google.load('visualization', '1', {'packages':['table']});function f1dj_getData(){var url='http://spreadsheets.google.com/tq?tq=select%20*&key='+f1dj_sskey+'&authkey='+f1dj_authkey+'&gid='+f1dj_sheet;var query = new google.visualization.Query(url); query.send(f1dj_displayTable);} function f1dj_displayTable(response){if (response.isError()) return;var data = response.getDataTable(); visualization = new google.visualization.Table(document.getElementById('f1dj__table'));visualization.draw(data, null);} google.setOnLoadCallback(f1dj_getData)</script><div id='f1dj__table'></div>");}, 1 );
You are calling .html() with a string contained in double quotes (") but your string contains double quotes when you initialize the f1dj_sskey variable. This means that your string is getting closed early. You need to change the quotes in the string either to single quotes or you need to escape them.
Single quotes (change " to '):
$body.html("<script type='text/javascript' src='http://www.google.com/jsapi'></script><script type='text/javascript'>var f1dj_sskey='tQQIIA7x9VuyVKE7UVdrytg';var f1dj_sheet=8;var f1dj_authkey='CITwr80K';google.load('visualization', '1', {'packages':['table']});function f1dj_getData(){var url='http://spreadsheets.google.com/tq?tq=select%20*&key='+f1dj_sskey+'&authkey='+f1dj_authkey+'&gid='+f1dj_sheet;var query = new google.visualization.Query(url); query.send(f1dj_displayTable);} function f1dj_displayTable(response){if (response.isError()) return;var data = response.getDataTable(); visualization = new google.visualization.Table(document.getElementById('f1dj__table'));visualization.draw(data, null);} google.setOnLoadCallback(f1dj_getData)</script><div id='f1dj__table'></div>");}, 1 );
Escaping (change " to \"):
$body.html("<script type='text/javascript' src='http://www.google.com/jsapi'></script><script type='text/javascript'>var f1dj_sskey=\"tQQIIA7x9VuyVKE7UVdrytg\";var f1dj_sheet=8;var f1dj_authkey='CITwr80K';google.load('visualization', '1', {'packages':['table']});function f1dj_getData(){var url='http://spreadsheets.google.com/tq?tq=select%20*&key='+f1dj_sskey+'&authkey='+f1dj_authkey+'&gid='+f1dj_sheet;var query = new google.visualization.Query(url); query.send(f1dj_displayTable);} function f1dj_displayTable(response){if (response.isError()) return;var data = response.getDataTable(); visualization = new google.visualization.Table(document.getElementById('f1dj__table'));visualization.draw(data, null);} google.setOnLoadCallback(f1dj_getData)</script><div id='f1dj__table'></div>");}, 1 );
Related
with a url of http://example.com?productName=Walkman is working right
<body>
<h1 id="productName"></h1>
</body>
<script type='text/javascript'>
// start by creating a function
function loadUp(){
var str = window.location.search.replace(/(?:(\D+=))/ig, "") //get the search parameters from the url and remove everything before the "=" sign
document.getElementById('productName').innerHTML = str //assign that string to the "innerHTML" of the h1 tag that has an id of "productName"
};
window.onload = loadUp; // once the page has loaded, fire off that function
</script>
the problem is that if i add 2 or more words in the URL
http://example.com?productName=Best_Walkman
on the page i have Best_Walkman but i want to show Best Walkman
how can i hide this symbol on th website _ ? inide the tag
<h1 id="productName"></h1>
just add another replace
str = window.location.search.replace(/(?:(\D+=))/ig, "").replace("_"," ")
edit
for all _ to be replaced, you need to replace using regex
replace(/(?:(\D+=))/ig, "").replace(/_/g," ")
str = window.location.search.replace(/(?:(\D+=))/ig, "").replace("_"," ").replace("_"," ").replace("_"," ").replace("_"," ").replace("_"," ")
This is my solution so far, if you have something better, please post it.
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'm working with mathdox, to insert equations in my web page. I have implemented all the symbols and mathematical expressions that I need, to insert them as openmath and convert them in to MathML, except subscript. I know that it's suppose to work like this:
<OMOBJ xmlns='http://www.openmath.org/OpenMath' version='2.0' cdbase='http://www.openmath.org/cd'>
<OMA style='sub'>
<OMV name='x'/>
<OMI>2</OMI>
</OMA>
</OMOBJ>
should convert to
<math xmlns="http://www.w3.org/1998/Math/MathML">
<msub>
<mi>X</mi>
<mn>2</mn>
</msub>
</math>
but I cannot find a way to implement it in javascript or find it's existing implementation in mathdox.
For me, this only works in Firefox. The main tools for the job are createElementNS and getElementsByTagNameNS. Additionally, I'm not sure where you get your openmath document, but I'm going to be retrieving it via AJAX.
So, assuming your file structure is:
/root
+-/js
| +-convert.js
|
+-/xml
| +-openmath.xml
|
+-index.html
And your files are as follows:
index.html
The only thing to note about index.html is that we set an id on the <math> element that we want to put the converted tags under. We also include the convert.js JavaScript file.
<html>
<head>
<title>Convert</title>
<script src="js/convert.js"></script>
</head>
<body>
<main>
<math xmlns="http://www.w3.org/1998/Math/MathML" id="target"></math>
</main>
</body>
</html>
openmath.xml
This file is just the XML that you posted in your question that we will be converting to the math namespace.
<OMOBJ xmlns='http://www.openmath.org/OpenMath' version='2.0' cdbase='http://www.openmath.org/cd'>
<OMA style='sub'>
<OMV name='x' />
<OMI>2</OMI>
</OMA>
</OMOBJ>
convert.js
The way that convert.js works is that it loads up the openmath document over xhr, then creates a new XML document with the document text using DOMParser() and parseFromString(). Then we feed that document to mathSubscriptConverter() which pulls all the OMA tags, gets the relevant data from them, and then converts them to msub tags. Once we have the msub tags, we add them as children under the <math> tag that exists in our index.html.
(function () {
"use strict";
var mathNS = "http://www.w3.org/1998/Math/MathML",
openMathNS = "http://www.openmath.org/OpenMath",
xhr = new XMLHttpRequest();
function mathSubscriptConverter(openmathDoc) {
var target = document.getElementById("target"),
omas = openmathDoc.getElementsByTagNameNS(openMathNS, "OMA");
// Make sure we have a math element to put this under
if (target) {
// Iterate each OMA tag
Array.prototype.forEach.call(omas, function (oma) {
var omv, omi, msub, mi, mn;
// Get the first OMV
omv = oma.getElementsByTagNameNS(openMathNS, "OMV")[0];
// Get the first OMV
omi = oma.getElementsByTagNameNS(openMathNS, "OMI")[0];
// Create a subscript tag in the math namespace
msub = document.createElementNS(mathNS, "msub");
// Create an mi tag in the math namespace
mi = document.createElementNS(mathNS, "mi");
// Create an mn tag in the math namespace
mn = document.createElementNS(mathNS, "mn");
// Set our math attributes
mi.innerHTML = omv.getAttribute("name");
mn.innerHTML = omi.innerHTML;
// Add our new elements to the target
msub.appendChild(mi);
msub.appendChild(mn);
target.appendChild(msub);
});
}
}
// Wait for document load
document.addEventListener("DOMContentLoaded", function () {
// Load our openmath document
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var parser = new DOMParser(),
mdoc = parser.parseFromString(xhr.responseText, "application/xml");
mathSubscriptConverter(mdoc);
}
};
xhr.open("GET", "xml/openmath.xml", true);
xhr.send();
});
}());
I wrote a small RSS reader with JQuery. At first theres a screen with the titles of the articles, when clicked on a title I load the content of that article. The problem is, it contains some google ads script, which will replace the content of the article and fill the whole screen with an advertisement.
The following script is what I am tying to replace or ignore:
<script type="text/javascript"><!--
google_ad_client = "ca-pub-8356817984200457";
/* ijsselmondenieuws.nl */
google_ad_slot = "9061178822";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
So I wrote a method which is supposed to remove the script by a simple replace:
var replaceScript='<script type="text/javascript"><!--\n' +
'google_ad_client = "ca-pub-8356817984200457";\n' +
'/* ijsselmondenieuws.nl */\n' +
'google_ad_slot = "9061178822";\n' +
'google_ad_width = 468;\n' +
'google_ad_height = 60;\n' +
'//-->\n' +
'</script>\n' +
'<script type="text/javascript"\n' +
'src="http://pagead2.googlesyndication.com/pagead/show_ads.js">\n' +
'</script>';
function removeADS(ads) {
removeAD = ads.replace(replaceScript, " ");
}
But this doesn't work, I think it's not flexible either (if it would work). When something changes in the script, the application will get stuck at the advertisement again. Is there some way to completely ignore this script while fetching the content from an RSS feed or a more flexible replacement script?
Any help is appreciated,
Thanks!
It's not very wise to parse xml/html with regex.
Use a dom parser (jquery is a beautiful one ...hint hint):
var rssContentString = '<rss version='2.0'>...',
xmlDoc = $.parseXml(rssContentString),
$xml = $(xmlDoc),
helper = $('<div />'),
result;
result = helper
.append(
$xml
.find('script')
.remove()
.end()
)
.text();
UPDATE
Based on the new comments, since you get your rss content like this :
content:$.trim($(v).find("content").text())
you can modify this expression to the following :
content:$.trim($(v).find("content").find('script').remove().end().text())
In a controller I try to render a javascript google ad to print it into some HTML using JSONP, like this
<script type="text/javascript"><!--
google_ad_client = "pub-23222424";
google_alternate_color = "FFFFFF";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript"
src="http://pagead2.google.com/pgad/show_ads.js">
</script>
So I do:
render :text "var s_response = { content: '<script type=\"text/javascript\"><!--\\ngoogle_ad_client = \"pub-23222424\";\\ngoogle_alternate_color = \"FFFFFF\";\\ngoogle_ad_width = 468;\\ngoogle_ad_height = 60;\\n//--><\\/script>\\n<script type=\"text/javascript\"\\n src=\"http://pagead2.google.com/pgad/show_ads.js\">\\n<\\/script>', id: '2'};">
But i get this error:
unterminated string literal
[Break on this error] var response = { content: '<script type="text/javascript"><!--
=> That seems like it is a multilines problem right ? But I don't know how to resolve it.
Thanks,
Lucas
In JavaScript, you cannot spread a string over multiple lines.
In this case, you can leave out those comments so you can put everything in a single line and get rid of the newline characters (\n).
BTW, a valid JSON response would surround every string, whether it represents a key or a value, with double quotes. Also see JSONLint's FAQ:
Proper format for a collection is: {
"key": "value" }
In the end, you get:
render :text "var s_response = { \"content\": \"<script type='text/javascript'>google_ad_client = 'pub-23222424';google_alternate_color = 'FFFFFF';google_ad_width = 468;google_ad_height = 60;<\\/script><script type='text/javascript' src='http://pagead2.google.com/pgad/show_ads.js'><\\/script>\", \"id\": \"2\"};">
Write huge strings like in my example below and stop escaping them:
render :text => %{
<script type="text/javascript">
//<!--
google_ad_client = "pub-23222424";
google_alternate_color = "FFFFFF";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.google.com/pgad/show_ads.js">
</script> }
Thanks for your responses !
Marcel > The problem is that if I get rid of the newline characters my ad can't display anymore, I tried it "manually". So I may need to replace the "/n" characters before to send the response by something like a unique string and to replace them again after the response is received by the server ?
floatless > Initially I did not escaped my response and it did not work. So I do not think it will change anything, but thanks anyway.