// WebHat setup:
//
//
//
// A Web object has an HTML representation in the output to the browser. It is an object that on
// the command DoWriteHtml with some appropriate parameters writes itself out into the HTML output
// stream.
//
//
// Use WebPageBroker.nui
//
//
// Image availability
// ------------------
//
// 1. Public. Anybody can request them as a separate URL without bothering
// the Web Application.
//
// 2. Semi private. This means that they are in fact publicly available but they
// reside in a folder that has its directory listing attribute set to false
// and the images are named in an non sequential way (using 64 random
// characters). This is security by obscurity.
//
// 3. Private. The image is located in a non-shared folder and is only sent
// out by a request sanctioned by the web app (the Archie-strategy)
//
//
// Image enumeration
// -----------------
//
// Public images (1) aren't enumerated.
//
//
//
// Design
// ------
//
// Design mekanismen skal baseres p† en stack. Set Design_Folder to lsFolderName
//
//
//
//
//
//
//
//
//
//
//
// Problem areas:
//
// Outer shell of system
//
// Form handling
//
// Page layout in general
//
// A common interface for integrating:
//
// Forms
// Reports
// Menues
// Images
// Image galleries
//
//
// Note on WAF:
//
// The thingy may be used in three ways:
//
// 1. As the way to develop Web applications (that's what I do). I use the DDBuilder of course, and
// the Studio to handcode the WAIP stuff. You have a nice overview of the project.
// 2.
//
// 3. In conjunction with FastView that is now able to update a remotely running WebApp with DDO's
// compiled into it. Very much in the FastView tradition. (I do this too)
//
//> doc.begin
//> Motivated by the wish to generate larger and more complex web applications I have come
//> up with a technique of letting all the HTML code be generated from within
//> the WebApp itself. In the process the number of ASP files are reduced to 1 which is a
//> very simple one:
//>
//> <%
//> Dim SessionVariables
//> SessionVariables = session ("SessionVariables")
//> oWebApp1Page.Call "msg_DoSetSessionVariables", SessionVariables
//> oWebApp1Page.Call "msg_DoWriteHtmlFullPage"
//> SessionVariables = oWebApp1Page.Call("get_SessionVariables")
//> session ("SessionVariables") = SessionVariables
//> %>
//>
//> The DoWriteHtmlFullPage class writes the entire document. The remaining lines are
//> concerned with session variables. Session variables are defined in the VDF code
//> code and stored in the ASP layer where they belong. This is achieved by encoding
//> all the values of session variables defined in the VDF code into one single value.
//>
//> The oWebApp1Page object is an empty shell except for the three messages called above.
//> these messages are delegated to a global WebPageBroker object which is where the
//> action starts taking place.
//>
//> This is the very basic idea. The rest is about figuring out a sensible way to
//> structure the insides of such an application.
//>
//> A few notes:
//>
//> * There is nothing hindering the normal use of the WebApp framework at the same
//> time as using the WAF approach (for the backend for example).
//>
//> * In designing the WAF I always used a process pooling license. It may or may not
//> be possible to run a WAF application on a non PP license.
//>
//>
//> Foundation - writing XHTML code
//> -------------------------------
//>
//> The cXmlBuilder class (XmlBuilder.nui) let's you build standard XML DOM in memory
//> documents with no pain of object handle house keeping. As a second feature
//> it lets you output the XML to a sequential channel as elements are being added (as
//> opposed to building the complete document in memory first, which is the standard
//> XML way).
//>
//> The WebAppXhtmlBuilder.nui package transforms this basic service into a set of
//> globally defined procedures for writing XHTML code directly into the output
//> stream of a web application. Brilliant, if I may say so.
//>
//> Using these procedures a XHTML document can be generated this way:
//>
//> send XHTML_StartXhtml
//> send XHTML_Add_Open_Element "html"
//> send XHTML_Add_Attribute "xmlns" "http://www.w3.org/1999/xhtml"
//>
//> send XHTML_Add_Attribute "xml:lang" "en"
//> send XHTML_Add_Attribute "lang" "en"
//>
//> send XHTML_Add_Open_Element "head"
//> send XHTML_Add_Closed_Element "title" "test page"
//> send XHTML_Close_Element // head
//> send XHTML_Add_Open_Element "body"
//> // Generate the body of the document here.
//> send XHTML_Close_Element // body
//> send XHTML_Close_Element // html
//> send XHTML_EndXhtml
//>
//> It's a technique one gets used to very fast. It lets you maintain the
//> overview of the page structure at the same time as it lets you focus on
//> the detail.
//>
//> At the same time it makes it pretty hard not to produce XHTML 1.0 compliant code.
//>
//> This is in contrast to the current implementation of the WebApp classes where
//> HTML code is written out in a writeln sort of way.
//>
//>
//> Layout objects
//> --------------
//> A layout object is used whenever you want to
//>
//>
//>
//>
//>
//> The application structure
//> -------------------------
//>
//> In trying not to make any assumptions about the nature of the applications that
//> need to built within this framework, I have come up with the following:
//>
//>
//> Modules (WebModule)
//> -------------------------
//>
//> A WAF system is composed from a number of modules. A module is a group of pages
//> that benefit from having access to a locally defined set of procedures and objects.
//>
//> These pages can be expected to have a (more or less) common page layout (or not).
//> A module is a part of the system that you'd like to program as one unit. A module
//> object functions as an encapsulation of web page objects that are likely to utilize
//> the same set of functions (and page items).
//>
//> An example of a module could be the user login system of an application. That
//> constitutes a number of pages with "sorry, wrong password" and "forgotten password"
//> dialogs.
//>
//> Another example is that of a number of reports untilizing the same basic search
//> mechanisms.
//>
//> Layout objects
//> --------------
//> A layout object defines a set of div layers (areas) and their attributes expressed
//> in terms of CSS proties (colors, sizes, positions, background image). More pages
//> can be associated with the same layout object. Layout objects can be declared locally
//> within modules or globally so that pages in all modules can use them.
//>
//>
//> Pages (WebPage)
//> ---------------------
//> A module is composed of pages. Each page points to a layout object and the page
//> object determines what goes inside the different div layers. It does so by means of
//> the OnWriteLayer procedure.
//>
//>
//> Web Forms
//> ---------
//> Lives an independant life inside WebBusinessProcess objects where they feed on
//> the services of conventional DataDictionary's. Web forms may or may not be data
//> base aware.
//>
//>
//> Page items
//> ----------
//> Page items are what the page objects puts inside a div layer (div layers that are defined a
//> layout object). Page items are thing likes forms, menues, reports, image or image galleries,
//> documents (by the time of writing these things aren't available). They are generating
//> the actual XHTML.
//>
//> The point here is that you declare objects to hold the actual data needed to render the
//> object and then you define other objects (or use the standard ones) for the actual
//> XHTML rendering.
//>
//> For example, you would declare a cWebMenu object and define what items are in that menu. Then
//> you will call a method in your preferred menu renderer passing a handle to the menu object
//> as a parameter.
//>
//> Structuring the objects this way has the advantage of developers being able to create custom
//> renderes that better suits their design.
//>
//>
//>
//>
//>
//>
//>
//> Preface
//> -------
//> This package was deviced so that all the programming of a web application may go in
//> the VDF code. The ASP files are done away with and there's only one ASP page left
//> with 5 sorry lines of code in it (could be rewritten as one, but then clarity
//> suffers ;-). This is the driving motivation.
//>
//>
//> * No ASP pages (=faster development)
//> * Full utilisation of DataDictionaries
//> * Handles data aware as well as non data aware forms.
//> * True XHTML 1.0 output (if you behave)
//> * Faster rendering (based on div layers)
//> * Still possible to get a decent design.
//> * Checkboxes no problem
//>
//>
//> doc.end
//>
//> Request sequence:
//>
//> Identification of module/page
//>
//>
//>
//>
//>
//>
//>
Use css.nui // CSS things
Use LanguageDictionary.nui // cLanguageDictionary class
Use WebAppXhtmlBuilder.nui // Global procedures for writing XHTML
Use copyright.nui // sCopyrightText function
Use WebSessionVariables.nui // Web session variables for ASP pages
Use WebForm.nui // WebForm class
Use WebError.nui
Use WebQueryString.nui // Functions for constructing valid links
Use WebMenu.nui
Use WebLayout.nui // Different layout objects
Use WebGlobalFunctions.nui //
Use WebSelectionList.nui
Use WebBrowser.nui // oWebBrowserInfo object
Use WebFormNew.nui
// ghoPageBroker points to the WebPageBroker object of the application
integer ghoPageBroker
Use ExtendedItemProp.nui // cExtendedItemPropertyArray class
//> A web page makes use of a layout object which it most
//> likely share with other objects (maybe there's only one layout object
//> in the whole application). The different layers of of the layout_object
//> are filled in by the web page object
class WebPage is a cArray
procedure construct_object
forward send construct_object
//> The WebPageBroker identifies pages using the value of the psPageName property
//> (in combination with the value of the psModuleName property of the encapsulating
//> WebModule object)
property string psPageName
//> Default behavior of procedure DoWriteHtml is to send DoWriteHtml
//> to this object.
property integer phPageLayoutObject
property integer piRefreshSeconds public 0 // Set to 60 in order to have the page refreshed every minut
// Setting pbIndependant to TRUE stops the object from automatically registering
// with the encapsulating WebModule object. This makes it possible to declare a
// WebPage object outside a WebModule structure and manually sending register_page
// to the WebModules that should include the page. There you are: reusable web
// pages!!!
property integer pbIndependant public FALSE
end_procedure
procedure OnWriteCell string lsName integer liAux
end_procedure
function bAvailable returns integer // WebPage
function_return TRUE
end_function
//> Make use of the session variables. Prepare data for display. Can also be used for
//> refusing to accept to display by delegating the displaying to another webmodule/webpage.
//> This may be achieved by calling the GotoPage method from within OnSetup.
procedure OnPageSetup string lsSubmitButton string lsFormName string lsFormCollection
ifnot (bAvailable(self)) send GotoPage "system" "pagenotavailable"
end_procedure
//> Store session variables. Clean up. I personally, have not used this yet.
procedure OnDebrief
end_procedure
procedure DoWriteHtml // WebPage
send DoWriteHtml of (phPageLayoutObject(self)) MSG_OnWriteCell self
end_procedure
procedure end_construct_object // WebPage
forward send end_construct_object
ifnot (pbIndependant(self)) send register_page self
end_procedure
end_class // WebPage
//> Modules should be used for encapsulating a set of pages (a set of
//> WebPage objects) that makes up some amount of functionality.
//> The login system for instance, could be such a module. There's a
//> a page for logging in, a page for 'forgotten password' a page for
//> 'sign up new user' asf.
//>
class WebModule is a cArray
procedure construct_object
forward send construct_object
property string psModuleName
property string psDefaultPage
end_procedure
item_property_list
item_property string psPageName.i
item_property integer phPage.i
end_item_property_list WebModule
function hFindPage.s string lsPage returns integer
integer liRow liMax
get row_count to liMax
decrement liMax
for liRow from 0 to liMax
if (psPageName.i(self,liRow)=lsPage) function_return (phPage.i(self,liRow))
loop
function_return 0
end_function
function DefaultPage returns string
string lsPageName
get psDefaultPage to lsPageName
if (lsPageName="") get psPageName.i 0 to lsPageName // If none is set, we just take the first
function_return lsPageName
end_function
procedure register_page integer lhObj
integer liRow lhTmp
string lsName
get psPageName of lhObj to lsName
get hFindPage.s lsName to lhTmp
if lhTmp error 235 (replace("#","Page already registered (#)",lsName))
else begin
get row_count to liRow
set psPageName.i liRow to lsName
set phPage.i liRow to lhObj
end
end_procedure
procedure OnModuleSetup string lsPage string lsSubmitButton string lsFormName string lsFormCollection
integer lhPage
if (lsPage="") get DefaultPage to lsPage // If no page, get default
get hFindPage.s lsPage to lhPage
ifnot lhPage error 238 (replace("#","Page could not be found (#)",lsPage))
else begin
send DetectRedirectionRecursion of ghoPageBroker lhPage
send OnPageSetup of lhPage lsSubmitButton lsFormName lsFormCollection
end
end_procedure
procedure onDebrief string lsPage
integer lhPage
if (lsPage="") get DefaultPage to lsPage // If no page, get default
get hFindPage.s lsPage to lhPage
ifnot lhPage error 239 (replace("#","Page could not be found (#)",lsPage))
else send onDebrief of lhPage
end_procedure
procedure DoWriteHTML string lsPage // WebModule. If lsFormName is <>"" then there was a form submitted
integer lhPage
if (lsPage="") get DefaultPage to lsPage // If no page, get default
get hFindPage.s lsPage to lhPage
ifnot lhPage error 237 (replace("#","Page could not be found (#)",lsPage))
else begin
send DoWriteHtml of lhPage
end
end_procedure
procedure end_construct_object // WebModule
forward send end_construct_object
send WafRegisterModule self
end_procedure
end_class // WebModule
// Every WebModule object declared will register with
// this object (oWafModuleList)
object oWafModuleList is a cArray
item_property_list
item_property string psModuleName.i
item_property integer phModule.i
end_item_property_list
function hFindModule.s string lsName returns integer
integer liRow liMax
get row_count to liMax
decrement liMax
for liRow from 0 to liMax
if (psModuleName.i(self,liRow)=lsName) function_return (phModule.i(self,liRow))
loop
function_return 0
end_function
procedure register_module integer lhObj
integer liRow lhTmp
string lsName
get psModuleName of lhObj to lsName
get hFindModule.s lsName to lhTmp
if lhTmp error 234 (replace("#","Module already registered (#)",lsName))
else begin
get row_count to liRow
set psModuleName.i liRow to lsName
set phModule.i liRow to lhObj
end
end_procedure
end_object // oWafModuleList
function WafModuleObject global string lsModule returns integer
integer lhObj
get hFindModule.s of oWafModuleList lsModule to lhObj
function_return lhObj
end_function
function WafPageObject global string lsModule string lsPage returns integer
integer lhObj
get WafModuleObject lsModule to lhObj
if lhObj get hFindPage.s of lhObj lsPage to lhObj
function_return lhObj
end_function
procedure WafRegisterModule global integer lhObj
send register_module of oWafModuleList lhObj
end_procedure
function WafPageLink global string lsModule string lsPage returns string
string lsAction
get waf_config_value WACFG_ASP_FILE to lsAction
send QryString_Prepare lsAction
send QryString_AddParam "m" lsModule
send QryString_AddParam "p" lsPage
function_return (QryString_Value())
end_function
function WafPageLinkSelect global string lsModule string lsPage string lsSelect string lsParam returns string
string lsAction
get waf_config_value WACFG_ASP_FILE to lsAction
send QryString_Prepare lsAction
send QryString_AddParam "m" lsModule
send QryString_AddParam "p" lsPage
send QryString_AddParam "s" lsSelect
send QryString_AddParam "r" lsParam // r is used because it's mostly a ecord id.
function_return (QryString_Value())
end_function
class WebPageBroker is a cArray
procedure construct_object
forward send construct_object
property string psHtmlLanguage public "en"
property string psHtmlHeaderTitle public "My fantastic application"
property string psHtmlHeaderCopyrightCompany public "Lego Ego"
property string psHtmlHeaderCopyrightYear public "2004"
property string psHtmlHeaderGenerator public "Visual DataFlex"
// property string psHtmlHeaderAppName public "CoolApp"
// property string psHtmlHeaderAppVer public "1.0"
// If module can't be determined any other way, we use this:
property string psDefaultModule
//
property string psNextModule
property string psNextPage
property integer pbRedirectionRecursion
move self to ghoPageBroker
object oRedirectionRecursion is a cStack
end_object
end_procedure
item_property_list
item_property string psPageName.i
item_property integer phPage.i
end_item_property_list WebPageBroker
function DefaultModule returns string
function_return (psDefaultModule(self))
end_function
procedure HandleError integer liError integer liErrorLine string lsErrorText
string lsError
move "Error # line #: #" to lsError
move (replace("#",lsError,string(liError))) to lsError
move (replace("#",lsError,string(liErrorLine))) to lsError
move (replace("#",lsError,lsErrorText)) to lsError
send XHTML_Add_Closed_Element "p" lsError
end_procedure
procedure DetectRedirectionRecursionReset integer lhPage
set pbRedirectionRecursion to false
send delete_data of oRedirectionRecursion
end_procedure
procedure DetectRedirectionRecursion integer lhPage
integer lbErr
get bIsOnStack.i of oRedirectionRecursion lhPage to lbErr
if lbErr set pbRedirectionRecursion to true
else send push.i of oRedirectionRecursion lhPage
end_procedure
procedure HandleErrorsDuringPreSubmit
#IFDEF Is$WebApp
// For this we use the standard WebApp way:
send OutputHTML of ghInetSession ""
send ReportAllErrors of ghInetSession "Errors occurred during pre-submit"
send OutputHTML of ghInetSession ""
send ClearErrors of ghInetSession
#ENDIF
end_procedure
procedure onNewRequest
end_procedure
procedure PreWriteBody
end_procedure
procedure PostWriteBody
end_procedure
procedure DoWriteHtmlHeaderSection integer lhPage
string lsValue
integer liValue
get psHtmlHeaderTitle to lsValue
if (lsValue="") move "No title" to lsValue
send XHTML_Add_Closed_Element "title" lsValue
get psHtmlHeaderGenerator to lsValue
if (lsValue<>"") begin
send XHTML_Add_Closed_Element "meta" ""
send XHTML_Add_Attribute "name" "generator"
send XHTML_Add_Attribute "content" lsValue
end
if (lhPage and piRefreshSeconds(lhPage)) begin // Set page refresh rate
send XHTML_Add_Closed_Element "meta" ""
send XHTML_Add_Attribute "http-equiv" "refresh"
send XHTML_Add_Attribute "content" (piRefreshSeconds(lhPage))
end
// Set no-cache
send XHTML_Add_Closed_Element "meta" ""
send XHTML_Add_Attribute "http-equiv" "pragma"
send XHTML_Add_Attribute "content" "no-cache"
get psHtmlHeaderCopyrightCompany to lsValue
get psHtmlHeaderCopyrightYear to liValue
if (lsValue<>"") begin
send XHTML_Add_Closed_Element "meta" ""
send XHTML_Add_Attribute "name" "copyright"
send XHTML_Add_Attribute "content" (sCopyrightText(liValue,lsValue))
end
send XHTML_Add_Closed_Element "script" ""
send XHTML_Add_Attribute "type" "text/javascript"
send XHTML_Add_Attribute "src" "inc/waf.js"
// get Waf_MetaInfo WA_STYLESHEET1 to lsValue
// if (lsValue<>"") begin
// send XHTML_Add_Closed_Element "link" ""
// send XHTML_Add_Attribute "rel" "stylesheet"
// send XHTML_Add_Attribute "href" lsValue
// send XHTML_Add_Attribute "type" "text/css"
// end
end_procedure
procedure DoSetUrlAndQueryString string lsUrl string lsQueryStr
string lsPrevQueryStr
get value of oBaseSessionVariables WSV_CURRENT_QRYSTR to lsPrevQueryStr
set value of oBaseSessionVariables WSV_PREV_QRYSTR to lsPrevQueryStr
set value of oBaseSessionVariables WSV_CURRENT_URL to lsUrl
set value of oBaseSessionVariables WSV_CURRENT_QRYSTR to lsQueryStr
end_procedure
//Firefox: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1
//Opera: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [en]
//Mozilla: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608
//IE 6.0: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
procedure DoSetBrowser string lsBrowser string lsVersion
send DecodeUserAgent of oWebBrowserInfo lsBrowser
end_procedure
procedure OnNewSession
end_procedure
register_function HandleSubmit returns string
register_procedure OnEndOfRequest // Called when the web application is done generating each html response
procedure DoWriteHTML // WebPageBroker
integer lbSessionActive lhModule lhPage lhWebForm lhErrHnd lbHtmlTest lbOk lbContinue liLng lhLayout
string lsModule lsPage lsError lsLang lsSubmitButton
string lsFormName lsFormCollection
// We start by setting the language, if the session is new
get value of oBaseSessionVariables WSV_SESSION_ACTIVE to lbSessionActive
ifnot lbSessionActive begin
set value of oBaseSessionVariables WSV_SESSION_ACTIVE to 1
set value of oBaseSessionVariables WSV_LANGUAGE to LNG_DEFAULT // Get session language to global variable
send OnNewSession
end
get value of oBaseSessionVariables WSV_LANGUAGE to liLng // Get session language to global variable
send select_current_language liLng
move 0 to ghFormSubmitted // Reset indication of form having been submitted. (It's set from within WebForm.nui)
#IFDEF Is$WebApp
send ErrorQueueStart To ghInetSession // Pick up errors during pre-submit code.
#ENDIF
// Get name of submitted form (if any):
get WafGetHtmlFormValue "htmlform_name" to lsFormName // If lsFormName is <>"" then there was a form submitted
// Get name of form collection for submitted form (if any):
get WafGetHtmlFormValue "htmlform_collection" to lsFormCollection
move (lowercase(WafGetQueryString("html"))="true") to lbHtmlTest
if lbHtmlTest set pbTest of oWebAppHtmlBuilder to true
send onNewRequest
#IFDEF Is$WebApp
send ErrorQueueEnd To ghInetSession // Stop error queue and report errors if any.
if (ErrorCount(ghInetSession)) send HandleErrorsDuringPreSubmit
else begin
#ELSE
if TRUE begin
#ENDIF
if (lbSessionActive<>0 and lsFormName<>"") begin
// A form has been submitted! We now have to identify this form within the application
// and let that handle the thing. Note that this happens at a time when the XHTML output
// hasn't been initiated yet:
get WebForm_FindFormObject lsFormName lsFormCollection to lhWebForm
set psNextModule to ""
set psNextPage to ""
get HandleSubmit of lhWebForm to lsSubmitButton
// Now check if the handling of the submit has determined which page
// we should now call:
get psNextModule to lsModule
get psNextPage to lsPage
end
else begin
move "" to lsModule
move "" to lsPage
send WebForm_ClearErrors // No errors hanging from somebody elses submit.
end
if (lsModule="" and lsPage="") begin
// Figure out which module/page we should call.
// First we see if page/module was passed on the HTML request query string:
get WafGetQueryString "m" to lsModule
move (lowercase(lsModule)) to lsModule
// If module was specified by the query string, we'll look for a page
if (lsModule<>"") begin
get WafGetQueryString "p" to lsPage
move (lowercase(lsPage)) to lsPage
end
else move "" to lsPage // If module is blank, ignore page parameter
end
if (integer(value(oBaseSessionVariables,WSV_SESSION_ACTIVE))) begin
// If module is blank, get previous module
if (lsModule="") begin
get value of oBaseSessionVariables WSV_MODULE_NAME to lsModule
if (lsModule<>"") get value of oBaseSessionVariables WSV_PAGE_NAME to lsPage
end
end
// If module is still blank, get default module
if (lsModule="") begin
get DefaultModule to lsModule
// If page is blank, get previous page
end
send DetectRedirectionRecursionReset
move 1 to lbOk
repeat
get WafModuleObject lsModule to lhModule
ifnot lhModule begin
move "Module could not be found (#)" to lsError
move (replace("#",lsError,lsModule)) to lsError
error 236 lsError
move 0 to lbOk
end
if (lsPage="") get DefaultPage of lhModule to lsPage
set psNextModule to lsModule
set psNextPage to lsPage
send OnModuleSetup of lhModule lsPage lsSubmitButton lsFormName lsFormCollection
move (psNextModule(self)=lsModule and psNextPage(self)=lsPage) to lbContinue
ifnot lbContinue begin
get psNextModule to lsModule
get psNextPage to lsPage
end
until lbContinue
if (pbRedirectionRecursion(self)) begin
move "system" to lsModule
move "error" to lsPage
end
if lbOk begin
// Activate our own web error handler:
move oWebErrorHandler to lhErrHnd
send delete_data of lhErrHnd
send DoActivate of lhErrHnd
set value of oBaseSessionVariables WSV_MODULE_NAME to lsModule
set value of oBaseSessionVariables WSV_PAGE_NAME to lsPage
get WafModuleObject lsModule to lhModule
get WafPageObject lsModule lsPage to lhPage
get phPageLayoutObject of lhPage to lhLayout
if (lhLayout<>0 and piType(lhLayout)=LAYOUTTYPE_HTML_PAGE) begin
send XHTML_StartXhtml
send DoDeactivate of lhErrHnd
send DoWriteHtml of lhModule lsPage
send XHTML_EndXhtml
end
else begin
send XHTML_StartXhtml
send XHTML_OpeningOath // This complete XHTML document.
send XHTML_Add_Open_Element "html"
send XHTML_Add_Attribute "xmlns" "http://www.w3.org/1999/xhtml"
get psHtmlLanguage to lsLang
if (lsLang="") move "en" to lsLang
send XHTML_Add_Attribute "xml:lang" lsLang
send XHTML_Add_Attribute "lang" lsLang
send XHTML_Add_Open_Element "head"
send DoWriteHtmlHeaderSection (WafPageObject(lsModule,lsPage))
send XHTML_Close_Element // head
send XHTML_Add_Open_Element "body"
send PreWriteBody
send DoWriteHtml of lhModule lsPage
if (ErrorCount(lhErrHnd)) begin
// Here we handle the incident that the error handling object
// has some un-handled errors.
send XHTML_Add_Open_Element "div"
send XHTML_Add_Attribute "class" "UnhandledErrors"
send DoDeactivate of lhErrHnd
send CallBack of lhErrHnd MSG_HandleError self
send XHTML_Close_Element // div
end
send PostWriteBody
send XHTML_Close_Element // body
send XHTML_Close_Element // html
send XHTML_EndXhtml
end
if lbHtmlTest set pbTest of oWebAppHtmlBuilder to false
send DoDeactivate of lhErrHnd // Very important!! Otherwise the error handler will survive to next request
send onDebrief of lhModule lsPage
broadcast recursive send OnEndOfRequest to desktop
// get value of oBaseSessionVariables WSV_SESSION_ACTIVE to lbSessionActive
// ifnot lbSessionActive set value of oBaseSessionVariables WSV_SESSION_ACTIVE to 1
// set value of oBaseSessionVariables WSV_MODULE_NAME to lsModule
// set value of oBaseSessionVariables WSV_PAGE_NAME to lsPage
end
end //
end_procedure
end_class // WebPageBroker
procedure GotoPage global string lsModule string lsPage
set psNextModule of ghoPageBroker to lsModule
set psNextPage of ghoPageBroker to lsPage
end_procedure
//send Delete_data to (oErrorHandlerQuiet(self))
//send DoActivate to (oErrorHandlerQuiet(self))