Thursday, July 27, 2017

About Those Frames Part III

No-frames Xpress Client.

In the previous two posts of this series I talked about why I wanted to examine changing the current Frames based interface for enCore, and the non-frames version of the Xpress Login screen that resulted. In this post I'll describe a non-frames version of the Xpress Client itself.

The Xpress client is a fundamental part of the Xpress interface because it is what the user interacts with the most frequently as Guest, Programmer, or Wizard. Since it is so fundamental to the operation of the whole enCore system any changes made should not interfere with the usability.


The client is a typical web page layout with a menu in a header bar and two columns below. The columns hold the text input and output from the MOO on the left and the WEB display generated by the MOO on the right.  In the existing frames based layout this is really very easy to generate with a frameset document whose contents are the output of the verbs on the xpress_client object.


I figured the same kind of changes I made for the Login screen should work, that is replacing the frameset document with an HTML layout that used iframes and CSS. If possible I wanted to avoid having to change anything other than verbs on the client object itself.

A key thing I wanted was to keep the layout the same at any screen size from fullscreen on a desktop monitor to a screen on a smartphone or tablet. I also wanted the columns to resize cleanly as the client window size changes and without adding extraneous scrollbars.  This is handled by the flexbox system like I used for the login.

Keeping the menu bar in place relative to the columns below was tricky and that is handled by a CSS directive called box-sizing. You can read the gory details of what it does here.

So thanks to Google 😀 and lots of experimenting I applied these tools to the same DIV / iframe setup I used for the login screen.

Surprisingly this worked pretty well, once the inevitable tweaks to make it look the same and behave well at multiple screen sizes were made of course. 

Here is the resulting CSS:

<style>
/*I love me some border-box*/
       * {
        box-sizing: border-box;
       }

       /*Just removing default browser padding/margin*/
        html,
        body {
            padding: 0;
            margin: 0;
            color: #ebebeb;
  }
        /*Flexbox gives us the flexiness we need.
        The top just stays put as there is no scrolling on the body due to the page
        never exceeding viewport height*/
       .menu-frame {
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: darkgreen;
            font-size: 3rem;
            position: relative;
            z-index: 10;
            height: 65px;
        }
        /*This is our main wrapping element, it's made 100vh high to ensure
        it is always the correct size and then moved into place and padded 
        with negative margin and padding*/
        .Container {
            display: flex;
            overflow: hidden;
            height: 100vh;
            margin-top: -65px;
            padding-top: 65px;
            position: relative;
            width: 100%;
            backface-visibility: hidden;
            will-change: overflow;
        }

        .java-frame,
        .web-frame {
            overflow: hidden;
            height: auto;
            padding-bottom: 0.5rem;
        }

        .java-frame {
            width: 50%;
            background-color: white;
        }

        .web-frame {
            flex:1;
            background-color: white;
        }
</style>



I modified the Xpress_Client object to get this code from a .CSS property for easy editing.

The only verb I needed to modify was :vertical_layout horizontal_layout and here is the modified verb that resulted:

"===========================================================";
"Copyright (C) 1999-2004, Jan Rune Holmevik";
"Generates the main enCore Xpress client user screen using three frames";
"Modified to use iframes and DIVs instead of frames";
"KRJ June 2017";
"Vertical layout only!";
"===========================================================";
if (caller != $httpd)
  return E_PERM;
endif
user = args[1];
html = {};
base_url = tostr("http://", $network.site, ":", $network.webport, "/Xpress_client/");
menu = tostr(base_url, "menu.html");
java = tostr(base_url, "java.html");
web = tostr(base_url, "web.html");
html = $list_utils:append(html, this.CSS);
html = {@html, "  <div class=\"menu-frame\">"};
html = {@html, tostr("               <iframe src=\"", menu, "\" name=\"", this.menu_frame, "\" width=\"100%\"  height=\"100%\" noresize=\"noresize\" scrolling=\"no\" marginwidth=\"0\" marginheight=\"0\" frameborder=\"", this.frameborder, "\"></iframe>")};
html = {@html, "  </div>"};
html = {@html, "  <div class=\"Container\">"};
html = {@html, "      <div class=\"java-frame\">"};
html = {@html, tostr("                    <iframe src=\"", java, "\" name=\"", this.java_frame, "\"height=\"100%\" width=\"100%\" scrolling=\"no\" marginwidth=\"0\" marginheight=\"0\" frameborder=\"", this.frameborder, "\"> </iframe>")};
html = {@html, "      </div>"};
html = {@html, "      <div class=\"web-frame\">"};
html = {@html, tostr("                    <iframe src=\"", web, "\" name=\"", this.web_frame, "\" height=\"100%\" width=\"100%\" scrolling=\"auto\" marginwidth=\"", this.frame_marginwidth, "\" marginheight=\"", this.frame_marginheight, "\" frameborder=\"", this.frameborder, "\"> </iframe>")};
html = {@html, "      </div> "};
html = {@html, "  </div>"};
result = this:build(user, html, tostr($httpd.server_name, $core_version), "", "", "", "", this.doctype_frameset);
return result;
"Last modified Sat Jun 17 10:54:40 2017 MDT by Wizard (#2).";



Now the existing Xpress_Client has lots of options for changing the display. Things like whether the client is aligned vertically or horizontally and how big the text display is relative to the web display.  To keep things simple the no-frames client only handles the vertical display, which I think most people use anyways.  Allowing those settings to be changed I will leave as an exercise for the reader 😀

Again to test this safely I did an "@dump with create $Xpress_Client", created a new enCore_CGI_Application object called Xpress_Client_Noframes, pasted the @dump into it making an exact copy of the original which I could modify, and then replaced the object number in #0 for the Xpress_Client with the new object. If it didn't work, more times than not frankly, I would just change the object number in #0 back to the original using the text client and still be able to login with the old client. 

This same system should be able to be used for any of the utilities in enCore too. Some of them like the Program Editor, Help Browser, and Mail Client would be tricky given the number of frames they use but I don't see any reason they couldn't be converted in a similar way.

I hope this client will be useful.

Let me know if you try it and how it works, and as always suggestions and critiques are welcome.

Thanks for reading.
KJ 




No comments:

Post a Comment