I'm trying to figure out how to make a dynamically generated csv available to a dygraphs JavaScript.
I'm using a wicket behavior to add the dygraph (JavaScript graph) to my markup like shown in the codesample bellow. Right now I've hardcoded it to use a csv file named "dygraph.csv". I want to change this, and instead make dygraph use the values from String csv, how do I achieve this?
Any help help is greatly appreciated.
public class DygraphBehavior extends AbstractBehavior {
private static final long serialVersionUID = -516501274090062937L;
private static final CompressedResourceReference DYGRAPH_JS = new CompressedResourceReference(DygraphBehavior.class, "dygraph-combined.js");
#Override
public void renderHead(IHeaderResponse response) {
response.renderJavascriptReference(DYGRAPH_JS);
}
#Override
public void onRendered(Component component) {
final String id = component.getId();
Response response = component.getResponse();
response.write(JavascriptUtils.SCRIPT_OPEN_TAG);
response.write("new Dygraph(document.getElementById(\""+id+"\"), \"dygraph.csv\", {rollPeriod: 7, showRoller: true, errorBars: true});");
response.write(JavascriptUtils.SCRIPT_CLOSE_TAG);
}
}
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
add(new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes())));
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
<div>
<h1>Dygraph:</h1>
<div wicket:id="graphdiv" id="graphdiv" style="width:500px; height:300px;"></div>
<a wicket:id="csv" href="#">dl generated csv</a>
</div>
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
ResourceLink<File> link = new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes()));
add( link );
//this is the url that should be passed to the javascript code
CharSequence url = link.urlFor( IResourceListener.INTERFACE );
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
There are other solutions based on the scope of your resource, maybe a dynamic shared resource would work better (if your graph parameters can simply be passed as url parameters), but this will work.
The JavaScript needs to see the data in some way after the page has been rendered. So you have two options:
Embed the data in the page (say in a hidden div) and then let JavaScript read the data from there as text.
Create a servlet where the JavaScript can download the data from.
The second option means that your page rendering code has to pass the data somehow to the servlet. You can try to put it into the session but then, it will sit there, occupying RAM. Probably not a problem if it's just a little bit of data and you have only a few users. But if that's not true, option #1 is probably better.
Related
I was trying to create a link with the username on it (i.e. dynamic data), and couldn't manage to get the StringResourceModel to work with a Link.
My code looked something like:
Properties:
some.key=User name is: {0}
Java:
StringResourceModel model =
new StringResourceModel("some.key", this, null, new Object[] { getUserName() });
add(new Link("someid", model) {
#Override
public void onClick() {
// do something ...
}
});
HTML:
<a wicket:id="someid">some text to replace</a>
However, that didn't work, i.e. the text was never replaced.
I tried a different direction, which did work, and looks something like this:
Java:
StringResourceModel model =
new StringResourceModel("some.key", this, null, new Object[] { getUserName() });
Link link;
add(link = new Link("someid") {
#Override
public void onClick() {
// do something ...
}
});
link.add(new LabeL("anotherid", model));
HTML:
<a wicket:id="someid"><span wicket:id="anotherid">some text to replace</span></a>
(the properties file is the same).
My question is, am I right to assume that the StringResourceModel doesn't work with Links (I call this an assumption since I didn't see anything about this in the JavaDOC) ?
If not, how can the StringResourceModel be used directly with the Link, without the mediator Label ?
The model parameter in the Link constructor isn't meant to be used as a display value. To set the text of the link you need to explicitly add a Label to it:
Link<Void> link = new Link<Void>("link");
link.add(new Label("label", model);
add(link);
and in HTML:
<a wicket:id="link"><span wicket:id="label"></span></a>
The model in the constructor is meant to be used in the onclick method (or similar). For example (from the JavaDoc):
IModel<MyObject> model = ...;
Link<MyObject> link = new Link<MyObject>("link", model) {
public void onClick() {
MyObject obj = getModelObject();
setResponsePage(new MyPage(obj));
}
};
add(link);
In your first example, you aren't telling wicket to replace the text. You just apply a model to the link without telling wicket what to do with it.
To fix this, you'd need to replace your HTML with something along the lines of
<a wicket:id="someid"><wicket:message key="some.key">some text to replace</wicket:message></a>
I don't remember the syntax completely and can't try this right now but it should help you anyway.
For my gwt app, I have certain html templates that are stored as static .html files on my website. e.g example.com/views/signup.html , example.com/views/foo.html , etc.
I want this to be a single page app like Twitter, so the user would navigate through all the pages without the page being refreshed.
I will have a HTMlPanel as the root element of my app on the host page. Whenever the user navigates to a different page, e.g by clicking a link in the navigation menu, I want to load the .html template for that page via ajax, and set the returned html into the HTMLPanel.
Is this a plausible solution? If so, how can I load the html templates via ajax from GWT?
Thanks.
That is precisely the case of http://gwtproject.org site.
It uses gwtquery to load an html page via ajax and insert it in a certain area of the page via the load() method.
// Load the file.html using ajax, and append the fragment with id=mid from
// the returned document inside the element with id=c in the current document.
$("#c").load("file.html #mid");
You can take a look to the GWTProjectEntryPoint.java (line 128) of the gwt-site-webapp as well.
Of course you have to handle any click on any anchor present in the inserted fragment, to do the appropriate action instead of replacing the gwt application. That can be done with the live() method of gQuery.
$("#c").live("click", new Function() {
public boolean f(Event e) {
String href = $(e).attr("href");
// Do something with href.
return false;
}
});
You may want to look at this SO Q&A.
The idea is:
You create a server call (e.g., RPC) to fetch your html template as a String.
You create a corresponding HTMLPanel that knows how to attach dynamic elements to your html template that you pass in the constructor.
You add this newly constructed HTMLPanel to your page root panel where you want it.
On this SO you can find a panel template code that may help you. The version therein does not have the "dynamic" html source, instead it is hard-coded in a ClientBundle. But it is easy to extend so the source html is dynamic, simply add a construtor like:
public HtmlPanelBase(final String htmlContentAsText)
where htmlContentAsText is your template html String from your server as follows:
public class HtmlPanelBase extends Composite
{
private String _dynPostfix = "";
protected final String id(final String staticId) { return staticId + _dynPostfix; }
private final String wrapId(final String id) { return "id=\"" + id + "\""; }
private final String wrapDynId(final String refId) { return wrapId(id(refId)); }
private String _htmlContentAsText = null;
protected String getHtmlContentAsText() { return _htmlContentAsText; }
private ArrayList<String> _idList = null;
protected HTMLPanel _holder = null;
private HTMLPanel createHtmlPanel(final boolean defineGloballyUniqueIds)
{
// HTML panel text containing the reference id's.
if (defineGloballyUniqueIds)
{
// Replace the reference id's with dynamic/unique id's.
for (String refId : _idList)
_htmlContentAsText = _htmlContentAsText.replace(wrapId(refId), wrapDynId(refId));
}
// Return the HTMLPanel containing the globally unique id's.
return new HTMLPanel(_htmlContentAsText);
}
public HtmlPanelBase(final String htmlContentAsText, final ArrayList<String> idList, final boolean defineGloballyUniqueIds)
{
_htmlContentAsText = htmlContentAsText;
_idList = idList;
this.setup(defineGloballyUniqueIds);
super.initWidget(_holder);
}
public HtmlPanelBase(final String htmlContentAsText)
{
this(htmlContentAsText, null, false);
}
private void setup(final boolean defineGloballyUniqueIds)
{
if (defineGloballyUniqueIds)
_dynPostfix = "_" + UUID.uuid().replace("-", "_");
_holder = createHtmlPanel(defineGloballyUniqueIds);
}
}
To use, fetch your htmlContentAsText on sever (could depend upon locale), upon success instantiate a derived class of the above base template passing the fetched htmlContentAsText in the constructor, and add therein all your logic modifying or adding upon the base html -- e.g., add handlers in response to user actions.
I have the following java and html code:
this.leakageModel = new PropertyListView<Leakage> ( "leakage", new ArrayList<Leakage> ()) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem (final ListItem<Leakage> item) {
Link<String> brandLink = new Link<String> ("brandLink") {
private static final long serialVersionUID = -480222850475280108L;
#Override
public void onClick () {
//change another model in the page to update
//another table when the link is clicked
}
};
brandLink.add (new Label ("brand"));
item.add (brandLink);
} };
add (this.leakageModel);
html file:
<tr wicket:id="leakage" class="testClass">
<td class="testClass">
<a wicket:id="brandLink" href="#">
<span wicket:id="brand"></span>
</a>
</td>
</tr>
What I want to do is to be able to call a javascript function from inside the onClick() method.
The model update that I currently do inside the onClick method works well and updates another table on the page.
However everything I have tried to call a javascript function or change the css style has failed.
For instance:
Adding a css class:
add (new AttributeAppender("class", new Model("anotherclass"), " "));
Using an AjaxLink type instead, and a number of other things I have tried to no avail.
On a related note, my original intention is to hide all rows in the table except the one I have clicked. Maybe I can do this just from the Java code and have no need for Javascript at all, but updating the css as above doesn't work.
Any suggestions as to what am I doing wrong?
On a related note, my original intention is to hide all rows in the
table except the one I have clicked.
Instead of answering your question, I will try to provide a solution to your problem :).
It makes perfect sense to hide the table row via javascript. I would suggest doing it with Jquery as described in Hiding all but first table row with jQuery:
$("#myTbl tr:not(nth-child(3))").hide();
Now, you have to execute the above javascript snippet each time a user clicks your Wicket link. For this, you can for example create your own link class like this:
public class JavascriptLink extends Label{
public JavascriptLink(String id, String label) {
super(id, label);
add(new AttributeAppender("onclick", "...your javascript here..."));
}
}
I leave it to you to combine the jquery with the JavascriptLink to meet your requirements. It should work going in this direction.
I'm trying to develop a little drag & drop application under Java FX. User will drop JFX components like Buttons, Menus, Labels on certain positions. When done, he will save this layout and later on he will reopen the layout and he will use it again.
Its important to store the information about all objects that are dropped on some position.
I decided to use serialization for this purpose. But I'm not able to serialize JavaFX components. I tried to serialize Buttons, Scenes, Stages, JFXPane but nothing seemed to work (I obtained NotSerializableException).
Any suggestions how to save all the components and then retrieve them ?
P.S.: I was trying to find out some method with FXML but I did not succeed.
Thank you very much for your answers :)
You are correct, JavaFX (as of 2.1) does not support serialization of components using the Java Serializable interface - so you cannot use that mechanism.
JavaFX can deserialize from an FXML document using the FXMLLoader.load() method.
The trick though, is how to write your existing components and states out to FXML?
Currently, there is nothing public from the platform which performs FXML serialization. Apparently, creating a generic scenegraph => FXML serializer is quite a complex task (and there is no public 3rd party API for this that I know of). It wouldn't be too difficult to iterate over the scenegraph and write out FXML for a limited set of components and attributes.
If the main goal of saving user components on the servers side - is to have a possibility to show the same interface to the user - why not to save all descriptive information you need about users components, and when it is needed - just rebuild user interface again, using stored descriptive information? Here is primitive example:
/* That is the class for storing information, which you need from your components*/
public class DropedComponentsCoordinates implements Serializable{
private String componentID;
private String x_coord;
private String y_coord;
//and so on, whatever you need to get from yor serializable objects;
//getters and setters are assumed but not typed here.
}
/* I assume a variant with using FXML. If you don't - the main idea does not change*/
public class YourController implements Initializable {
List<DropedComponentsCoordinates> dropedComponentsCoordinates;
#Override
public void initialize(URL url, ResourceBundle rb) {
dropedComponentsCoordinates = new ArrayList();
}
//This function will be fired, every time
//a user has dropped a component on the place he/she wants
public void OnDropFired(ActionEvent event) {
try {
//getting the info we need from components
String componentID = getComponentID(event);
String component_xCoord = getComponent_xCoord(event);
String component_yCoord = getComponent_yCoord(event);
//putting this info to the list
DropedComponentsCoordinates dcc = new DropedComponentsCoordinates();
dcc.setX_Coord(component_xCoord);
dcc.setY_Coord(component_yCoord);
dcc.setComponentID(componentID);
} catch (Exception e) {
e.printStackTrace();
}
}
private String getComponentID(ActionEvent event){
String componentID;
/*getting cpmponentID*/
return componentID;
}
private String getComponent_xCoord(ActionEvent event){
String component_xCoord;
/*getting component_xCoord*/
return component_xCoord;
}
private String getComponent_yCoord(ActionEvent event){
String component_yCoord;
/*getting component_yCoord*/
return component_yCoord;
}
}
I need to pull a JavaScript var off a site so I can use it in my code. Following this tutorial, I was able to display the string in an alert message. But what do I have to do to use the string outside of the alert message? Thanks.
EDIT: My code is basically the same as in the tutorial.
Instead of calling AlertDialog, just do something in Java with the value of the "html" parameter, unless I'm completely misunderstanding what you are asking.
String savedHtml = null;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
#SuppressWarnings("unused")
public void showHTML(String html)
{
savedHtml = html; // this ought to work.
}
}