We have an application built on GWT framework where we want to display a PDF file without any browser plugin and are currently evaluating PDF.js to do that.
The problem is, no matter what I do, I am not able to render a PDF file onto a canvas in our GWT application. Do give some background
The PDF file ticket is retrieved from server.
The PDF.js file ticket is retrieved from server and is embedded in the HTML body by using this script
var head= document.getElementsByTagName('body')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.setAttribute('charset', 'UTF-8');
script.src=url;
head.appendChild(script);
Canvas element is created in the View (using googles MVP pattern here) and a JSNI call is made to the script which embeds the PDF.js in the HTML body using the above function. The script then makes a call to function which works with PDFJS class defined in PDF.js file.
The function to render the PDF file on canvas is as below :
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf)
{
pdf.getPage(1).then(function getPageHelloWorld(page)
{
var scale = 1.25;
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: context, viewport: viewport});
page.startRendering(context);
alert("Finished rendering");
});
});
The canvas and context are created in the View class and passed to the javascript.
The problem here is, after the call to JSNI is made, I show alerts of all variables. The browser shows alerts except when I make a call alert(PDFJS). This shows that PDFJS variable is not being recognised in the script.
This makes me think PDF.js file is not correctly embedded in the view or there is something else that I am missing.
Note: I have downloaded most of the examples over the net and most of them work locally i.e. I can modify the PDF.js file path to pick up a local copy and the HTML still renders the PDF. It has no problem reading the PDFJS variable. Its only in this GWT application that I see these problems.
Does anyone have any clue whats happening. Your help will be highly appreciated.
Thanks
Your problem is that you're injecting the script so it aloads asynchronously, but you don't wait until after it's loaded to start using it.
Try using ScriptInjector.FromUrl to inject the script and put the rest of your code in the Callback's onSuccess.
Injecting the script synchronously (by adding it to your HTML host page, or GWT Module descriptor —note: won't work with the xsiframe linker—), as proposed by Ilya is of course also a solution.
Try to add <script src="PDF.js"/> in your .gwt.xml file and put PDF.js file in your public director
Related
I am currently working my way into wicket and developed a small demo application. Now I want to display a static image in that application (to be more specific, this image should be added to a panel which is then added to the home page).
This is what I have so far:
1) The HTML code for the panel that should hold the image. There is no specific wicket code present, it should only hold an image present in the project structure.
<html><body>
<wicket:panel>
Just some static text inside the image panel...<br/>
<img src="test.jpg"></img>
</wicket:panel>
</body></html>
The panel is called ImagePanel and all three files (ImagePanel.java, ImagePanel.html, test.jpg) are located in the same package.
2) The Java code for the ImagePanel - rather short, as there is nothing really to do:
public class ImagePanel extends Panel {
public ImagePanel(String id) {
super(id);
}
}
3) The HTML code for the homepage:
<html><body>
<div wicket:id="dynamicComponent"></div>
</body></html>
4) And the Java code for the homepage:
public HomePage() {
add(new ImagePanel("dynamicComponent"));
}
Please note the following: In practice, HomePage.java and ImagePanel.java are located in different OSGi-projects. The code for the HomePage is simplified here, in practice the ImagePanel is located via a service and dynamically added. This works so far, I see the static text. But the image is not loaded, I just get this broken-image-thumbnail.
Like I said, all three ImagePanel-related files (.java, .html, the picture) are located in the very same package. I can access the Panel itself from the homepage-project as I can see the static text. But I can't get the image to display.
The Application Server I use is Jetty, started from inside the project that holds the homepage.
Update:
I've narrowed the problem to the following:
Everything works fine as long as I only display static text inside of ImagePanel.html. As soon as I want to add the image (even if inside of a wicket:link-tag as suggested below) I end up with the following exception:
[qtp401543768-20] WARN org.apache.wicket.core.util.lang.WicketObjects - Could not resolve class [plugin.ImagePanel]
java.lang.ClassNotFoundException: plugin.ImagePanel
So without the image the server bundle is able to load the class from the gui bundle and display the static text. With the image I end up with a ClassNotFoundException for the same class.
Find the whole stack trace here: stack trace
In your template, put a around
<wicket:link>
<img src="test.jpg"></img>
</wicket:link>
Wicket will rewrite the url so that the image works.
If you have a dynamic Image that you want to load a Package Resource, you use PackageResourceReference.
e.g.
add(new Image("myImage", new PackageResourceReference(MyClass.class, "test.jpg"));
Thanks for the help, though meanwhile I managed to solve the problem myself. It was not a sole wicket problem but also some difficulties with the OSGi-bundle-setup.
As I mentioned before, the ImagePanel is located in a different OSGi bundle than the HomePage. The problem arised as all Wicket-libraries are located in the HomePage-bundle (I get Linker errors if both bundles use their own libraries). Therefore loading an image in the ImagePanel used classes located in the HomePage-bundle who now couldn't access the image.
I solved the problem by introducing an OSGi-Service in the ImagePanel-bundle that passes all used images as byte arrays to the HomePage-bundle. The HomePage-bundle has now access to all resources and registers them as SharedResource with an id given again by the ImagePanel-bundle.
After registration, it is no problem to access the images in the ImagePanel-bundle via SharedResourceReference.
I am currently working on a GWT project where I am displaying an HTML file within an iframe in my application. This HTML file is actually being written to as it is getting displayed, and I am hoping to be able to reload the frame so that the changes made to the HTML file are reflected on screen. I am able to do this two different ways that both work when running in development mode, however neither seem to work when the project is deployed.
The first method I tried was setting the frame's URL to itself:
frame.setUrl(frame.getUrl());
The second method I tried using JSNI:
public native void refresh() /*-{
if($doc.getElementById('__reportFrame') != null) {
$doc.getElementById('__reportFrame').src =
$doc.getElementById('__reportFrame').src;
}
}-*/;
When deployed, the frame gets displayed in a Window, and when the file is finished being written to, a call to either of these refresh methods is made, and the frame refreshes to contain the finished HTML file. When I am deployed, the call to refresh does not reload the contents of the frame, however if I bring up the frame's context menu (in Firefox), then go into 'This Frame', and click Reload, it successfully reloads the frame to contain the finished HTML file. I have tested this on multiple versions of Firefox without any luck.
Does anyone have any suggestions? Why would the behavior be different from one mode to the other?
Thanks.
wow, google is really fast with his search^^
You can use some JSNI to do this. Create a method such as
protected native void reloadIFrame(Element iframeEl) /-{
iframeEl.contentWindow.location.reload(true); }-/;
Then call it with your iFrame element
so your question you posted twice was already answerd here
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/64aa7712890652d3
We had a requirement where one GWT application(parent) had another GWT application(child) loaded in an iframe. The child application had to refresh the iframe after it performs certain DB operations. We used JSNI to accomplish the same.
private native void refreshChild(String url)/*-{
$wnd.location.href=url;
}-*/
In case, if the child frame needs to be redirected to another webpage, the url can be modified accordingly.
We did try to use the reload() method, but it did not help.
The above piece of code, of course needs to be written in the child application.
I just want to read a HTML file and display its content in a GWT widget. Already I have done it but i'm not getting its css and javascripts. So can anyone help me to get the content with its css and javascripts?
I tried the following code,
public class FrameExample implements EntryPoint {
public void onModuleLoad() {
Frame frame = new Frame("http://www.google.com/");
RootPanel.get().add(frame);
}
}
I got a rectangular box only. But I don't get the expected result. Can you help me?
Forget everything I said, you can get the answerer here!
(Iframe not displaying some pages)
Basically: google has a mechanism to detect if it is not hosted in a iframe. This of course raises the question why they us it in their examples.....
BTW: a site like http://en.wikipedia.com works.
i have a big problem here..i am using Microsoft charting controls in my asp.net mvc application..pie chart is working in my Mozilla Firefox perfectly when i open try to run the application in IE the chart is not displaying. when i refresh the page couple of times its showing the chart there?
is there anything doing wrong?
please can anybody help me out
thanks
I use also Microsoft Chart control in my ASP.NET MVC application. The problem which you describe can not appears in my case. I can explain why. I have a MVC Controller with the method GetChart which gives back pure PNG file as a stream. So I define on a HTML page (on a View to be exactly) a <img> element with src attribute like "<%= Url.Content ("~/Home/GetChart")%>". So web browser load and display a PNG graphic only. Such implementation works perfect in all browsers. It is also tested and works with IE6.
My GetChart method looks like following:
public FileStreamResult GetChart (/*some additional parameters*/) {
MyChartModel model = new MyChartModel ();
System.Web.UI.DataVisualization.Charting.Chart chart =
model.CreateChart (/*some parameters*/);
// Save the chart in a MemoryStream
MemoryStream imageStream = new MemoryStream ();
chart.SaveImage (imageStream, ChartImageFormat.Png);
// Reset the stream’s pointer back to the start of the stream.
imageStream.Seek (0, SeekOrigin.Begin);
return new FileStreamResult (imageStream, "image/png");
}
The code of the model MyChartModel is a little longer, but if you have already a implementation of Microsoft Chart you have already all needed.
I'm new to GWT, and I'm sure this is answered in SO somewhere but I've yet to find
I downloaded the GWT 2.0 eclipse plugin, and was pleased to see it comes with a starter project.
However, I was surprised that when running it, there is an unpleasent flickering...
The text loads without the CSS first
It takes a while untill the select box apears
(If you don't see the flicker, try and press F5 to refresh)
All mature GWT apps seem to have a loader before that but I didn't find an easy, standard way to add it.
It seems this app loads in this order: (correct me please if I mixed it up, its only my guess)
Basic layout HTML,
All JavaScript, and CSS
Runs the logic on the "onload" event (soonest time your compiled javaScript can start - ?)
So I can't programmatically add a loading spinner before GWT was loaded, a bit of a catch 22 for me
Am I missing something basic? is there a best practice way to add that initial spinner?
I was thinking simply adding a div with an animated gif, and in the onload event - hide it.
But I'm sure there is something better.
Let me know if this is a duplicate question
Update: found this related question, not answering mine though...
I've handled this problem before by not using the GWT module to load CSS, but loading it directly in the tag itself. If you do this, the browser will always load the CSS first, even before the GWT JS is loaded.
This means you'll lose a bit of flexibility and speed, but its the only workaround I've used so far.
EDIT: Extra info cause I want the bounty :D
If you do not remove the
<inherits name='com.google.gwt.user.theme.standard.Standard'/> from your module.gwt.xml file, then the GWT standard theme is loaded in the JS file that GWT creates. This JS file loads after the HTML page renders, and injects the CSS after load. Hence the flicker.
To avoid the flicker, you can comment out that line and insert your own stylesheet into the <head> of your HTML file. This ensures your CSS loads before the HTML renders, avoiding any flicker. If you really want the GWT theme, you get it out of the source code.
To use a spinner with GWT is quite easy. One simple way would be to keep it in a div with an id in the HTML file itself. Then, in the onModuleLoad(), simply hide that div by calling RootPanel.get("spinner").setVisible(false);
That should show the spinner till GWT loads itself.
Here's what we do to implement a spinner.
You put something like the following HTML just below the script line that loads your application (ie. the one with nocache.js). e.g.:
<div id="loading">
<div id="loading-msg">
<img src="icons/loading-page.gif" lt="loading">
<span>Loading the application, please wait...</span>
</div>
</div>
Then in your application EntryPoint you reach into the page using the DOM and remove that div. e.g.
final RootPanel loading = RootPanel.get("loading");
if (loading != null) {
DOM.removeChild(RootPanel.getBodyElement(),
loading.getElement());
}
Ehrann: I'm afraid the practice mentioned in the above answers is the only way for now. GWT doesn't provide similar features to show/hide a "loading" frame "on the fly". I guess one of the reason is that this requirement is not so "common" for all GWT users, one person might want a very different style of the "loading" than others. So you have to do that by yourself.
You can have a look at the GXT showcase page (based on GWT too): http://www.extjs.com/explorer/ for how they do that. For the source of it, download Ext GWT 2.1.0 SDK here: http://www.extjs.com/products/gxt/download.php and check the samples/explorer folder after extracting it. For details see the edit below:
EDIT
Check the source code for http://www.extjs.com/examples/explorer.html and you can see a div with id "loading". For each samples (extending Viewport), GXT.hideLoadingPanel(loadingPanelId) is called in onAttach() (the initialization), which hides the loading frame.
Check source code of Viewport here
Check source code of GXT.hideLoadingPanel here
You can do it in a similar way.
You could put an HTML loading message in the host page (use style attributes or embed the style tag in the header to make sure that it's styled), and remove the message once your modules has loaded, e. g. Document.get().getBody() with .setInnerHTML("") or .removeChild(), and then present your application programmatically however you want.