want to capture link click in a file viewer application

Greetings Vaadin experts:
As a new user of Vaadin, I am still getting my feet wet, and want to make sure I don’t go off and implement something the wrong way.

Right now I have a simple file viewer application that is based on the sample application. The left side is a Tree using HierarchicalContainer, and the right side (the file viewer) is a Panel containing the contents of the file the user has clicked on. So far, so good, and it all works perfectly. If the user clicks on a text or html file, I use a TextFileProperty as the property data source for a Label (created with ContentMode.HTML), and that is set as the contents of the Panel. Graphic files are put in an Image and that is placed in the panel.

The issue is with html files. They show up just fine, the html renders correctly, but I need to handle clicks on links in the content.

I want to capture the event when the user clicks on a link in the right hand side. Once captured, I can decide what to do with the click. If the files are relative urls to other files, or absolute urls to other files, I want to replace the Label’s content with the contents of this new file. External URLs will be handled differently, perhaps in a new tab or window. I haven’t decided yet.

I read something on the forum about using a URIFragment, but it looks like that involves parsing the file contents, etc. and is possibly the wrong way to handle this.

This looks like a simple thing to me, but I don’t know how to proceed.

Thoughts?

Does this question need more detail? Does anyone have thoughts on this?

I don’t know whether i understood your question correctly but i also had a problem once when i was trying to make a call from an embedded html page to a Java server side class (My UI). If you want to look at thread where Leif Åstrand helped me solving it look
here
.
To summarize the solutions. You can either 1, use JavaScript.getCurrent().addFunction() to add a function which you can call from an embedded html page like href=‘javascript:(function(){window.parent.somefunction(someparameters…);})();’ which might work if the Vaadin app and html page come from the same domain, 2, embedd the Html Page using a CustomLayout. This will make the JavaScript to Java call more reliable but will be a bit problematic to embedd the html as Customlayout, especially if you have code in your head tag of your file. When i ran into these problems i finally used 3: Creating a Custom Javascript Component. which made the JS to Java call reliable and had no problems adding a head to the html of the JS component.
Mind you that in my case i had a static html where i only changed a few href links according to input parameters so i don’t know exactly how possible these options are in your case or if there is another way that would work better for you.

Btw. yes when using the URIFragment way you would have to parse your necessary parameters and “send” it to vaadin by changing the url to something like …yourApp#someparameters…

Thanks for the ideas Marius. From your followup, and the thread you refer to, I get the impression you are in control of the contents of the HTML files in question.

That is not the case for me. My file browser application is basically a report browser, and the reports (HTML) have links to “drill-down” reports containing more details. These drill-down links can go down 4 or 5 levels, depending on the situation. Right now, these drill-down links are relative URLs to other files that are to be found somewhere under a common subdirectory. That’s about as tightly as the definition is for what I am displaying. When a user clicks on a drill-down URL, I want to capture that click, examine the url, find the file, and replace the current file with the new one, and they can drill down some more if they like. I eventually plan on giving them a localized “Back” button as well, but that comes later. Once I get control of mouse/url clicks in the panel displaying the file, I think my main problem will be solved.

While the tree displayed in the left side of my split panel will likely contain the html files shown in the links on the right, navigating a drill-down exploration from the tree is a little clumsy. When they see a link in an area of the report, the inclination is for them to click that link to find more information. The HTML contents in the area of the link is more instructive to them than the tree structure is, once they get started drilling down.

I think you what you want is a JavaScriptComponent that, when the report is loaded into the DOM, finds all elements in it and adds a custom JS click listener to each of them. The click listener calls the server (using Vaadin’s JavaScript RPC), asking it to send a new report, and then returns false (or calls preventDefault on the click event) to stop the browser from actually navigating to the linked page.

Of course, you could do this with a regular Java/GWT component as well, but if you’re comfortable using JS, in this case the JS way is probably faster and you don’t need to fiddle with the widgetset compilation.

The files can be overwritten or deleted by a report generator process at any time. I don’t have any control over the contents of the HTML files. Do you mean insert the javascript into the HTML before I display it? Any javascript in the HTML report would have to be added by me at display time.

Yes, this would be done at display time, on the client side. And you don’t even need to modify the HTML content, just let the browser first render the HTML, then grab the
DOM
subtree, find all elements and add a click listener to each of them (this can be done in a single line of code with
jQuery
, for instance).

I have just finished reading in the BoV about Navigator for view management, and in general about URI Fragments. The URI Fragment is generated by the code itself with something like Page.getCurrent().setURIFragment(“something useful”). I do not have the information at hand to generate any URI Fragments (if I did, I could solve the problem). I also tried putting my Label instance in a VerticalLayout and implementing a LayoutClickEvent to capture a mouse click in this label. That worked fine, and it lets me see where the mouse was clicked in the label. However, I cannot find a way to use that information to find what text is under the mouse. What I am after is the url under the mouse when the mouse is clicked.

I guess this boils down to one question about clicks on arbitrary HTML links in a label (or other component).
Before I started trying to capture the mouse click, the web browser tried to process the url, supposedly to display the contents. Since the url was not really valid, there was nothing for the browser to do.
How so I capture that url in Vaadin? If I could do that, my problem would be solved, since I could find the file in my file browser component, and display that file’s contents in my label.

The problem is that when you are displaying an external html inside Vaadin with a Browser Embedded Component or using Page.open/Vaadin Link component you don’t have control over what the links inside the html do. So when they are linking to another page/subpage they will affect the url directly and in ‘plain’ server side vaadin you can’t really do anything to stop it.
The only thing that might (or should) work ist what Johannes suggested which i find actually quite genius. You just have to write a JavaScript component and integrate it as described
here
. On the JavaScript side you look through the DOM tree and modify the elements using f.e. jQuery as Johannes already pointed out.

Yep. To a browser, a link is a link, no matter if it happens to be embedded in a Vaadin application or not. The only way for Vaadin to take control of the links is to programmatically modify the links to do something else than the default.

For me at least, I found a simpler solution than working with Javascript. I rewrote the urls in the files to include a uri fragment that I could capture and process.

For example, my app is at pkrouse-e6410:8080/FileBrowser/, and a URL that said
newlink
now says:
newlink

Using a URI Fragment like this seems more straightforward to me, but then again I am new to Vaadin. Javascript interaction section is next for me in the BoV, so I may end up going that route eventually.