I'm trying to insert a chart dynamically with javascript. I found an example of how to do such a thing and it almost works. The chart loads but then underneath the chart, part of the Javascript used to display the chart actually shows as text on the page. It otherwise works fine.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div id="tvTest"></div>
<script>
/* helpers
*/
// runs an array of async functions in sequential order
function seq (arr, callback, index) {
// first call, without an index
if (typeof index === 'undefined') {
index = 0
}
arr[index](function () {
index++
if (index === arr.length) {
callback()
} else {
seq(arr, callback, index)
}
})
}
// trigger DOMContentLoaded
function scriptsDone () {
var DOMContentLoadedEvent = document.createEvent('Event')
DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true)
document.dispatchEvent(DOMContentLoadedEvent)
}
/* script runner
*/
function insertScript ($script, callback) {
var s = document.createElement('script')
s.type = 'text/javascript'
if ($script.src) {
s.onload = callback
s.onerror = callback
s.src = $script.src
} else {
s.textContent = $script.innerText
}
// re-insert the script tag so it executes.
document.head.appendChild(s)
// clean-up
$script.parentNode.removeChild($script)
// run the callback immediately for inline scripts
if (!$script.src) {
callback()
}
}
// https://html.spec.whatwg.org/multipage/scripting.html
var runScriptTypes = [
'application/javascript',
'application/ecmascript',
'application/x-ecmascript',
'application/x-javascript',
'text/ecmascript',
'text/javascript',
'text/javascript1.0',
'text/javascript1.1',
'text/javascript1.2',
'text/javascript1.3',
'text/javascript1.4',
'text/javascript1.5',
'text/jscript',
'text/livescript',
'text/x-ecmascript',
'text/x-javascript'
]
function runScripts ($container) {
// get scripts tags from a node
var $scripts = $container.querySelectorAll('script')
var runList = []
var typeAttr
[].forEach.call($scripts, function ($script) {
typeAttr = $script.getAttribute('type')
// only run script tags without the type attribute
// or with a javascript mime attribute value
if (!typeAttr || runScriptTypes.indexOf(typeAttr) !== -1) {
runList.push(function (callback) {
insertScript($script, callback)
})
}
})
// insert the script tags sequentially
// to preserve execution order
seq(runList, scriptsDone)
}
$(document).ready(function()
{
var htmlContent = `<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script type="text/javascript">
new TradingView.widget({
"width": 500,
"height": 400,
"symbol": "BINANCE:AMBETH",
"interval": "60",
"timezone": "Etc/UTC",
"theme": "Dark",
"style": "1",
"locale": "en",
"toolbar_bg": "#f1f3f6",
"enable_publishing": false,
"allow_symbol_change": true,
"hideideas": true
});
</script>`;
var $container = document.querySelector('#tvTest');
$container.innerHTML = htmlContent;
runScripts($container);
});
</script>
</body>
</html>
If I run that, the chart displays and just underneath it, I see the code var $container = document.querySelector('#tvTest'); $container.innerHTML = htmlContent; runScripts($container); }); as text in the DOM. How can I get it to render the chart without printing any code to the DOM?
By default this trading view library appends to the body. You can override that by passing "container_id" property. Here is a simplified example of your code:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://s3.tradingview.com/tv.js"></script>
</head>
<body>
<div id="tvTest"></div>
<script type="text/javascript">
new TradingView.widget({
"container_id": "tvTest", // THIS IS THE LINE I ADDED
"width": 500,
"height": 400,
"symbol": "BINANCE:AMBETH",
"interval": "60",
"timezone": "Etc/UTC",
"theme": "Dark",
"style": "1",
"locale": "en",
"toolbar_bg": "#f1f3f6",
"enable_publishing": false,
"allow_symbol_change": true,
"hideideas": true
});
</script>
</body>
</html>
You need to escape the <\/script> inside of the string template
Related
I would like to integrate a JS code to a Shiny application to load a TradingView JS widget.
The problem is when the app is loading, the selector input disappears and the TradingView widget replaces the whole UI, I do not know why.
library(shiny)
library(shinyjs)
jsCode <- 'shinyjs.pageCol = function(para){new TradingView.widget( {"width": 640,"height": 400,"symbol": para,"interval": "D","timezone": "Etc/UTC","theme": "light", "style": "1",
"locale": "en", "toolbar_bg": "#f1f3f6","enable_publishing": false, "allow_symbol_change": true,"container_id": "tradingview_e9634"} );}'
shinyApp(
ui = fluidPage(
div(selectInput("ticker", "Ticker:",
c('NASDAQ:AMD', 'NASDAQ:TSLA', 'NASDAQ:GE'))),
tags$head(HTML('<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>')) ,
useShinyjs(),
div(extendShinyjs(text = jsCode, functions = c("pageCol")))
),
server = function(input, output) {
observeEvent(input$ticker, {
js$pageCol(input$ticker)
})
}
)
There are two ways of making it work, as described in this other post (related only to Javascript): TradingView widget replacing entire HTML body.
Either give the ID attribute name you chose in your jsCode to the div tag:
div(id="tradingview_e9634", extendShinyjs(text = jsCode, functions = c("pageCol")))
Or use an iframe: place the following chart.html file in a www subfolder of your app folder.
<html>
<head>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
function getParameterByName(name, url) {
if (!url) {
url = window.location.href;
}
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var para = getParameterByName('value');
console.log(para);
var fxWidget = new TradingView.widget({
"width": 640,
"height": 400,
"symbol": para,
"interval": "1",
"timezone": "Etc/UTC",
"theme": "light",
"style": "1",
"locale": "en",
"toolbar_bg": "#f1f3f6",
"enable_publishing": false,
"allow_symbol_change": true,
"container_id": "tradingview_e9634"
});
</script>
</head>
<body>
</body>
</html>
and use this app.R (simpler than the other version, no need for shinyjs):
library(shiny)
shinyApp(
ui = fluidPage(
div(selectInput("ticker", "Ticker:",
c('NASDAQ:AMD', 'NASDAQ:TSLA', 'NYSE:GE'))),
htmlOutput("frame")
),
server = function(input, output) {
observeEvent(input$ticker, {
query <- paste0("chart.html?value=", input$ticker)
output$frame <- renderUI({
tags$iframe(src=query, width=660, height=450)
})
})
})
I wrote a custom Google Script which outputs an object for me and I would like to be able to call it and assign it to a variable which is then used to display data on a website.
HTML Header:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>JQVMap - World Map</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<link href="../dist/jqvmap.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="../dist/jquery.vmap.js"></script>
<script type="text/javascript" src="../dist/maps/jquery.vmap.world.js" charset="utf-8"></script>
<script type="text/javascript" src="js/jquery.vmap.sampledata.deaths.js"></script>
<script type="text/javascript" src="js/jquery.vmap.sampledata.infected.js"></script>
<script>
jQuery(document).ready(function () {
jQuery('#vmap').vectorMap({
map: 'world_en',
backgroundColor: '#333333',
color: '#ffffff',
hoverOpacity: 0.8,
selectedColor: '#3498DB',
enableZoom: true,
showTooltip: true,
scaleColors: ['#F3A291', '#FF4F3B'],
values: infected_data,
normalizeFunction: 'polynomial',
onLabelShow: function (event, label, code) {
label.html('<div class="map-tooltip"><h1 class="header"> ' + label.html() + '</h1><p class="description">Infected: ' + infected_data[code] + '</p><p class="description">Deaths: ' + death_data[code] + '</p></div>');
}
});
});
</script>
</head>
Google Scripts File:
function doGet() {
var result = {};
var infected = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getDataRange().getValues();
var death = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getDataRange().getValues();
result = makeObject(infected);
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
function makeObject(multiArr) {
var obj = {};
var countrystats = {};
var headers = multiArr.shift();
for (var i = 0; i < headers.length; i++) {
countrystats[i] = multiArr.map(function (app) {
return app[i];
})
}
for (var m = 0; m < countrystats[1].length; m++) {
obj[countrystats[1][m]] = 0;
}
for (var j = 0; j < countrystats[1].length; j++) {
var TempVar;
TempVar = obj[countrystats[1][j]];
obj[countrystats[1][j]] = TempVar + countrystats[3][j];
}
return obj;
}
Google Scripts Output (using the JSON View chrome extension):
{
cn: 8134,
th: 23,
mo: 7,
us: 5,
jp: 11,
kr: 4,
sg: 10,
vn: 2,
fr: 5,
np: 1,
my: 8,
ca: 3,
ci: 1,
lk: 1,
au: 9,
de: 4,
fn: 1
}
This is a public link with the object/data i want on it (the same object shown above):web app: https://script.google.com/macros/s/AKfycbzsyQNJwDvQc5SvNGEDZZOoNI3XxNar9PA9sRucZx7mgzfWpFQ/exec
So basically anyone who uses it should be able to access it. I just need a way to assign that data to a local JS variable. The google sheets script is published as a web app. If I'm not mistaken there is a setting to allow anyone, even anonymous to access it.
Here is my attempt at an AJAX request:
var url = "https://script.google.com/macros/s/AKfycbzsyQNJwDvQc5SvNGEDZZOoNI3XxNar9PA9sRucZx7mgzfWpFQ/exec";
var infected_data = jQuery.ajax({
crossDomain: true,
url: url,
method: "GET",
//dataType: "jsonp"
});
If I uncomment the jsonp I get an error:
jquery-1.11.3.min.js:5 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://script.googleusercontent.com/macros/echo?user_content_key=JXkCjiJjhcjndRREjoGyVNkZNkD-HvKpEPkpicQBm9nR9OkxjGXdYuOPsLxbJf-B9Rgifl5NWMtzgjfVGuMdGxTJrjKnRpdcOJmA1Yb3SEsKFZqtv3DaNYcMrmhZHmUMWojr9NvTBuBLhyHCd5hHazTNYZyoqG0ZuVXpWSNdoeLErB4AfUCNPKJHgELe5WaAmN5SlwIhonlWkkbFzR8kUwjKrMtdq9u-YqreD7W_KJ_aVqKVBTehAuogPCoZCfVc4yJf5ieDCdMDbXQ8FZZq8iSedsk1Px1LnPBLM8W-ZRcknnbJNT8dS525XG1pNEBR&lib=Mw_Scq3iKhByBS86NJpd_CngcdEShCw7K with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I don't get any errors if i remove it. However, i still can't see the data on my interactive map (My application).
Using Fetch:
const url = "https://script.google.com/macros/s/AKfycbzsyQNJwDvQc5SvNGEDZZOoNI3XxNar9PA9sRucZx7mgzfWpFQ/exec";
// Declare an async function
const getData = async () => {
// Use the await keyword to let JS know this variable has some latency so it should wait for it to be filled
// When the variable is fetched, use the .then() callback to carry on
const DataJSON = await fetch(url).then(response =>
response.json()
).then(parsedResponse => parsedResponse)
return await DataJSON
};
console.log(getData());
var infected_data = getData();
Converting Integers in object to Strings
The object needs to be in a format like this:
var infected_data = {
cn: "83",
th: "0",
mo: "0",
au: "0",
sg: "0",
tw: "0",
us: "0",
jp: "0",
my: "0",
kr: "0",
fx: "0",
vn: "0",
kh: "0",
ca: "0",
ci: "0",
np: "0",
lk: "0",
};
You're likely having issues with the call being asynchronous, which would mean you're reading the data before it is actually returned from Google's servers. Try using promises and the fetch API
const url = "https://script.google.com/macros/s/AKfycbzsyQNJwDvQc5SvNGEDZZOoNI3XxNar9PA9sRucZx7mgzfWpFQ/exec";
// Declare an async function
const getData = async () => {
// Use the await keyword to let JS know this variable has some latency so it should wait for it to be filled
// When the variable is fetched, use the .then() callback to carry on
const DataJSON = await fetch(url).then(response =>
response.json()
).then(parsedResponse => parsedResponse)
return await DataJSON
};
console.log(await getData())
Assuming the data is not sensitive, You could use jsonp to bypass cors:
Server side:
return ContentService.createTextOutput("infect(" +JSON.stringify(result)+ ")").setMimeType(ContentService.MimeType.JAVASCRIPT);
Client side:
<script>function infect(data){ infectedData = data }</script>
<script src="URL_OF_YOUR_SCRIPT"></script>
References:
Jsonp
Same origin policy
Answering the Question to Convert Integers to Strings:
Try something like this:
function toString(o) {
Object.keys(o).forEach(k => {
if (typeof o[k] === 'object') {
return toString(o[k]);
}
o[k] = '' + o[k];
});
return o;
}
I'm trying to get my table to load on intervals. I am now receiving the below error:
TypeError: g is null
The user will enter form parameters and then hit the submit button which has a click event. As follows:
$('.searchSubmit').on('click', function()
{
var data = {
searchCriteria: {
bill: $('#import_bill').val(),
ramp: $('#import_ramp').val(),
// few other parameters
}
};
$.ajax({
url: 'api/railmbs.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR)
{
var jsonObject = $.parseJSON(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{ "data": "BILL" },
{ "data": "RAMP" },
// few more columns
],
"iDisplayLength": 25,
"paging": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
var idle = 0;
var idelInterval = setInterval(timer, 10000);
$(this).mousemove(function(e){idle = 0;});
$(this).keypress(function(e){idle = 0;});
function timer()
{
idle = idle + 1;
if(idle > 2)
{
$('#example1').DataTable().ajax.reload(); // <--error occurs here
console.log('table reloaded');
}
}
},
error: function(jqHHR, textStatus, errorThrown)
{
console.log('fail');
}
});
});
Here's the funny part...above, where I pointed to where the error was occurring, I originally had it looking like this:
$('#example').DataTable().ajax.reload();
Notice the table name was 'example' instead of 'example1'. The table ID is indeed example1, as I indicated up near where the success function begins. When I saw the reload interval was looking at a different table ID, I changed it, which now is causing the error at the top.
I don't think I should keep the ID as 'example' because that is not the correct ID.
With that said, why am I getting the error?
I've worked out a solution that seems to do the trick. I tried to keep this as simple as I could, while still incorporating jQuery and (I think) solving the issue you were having.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax Reloader</title>
</head>
<body>
<header>
<h1>AJAX Reloader</h1>
</header>
<section>
<form id="theForm">
<input id="theButton" type="button" value="Click me to load data">
</form>
</section>
<section>
<p>
<h3>Data Reload in: <span id="reloadCounter">5</span></h3>
</section>
<section>
<table id="theTable"></table>
</section>
<template id="theTemplate">
<tr>
<td>Name:</td>
<td data-js></td>
</tr>
</template>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous">
</script>
<script>
(function() {
const $btn = $('#theButton');
const $tbl = $('#theTable');
const $tmpl = $('#theTemplate');
const $span = $('#reloadCounter');
let isLoading = false;
let counter = 5;
// Load data on Button click.
$btn.click(() => {
loadData(true);
});
// Auto-reload table data every 5 seconds.
// Add a countdown, just for gits and shiggles
window.setInterval(() => {
if (counter === 0) {
loadData(false);
counter = 5;
} else {
counter--;
}
$span[0].textContent = counter.toString();
}, 1000);
function loadData(isBtnClick) {
if (!isLoading) {
isLoading = true;
let file = (isBtnClick) ? 'data1' : 'data2';
$.ajax({
url: `./${file}.json`,
type: 'GET',
dataType: 'json',
success: (data, status) => {
console.log('loadData::success - Got data!', data);
$tbl[0].innerHTML = '';
let td = $tmpl[0].content.querySelector('td[data-js]');
data.forEach((item, idx, arr) => {
td.textContent = item.name;
let tr = document.importNode($tmpl[0].content, true);
$tbl[0].appendChild(tr);
});
isLoading = false;
}
});
if (isBtnClick) {
console.log('loadData - Button clicked');
} else {
console.log('loadData - Interval triggered');
}
}
}
})();
</script>
</body>
</html>
data1.json
[
{"name": "Rincewind"},
{"name": "Mustrum Ridcully"},
{"name": "Ponder Stibbons"},
{"name": "Gaspode The Wonder Dog"},
{"name": "CMOT Dibbler"},
{"name": "Nanny Ogg"}
]
data2.json
[
{"name": "Jason Ogg"},
{"name": "Tiffany Aching"},
{"name": "Rob Anybody"},
{"name": "Mrs. Cake"},
{"name": "Nobby Nobbs"},
{"name": "Fred Colon"}
]
My style of coding is a little different from yours, but the same basic concepts should be in play here.
Hope it helps. :-)
How do you expect ajax.reload() to work? There is no AJAX in use and therefore no previous AJAX to reload. Do this instead (schematic) :
var table = $('#example1').DataTable({
ajax: {
url: 'api/railmbs.php',
data: function() {
return {
searchCriteria: {
bill: $('#import_bill').val(),
ramp: $('#import_ramp').val(),
// few other parameters
}
}
}
},
"columns": [
{ "data": "BILL" },
{ "data": "RAMP" },
// few more columns
],
"iDisplayLength": 25,
"paging": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
Now you should be able to table.ajax.reload() from anywhere where table is available.
I am trying to do a test of loading up an html page in jsdom which will eventually generate graphs. I cannot overcome the first hurdle of just loading the html page and having the javascript execute.
Below is my html page which I am trying to load which doesnt take any parameters and just renders a simple graph.
<html>
<head>
<script src="http://code.jquery.com/jquery.min.js"/>
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"/>
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.charts.js"/>
<script src="http://static.fusioncharts.com/code/latest/themes/fusioncharts.theme.fint.js"/>
<script>
var testVar = true;
function test(){
testVar = false;
};
</script>
<script>
$(document).ready(function(){
FusionCharts.ready(function () {
var revenueChart = new FusionCharts({
type: 'column2d',
renderAt: 'container',
width: '400',
height: '200',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Split of Revenue by Product Categories",
"subCaption": "2014",
"numberPrefix": "$",
"theme": "fint",
"captionFontSize": "13",
"subcaptionFontSize": "12",
"subcaptionFontBold": "0",
"showValues": "0"
},
"data": [{
"label": "Food",
"value": "28504"
}, {
"label": "Apparels",
"value": "14633"
}, {
"label": "Electronics",
"value": "10507"
}, {
"label": "Household",
"value": "4910"
}]
}
}).render();
});
var svg = $('#container').html();
});
</script>
<head>
<body>
<div id="container">Charts will render here</div>
</body>
Here is the code in node where I am trying to load this page..
var config = {
file: path.join(__dirname, "chart.html"),
features:{
FetchExternalResources: ["script"],
ProcessExternalResources: ["script"],
MutationEvents: '2.0'
},
scripts:[
"http://code.jquery.com/jquery.min.js",
"http://static.fusioncharts.com/code/latest/fusioncharts.js",
'http://static.fusioncharts.com/code/latest/fusioncharts.charts.js',
"http://static.fusioncharts.com/code/latest/themes/fusioncharts.theme.fint.js"
],
onload: function(err, window) {
console.log('*******onload')
},
created: function(err, window) {
console.log('*******created')
},
done: function(err, window) {
console.log('*******done')
if(err){
console.log('*****got err ' + err.message);
callback(err);
}
global.window = window;
console.log('inside done ----------')
var $ = window.jQuery || window.$,
FusionCharts = window.FusionCharts,
document = window.document;
if(typeof FusionCharts == 'undefined')
console.log('FusionCharts NOT LOADED')
else
console.log('FusionCharts LOADED')
if(typeof $ == 'undefined')
console.log('JQUERY NOT LOADED')
else
console.log('JQUERY LOADED')
console.log('testVar ' + window.testVar)
console.log(window.test())
console.log('testVar ' + window.testVar)
console.log('svg is ' + window.svg);
console.log($('#container').html());
window.close();
}
}
jsdom.env(config);
The strange thing here is that if i do not include scripts in the config object, it will not load them and make them available in the done callback even thought it is there on the html page.
Also, testVar is never defined in the callback even thought it is present in the page, the same with window.test(), even though its in the html page it just does not seem to be available in the callback.
I have tried all different variations of creating the jsdom object, but none of them allows the page to load the scripts rather than me passing it into the config object, and none of the different versions allow me to access variables and functions defined in the script tags.
Is there something I am missing ?
Change your script elements so that they are correct HTML:
<script src="http://code.jquery.com/jquery.min.js"></script>
If you do that everything will load fine and you won't have to use scripts in your configuration.
I'm using lazy_high_charts and foundation 4.
In my view I have <%= high_chart("my_id", #chart) %>, which generates the following:
<section>
<script type="text/javascript">
(function() {
var onload = window.onload; # I think
window.onload = function(){ # the issue
if (typeof onload == "function") onload(); # is here
var options = { "title": { "text": "Combination chart" },"legend": { "layout": "vertical","style": { } },"xAxis": { },"yAxis": { "title": { "text": null },"labels": { } },"tooltip": { "enabled": true },"credits": { "enabled": false },"plotOptions": { "areaspline": { } },"chart": { "defaultSeriesType": "line","renderTo": "my_id" },"subtitle": { },"series": [{ "type": "spline","name": "Average","data": [ 3,2.67,3,6.33,3.33 ] }] };
window.chart_my_id = new Highcharts.Chart(options);
};
})()
</script>
<div id="my_id"></div>
</section>
However, it is not displaying because of the following lines generated by foundation 4 in my application.js
$(document).foundation();
$(function(){ $(document).foundation(); });
If I delete those lines the chart loads.
How can I use foundation and lazy_high_charts together?
instead of
(function() {
var onload = window.onload; # I think
window.onload = function(){ # the issue
write
$(function(){
The resulting script tag will look:
<section>
<script type="text/javascript">
$(function() {
var options = { "title": { "text": "Combination chart" },"legend": { "layout": "vertical","style": { } },"xAxis": { },"yAxis": { "title": { "text": null },"labels": { } },"tooltip": { "enabled": true },"credits": { "enabled": false },"plotOptions": { "areaspline": { } },"chart": { "defaultSeriesType": "line","renderTo": "my_id" },"subtitle": { },"series": [{ "type": "spline","name": "Average","data": [ 3,2.67,3,6.33,3.33 ] }] };
window.chart_my_id = new Highcharts.Chart(options);
});
</script>
<div id="my_id"></div>
</section>
Make sure you have put jquery script before it.
I solved the problem updating the zurb-foundation and lazy_high_charts gems:
In my Gemfile:
gem 'zurb-foundation', '~> 4.0.0'
gem 'lazy_high_charts'
Then:
bundle install
bundle update lazy_high_charts
rails g foundation:install
I have also included the following lines in the application.html.erb:
...
<%= javascript_include_tag "vendor/custom.modernizr" %>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
...
After that, the <%= high_chart("my_id", #chart) %> code is generating the following javascript:
<script type="text/javascript">
(function() {
var f = function(){
document.removeEventListener('page:load', f, true);
...
I hope it helps people facing the same problem.