Avoiding multiple html tags

I have a WebButton defined in Xojo which is outside an HTMLViewer control on the page. The HTMViewer has some javascript in it that is loaded using LoadPage.

The Action event in the WebButton is something like HTMLViewer1.ExecuteJavascript(“Xojo.get(‘cv1’).showmsg();”) where id is cv1 and javascript function is showmsg. The button doesn’t work. I get an error message saying something like the function referred to in the WebButton is not defined.

If I declare the button in the html source in HTMLViewer using LoadPage, the button works. I don’t want to do it this way because I want to use xojo style sheet for button. If I could figure out how to refer to a style sheet in Xojo for a html input button in the LoadPage that might work but I couldn’t figure that out either.

I am wondering if the multiple html tags produced by HTMLViewer is the problem. Any ideas? I think this problem might be related to the forum post here but that post is not quite the same.

The HTMLViewer creates a frame, which holds a whole 'nother web page. That’s how HTML works. Further, HTML5 has a security model that keeps Javascript from manipulating things across frames. Instead, you’ll need to send that other frame a message, and that other frame will need to handle the message. There’s a good intro here:


Depending on what you are trying to accomplish, you might want to look at the WebSDK. It’s in the Extras folder next to the Xojo application.

Awesome. That’s gotta be it. I will have another look at the WebSDK too. Thanks!

Greg, I need to go through the entire Web Control SDK manual and really understand the HTMLArea example (which I don’t, even though I can do the example in the manual and get it to run fine). Let me know if there are any other examples you know of that would help me figure this out.

I have one question at this point. When I read “…send events back to the server…” in the Two-Way Communication section (1st paragraph) of the Web Control SDK manual it made me think this wasn’t what I was looking for. After all, the two separate controls are on the same page, albeit in separate html sections. Also, I thought Javascript only ran on the client. Apparently, Javascript across html sections won’t work for security reasons but two-way communication (client to server then server back to client?) is a way to make it work. Is there a way to avoid the separate html sections by using a different web control?

What might help me is a schematic showing all the objects in the library and how to make connections across objects. I know that’s not easy but I think it would clear up some of my confusion. I am used to desktop apps where everything in the window can communicate with everything else in the window. Something like Figure 3.2 Web Control Hierarchy (page 119) of the User Guide - User Interface manual showing all the direct connections that are possible among objects in the library might be helpful.

Thanks again for your help.

There are no direct connections between our controls. If you click a button, an event is sent to the server, your code executes and then a response of some kind is sent back to the page. I’m still not clear what your end goal is though. If you describe what you are trying to do, we might be able to offer more suggestions.

I am trying to control playback of a youtube video using Xojo WebButtons (not the youtube player controls).

I have an html page that works great outside Xojo and I can get html input buttons on the html page to control the youtube video playback.

I am just trying to incorporate this html page into Xojo and use Xojo WebButtons that are outside the htmlviewer control to control playback of the youtube video.

I can load the contents of the html page into an htmlviewer control pagesource and it works fine. What I can’t figure out is how to get webbuttons that are outside the htmlviewer to control the playback of the youtube video. When I press the webbutton is just says object is null. I assume it has something to do with the fact that the htmlviewer control is really a subpage of the main page so the webbuton can’t access it. I tried using a pagesource (because that worked for controlling audio via webbuttons) but couldn’t get the youtube html souce to load in the pagesource (got some errors but can’t remember what they were).

Right. You need to implement the YouTube Javascript API. You’ll spend a lot of time, and pull out a lot of hair doing that. Or you could purchase a Studio Stable Web Essentials license and save a lot of effort. A demo of the YouTube controls is here:


Click #2 (top left), then “YouTube” (top right) for the YouTube demo.


I am using the Youtube Javascript api. I was already aware of the link you sent.

Ah, okay. You need access to the DOM that’s inside the htmlviewer.


Not sure I follow you. How are these commands (contentDocument and contentWindow) different from document.getElementByID?

Anyway, I did try contentDocument and contentWindow and neither one seems to work (I have no idea why). Besides, there are all kinds of browser incompatibility issues with these commands I’d rather not have to mess with. If I have to, I’ll just use the youtube controls or put buttons in the same htmlviewer. The bigger problem here (which is why I am not just dropping it) is that I have lots of components that need to communicate with each other (I am converting a RB desktop app to Xojo web app) so if I can’t get this to work it raises a bigger question about whether it is feasible for me to use Xojo Web at all.

I have also tried a test page with structure (not code) below (iframe is based on Youtube Javascript API) and the button controls the youtube player window fine so what I thought was causing the problem (namely, iframe on a separate subpage) appears not to be the case.

Again, a page with above structure works fine outside of Xojo.

At this point, it seems to me like Xojo is making components on the same page behave like cross-domain components. It also seems like learning Xojo is like learning a whole new programming language. I hope I am wrong; I am hoping there is a simple explanation for why this isn’t working in Xojo.

Anyway, I hope someone can help clear this all up soon.

[quote=62941:@Loren Staplin]At this point, it seems to me like Xojo is making components on the same page behave like cross-domain components. It also seems like learning Xojo is like learning a whole new programming language. I hope I am wrong; I am hoping there is a simple explanation for why this isn’t working in Xojo.

Embedded frames are cross-domain components with a strict security model. An HTMLViewer creates an embedded frame. The YouTube Javascript API uses embedded frames. YouTube has a client library that makes communication with the embedded frame a little easier. But it’s not easy stuff. To get it to work, you need a strong understanding of HTML5, JavaScript, and the YouTube JavaScript API. To get it to work with Xojo, you also need a strong understanding of how Xojo web apps communicate with the client. Unfortunately, there are no shortcuts. This is complicated stuff.

What the Xojo Web Edition development environment and third party additions attempt to do is make these complicated things simpler for developers to deal with, so developers don’t have to know all these details. IMHO, Xojo doesn’t have the most useful YouTube control built in. That’s why I invested a little effort in making one for my Web Essentials customers. Not an easy task, but not because Xojo is particularly difficult. The Xojo end is pretty easy.

I agree. The Youtube control in Xojo is not useful; too barebones.

Again, I have a working html page based on the youtube javascript API.

I am not looking for shortcuts. Tell me what to read and I will read it.

All I know for sure is that Xojo is definitely adding to the complexity. That’s okay if there were a resource to help people learn how to do this sort of thing. The documentation isn’t helping me.

If it is easier to do this in a text editor, why bother with Xojo? If the Xojo part were easy, I would be able to figure it out.

All I am asking for are some helpful comments.

They’re different because you are trying to get access to the items inside the HTMLViewer which is considered a different document. You’d need to do something like this:

[code]//Get the control associated with the HTMLViewer
var x = document.getElementById('HTMLViewerControlID")

//Get the window/document INSIDE the HTMLViewer
var doc = (x.contentWindow || x.contentDocument);

//If the item returned was a Window, get the document object
if (doc.document)y = doc.document;

//Now use “doc” instead of “document”
Keep in mind that code like this is subject to break as the web framework evolves. We change things from time to time to fix bugs and improve performance.

Greg - Thanks for your response; I really appreciate it.

I did try the example at the link you supplied earlier and the one you just supplied tailored to this problem but couldn’t get either to work. I quit trying yesterday when I read contentDocument doesn’t work in Chrome here or at least doesn’t work with local files.

Anyway, here is what I tried before but couldn’t get to work. I put this code in the action event of a webbutton:

Dim p as string
p = "var x = document.getElementById('"+HTMLViewer1.ControlID+"');"
p = p + "var doc = (x.contentWindow || x.contentDocument);"
p = p + "if (doc.document)doc = doc.document;"
p = p + "doc.pauseVideo();"

Error received when pressing button:

[quote]Could not execute returned javascript: Cannot read property ‘document’ of undefined
Source: var x = document.getElementById(‘VlODlk01’);var doc = (x.contentWindow || x.contentDocument);if (doc.document)doc = doc.document;doc.pauseVideo();[/quote]

I tried a number of things (e.g., using IE 11, using HTMLViewer1.ExecuteJavascript, taking out the line with “if” in it, using doc.script.stopVideo();, and using single line document.getElementById(’"+HTMLViewer1.ControlID+"’).contentWindow.pauseVideo():wink: but nothing I tried works.

I am using Chrome on Windows 7 64-bit PC.

I also wanted to mention that the pauseVideo is a function in HTMLViewer1 script and the actual player is called player (just like the Youtube iframe demo here). The function in the script is:

function pauseVideo() {player.pauseVideo();}

I hope someone can see what I am doing wrong. Thanks in advance for your help.

Ok. I finally figured it out using an earlier post of Brad’s here (loading youtube via url only; otherwise, you end up with 2 iframes) and this jsfiddle snippet cited here which uses postMessage.

Here is what goes in the WebButton action event (to play the video):

dim p as string p = "var div = document.getElementById('"+HTMLViewer1.ControlID+"');" p = p + "var iframe = div.getElementsByTagName('iframe')[0].contentWindow;" p = p + "iframe.postMessage('{""event"":""command"",""func"":""playVideo"",""args"":""""}','*');" me.ExecuteJavaScript(p)

I still don’t understand why the postMessage is needed (namely, why it is considered cross-site or some other security risk) but at least it works now. Thanks Brad and Greg for your expert help. Much appreciated.