I'm very very very new to d3, and I have a problem getting a line graph with json.
In my ReportBucketDAO.java, I generate out json with my database data.
while (rs.next())
{
String currency = rs.getString("currency");
Timestamp pointDateTimeTs = rs.getTimestamp("point_datetime");
String pointDateTime = pointDateTimeTs.toString();
pointDateTime = pointDateTime.substring(0, pointDateTime.indexOf('.'));
double pointValue = rs.getDouble("sum(`point_value`)");
org.json.JSONObject jobj = new org.json.JSONObject();
jobj.put("currency", currency);
jobj.put("pointDateTime", pointDateTime);
jobj.put("pointValue", pointValue);
jArray.add(jobj);
}
The json string is:
[{"pointValue":274,"pointDateTime":"2015-01-20 00:00:00","currency":"GBP"},
{"pointValue":571,"pointDateTime":"2015-01-20 00:00:00","currency":"SGD"},
{"pointValue":561,"pointDateTime":"2015-01-20 00:00:00","currency":"USD"}]
I also had a jsp called getVolumeData.jsp which allow me to save the above json to "data.json"
<%#page import="java.util.ArrayList"%>
<%#page import="com.ach.model.ReportBucket"%>
<%#page import="com.ach.model.ReportBucketDAO"%>
<%#page import="java.io.*"%>
<%#page import="org.json.simple.*"%>
<%
ReportBucketDAO rbDAO = new ReportBucketDAO();
JSONArray rbjson = rbDAO.retrieveByReportTypeJson();
System.out.println(rbjson);
request.setAttribute("rbJsonString", rbjson);
try {
FileWriter jsonFileWriter = new FileWriter("data.json");
jsonFileWriter.write(rbjson.toJSONString());
jsonFileWriter.flush();
jsonFileWriter.close();
System.out.println("Done");
} catch (IOException e) {
e.printStackTrace();
}
%>
I call the d3 content within home.jsp content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Project</title>
<link rel="shortcut icon" href="assets/img/tBank.ico">
<!-- Bootstrap core CSS -->
<link href="assets/css/bootstrap.min.css" rel="stylesheet">
<script data-require="d3#3.5.3" data-semver="3.5.3" src="assets/js/d3.js"></script>
<!-- Custom styles for this template -->
<link href="assets/css/dashboard.css" rel="stylesheet">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="assets/js/script.js"></script>
<script>
$(function() {
$("#header").load("header.jsp");
$("#sidebar").load("sidebar.html");
//$("#d3content").load("getVolumeData.jsp");
});
</script>
</head>
<body>
<div id="header"></div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar" id="sidebar">
<!--Sidebar here-->
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<!-- <img id="loading" src="assets/img/ajax_load.gif" alt="loading" />-->
<div id="pageContent">
<!-- this is where our AJAX-ed content goes -->
<h1 class="page-header">My Dashboard</h1>
</div>
<div id="d3content">
<script type="text/javascript">
$("#d3content").load(function(event){
// Set the dimensions of the canvas / graph
var margin = {
top: 30,
right: 20,
bottom: 70,
left: 50
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d %X").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var priceline = d3.svg.line()
.x(function(d) {
return x(d.pointDateTime);
})
.y(function(d) {
return y(d.pointTime);
});
// Adds the svg canvas
var svg = d3.select("#d3content")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.json("data.json", function(error, data) {
data.forEach(function(d) {
d.symbol = d.currency;
d.pointDateTime = parseDate(d.pointDateTime);
d.pointTime = +d.pointValue;
});
console.log(data);
// Scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.pointDateTime;
}));
y.domain([0, d3.max(data, function(d) {
return d.pointTime;
})]);
// Nest the entries by symbol
var dataNest = d3.nest()
.key(function(d) {
return d.symbol;
})
.entries(data);
console.log(dataNest);
var color = d3.scale.category10(); // set the colour scale
legendSpace = width / dataNest.length; // spacing for the legend
// Loop through each symbol / key
dataNest.forEach(function(d, i) {
console.log(d);
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key);
})
.attr("id", 'tag' + d.key.replace(/\s+/g, '')) // assign ID
.attr("d", priceline(d.values));
// Add the Legend
svg.append("text")
.attr("x", (legendSpace / 2) + i * legendSpace) // space legend
.attr("y", height + (margin.bottom / 2) + 5)
.attr("class", "legend") // style the legend
.style("fill", function() { // Add the colours dynamically
return d.color = color(d.key);
})
.on("click", function() {
// Determine if current line is visible
var active = d.active ? false : true,
newOpacity = active ? 0 : 1;
// Hide or show the elements based on the ID
d3.select("#tag" + d.key.replace(/\s+/g, ''))
.transition().duration(100)
.style("opacity", newOpacity);
// Update whether or not the elements are active
d.active = active;
})
.text(d.key);
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
});
</script>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script data-require="bootstrap#3.3.1" data-semver="3.3.1" src="assets/js/bootstrap.min.js"></script>
<!--<script src="assets/js/docs.min.js"></script>-->
</body>
</html>
I wish the d3 to be loaded inside d3content, but it doesnt show/display anything, any help?
Here's the problems:
1.) You don't load d3.js
2.) Your variables aren't mapped correctly. In this block:
data.forEach(function(d) {
d.currency = +d.currency; // this is a string do not use +
d.pointDateTime = parseDate(d.pointDateTime);
d.pointTime = +d.pointTime; // your json is pointValue, not pointTime
});
3.) Your date parse function is wrong. Should be:
var parseDate = d3.time.format("%Y-%m-%d %X").parse;
Cleaning this up, produces this example.
Related
I'm generating pdf with wkhtmltopdf. There is a problem, that I cannot disable --footer-html on first THREE pages.
Below is java code for generating pdf:
pdf.addPageFromString(parseThymeleafTemplate());
pdf.addParam(new Param("--page-size", "A4", "-B", "35mm", "-L", "0", "-R", "0", "-T", "0"));
pdf.addParam(new Param("--footer-html", "/Users/kuanysh/IdeaProjects/pdf-report-sender/src/main/resources/templates/footer.html"));
And my footer.html
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script>
function subst() {
var vars = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) {
var z = x[i].split('=', 2);
vars[z[0]] = unescape(z[1]);
}
var x = ['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection'];
for (var i in x) {
var y = document.getElementsByClassName(x[i]);
for (var j = 0; j < y.length; ++j) y[j].textContent = vars[x[i]];
if (vars['page'] === 1) { // If page is 1, set FakeHeaders display to none
document.getElementById("stopFooter").style.display = 'none';
}
if (vars['page'] === 2) { // If page is 1, set FakeHeaders display to none
document.getElementById("stopFooter").style.display = 'none';
}
if (vars['page'] === 3) { // If page is 1, set FakeHeaders display to none
document.getElementById("stopFooter").style.display = 'none';
}
}
}
</script>
</head>
<body>
<div onload="subst()">
<footer class="footer" id="stopFooter">
<p>I am footer</p>
<div class="line"></div>
<p>Hello</p>
</footer>
</div></body>
</html>
And it's not working. Does wkhtmltodpf library give us some functions for that?
Remove onload="subst()" from the div.
Then change your function into a self invoking function by changing its opening and closing lines:
function subst() { becomes (function () {
and the last (closing) } becomes })();
Don't forget to remove the script from the head. Place it into the body below your div. Otherwise the script will run before the HTML get's loaded without having any effect.
I want to scan a barcode in an html textfield but only need a few characters from that barcode.. I've tried str.substring using the code below. But I want to replace 'helloworld' with the value from the textbox.
<script>
function myFunction() {
var id = "helloworld";
var res = id.substring(1, 7);
document.getElementById("out").innerHTML = res;
}
</script>
Are you trying to get a value from a text box?
HTML: index.html
<!DOCTYPE html>
<html>
<head>
<title>
Barcode Example
</title>
<link href="script.js" rel="JavaScript" type="text/js" />
</head>
<body>
<input type="text" name="barcode" id="textbox" onkeyup="validateBarcode()" />
<br />
<span id="barcode_error" style="display: none; color: red;">
Barcode must only have numbers
</span>
<br />
<button id="submit_btn" onClick="myFunction()">
Submit
</button>
</body>
</html>
If so, here's the code:
JavaScript: myscript.js
var barcode;
var textbox;
function myFunction() {
barcode = document.getElementById('textbox').value;
document.getElementById('out').innerHTML = "Barcode: " + barcode + "<br />";
// ^ br is to make it have multiple barcodes listed
}
function validateBarcode() {
textbox = document.getElementById('textbox');
if (isNaN(parseFloat(textbox.value))) {
document.getElementById('textbox').style.color = 'red';
document.getElementById('barcode_error').style.display = 'block';
document.getElementById('submit_btn').diabled = true;
}
else {
document.getElementById('textbox').style.color = 'black';
document.getElementById('barcode-error').style.display = 'none';
document.getElementById('submit_btn').diabled = false;
}
}
Hope this helps :-)
I am working on a project where the client's requirement is to add a dynamic text box. I made the dynamic text box but I'm not getting the unique name of the text box.
Here is my code:
<script type="text/javascript">
function addfieldset() {
var namefieldset = document.getElementById("name").cloneNode(true);
document.getElementById("names").appendChild(namefieldset);
}
function deletefieldset(e) {
var namefieldset = e.parentNode;
namefieldset.parentNode.removeChild(namefieldset);
}
</script>
<body>
<%! public static int i = 1;%>
<% if (i > 0) { %>
<div id="names"><div id="name"><% out.print(i);%>Name: <input name="namefield<%= i%>" type="text"/>delete</div></div>
<input id="addnamebtn" type="button" value="Add Name" onclick="addfieldset()"/>
<% i++;
}%>
</body>
You are mixing two different codes. The key is to realize, where and when each code is executed - JSP on the server when the page is requested and rendered (i.e. before the response is sent to the browser) and Javascript in the browser, after the browser receives the already generated response.
I.e. you have to change the name of the new text field in the addfieldset() function (which means you have to have a counter, how many text fields there already is).
The java code in scriptlet is executed on the server side. Hence, cloning it again through Javascript will not execute the scriptlet again.
An another approach of what you are trying to achieve will be to store the count variable in javascript.
var count = 1;
function addfieldset() {
count++;
var namefieldset = document.getElementById("name").cloneNode(true);
var textField = namefieldset.getElementsByTagName('input')[0];
textField.setAttribute("name", "namefield" + count);
textField.value = "";
document.getElementById("names").appendChild(namefieldset);
}
function deletefieldset(e) {
var namefieldset = e.parentNode;
namefieldset.parentNode.removeChild(namefieldset);
}
<body>
<div id="names">
<div id="name">
<span>Name:</span>
<input name="namefield1" type="text" />
delete
</div>
</div>
<input id="addnamebtn" type="button" value="Add Name" onclick="addfieldset()" />
</body>
try this JavaScript and HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
var i = 0;
function generateRow() {
i++;
var d = document.getElementById("div");
d.name = "food";
d.innerHTML += "<p>name"+i+" :<input type='text' name='name" + i + "' /> <a href='#' onclick='deletefieldset(this)'>delete</a></p>";
}
function deletefieldset(e) {
var namefieldset = e.parentNode;
namefieldset.parentNode.removeChild(namefieldset);
}
function onLoad() {
generateRow();
}
window.onload = onLoad;
</script>
<body>
<div id="div"></div>
<p>
<input type="button" id="addnamebtn" value="Add Name" onclick="generateRow()" />
</p>
</body>
</html>
I'm trying to make the autocomplete textbox, but how can i include SQL Data to jquery available tag and loop it? I failed to perform the function based on the following code. Any help would be appreciated! Thanks
This is my expected output : Expected Result Demo
Error on jquery code
My textbox only list the last row of data from database.
<%
String FRUIT_CODE = "";
String FRUIT_DESCP= "";
Vector vFruit = new Vector();
TEST.makeConnection();
String SQL = "SELECT CODE,DESCP FROM TB_FRUIT WITH UR";
TEST.executeQuery(SQL);
while(TEST.getNextQuery())
{
FRUIT_CODE = TEST.getColumnString("CODE");
FRUIT_DESCP = TEST.getColumnString("DESCP ");
Vector vRow = new Vector();
vRow.addElement(FRUIT_CODE);
vRow.addElement(FRUIT_DESCP);
vFruit.addElement(vRow);
}
TEST.takeDown();
%>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script>
$(function() {
var availableTags =
[{
<%
String COMBINE = "";
String CODE2 = "";
String DESC1 = "";
for(int i=0;i<vFruit.size();i++)
{
Vector vRow = (Vector) vFruit.elementAt(i);
CODE2 = (String) vRow.elementAt(0);
DESC1 = (String) vRow.elementAt(1);
COMBINE += "\"" + CODE2 +" "+ DESC1 + "\",";
}
COMBINE = COMBINE.substring(0, COMBINE.length()-1);
//Combine result = "10000 Apple","20000 Orange", "30000 Mango", "40000 Banana"
%>
"value": <%=CODE2%>,
"label": <%=COMBINE%>
}];
$("#MODEL").autocomplete({
source: availableTags,
focus: function (event, ui) {
event.preventDefault();
$("#MODEL").val(ui.item.value);
}
});
});
</script>
<body>
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="MODEL">
</div>
</body>
</html>
The scriptlet to generate availableTags does not add new object for each value in the vFruit Vector, only for the last one. It should be patched like this:
var availableTags = [
<%
String CODE2 = "";
String DESC1 = "";
for(int i=0;i<vFruit.size();i++)
{
Vector vRow = (Vector) vFruit.elementAt(i);
CODE2 = (String) vRow.elementAt(0);
DESC1 = (String) vRow.elementAt(1);
if (i > 0) out.print(",");
%>
{
"value": "<%= CODE2 %>",
"label": "<%= DESC1 %>"
}
<%
}
%>
];
$("#MODEL").autocomplete({
...
Btw. Why Vector and not e.g. ArrayList? Do you need a thread safe implementation here? It does not seem so.
I have the following html (sized down for literary content) that is passed into a java method.
However, I want to take this passed in html string and add a <pre> tag that contains some text passed in and add a section of <script type="text/javascript"> to the head.
String buildHTML(String htmlString, String textToInject)
{
// Inject inject textToInject into pre tag and add javascript sections
String newHTMLString = <build new html sections>
}
-- htmlString --
<html>
<head>
</head>
<body>
<body>
</html>
-- newHTMLString
<html>
<head>
<script type="text/javascript">
window.onload=function(){alert("hello?";}
</script>
</head>
<body>
<div id="1">
<pre>
<!-- Inject textToInject here into a newly created pre tag-->
</pre>
</div>
<body>
</html>
What is the best tool to do this from within java other than a regex?
Here's how to do this with Jsoup:
public String buildHTML(String htmlString, String textToInject)
{
// Create a document from string
Document doc = Jsoup.parse(htmlString);
// create the script tag in head
doc.head().appendElement("script")
.attr("type", "text/javascript")
.text("window.onload=function(){alert(\'hello?\';}");
// Create div tag
Element div = doc.body().appendElement("div").attr("id", "1");
// Create pre tag
Element pre = div.appendElement("pre");
pre.text(textToInject);
// Return as string
return doc.toString();
}
I've used chaining a lot, what means:
doc.body().appendElement(...).attr(...).text(...)
is exactly the same as
Element example = doc.body().appendElement(...);
example.attr(...);
example.text(...);
Example:
final String html = "<html>\n"
+ " <head>\n"
+ " </head>\n"
+ " <body>\n"
+ " <body>\n"
+ "</html>";
String result = buildHTML(html, "This is a test.");
System.out.println(result);
Result:
<html>
<head>
<script type="text/javascript">window.onload=function(){alert('hello?';}</script>
</head>
<body>
<div id="1">
<pre>This is a test.</pre>
</div>
</body>
</html>