i am trying some time now, to get the Chart.js in external file working with Thymeleaf. I was checking in countless external forums but couldnt find an answer. The closes to what i could find is the following
Thymeleaf external javascript file shares the module attributes with html file
but i still didn't manage to do it.
Here is my Controller
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class ChartController {
#RequestMapping("/ExternalChart")
public String hello(Model model) {
String label[] = {"a","b","c","d","e","f","g","adasda","adasda2"};
int point[] = {5,3,7,1,8,3,4,50};
model.addAttribute("label",label);
model.addAttribute("point",point);
return "ExternalChart";
}
}
html file is located in src/main/resources/templates/
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link href="../static/css/Layout.css" th:href="#{/css/test.css}"
rel="stylesheet" />
<link href="../static/js/drawChart.js" th:href="#{/js/drawChart.js}"
rel="javascript" />
</head>
<body>
<h2>Donkey</h2>
<p>punch</p>
<canvas id="ChartDemo"></canvas>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
<script type="text/javascript" th:inline="javascript"
th:src="#{/js/drawChart.js}">
/*<![CDATA[*/
var xAxisData = /*[[ ${label} ]]*/[];
var yAxisData = /*[[ ${point} ]]*/[];
drawchart(xAxisData, yAxisData);
/*]]>*/
</script>
</body>
</html>
My javascript. it is located in src/main/resources/static/js
function drawchart(xAxisData, yAxisData) {
var ctx = document.getElementById("ChartDemo").getContext('2d');
var ChartDemo = new Chart(ctx, {
type : 'line',
data : {
labels : xAxisData,
datasets : [ {
label : "Chart-1",
borderColor : 'rgb(255, 0, 0)',
lineTension : 0,
fill : false,
data : yAxisData,
}, ]
},
options : {
responsive : true,
}
});
}
What i have noticed is that the attributes xAxisData and yAxisData get the values, but it seams that the drawChart(xAxisData,yAxisData) doesn't not get executed in browser.
I assume that i am making some silly mistake, and prospects of me finding it alone is close to zero. Thanks to anybody even trying to help me out
BR HK
p.s. i am really new with JS
I kind of have an answer. In this youtube video
https://www.youtube.com/watch?v=AEy7Hlz58bw? it is explained how to "externalize" JavaScript files. However, it is not really intuitive.
Javascript had to be written without function() part (which is something that i dont really understand)
//function done(xAxisData, yAxisData) {
var ctx = document.getElementById("ChartDemo").getContext('2d');
var ChartDemo = new Chart(ctx, {
type : 'line',
data : {
labels : xAxisData,
datasets : [ {
label : "Chart-1",
borderColor : 'rgb(10, 0, 0)',
lineTension : 0,
fill : false,
data : yAxisData,
}, ]
},
options : {
responsive : true,
}
});
//}
and respective HTML needs to look like this
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link href="../static/css/Layout.css" th:href="#{/css/test.css}"
rel="stylesheet" />
<link href="../static/js/drawChart.js" th:href="#{/js/drawChart.js}"
rel="javascript" />
</head>
<body>
<h2>Donkey</h2>
<p>punch</p>
<canvas id="ChartDemo"></canvas>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var xAxisData = /*[[ ${label} ]]*/[];
var yAxisData = /*[[ ${point} ]]*/[];
/*]]>*/
</script>
<script src="/js/drawChart.js"></script>
</body>
</html>
basically part where attributes xAxisData and yAxisData are initialized, could not contain the external script file.
If i manage to find more suitable solution, i will be glad to post it as an update to this answer as i have noticed that a lot of people get stuck in similar problems
BR DK
Related
Im using botman.io package for chatboot widget.
Everything works perfectly but problem is that i can't change default background color of chat widget. On inspect console it shown that boman widget calls ( https://cdn.jsdelivr.net/npm/botman-web-widget#0.0.20/build/assets/css/chat.css ) link, but i cant find that call on my localhost project. If anyone know solution i would appreciate.
<script src="{{ asset('/js/webflow.js') }}"></script>
<script>
var botmanWidget = {
title:'Scarletbot',
introMessage: 'Hello, I am a Scarlet! I am here to assist you and answer all your questions about our products and services!',
mainColor:'#c02026',
aboutText:'',
bubbleBackground:'#c02026',
headerTextColor: '#fff',
};
</script>
<script id="botmanWidget" src="{{ asset('/js/widget.js') }}"></script>
You may add frameEndpoint in
var botmanWidget = {
frameEndpoint: '<?php echo base_url('botdemo/chatserver1');?>',
title:'Scarletbot',
introMessage: 'Hello, I am a Scarlet! I am here to assist you and answer all your questions about our products and services!',
mainColor:'#c02026',
aboutText:'',
bubbleBackground:'#c02026',
headerTextColor: '#fff',
};
frameEndpoint is nothing but source of iframe loaded by botman-widget
frameEndpoint source is like :
<!doctype html>
<html>
<head>
<title>BotMan Widget</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/assets/css/chat.min.css">
</head>
<body>
<script id="botmanWidget" src='https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/js/chat.js'></script>
</body>
</html>
Here you may use own css as well.
I quickly checked out the web widget on the botman github.
There is a simple link to the chat.css in the head of chat.html located in the src folder.
This points to assets/css/chat.css, which you can edit freely and add a background-color to.
I use brute force in the iframe to change background with jquery
$(document).on('click', '.desktop-closed-message-avatar img', function() {
var iframe = document.getElementById("chatBotManFrame");
iframe.addEventListener('load', function () {
var htmlFrame = this.contentWindow.document.getElementsByTagName("html")[0];
var bodyFrame = this.contentWindow.document.getElementsByTagName("body")[0];
var headFrame = this.contentWindow.document.getElementsByTagName("head")[0];
var image = "https://images.unsplash.com/photo-1501597301489-8b75b675ba0a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80"
htmlFrame.style.backgroundImage = "url("+image+")";
bodyFrame.style.backgroundImage = "url("+image+")";
});
});
I have an HTML and JS file. Should the user want to overwrite the default settings that are declared in the external JS file all they have to do is include the following as an inline script:
<script>
userControls = {
transition : 'fade',
nextText : 'Next'
}
</script>
The problem I am facing is that my external script is not picking up the user settings and is setting everything as default.
var defControls = {
transition : 'default',
nextText : 'Next »'
};
var userControls = {};
// CHECKS FOR userControls
if (Object.getOwnPropertyNames(userControls).length > 0) {
var controls = Object.assign({}, defControls, userControls);
} else {
controls = defControls;
}
console.log(userControls);
console.log(controls);
console.log(defControls);
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- EXTERNAL SCRIPT THAT ACCEPTS USER'S NEW SETTINGS -->
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<!-- SENDS THE NEW PARAMETERS TO script.js -->
<script>
userControls = {
transition : 'fade',
nextText : 'Next'
}
</script>
</body>
</html>
You have four and half mistakes in your code:
You have to write inline script with code: var userControls = {transition: 'fade', nextText: 'Next'}; before external JS file. And do not forget ; on the end (it is the half mistake).
The line var userControls = {}; in external JS file has overwrited the settings in userControls in inline script. I think you wanted to write instead var controls = {};.
The var controls = {}; you have to write before if...else statement.
You write console.log(userControls); instead of console.log(JSON.stringify(userControls)); Your code writes only [object Object] in developer console from IE. But in Chrome it is okey.
Solution with corrected code
<!DOCTYPE html>
<html><head>
<!--
<link type="text/css" rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
-->
<!-- SENDS THE NEW PARAMETERS TO script.js -->
<script type="text/javascript">
var userControls =
{
transition : 'fade',
nextText : 'Next'
};
</script>
<!-- EXTERNAL SCRIPT THAT ACCEPTS USER'S NEW SETTINGS
src="script.js" -->
<script type="text/javascript">
var defControls =
{
transition : 'default',
nextText : 'Next »'
};
//THIS WAS THE MISTAKE: var userControls = {}; this line has overwrited the settings
var controls = {};
// CHECKS FOR userControls
if(Object.getOwnPropertyNames(userControls).length > 0)
{
controls = Object.assign({}, defControls, userControls);
}
else
{
controls = defControls;
}
console.log('userControls =\n' + JSON.stringify(userControls, null, '\t'));
console.log('controls =\n' + JSON.stringify(controls, null, '\t'));
console.log('defControls =\n' + JSON.stringify(defControls, null, '\t'));
</script>
</head>
<body></body>
</html>
It's because that you inserted the user choice after your js file loads. It goes through the following control first
if (Object.getOwnPropertyNames(userControls).length > 0)
so this will always evaluate to false. That's why you keep getting default values. You should either insert the user choice script first or some async functionality in the js file.
I would like to do the equivalent of the following Python in stand-alone BokehJS
color_mapper = bokeh.models.mappers.LogColorMapper('Viridis256',low=vmin,high=vmax)
How do I do it? Where are the color mappers located in the javascript CDN files?
They don't seem to be here, for example:
https://cdn.bokeh.org/bokeh/release/bokeh-widgets-0.12.7.js
and not here either:
https://cdn.bokeh.org/bokeh/release/bokeh-api-0.12.7.js
I am trying to follow examples like these:
https://docs.bokeh.org/en/latest/docs/user_guide/bokehjs.html#minimal-complete-example
Thanks in advance
After reading Bokeh docs and js source this seems to work with version 0.12.5
var color_mapper = new Bokeh.LogColorMapper({palette:'Viridis256', low:0, high:16});
I did try to get some sane result in example below but without much success. Maybe you can improve this code further. This is based on python source from Updating color mapper in a bokeh plot with taptool
Try to click on button "Add some data!" many times, more then 10.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-0.12.5.min.css" type="text/css"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-0.12.5.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-0.12.5.min.js"></script>
<title> by bokeh</title>
</head>
<body>
<div>
<div id="myplot" />
</div>
<button onclick="addPoint()">Add some data!</button>
<script type='text/javascript'>//<![CDATA[
// arrays to hold data
var source = new Bokeh.ColumnDataSource({
data: { x: [Math.random() * 10.0], y: [Math.random() * 10.0], humidity: [0, 10.0] }
});
var color_mapper = new Bokeh.LogColorMapper({palette:'Viridis256', low:0, high:16});
// make the plot and add some tools
var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save";
var plot = Bokeh.Plotting.figure({title:'Example of Random data', tools: tools, height: 300, width: 300});
var pglyph = plot.patches({ field: "x" }, { field: "y" },
{ fill_color: { field: "humidity", transform: color_mapper}},
{ source: source, alpha: 1, line_width: 4})
var scatterData = plot.line({ field: "x" }, { field: "y" },
{ source: source, line_width: 10 });
// Show the plot, appending it to the end of the current
// section of the document we are in.
Bokeh.Plotting.show(plot, document.getElementById('myplot'));
function addPoint() {
// The data can be added, but generally all fields must be the
// same length.
source.data.x.push(Math.random() * 10.0);
source.data.y.push(Math.random() * 10.0);
// Also, the DataSource object must be notified when it has changed.
source.trigger('change');
}
//]]>
</script>
</body>
</html>
Models are located inside the main JS file (at least, for Bokeh 0.12.9): https://cdn.bokeh.org/bokeh/release/bokeh-0.12.9.js
You can get LogColorMapper in your code by using:
Bokeh.require('models/mappers/log_color_mapper').LogColorMapper
I am trying to create a custom gadget in WSO2 DAS Dashboard. I already created it. I can drag and drop it in a container in the dashboard designer, and there I can see it moving when I add new data to the table (the gadget is a gauge that shows the latest value introduced in a DAS table).
The problem is, that when i click "view", the gadget disappears from the container. If I reopen the design view of the page, the gadget is not longer there. If I open the Chrome developer console, I have an error saying "draw is not defined". As far as I can understand, you have to define this "draw" function so that the page can render the graphic in runtime.
But, in other already created gadgets, this function uses wso2gadgets.js functions and some kind of wrapper to use VIZGrammar, but you are really limited to only a few type of gadgets(line, bar, pie, number, and perhaps one or two more), and we wanted to use d3 to create better and more complex graphs and gadgets.
Sadly, this thing of "creating a custom gadget" is really poor documented, and even if you follow the WSO2 tutorial here https://docs.wso2.com/display/DAS310/Manually+Creating+a+Custom+Gadget it does not work when you click "view".
I am posting the code for my gadget.xml below.
Thank you all
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Gauge" description="This is a template gadget">
<Require feature="dynamic-height"/>
<Require feature="wso2-gadgets-identity"/>
</ModulePrefs>
<UserPref name="windowSize"
display_name="Window Size"
default_value="10"/>
<Content type="html">
<![CDATA[
<head>
<meta charset="utf-8">
<style>
.label{
font-size:22.5px;
fill:#ffffff;
text-anchor:middle;
alignment-baseline:middle;
}
.face{
stroke:#c8c8c8;
stroke-width:2;
}
.minorTicks{
stroke-width:2;
stroke:white;
}
.majorTicks{
stroke:white;
stroke-width:3;
}
</style>
<svg width="400" height="400"></svg>
<link href="/portal/libs/analytics-wso2-2.0.0/common.css" rel="stylesheet" type="text/css" >
<script src="/portal/libs/jquery_1.11.0/jquery-1.11.3.min.js"></script>
<script src="js/provider-libs/ws-client.js"></script>
<script src="http://vizjs.org/viz.v1.0.0.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/d3.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/vega.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/VizGrammar.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/wso2gadgets.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/chart-utils.js"></script>
<script src="/portal/js/carbon-analytics.js"></script>
<script src="js/core/provider-client.js"></script>
<script src="js/core/gadget-util.js"></script>
<script src="js/core/gadget-core.js"></script>
<script>
var username = "********";
var password = "********";
var server_url = "https://localhost:9445/portal/apis/analytics";
var client = new AnalyticsClient().init(username,password,server_url);
var svg=d3.select("svg");
var g=svg.append("g").attr("transform","translate(200,200)");
var domain = [0,100];
var gg = viz.gg()
.domain(domain)
.outerRadius(150)
.innerRadius(30)
.value(0.5*(domain[1]+domain[0]))
.duration(1000);
gg.defs(svg);
g.call(gg);
var queryInfo = {
tableName : "ROBICON_DEBUG_GENERAL_COMPLETO", //table being queried
searchParams : {
query : "*:*", //lucene query to search the records
start : 0, //starting index of the matching record set
count : 100,
sortBy:
[
{
field: "Timestamp",
sortType: "DESC"
}
]
}
};
d3.select(self.frameElement).style("height", "400px");
setInterval(
function(){
client.tableExists("ROBICON_DEBUG_GENERAL_COMPLETO", function(data) {
console.log (data["message"]);
client.search(queryInfo, function(data) {
var datos = JSON.parse(data["message"]);
console.log (datos[0].values.LineSide_Voltage);
var LSV = datos[0].values.LineSide_Voltage;
gg.setNeedle(parseFloat(LSV).toFixed(2));
}, function(error) {
console.log("error occured: " + error);
gg.setNeedle(domain[0]+Math.random()*(domain[1]-domain[0]));
});
}, function(error) {
console.log("error occured: " + error);
});
},30000);
</script>
</head>
<body>
<div id="canvas"></div>
</body>
]]>
</Content>
</Module>
If your requirement is to write a custom gadget,you don't need to include any of the libraries with script tags unless you use them in your gauge gadget. WSO2 DAS is capable of rendering any gadget which is written following the google open social spec
So one thing you can try is try removing unused script tags from below.
<script src="/portal/libs/jquery_1.11.0/jquery-1.11.3.min.js"></script>
<script src="js/provider-libs/ws-client.js"></script>
<script src="http://vizjs.org/viz.v1.0.0.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/d3.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/vega.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/VizGrammar.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/wso2gadgets.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/chart-utils.js"></script>
<script src="/portal/js/carbon-analytics.js"></script>
<script src="js/core/provider-client.js"></script>
<script src="js/core/gadget-util.js"></script>
<script src="js/core/gadget-core.js"></script>
I am using swfupload plugin(http://demo.swfupload.org/Documentation/) to upload multiple files. I have the following swfupload settings object defined. Everything is working fine except the cursor doesn't change to 'hand' form. Here is the code:
var initialize_swfupload_for_image = function () {
if ($('#image-attach').length == 0){
return;
}
var url = $('#image-attach').data('url');
var params = $('#image-attach').data('params');
var buttonStyle = '.image-link {color: #FFF' +
';text-align: center'+
';} ' +
'.image-link:hover {color: #0FF' +
';} ';
var settings = {
upload_url:url,
flash_url: "<%= asset_path('swfupload/swfupload.swf') %>",
flash9_url: "<%= asset_path('swfupload/swfupload_fp9.swf') %>",
http_success:[ 200, 201, 204 ],
file_post_name:"file",
file_types: "*.jpg; *.gif; *.png; *.jpeg",
file_upload_limit:1,
file_queue_limit:0,
file_size_limit:"10 MB",
prevent_swf_caching:false,
custom_settings:{
progressTarget:"divImageProgressContainer",
cancelButtonId:"btnImageCancel"
},
button_placeholder_id:"image-attach",
button_text: "<span class='image-link'>Edit Photo</span>",
button_text_style: buttonStyle,
button_width: 90,
button_height: 20,
button_cursor:SWFUpload.CURSOR.HAND,
button_window_mode:SWFUpload.WINDOW_MODE.TRANSPARENT,
button_action:SWFUpload.BUTTON_ACTION.SELECT_FILE,
file_queued_handler:fileQueued,
file_queue_error_handler:fileQueueError,
file_dialog_complete_handler:fileDialogComplete,
upload_start_handler:uploadStartImage,
upload_error_handler:uploadError,
upload_progress_handler:uploadProgressImage,
upload_success_handler:uploadSuccessImage,
upload_complete_handler:uploadCompleteImage,
queue_complete_handler:uploadCompleteImage,
post_params:params
};
if (FlashDetect.versionAtLeast(9)) {
swf_image = new SWFUpload(settings);
} else {
//intentionally left blank
//TODO: javascript fallback when swfupload doesn't work
}
Any insights on why the cursor isn't changing on hovering over the object will be really helpful.
I have experienced the same problem. In my case the culprit was a 'px' that I had added accidentally to the button_width and button_height properties: button_width: "20px".
Your problem is obviously not the same one but it might be related in that you might have passed an invalid value to SWFUpload.
I copied your code and after cleaning it from the custom stuff I had no trouble getting the hand to show (didn't even change anything). Here's the code, tested with swfupload.swf 2.2.0.1 and swfupload.js 2.2.0 2009-03-25 (note that swfupload.swf and swfupload.js are in the same folder as the html file):
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>index</title>
<script type="text/javascript" src="swfupload.js"></script>
<script type="text/javascript" charset="utf-8">
var init = function () {
var settings = {
upload_url:'url',
flash_url: "swfupload.swf",
http_success:[ 200, 201, 204 ],
file_post_name:"file",
file_types: "*.jpg; *.gif; *.png; *.jpeg",
file_upload_limit:1,
file_queue_limit:0,
file_size_limit:"10 MB",
prevent_swf_caching:false,
custom_settings:{
progressTarget:"divImageProgressContainer",
cancelButtonId:"btnImageCancel"
},
button_placeholder_id:"image-attach",
button_text: "<span class='image-link'>Edit Photo</span>",
button_width: 90,
button_height: 20,
button_cursor:SWFUpload.CURSOR.HAND,
button_window_mode:SWFUpload.WINDOW_MODE.TRANSPARENT,
button_action:SWFUpload.BUTTON_ACTION.SELECT_FILE,
};
swf_image = new SWFUpload(settings);
}
</script>
</head>
<body id="index" onload="init()">
<div style="width:100px;height:100px;background-color:blue">
<div id="image-attach"></div>
</div>
</body>
</html>
My guess remains that maybe SWFUpload doesn't like one of the parameters (e.g. the <%asset stuff). Hope this helps anyway.