WebView not showing anything - java

I have a pretty simple application that lists rows from a database in a tableview. When the user clicks on a row in that list, the application grabs the XML column from that row, and is supposed to display it in a WebView in the same window. Everything other than actually displaying the XML works fine. I've been beating my head on this for a while, but I'm not getting anywhere. Here's the code that the listener calls:
#FXML
private void showXML(QueryRow row) {
String msg = "";
try {
msg = mainApp.getMsg(row.getID().get());
} catch (SQLException e) {
e.printStackTrace();
}
final String fm = msg;
System.out.println(msg);
//tb.setText(msg);
webEngine = webView.getEngine();
// webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
//
// public void changed(ObservableValue ov, State oldState, State newState) {
//
// if (newState == Worker.State.SUCCEEDED) {
// System.out.println("inside");
// webEngine.load(fm);
// //stage.setTitle(webEngine.getLocation());
// }
//
// }
// });
System.out.println("Go baby go!");
webEngine.load(fm);
}
What am I missing?

If you want to load XML and fm is not link then you should probably use
webEngine.loadContent(fm);
/**
* Loads the given HTML content directly. This method is useful when you have an HTML
* String composed in memory, or loaded from some system which cannot be reached via
* a URL (for example, the HTML text may have come from a database). As with
* {#link #load(String)}, this method is asynchronous.
*/
public void loadContent(String content) {
loadContent(content, "text/html");
}
But this will not make xml visible, so if you want your xml to be displayed, you have to put it in some default html page. Something like this:
https://gist.github.com/jewelsea/1463485
or simple way:
webEngine.loadContent(
<textarea readonly style='width:100%; height:100%'>"+ fm +"</textarea>")

Ok, I just tested a little bit. text/html is the correct way, but you need to do some work on your xml data: You have to escape the XML entities (I use commons-lang3 StringEscapeUtils for that) and then wrap all in a preformatted html string:
public class JavaFXTest extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test to display XML");
BorderPane content = new BorderPane();
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tag1>\n <tag2>hello</tag2>\n</tag1>";
String escaped = StringEscapeUtils.escapeHtml4(xml);
String html = "<html><head></head><body><pre>" + escaped + "</pre></body>";
webEngine.loadContent(html, "text/html");
content.setCenter(webView);
primaryStage.setScene(new Scene(content, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This produces the following window:
Addition: You might need to do some pretty printing on the xml before escaping; I just used hard coded line breaks and spaces.

Related

Android - is there any Function or Way to Search a specific text in an HTML Webview text

Hello to all Android Programmers, is there any way to search a specific word in an HTML Webview? Or lets say when you put a word in search box and search it and then it will automatically scroll to the word or highlight it but the text is not in TextView the text are formatted using WebView? Sure it may be possible when you store a paragraph in the database and it can be searched easily but the problem on it is it isn't formatted like HTML so is this possible?
Please see the image on this link
For Highlighting search word:
titleWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
if (searchText != null && !searchText.equals("")) {
int i = titleWebView.findAll(searchText);
Toast.makeText(getApplicationContext(), "Found " + i + " results !",
Toast.LENGTH_SHORT).show();
try {
Method m = WebView.class.getMethod("setFindIsUp", Boolean.TYPE);
m.invoke(titleWebView, true);
} catch (Throwable ignored) {
}
searchText = "";
}
}
});
You can achieve it by reading source of page in webview.
Inside
Add this method in onPageFinished() of webviewclient:
webView.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+" +
"document.getElementsByTagName('html')[0].innerHTML+'</html>');");
Declaration for above called method processHTML() which helps to
process source html to String/JSON Obj.
#SuppressWarnings("unused")
#JavascriptInterface
public String processHTML(final String html)
{
// Log.i("processed html",html);
Thread OauthFetcher=new Thread(new Runnable() {
#Override
public void run() {
htmlString= Html.fromHtml(html).toString();
// Log.i("htmlString",htmlString);
Gson gson = new Gson();
CustomPojoObject obj = gson.fromJson(htmlString, CustomPojoObject.class);
}
});OauthFetcher.start();
return htmlString;
}

Refresh panel in Wicket with BootstrapDownloadLink

My problem is simple but I have no clue how to solve it. I have a feedbackPanel and I want to show an error message if the BootstrapDownloadLink fails. With a submit I could easily do:
protected void onSubmit(AjaxRequestTarget target) {
...
error("File_not_found"); //Wicket will print this on the feedback panel
target.add(getModalPanel().getFeedbackPanel()); //But i need to refresh it first
}
But the button is inside a panel which I fill with a populateItem and is the only way I know to insert Bootstrap Styles to it. The code of the button:
BootstrapDownloadLink downloadDocument = new BootstrapDownloadLink(IDITEMREPEATER, file) {
#Override
public void onClick() {
File file = (File)getModelObject();
if(file.exists()) {
IResourceStream resourceStream = new FileResourceStream(new org.apache.wicket.util.file.File(file));
getRequestCycle().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(resourceStream, file.getName()));
} else {
error(getString("error_fichero_no_existe"));
/// ???? need to refresh-> getModalPanel().getFeedbackPanel()
}
}
};
downloadDocument.setIconType(GlyphIconType.clouddownload);
downloadDocument.add(new AttributeModifier("title", getString("documentos.descargar")));
downloadDocument.add(new AttributeModifier("class", " btn btn-info negrita btn-xs center-block"));
downloadDocument.setVisible(Boolean.TRUE);
list.add(downloadDocument);
You could create or extend from an AjaxDownloadLink, for example like here.
The main idea is to have an AjaxBehavior that does the download, and you get a public void onClick(AjaxRequestTarget target) in which you can add the FeedbackPanel
downloadBehavior = new AbstractAjaxBehavior()
{
private static final long serialVersionUID = 3472918725573624819L;
#Override
public void onRequest()
{
[...]
ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(
AjaxDownloadLink.this.getModelObject(), name);
handler.setContentDisposition(ContentDisposition.ATTACHMENT);
getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
}
};
And use that behavior in the onclick:
#Override
public void onClick(AjaxRequestTarget aTarget)
{
String url = downloadBehavior.getCallbackUrl().toString();
if (addAntiCache) {
url = url + (url.contains("?") ? "&" : "?");
url = url + "antiCache=" + System.currentTimeMillis();
}
// the timeout is needed to let Wicket release the channel
aTarget.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);");
}
You can use target.addChildren(getPage(), IFeedback.class). This will add all instances of IFeedback interface in the page to the AjaxRequestTarget.
You can also use FeedbackPanel.class instead of the interface.
Or use getPage().visit(new IVisitor() {...}) to find a specific feedback panel if you don't want to add others which are not related.

Wicket, modify HTML <body> element

I want to modify the HTML body tag when I open a Wicket-Bootstrap Modal. What I'm trying to achieve is <body class="modal-open"> instead of <body>
Using Wicket 8 M8 , I have this code:
owsImportDialog = new MyModalBootstrapDialog("owsImportDialog"
, new CompoundPropertyModel<>(new BopOwsTO())) {
#Override
void importOws(AjaxRequestTarget target, IModel<BopOwsTO> owsModel) {
appendCloseDialogJavaScript(target);
BopOwsTO owsTo = owsModel.getObject();
try {
importOwsCapabilities(owsTo);
owsViewDialog.header(Model.of("OWS anzeigen"))
.setModel(Model.of(owsTo.getServiceId()));
owsViewDialog.appendShowDialogJavaScript(target);
}
catch (OwsCapsImportException e) {
String localizedMessage = e.getLocalizedMessage();
importAlert.setModelObject(localizedMessage);
importAlert.appendShowDialogJavaScript(target);
error(localizedMessage);
}
finally {
target.appendJavaScript("document.getElementsByTagName('body')[0]" +
".setAttribute('class', 'modal-open');");
// target.appendJavaScript("document.body.setAttribute('class', 'modal-open');");
// target.prependJavaScript("document.body.setAttribute('class', 'modal-open');");
// target.appendJavaScript("alert('Hallo');");
// owsViewDialog is a child of owsView WebMarkupContainer
target.add(owsView, feedback);
}
}
#Override
void saveOws(AjaxRequestTarget target, IModel<BopOwsTO> owsModel)
{ }
#Override
void cancel(AjaxRequestTarget target)
{ }
};
If the line target.appendJavaScript("alert('Hallo');"); is active I actually see the alert window.
I also tried this code in the page class:
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
PackageResourceReference resourceReference = new PackageResourceReference(
getClass(), "../css/BuiOwsPage.css");
CssReferenceHeaderItem cssRef = CssReferenceHeaderItem.forReference(resourceReference);
response.render(cssRef);
response.render(OnLoadHeaderItem
.forScript("document.body.setAttribute('class', 'modal-open');"));
}
But none of my attempts was succesful.
Update
The answer of #martin-g didn't solve the issue.
I'm quite sure that the problem is caused by the sequence of these statements:
{
appendCloseDialogJavaScript(target);
...
try {
owsViewDialog.appendShowDialogJavaScript(target);
....
}
catch { ... }
finally {
target.add(owsView, feedback);
}
}
When this modal is closed because of appendCloseDialogJavaScript() ,
the class modal-open is erased from the class attribute of the <body> .
Then owsViewDialog opens, but modal-open isn't inserted in class, no matter if I append the snippet jQuery(document.body).addClass('modal-open') or not. The missing modal-open means that the page can't be scrolled.
Since Wicket and Bootstrap are used then jQuery is also available. I would recommend you to use jQuery(document.body).addClass('modal-open').
There must be a reason why jQuery has both addClass() and attr()!

Editor persist throws "A request is already in progress "

I'm trying to set up a basic editor in gwt. Everything works fine, the editor displays the data and saves but when I try to save again (i.e. press the save button 2 times) it throws me the error "A request is already in progress " in the second save, but the first time the editor saves the data correctly.
//
//Methods that edit and save the editor, located in ComposerEditorContainer class
//
public void edit(RequestContext requestContext) {
editorDriver = GWT.create(Driver.class);
editorDriver.initialize(requestFactory, composerEditor);
editorDriver.edit(composer, requestContext);
}
public void save() {
ComposerRequest composerRequest = (ComposerRequest) editorDriver
.flush();
ComposerProxy newProxy = composerRequest.edit(composer);
composerRequest.persist(newProxy).fire();
}
//
//Events in a presenter that save and initialize the editor
//
eventBus.addHandler(SaveButtonClickedEvent.TYPE,
new SaveButtonClickedEventHandler() {
#Override
public void onSaveButtonClicked(SaveButtonClickedEvent event) {
((ComposerEditorContainer) composerEditorContainer)
.save();
}
});
//This method gets the ComposerProxy from the event and initializes the editor in ComposerEditorContainer (above)
//
eventBus.addHandler(BrowserItemClickedEvent.TYPE,
new BrowserItemClickedEventHandler() {
#Override
public void onBrowserItemClicked(
BrowserItemClickedEvent event) {
requestFactory = GWT.create(AppRequestFactory.class);
requestFactory.initialize(new SimpleEventBus());
ComposerRequest request = requestFactory
.getComposerRequest();
Request<ComposerProxy> req = request.findComposer(event
.getclickedItem().getValue());
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerEditorContainer editorContainer = new
ComposerEditorContainer(
requestFactory, arg0);
editorContainer.edit(requestFactory
.getComposerRequest());
view.clear();
view.addWidget(editorContainer);
composerEditorContainer = editorContainer;
}
});
}
});
//Error that appears when saving for the second time
Caused by: java.lang.IllegalStateException: A request is already in
progress
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.checkLocked(AbstractRequestContext.java:
960)
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.editProxy(AbstractRequestContext.java:
510)
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.edit(AbstractRequestContext.java:
502)
at
com.google.test.client.editor.ComposerEditorContainer.save(ComposerEditorContainer.java:
58)
at com.google.test.client.presenter.BrowserDetailPresenter
$1.onSaveButtonClicked(BrowserDetailPresenter.java:48)
at
com.google.test.client.event.SaveButtonClickedEvent.dispatch(SaveButtonClickedEvent.java:
17)
Answered on the Google Group: https://groups.google.com/d/msg/google-web-toolkit/TfXd_SEJF30/ZTLkfXUQ2vUJ
A RequestContext is a "builder"; you queue things into it and then fire(). Once fire()d, it's no longer usable; you have to create a new one and start over.

How to hook into the internal Eclipse browser?

For my eclipse plugin I want to track every URL that is opened with the internal (and if possible also external) Eclipse browser.
So far I use
org.eclipse.swt.browser.Browser;
and
addLocationListener(...)
But I would prefer that it works also for the internal Eclipse browser. How can I achieve that?
One possible solution for the Eclipse Internal Browser would be to create an eclipse plugin that registers an IStartup extension. In your earlyStartup() method you would register an IPartListener on the workbenchPage. Then when the internal browser part is created, you will receive a callback with a reference to the WebBrowserEditor (or WebBrowserView). Since there is no direct API you will have to hack a bit and use reflection to grab the internal SWT Browser instance. Once you have that, you can add your location listener.
Sometimes during early startup there is no active Workbench window yet so you have to loop through all existing workbench windows (usually just one) and each of their workbench pages to add part listeners also.
Here is the snippet of code for the earlyStartup() routine. Note that I have omitted any cleanup of listeners during dispose for windows/pages so that still needs to be done.
//Add this code to an IStartup.earlyStartup() method
final IPartListener partListener = new IPartListener() {
#Override
public void partOpened(IWorkbenchPart part) {
if (part instanceof WebBrowserEditor)
{
WebBrowserEditor editor = (WebBrowserEditor) part;
try {
Field webBrowser = editor.getClass().getDeclaredField("webBrowser");
webBrowser.setAccessible(true);
BrowserViewer viewer = (BrowserViewer)webBrowser.get(editor);
Field browser = viewer.getClass().getDeclaredField("browser");
browser.setAccessible(true);
Browser swtBrowser = (Browser) browser.get(viewer);
swtBrowser.addLocationListener(new LocationListener() {
#Override
public void changed(LocationEvent event) {
System.out.println(event.location);
}
});
} catch (Exception e) {
}
}
else if (part instanceof WebBrowserView)
{
WebBrowserView view = (WebBrowserView) part;
try {
Field webBrowser = editor.getClass().getDeclaredField("viewer");
webBrowser.setAccessible(true);
BrowserViewer viewer = (BrowserViewer)webBrowser.get(view);
Field browser = viewer.getClass().getDeclaredField("browser");
browser.setAccessible(true);
Browser swtBrowser = (Browser) browser.get(viewer);
swtBrowser.addLocationListener(new LocationListener() {
#Override
public void changed(LocationEvent event) {
System.out.println(event.location);
}
});
} catch (Exception e) {
}
}
}
...
};
final IPageListener pageListener = new IPageListener() {
#Override
public void pageOpened(IWorkbenchPage page) {
page.addPartListener(partListener);
}
...
};
final IWindowListener windowListener = new IWindowListener() {
#Override
public void windowOpened(IWorkbenchWindow window) {
window.addPageListener(pageListener);
}
...
};
IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWindow != null)
{
IWorkbenchPage activePage = activeWindow.getActivePage();
if (activePage != null)
{
activePage.addPartListener(partListener);
}
else
{
activeWindow.addPageListener(pageListener);
}
}
else
{
for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows())
{
for (IWorkbenchPage page : window.getPages()) {
page.addPartListener(partListener);
}
window.addPageListener(pageListener);
}
PlatformUI.getWorkbench().addWindowListener(windowListener);
}
One last detail about this code snippet is that it requires a dependency on the org.eclipse.ui.browser plugin to have access to the WebBrowserEditor class.

Categories