Live Scoreboard

I have a form which is called frmscoreboard on that form is a WebContainer which has labels etc and also the HTMLViewer.

scoreboardpages(-1) Type frmScoreboard

For i As Integer = 0 To uBound(ScoreboardPages) scoreboardpages(i).WebContainer1.htmlViewer1.loadpage(clock) // THIS CLEARS THE IFRAME NOT WORKING scoreboardpages(i).WebContainer1.label.text = "HELLO" // THIS WORKS Next i

I’ve tested and put me.loadpage(clock) in the htmlViewer1.open event and that loads and starts the clock but as soon as I push from the server scoreboardpages(i).WebContainer1.htmlViewer1.loadpage(clock) the iframe is cleared.

I’ve thought of using

ScoreboardPages(i).WebContainer1.htmlViewer1.ExecuteJavaScript("document.getElementById('" + ScoreboardPages(i).WebContainer1.htmlViewer1.ControlID + "').contentWindow.startstop();")

but that causes Could not execute returned javascript: Cannot read property ‘startstop’ of undefined
Source: document.getElementById(‘M3Hp280n’).contentWindow.startstop();

content of clock if thats any help


<!DOCTYPE html>

<head>
<meta charset="utf-8">
<title>Running Clock</title>
<SCRIPT LANGUAGE="JavaScript">
    var ms = 0;
    var state = 0;

    function setCharAt(str, index, chr) {
        if (index > str.length - 1) return str;
        return str.substr(0, index) + chr + str.substr(index + 1);
    }

    function pad(n) {
        return (n < 10) ? ("0" + n) : n;
    }

    // Start Stop Clock
    function startstop() {
        state = 1;
        then = new Date();
        then.setTime(then.getTime() - ms);
    }

    // Reset Clock
    function swreset() {
        state = 0;
        ms = 0;
        document.stpw.time.value = "RESET";
    }

    function display() {

        setTimeout("display();", 50);

        // Check We Want The Clock To Display
        if (state == 1) {

            now = new Date();

            ms = (((now.getTime() - then.getTime()) / 1000) / 1);

            var tf = "        ";

            var t1 = Math.floor(ms / 60);
            var t2 = t1 * 60;

            // Check t1 more than a minute
            if (t1 > 0) {

                // Convert Tto String
                var t1_string = t1.toString();

                // Check t1 more or less than 10
                if (t1 < 10) {
                    tf = setCharAt(tf, 1, t1_string);
                    tf = setCharAt(tf, 2, ".");
                } else {
                    tf = setCharAt(tf, 0, t1_string.substring(0, 1));
                    tf = setCharAt(tf, 1, t1_string.substring(1, 2));
                    tf = setCharAt(tf, 2, ".");
                }

            }

            // Seconds
            var seconds = ms - t2;

            if (t1 == 0 && seconds < 10) {

                // One Decimal Place
                seconds = seconds.toFixed(1);

                // Convert to String
                seconds = seconds.toString();

                tf = setCharAt(tf, 4, seconds.substring(0, 1));
                tf = setCharAt(tf, 5, seconds.substring(1, 2));
                tf = setCharAt(tf, 6, seconds.substring(2, 3));

            } else {

                // One Decimal Place and Pad with zero at front
                seconds = pad(seconds.toFixed(2));

                // Convert to String
                seconds = seconds.toString();

                tf = setCharAt(tf, 3, seconds.substring(0, 1));
                tf = setCharAt(tf, 4, seconds.substring(1, 2));
                tf = setCharAt(tf, 5, seconds.substring(2, 3));
                tf = setCharAt(tf, 6, seconds.substring(3, 4));

            }

            // Update Inner HTML of RunningCLock
            document.getElementById("RunningClock").innerHTML = tf;

        }
    }

    window.onload = display
    
    // Auto Start
    startstop();
   
</SCRIPT>
<style media="screen" type="text/css">
body {
	background-color: rgb(180,180,180);
	margin: 0px auto;
	font-size: 10pt;
}
.RunningTime {
	font-family: Verdana, sans-serif;
	font-size: 140%;
	text-align: right;
	color: rgb(255,255,255);
	cursor: default;
}
</style>
</head>

<body>
<div class="RunningTime" style="position: absolute; left: 0px; right: 0px; top: 50%; overflow: hidden; margin-top: -11px; height: 23px; max-height: 23px;">
  <p style="margin: 0px;" id="RunningClock"></p>
</div>
</body>
</html>

If you have one class (WebContainer) which contains one HTMLViewer and display multiple instances, instances in fact refer to a unique iFrame. Hence trying to load pages in each instance loads in fact the JavaScript into the unique class DOM, where it crashes.

If you do not need to instantiate the WebContainers dynamically, the solution is to use an HTMLViewer control set into which you load the clock page.

I just tried this and it works fine :

For i As Integer = 0 To 5 htmlViewer1(i).loadpage(clock) Next i

The different HTMLViewer created statically can be stored outside of the WebPage (on the left) and moved in if you need dynamic layout.

I have a form (form1) on form1 I have WebContainer (WebContainer1)

WebContainer1 contains some labels and the WebHTMLViewer (htmlViewer1)

In the App. I have

ScoreboardPages(-1) As form1

AddPage

ScoreboardPages.Append(page)

On form1 open event I have

htmlViewer1.loadpage(clock)
App.AddPage(Self)

So my understand of the below which sits in App.UpdateClients is I’m looping round the sessions and updating the client content which the server pushes out

For i As Integer = 0 To uBound(ScoreboardPages)
scoreboardpages(i).WebContainer1.htmlViewer1.loadpage(clock)            
scoreboardpages(i).WebContainer1.label1.text = str(val(scoreboardpages(i).WebContainer1.label1.text) + 1)                        
Next i

The content of label one is updated every time that loop runs why would it be any different for htmlViewer1, it seems to something because it clears what was in the iframe on load

A button is an HTML control. When you update an HTML control, that changes a static content.

With clock, code is executed inside the HTLViewer iFrame. Trying to run several programs inside one HTMLViewer obviously does not work.

Instead of a unique HTMLViewer inside a WebContainer instantiated a number of times, use several HTMLViewers in a control set.

Now, what is most important : saying that it should work one way or the other, or finding a way to get to a functioning result ? You started with an unsatisfactory server side method. Then I pointed you to a JavaScript site which had client side solutions. Then you could not get a WebSDK control to work, so I suggested the HTMLViewer method. Then you try to place the HTMLViewer on a WebContainer and instantiation does not work. I try to find you another solution, you insist on using the Webcontainer. Suit yourself, but I think you got more help through this one than most …

Good luck, Pal.

Michel Thats not what I’m trying to say sorry if thats the way it read.

Also I’m using the container control so I can centre the content on the page.

Example below first row of buttons are on the form second row of buttons are in a container.

If I could get the first row of buttons to look like the second row without a container I wouldn’t need the container

I’ve found a working solution not sure if it’s the best but it works, many thanks for your help Michel it really is appreciated.

I can’t use document.getElementById because it seems the iframe doesn’t have a ID value but as long as I only have one iframe on the page window.frames[0] should be fine from what I’ve read.

Open Event for WebHTMLViewer

me.LoadPage(clock)

Starts the Clock

For i As Integer = 0 To uBound(ScoreboardPages) scoreboardpages(i).WebContainer1.HTMLRunningTime.ExecuteJavaScript("window.frames[0].swstart();") scoreboardpages(i).WebContainer1.label.text = "HELLO" Next i

Resets the Clock

For i As Integer = 0 To uBound(ScoreboardPages) scoreboardpages(i).WebContainer1.HTMLRunningTime.ExecuteJavaScript("window.frames[0].swreset();") scoreboardpages(i).WebContainer1.label.text = "HELLO" Next i

clock

[code]

Running Clock body { background-color: rgb(180,180,180); margin: 0px auto; font-size: 10pt; } .RunningTime { font-family: Verdana, sans-serif; font-size: 140%; text-align: right; color: rgb(255,255,255); cursor: default; }

0.0

[/code]

Control arrangement problems like this are best solved by:

  1. Set locks on all controls to top/left so that there isn’t any automatic movement/resizing.
  2. Create a method, ArrangeControls, that takes the width and height of the browser window into consideration in order to place/resize the controls.
    2a. e.g: Using WEControlUtiilities from Studio Stable Web Essentials:

const kSpacing = 12 dim x as integer = (self.width - btn1.width - btn2.width - btn3.width - kSpacing - kSpacing) / 2 btn1.left = x btn2.PlaceRight(btn1, kSpacing) btn3.PlaceRight(btn2.kSpacing)
3. Call ArrangeControls in Shown (or PrepareToShow, if you’re using Web Essentials) and Resized events of WebPage.

Yes, it’s a little work the first few times you implement this. When you get the hang of it, you’ll realize why automatic layout systems are just a PITA. Save containers for encapsulation, not for control positioning.

The advice you were getting was pretty awful, so I decloaked. Back to lurking.

[quote=118312:@Brad Hutchings]Control arrangement problems like this are best solved by:

  1. Set locks on all controls to top/left so that there isn’t any automatic movement/resizing.
  2. Create a method, ArrangeControls, that takes the width and height of the browser window into consideration in order to place/resize the controls.
    2a. e.g: Using WEControlUtiilities from Studio Stable Web Essentials:

const kSpacing = 12 dim x as integer = (self.width - btn1.width - btn2.width - btn3.width - kSpacing - kSpacing) / 2 btn1.left = x btn2.PlaceRight(btn1, kSpacing) btn3.PlaceRight(btn2.kSpacing)
3. Call ArrangeControls in Shown (or PrepareToShow, if you’re using Web Essentials) and Resized events of WebPage.

Yes, it’s a little work the first few times you implement this. When you get the hang of it, you’ll realize why automatic layout systems are just a PITA. Save containers for encapsulation, not for control positioning.

The advice you were getting was pretty awful, so I decloaked. Back to lurking.[/quote]

Thanks I’ll give that a try, with regards to why I did using containers is it’s in the xojo docs.

http://documentation.xojo.com/index.php/WebContainer

[quote=118318:@Graham Spratt]Thanks I’ll give that a try, with regards to why I did using containers is it’s in the xojo docs.
[/quote]

Right. That advice doesn’t scale. While you can certainly do things that way, you can quickly end up with a mess. Use containers for reusable elements, not to create a control hierarchy that the layout editor doesn’t naturally support.

Really, back to lurking.

One thing I have noticed is if you do ExecuteJavaScript inside the webhtmlviewer shown event it sometimes works and other times doesn’t.

Doing the below stops Xojo throwing a javascript undefined error.

ExecuteJavaScript("try { window.frames[0].swstart(); } catch(err) { }")

I thought the shown event on the webhtmlviewer was fired after the page had loaded?