Saturday, July 1, 2017

About those frames... Part II

Happy Canada Day!

Previously I wrote about why I wanted to examine changing the current Frames based interface for enCore.

After much experimentation, reading up on "current" web development tools, plus a dash of hair pulling, some heavy coffee consumption, and staring at the ceiling going "Why me..." for longer than my wife thought healthy 😆, I have a no-frames version of both the login page and the Xpress Client.


I'll start with the Login page first. Mainly because it is just a two column layout with one fixed page, the welcome page, and the login page. The welcome page is a static html file and the login screen is built by a verb on the Xpress_login object and is also basically an html file.

I experimented with a pure html/CSS/javascript design but I couldn't make it robust. That is it was difficult to make it work without changing more of the MOO code associated with the login object itself. So following my "If it isn't broke don't fix it "plan, I looked for ways to use the existing functionality as much as possible.

The best option turned out to be the last remaining "frame" allowed in current web development, the lowly iframe!

I replaced the frameset with a page using divs that held two iframes whose source is the output of the two verbs on the Xpress_login object.  The problem was then to arrange the display of the page in such a way that extraneous scrollbars from the iframes were removed  and the page would resize without getting too badly messed up.  This took a while to do and much of what I tried looked OK at full screen but scrambled badly when the browser screen was shrunk to what a mobile or tablet user would see..

However, since we need to be using HTML5 capable browsers anyways I figured I might as well use some of the newer CSS tools. Flexbox and viewport relative sizes were the key.

The resulting page is mobile friendly, and does not need any javascript at all.  I put the required CSS in a property on the object called login_css, and added it to the html being generated by the verb.
It still uses two vertical columns and the login column is a fixed size but that could be changed using flexbox settings in the CSS if desired.

Here is the revised verb on Xpress_Login:

"===========================================================";
"Copyright (C) 2001-2004, Jan Rune Holmevik";
"Generates the main enCore Xpress Login Screen";
"Revised to us a defined welcome page named on this.welcome_page";
"KRJ Sep 3, 2015";
"Revised to replace Frame set layout with CSS/iframe";
"KRJ June 9, 2017";
"===========================================================";
if (caller != $httpd)
  return E_PERM;
endif
{user, ?message = ""} = args;
html = {};
base_url = tostr($encore_web_utils:baseurl(), "/Xpress_Login/");
login = tostr(base_url, "login");
"Revised Welcome Screen to use locally hosted webpage";
"Set page name in this.welcome_page";
welcome = tostr($xpress_client.external_baseurl, this.welcome_page);
if (message)
  message = tostr("onload=\"", message, "\"");
endif
html = $list_utils:append(html, this.login_css);
html = {@html, "<body>"};
html = {@html, "    <div id=\"wrap\">"};
html = {@html, "        <div id=\"login-frame\">"};
html = {@html, tostr("               <iframe src=\"", login, "\" name=\"login\" width=\"100%\" height=\"100%\" noresize=\"noresize\" marginwidth=\"", this.frame_marginwidth, "\" marginheight=\"", this.frame_marginheight, "\" frameborder=\"", this.frameborder, "\" title=\"Login frame\"></iframe>")};
html = {@html, "        </div>"};
html = {@html, "        <div id=\"welcome-frame\">"};
html = {@html, tostr("               <iframe src=\"", welcome, "\" name=\"welcome\" width=\"100%\" height=\"100%\" marginwidth=\"", this.frame_marginwidth, "\" marginheight=\"", this.frame_marginheight, "\" frameborder=\"", this.frameborder, "\" title=\"Welcome screen\"></iframe>")};
html = {@html, "        </div>"};
html = {@html, "    </div>"};
html = {@html, "</body>"};
html = this:build(user, html, "Login", message, "", "", "", this.doctype_frameset);
return html;
"Last modified Fri Jun  9 21:17:55 2017 MDT by Wizard (#2).";

"===========================================================";

And here is the CSS data:

<style>
        body,
 html {
     margin:0;
     padding:0;
     color:#000;
     background:grey;
 }
 #wrap {
     display: flex;
     height:100%;
 }
 #welcome-frame {
     flex: 1;  /* grow */
     background:white;
 }
 #login-frame {
     height:450px;/* fall back for old browsers */
     height:100vh;
            flex: 0 0 200px; /* do not grow, do not shrink, start at 200px */
 }
</style>

Note that this must be stored in .login_css as a list of strings. I used the object editor to store the CSS as a description and then copied that over using the program editor.

The magic here is the way the CSS "display:flex" allows the columns to dynamically resize as the browser window does. Because the CSS is held in a separate property it can be edited and adjusted without messing with the verb so lots of customization is possible.

To test this safely I did an "@dump with create $Xpress_Login", created a new enCore_CGI_Application object called Xpress_Login_Noframes, pasted the @dump into it making an exact copy of the original, then replaced the object number in #0 for the Xpress_Login with the new object. That way, as I messed things up (which happend A LOT) I could change the object number back to the default value when logged in through the text only client, and still be able to use Xpress. 

Next time I'll discuss the more complicated layout for the Xpress_Client.

Thanks for reading
KJ

No comments:

Post a Comment