Web Development (CGI Library)
In this chapter we will learn about developing Web applications using a CGI Library written in the Ring language.
Configure the Apache web server
In this section we will learn about using Ring with the Apache HTTP Server. We can also use Ring with any web server that supports CGI.
Note
If you are developing your application using Ring Notepad then there’s no need to configure Apache manually.
Using XAMPP Apache web server
Here we will use the XAMPP application that has Apache web server already been included. You can download XAMPP package from this link
XAMPP : https://www.apachefriends.org/download.html
Install then open the configuration file from the XAMPP application or search for it in the following locations based on your operating system.
For Windows:
xampp\apache\conf\httpd.conf For Linux:
/opt/lampp/etc/httpd.conf For macOS:
/Applications/XAMPP/xamppfiles/etc/httpd.conf Search for the next line and make sure that it’s not commented
LoadModule cgi_module modules/mod_cgi.so Search for : AddHandler cgi-script
Then add “.ring” to the supported cgi extensions
Example
AddHandler cgi-script .cgi .ring Example
AddHandler cgi-script .cgi .pl .asp .ring Restart/Start the server using XAMPP “Manage Servers” or “Services” section
Create your web applications in a directory supported by the web server.
For Windows:
xampp\htdocs\mywebapplicationfolder For Linux:
/opt/lampp/htdocs/mywebapplicationfolder For macOS:
Open XAMPP application then go to "Volumes" section Mount the "/opt/lampp" volume Open Finder then you will find it mounted as an IP address under "Locations" on the left menu Setting the shebang line
For Ring files to run properly under CGI we need to set the shebang line to locate the executable file of Ring. So, Inside the source code file (*.ring), Add next line as the very first line in the file:
For Windows:
#!ring -cgi For Linux:
#!/usr/bin/ring -cgi For macOS:
#!/usr/local/bin/ring -cgi Note
Change the previous line based on the path to ring executable in your machine
Grant Ring files execution permission
In Linux and Mac operating systems ring files cannot be run properly using CGI until we grant them executable permission. You can do that using the properties section of your preferred File manager or you can do it using Terminal as follow:
sudo chmod +x ringAppFile.ring Note
If you are developing your application using Ring Notepad then this step will be done automatically.
Ring CGI Hello World Program
The next program is the Hello World program
For Windows:
#!ring -cgi See "content-type: text/html" +nl+nl+ "Hello World!" + nl For Linux:
#!/usr/bin/ring -cgi See "content-type: text/html" +nl+nl+ "Hello World!" + nl For macOS:
#!/usr/local/bin/ring -cgi See "content-type: text/html" +nl+nl+ "Hello World!" + nl Hello World Program using the Web Library
We can use the web library to write CGI Web applications quickly
Example (1) :
#!ring -cgi Load "weblib.ring" Import System.Web New Page { Text("Hello World!") } Example (2) :
#!ring -cgi Load "weblib.ring" Import System.Web WebPage() { Text("Hello World!") } Tip
the difference between ex. 1 and ex. 2 is using WebPage() function to return the page object instead of creating the object using new statement.
Web Library Features
The next features are provided by the Web library to quickly create web applications.
Generate HTML pages using functions
Generate HTML pages using objects
HTTP Get
HTTP Post
Files Upload
URL Encode
Templates
CRUD MVC Sample
Users Logic & Registration Sample
HTTP Get Example
The Page User Interface
#!ring -cgi Load "weblib.ring" Import System.Web New Page { Title = "Test HTTP Get" divstart([ :style = StyleSizeFull() ] ) boxstart() text( "Test HTTP GET" ) newline() boxend() divstart([ :style = Styledivcenter("600px","550px") + StyleGradient(21) ]) divstart([:style = stylefloatleft() + stylesize("100px","100%") + stylecolor("black") + stylegradient(58)]) formstart("ex5.ring") tablestart([ :style = stylesize("65%","90%") + stylemarginleft("35%") + stylemargintop("30%") ]) rowstart([]) cellstart([]) text ( "Name : " ) cellend() cellstart([]) cTextboxStyle = StyleMarginLeft("5%") + StyleWidth("250px") + StyleColor("black") + StyleBackColor("white") textbox([ :name = "Name", :style = cTextboxStyle ] ) cellend() rowend() rowstart([]) cellstart([]) text ( "Address : " ) cellend() cellstart([]) textbox([ :name = "Address", :style = cTextboxStyle] ) cellend() rowend() rowstart([]) cellstart([]) text ( "Phone : " ) cellend() cellstart([]) textbox([ :name = "Phone", :style = cTextboxStyle ]) cellend() rowend() rowstart([]) cellstart([]) text ( "Age : " ) cellend() cellstart([]) textbox([ :name = "Age", :style = cTextboxStyle ]) cellend() rowend() rowstart([]) cellstart([]) text ( "City: " ) cellend() cellstart([]) listbox([ :name = "City", :items = ["Cairo","Riyadh","Jeddah"], :style = stylemarginleft("5%") + stylewidth("400px") ] ) cellend() rowend() rowstart([]) cellstart([]) text ( "Country : " ) cellend() cellstart([]) combobox([ :name = "Country", :items = ["Egypt","Saudi Arabia","USA"], :style = stylemarginleft("5%") + stylewidth("400px")+ stylecolor("black")+ stylebackcolor("white")+ stylefontsize("14px") ]) cellend() rowend() rowstart([]) cellstart([]) text ( "Note : " ) cellend() cellstart([]) editbox([ :name = "Notes", :style = stylemarginleft("5%") + stylesize("400px","100px")+ stylecolor("black")+ stylebackcolor("white") , :value = "write comments here..." ] ) cellend() rowend() rowstart([]) cellstart([]) cellend() cellstart([]) submit([ :value = "Send" , :Style = stylemarginleft("5%") ]) cellend() rowend() tableend() formend() divend() divend() divend() } Screen Shot:
The Response
#!ring -cgi Load "weblib.ring" Import System.Web New Page { divstart([ :style = styledivcenter("800px","500px") ]) boxstart() text ( "HTTP GET Response" ) newline() boxend() divstart([ :style = stylefloatleft()+stylewidth("10%")+ stylecolor("black")+stylegradient(58) ]) newline() text ( "Name : " ) newline() newline() text ( "Address : " ) newline() newline() text ( "Phone : " ) newline() newline() text ( "Age : " ) newline() newline() text ( "City : " ) newline() newline() text ( "Country : " ) newline() newline() text ( "Note : " ) newline() newline() divend() divstart([ :style = stylefloatleft()+stylewidth("90%")+ stylecolor("black")+stylegradient(47) ]) divstart([ :style = stylefloatleft() + stylewidth("1%") ]) newline() divend() divstart([ :style = stylefloatleft() + stylewidth("95%") ]) newline() text ( aPageVars["Name"] ) newline() newline() text ( aPageVars["Address"] ) newline() newline() text ( aPageVars["Phone"] ) newline() newline() text ( aPageVars["Age"] ) newline() newline() text ( aPageVars["City"] ) newline() newline() text (aPageVars["Country"] ) newline() newline() text ( aPageVars["Notes"] ) newline() newline() divend() divend() divend() } Screen Shot:
HTTP POST Example
The Page User Interface
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text( "Post Test") newline() boxend() divstart([ :style=StyleFloatLeft()+StyleWidth("100px") ]) newline() text( "Number1 : " ) newline() newline() text( "Number2 : " ) newline() newline() divend() formpost("ex7.ring") divstart([ :style = styleFloatLeft()+StyleWidth("200px") ]) newline() textbox([ :name = "Number1" ]) newline() newline() textbox([ :name = "Number2" ]) newline() newline() submit([ :value = "Send" ] ) divend() formend() } Screen Shot:
The Response
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text( "Post Result" ) newline() boxend() divstart([ :style = styleFloatLeft()+styleWidth("200px") ]) newline() text( "Number1 : " + aPageVars["Number1"] ) newline() newline() text( "Number2 : " + aPageVars["Number2"] ) newline() newline() text( "Sum : " + (0 + aPageVars["Number1"] + aPageVars["Number2"] ) ) newline() divend() } Screen Shot:
Upload Files
The Page User Interface
#!ring -cgi Load "weblib.ring" Import System.Web New page { boxstart() text( "Upload File" ) newline() boxend() for x = 1 to 3 newline() next formupload("ex9.ring") text( "Customer Name : " ) textbox([ :name = "custname" ]) newline() newline() divstart([ :style = styleFloatLeft() + styleWidth("90px") ]) uploadfile("file") newline() newline() uploadfile("file2") newline() newline() submit([ :value = "Send" ]) divend() formend() } Screen Shot:
The Response
#!ring -cgi Load "weblib.ring" Import System.Web cUploadPath = "C:/Apache2.2/htdocs/ringapp/upload/" cUploadFolder = "/ringapp/upload/" New page { boxstart() text( "Upload Result" ) newline() boxend() newline() divstart([ :style= styleFloatLeft() + styleWidth("100px") ]) text( "Name : " + aPageVars["custname"] ) newline() divend() if aPageVars["file"] != char(13) getuploadedfile(self,"file") ok if aPageVars["file2"] != char(13) getuploadedfile(self,"file2") ok } Func getuploadedfile oObj,cFile # here we use object.property # instead of object { } to avoid executing braceend method cFileName = cUploadPath + oObj.getfilename(aPageVars,cFile) write(cFileName,aPageVars[cFile]) system("chmod a+x "+cFileName) oObj.newline() oObj.text( "File "+cFileName+ " Uploaded ..." ) oObj.newline() imageURL = cUploadFolder + oObj.getfilename(aPageVars,cFile) oObj.link([ :url = imageURL, :title = "Download" ]) oObj.newline() oObj.image( [ :url = imageURL , :alt = :image ] ) oObj.newline() Screen Shot:
URL Encode
The Page User Interface
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text( "URLEncode" ) newline() boxend() link([ :url = "ex5.ring?Name="+URLEncode("-*{Mahmoud}*-")+ "&Address=Egypt&Phone=123456&Age=28&Notes=Programmer", :title = "Test URL Encode" ]) } Screen Shot:
Screen Shot:
Templates
Using Templates we can write Ring code inside HTML files
Syntax:
<%= Ring Expression %> <% Ring Statements %> The HTML Code
<h1>Listing Numbers</h1> <table> <tr> <th> <%= myheader.cColumn1 %> </th> <th> <%= myheader.cColumn2 %> </th> <th></th> <th></th> <th></th> </tr> <% for x in aNumbers %> <tr> <td> <%= x.nValue %> </td> <td> <%= x.nSquare %> </td> </tr> <% next %> </table> The Ring Code
#!ring -cgi Load "weblib.ring" Import System.Web New NumbersController { start() } Class NumbersController MyHeader aNumbers Func Start MyHeader = New Header { cColumn1 = "Number" cColumn2 = "Square" } aNumbers = list(20) for x = 1 to len(aNumbers) aNumbers[x] = new number { nValue = x nSquare = x*x } next cTemp = Template("mynumbers.html",self) New Page { boxstart() text( "Test Templates" ) newline() boxend() html(cTemp) } Class Header cColumn1 cColumn2 Class Number nValue nSquare Screen Shot:
HTML Special Characters
The text() function display HTML special characters.
If you want to write html code, use the html() function.
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text("HTML Special Characters") newline() boxend() text(' <html> <body> <p> "hello world" </p> </body> </html> ') } Screen Shot:
Hash Functions
The Page User Interface
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text( "Hash Test") newline() boxend() divstart([ :style = StyleFloatLeft() + StyleWidth("100px") ]) newline() text( "Value : " ) newline() newline() divend() formpost("ex16.ring") divstart([ :style = StyleFloatLeft() + StyleWidth("300px") ]) newline() textbox([ :name = "Value" ]) newline() newline() submit([ :value = "Send" ]) divend() formend() } Screen Shot:
The Response
#!ring -cgi Load "weblib.ring" Import System.Web New Page { boxstart() text( "Hash Result" ) newline() boxend() divstart([ :style = styleFloatLeft() + styleWidth("100%") ]) newline() text( "Value : " + aPageVars["Value"] ) newline() text( "MD5 : " + MD5(aPageVars["Value"]) ) newline() text( "SHA1 : " + SHA1(aPageVars["Value"]) ) newline() text( "SHA256 : " + SHA256(aPageVars["Value"]) ) newline() text( "SHA224 : " + SHA224(aPageVars["Value"]) ) newline() text( "SHA384 : " + SHA384(aPageVars["Value"]) ) newline() text( "SHA512 : " + SHA512(aPageVars["Value"]) ) newline() divend() } Screen Shot:
Random Image
#!ring -cgi Load "weblib.ring" Import System.Web cUploadPath = "C:/Apache2.2/htdocs/ringapp/upload/" New Page { boxstart() text( "Random Test") newline() boxend() divstart([ :style = styleFloatLeft() + styleWidth("400px") ]) newline() aList = dir(cUploadPath) if len(aList) > 0 nIndex = random(len(aList)) if nindex = 0 nIndex = 1 ok cItem = "upload/" + aList[nIndex][1] newline() image( [ :url = cItem , :alt = :image ] ) else text("No images!") newline() ok divend() } Screen Shot:
HTML Lists
The next example print a list contains numbers from 1 to 10
Then print a list from Ring List.
Finally we have a list of buttons and when we press on a button we get a message contains the clicked button number.
To start the list we uses the ulstart() function.
To end the list we uses the ulend() function.
We uses listart() and liend() to determine the list item.
#!ring -cgi Load "weblib.ring" Import System.Web Func Main New Page { ulstart([]) for x = 1 to 10 listart([]) text(x) liend() next ulend() list2ul(["one","two","three","four","five"]) ulstart([]) for x = 1 to 10 listart([]) cFuncName = "btn"+x+"()" button([ :onclick = cFuncName , :value = x]) script(scriptfuncalert(cFuncName,string(x))) liend() next ulend() } Screen Shot:
HTML Tables
In this example we will learn how to generate HTML tables using the tablestart(), tableend(), rowstart(), rowend() ,headerstart(), headerend(), cellstart() and cellend() functions.
#!ring -cgi Load "weblib.ring" Import System.Web Func Main New Page { divstart([ :style = styledivcenter("400px","500px") ] ) style(styletable() + styletablerows("t01")) tablestart([ :id = :t01 , :style = stylewidth("100%") ]) rowstart([]) headerstart([]) text("Number") headerend() headerstart([]) text("square") headerend() rowend() for x = 1 to 10 rowstart([]) cellstart([]) text(x) cellend() cellstart([]) text(x*x) cellend() rowend() next tableend() divend() } Screen Shot:
Gradient
In this example we will learn how to use the StyleGradient() function.
The function takes the style number as input (range from 1 to 60).
#!ring -cgi Load "weblib.ring" Import System.Web Func Main New Page { boxstart() text("StyleGradient() Function") boxend() for x = 1 to 60 divstart([ :id = x , :align = "center" , :style = stylefloatleft() + stylesize(string(100/60*6)+"%","50px") + stylegradient(x) ]) h3(x) divend() next } Screen Shot:
Generating Pages using Objects
Instead of using functions/methods to generate HTML pages, we can use an object for each element in the page.
This choice means more beautiful code but slower.
The fastest method is to print HTML code directly, then using functions then using templates then using objects (slower).
#!ring -cgi Load "weblib.ring" Import System.Web Func Main WebPage() { Title = "Using objects to create the Web Page content" h1 { text("welcome") } link { Title = "Google" Link = "http://www.google.com" } div { id = "div1" style = stylegradient(30) + stylesize("50%","50%") text("Outer Div") div { id = "div2" color = "white" backgroundcolor = "green" width = "50%" height = "50%" marginleft = "5%" margintop = "5%" text("Inner Div") } } div { id = "div3" color = "black" backgroundcolor = "silver" width = "100%" height = "100%" text("Form") form { method = "POST" Action = "helloworld.ring" Table { style = stylewidth("100%") + stylegradient(24) TR { TD { WIDTH="10%" text("Name : " ) } TD { Input { type = "text" } } } TR { TD { WIDTH="10%" text("Email : " ) } TD { Input { type = "text" } } } TR { TD { WIDTH="10%" text("Password : " ) } TD { Input { type = "password" } } } TR { TD { WIDTH="10%" text("Notes") } TD { TextArea { width="100%" rows = 10 cols = 10 text("type text here...") } } } TR { TD { WIDTH="10%" text("Gender") } TD { select { width = "100%" option { text("Male") } option { text("Female") } } } } TR { TD { WIDTH="10%" text("Role") } TD { select { multiple = "multiple" width = "100%" option { text("student") } option { text("admin") } } } } } Input { type = "submit" value = "send" } Image { src="upload/profile1.jpg" alt="profile"} Input { type = "checkbox" value = "Old Member"} text("old member") Input { type = "range" min=1 max=100} Input { type = "number" min=1 max=100} Input { type = "radio" color="black" name="one" value = "one"} text("one") } } div { color = "white" backgroundcolor = "blue" width = "100%" UL { LI { TEXT("ONE") } LI { TEXT("TWO") } LI { TEXT("THREE") } } } div { audio { src = "horse.ogg" type = "audio/ogg" } video { width = 320 height = 240 src = "movie.mp4" type = "video/mp4" } Input { type = "color" value = "#ff0000" onchange = "clickColor(0, -1, -1, 5)" } } } Screen Shot:
HtmlPage Class
Using this class we can create HTML documents without printing the output to the standard output
So instead of using the WebLib in Web Applications only
We can use it in Console/GUI/Mobile Applications too
Example:
load "stdlib.ring" load "weblib.ring" import System.Web func main mypage = new HtmlPage { h1 { text("Customers Report") } Table { style = stylewidth("100%") + stylegradient(4) TR { TD { WIDTH="10%" text("Customers Count : " ) } TD { text (100) } } } Table { style = stylewidth("100%") + stylegradient(26) TR { style = stylewidth("100%") + stylegradient(24) TD { text("Name " ) } TD { text("Age" ) } TD { text("Country" ) } TD { text("Job" ) } TD { text("Company" ) } } for x = 1 to 100 TR { TD { text("Test" ) } TD { text("30" ) } TD { text("Egypt" ) } TD { text("Sales" ) } TD { text("Future" ) } } next } } write("report.html",mypage.output()) Using Bootstrap Library using Functions
The next example uses the Bootstrap JavaScript Library when generating the HTML page.
#!ring -cgi Load "weblib.ring" Import System.Web Func Main new BootstrapPage { divstart([ :class = "container" ]) divstart([ :class = "jumbotron" ]) h1("Bootstrap Page") divend() divstart([ :class = :row ]) divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "Using a scripting language is very fun!" ]) divend() divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "using a scripting language is very fun!" ]) divend() divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "using a scripting language is very fun!" ]) divend() divend() divend() } Screen Shot:
Using Bootstrap Library using Objects
The next example uses the Bootstrap JavaScript Library when generating the HTML page.
Instead of using functions to generate the HTML elements, we will use objects.
#!ring -cgi Load "weblib.ring" Import System.Web Func Main BootStrapWebPage() { div { classname = :container div { classname = :jumbotron H1 { text("Bootstrap Page") } } div { classname = :row for x = 1 to 3 div { classname = "col-sm-4" H3 { html("Welcome to the Ring programming language") } P { html("Using a scripting language is very fun!") } } next } div { classname = :row div { classname = "col-sm-4" Button { classname = "btn btn-info btn-lg" datatoggle= "modal" datatarget = "#myModal" text("Open Large Modal") } } div { classname = "col-sm-4" Button { classname = "btn btn-default btn-lg" text("default") } Button { classname = "btn btn-primary btn-md" text("primary") } Button { classname = "btn btn-success btn-sm" text("success") } Button { classname = "btn btn-info btn-xs" text("info") } Button { classname = "btn btn-warning" text("warning") } Button { classname = "btn btn-danger" text("danger") } Button { classname = "btn btn-link" text("link") } } div { classname = "col-sm-4" Button { classname = "btn btn-default btn-block" text("default") } Button { classname = "btn btn-primary btn-block" text("primary") } Button { classname = "btn btn-success btn-block" text("success") } Button { classname = "btn btn-info btn-block" text("info") } Button { classname = "btn btn-warning btn-block" text("warning") } Button { classname = "btn btn-danger btn-block" text("danger") } Button { classname = "btn btn-link btn-block" text("link") } } div { classname = "col-sm-4" div { classname = "btn-group" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } div { classname = "col-sm-4" div { classname = "btn-group btn-group-lg" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } div { classname = "col-sm-4" div { classname = "btn-group-vertical btn-group-lg" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } } div { classname="modal fade" id="myModal" role="dialog" div { classname = "modal-dialog modal-lg" div { classname="modal-content" div { classname="modal-header" button { classname="close" datadismiss="modal" html("×") } h4 { classname="modal-title" text("Modal Header") } } div { classname = "modal-body" p { text("This is a large model.") } } div { classname="modal-footer" button { classname = "btn btn-default" datadismiss="modal" text("close") } } } } } } } Screen Shot:
CRUD Example using MVC
The next example uses the weblib.ring & datalib.ring.
The datalib.ring contains classes for creating database applications using MVC pattern.
In this example we create an object from the SalaryController class then call the Routing method.
We define the website variable to contains the basic url of the page.
When we create the SalaryModel class from the ModelBase class, the salary table will be opened and the columns data will be defined as attributes in the model class.
The SalaryView class create an object from the SalaryLanguageEnglish class to be used for translation.
The method AddFuncScript is used to call the form for adding/modifying record data.
The method FormViewContent is used to determine the controls in the form when we add or modify a record.
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Import System.Web website = "ex24.ring" New SalaryController { Routing() } Class SalaryModel from ModelBase Class SalaryController From ControllerBase Class SalaryView From ViewBase oLanguage = new SalaryLanguageEnglish Func AddFuncScript oPage,oController return oPage.scriptfuncajax("myadd",oController.cMainURL+ oController.cOperation+"=add","mysubpage") Func FormViewContent oController,oTranslation,oPage return [ [ oTranslation.aColumnsTitles[2], "textbox", "name", oController.oModel.Name, oPage.stylewidth("100%") ], [ oTranslation.aColumnsTitles[3], "textbox", "salary", oController.oModel.Salary, oPage.stylewidth("50%") ] ] Class SalaryLanguageEnglish cTitle = "Salary Table" cBack = "back" aColumnsTitles = ["ID","Name","Salary"] cOptions = "Options" cSearch = "Search" comboitems = ["Select Option...","Edit","Delete"] cAddRecord = "Add Record" cEditRecord = "Edit Record" cRecordDeleted = "Record Deleted!" aMovePages = ["First","Prev","Next","Last"] cPage = "Page" cOf = "of" cRecordsCount = "Records Count" cSave = "Save" temp = new page cTextAlign = temp.StyleTextRight() cNoRecords = "No records!" Screen Shot:
Users registration and Login
We have the users classes (Model, View & Controller) to deal with the users data like username & email.
The next code is stored in ex25_users.ring
Class UsersModel from ModelBase cSearchColumn = "username" Class UsersController From ControllerBase aColumnsNames = ["id","username","email"] Func UpdateRecord oModel.id = aPageVars[cRecID] oModel.updatecolumn("username", aPageVars[:username] ) oModel.updatecolumn("email", aPageVars[:email] ) oView.UpdateView(self) Class UsersView from ViewBase oLanguage = new UsersLanguageEnglish Func AddFuncScript oPage,oController return oPage.scriptfunc("myadd",oPage.scriptredirection("ex26.ring")) Func FormViewContent oController,oTranslation,oPage return [ [oTranslation.aColumnsTitles[2],"textbox","username", oController.oModel.UserName,oPage.stylewidth("100%")], [oTranslation.aColumnsTitles[3],"textbox","email", oController.oModel.Email,oPage.stylewidth("50%")] ] Class UsersLanguageEnglish cTitle = "Users Table" cBack = "back" aColumnsTitles = ["ID","User Name","Email"] cOptions = "Options" cSearch = "Search" comboitems = ["Select Option...","Edit","Delete"] cAddRecord = "Add Record" cEditRecord = "Edit Record" cRecordDeleted = "Record Deleted!" aMovePages = ["First","Prev","Next","Last"] cPage = "Page" cOf = "of" cRecordsCount = "Records Count" cSave = "Save" temp = new page cTextAlign = temp.StyleTextRight() cNoRecords = "No records!" In the file ex25.ring we load ex25_users.ring then create an object from UsersController class.
Using the created object, we call the routing method.
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web website = "ex25.ring" New UsersController { Routing() } Screen Shot:
See the next code for the registration page
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Import System.Web website = "ex26.ring" new page { boxstart() text( "Register") newline() boxend() divstart([:style = stylegradient(6) + stylesize("100%","95%") ]) link([ :url = website, :title = "back" , :style = stylecolor("white")]) newline() divstart([ :style= styledivcenter("500","160") + stylegradient(52) ]) formpost("ex27.ring") tablestart([ :Style = stylemarginleft("2%") + stylemargintop("2%") + stylewidth("90%") ]) rowstart([]) cellstart([:style = stylewidth("20%") + styleheight(30)]) text("User Name") cellend() cellstart([ :style = stylewidth("80%") ]) textbox([:name = "username", :style = stylewidth("100%")]) cellend() rowend() rowstart([]) cellstart([ :Style = styleheight(30)]) text("Password") cellend() cellstart([]) textbox([:name = "password" , :type = "password"]) cellend() rowend() rowstart([]) cellstart([ :style = styleheight(30)]) text("Email") cellend() cellstart([]) textbox([:name = "email" , :style = stylewidth("100%")]) cellend() rowend() rowstart([]) cellstart([ :style = styleheight(30)]) cellend() cellstart([ :style = styleheight(30)]) submit([:value = "Register" ]) cellend() rowend() tableend() formend() divend() divend() } Screen Shot:
The Registration response
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web oUser = new UsersModel oUser.Connect() if oUser.findwith("username",aPageVars["username"]) new page { text("The user name is already registered") } return ok if oUser.findwith("email",aPageVars["email"]) new page { text("This email is already registered") } return ok aPageVars["salt"] = str2hex(RandBytes(32)) aPageVars["pwhash"] = sha256(aPagevars["password"]+aPageVars["salt"]) aPageVars["sessionid"] = str2hex(randbytes(32)) oUser.Insert() new page { cookie("sessionid",aPageVars["sessionid"]) text("New User Created!") newline() text("User Name : " + aPageVars["username"]) newline() } oUser.Disconnect() See the next code for the Login page
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Import System.Web website = "ex28.ring" new page { boxstart() text( "Login") newline() boxend() divstart([:style = stylegradient(6) + stylesize("100%","95%") ]) link([ :url = website, :title = "back" , :style = stylecolor("white")]) newline() divstart([ :style= styledivcenter("500","130") + stylegradient(52) ]) formpost("ex29.ring") tablestart([ :Style = stylemarginleft("2%") + stylemargintop("2%") + stylewidth("90%") ]) rowstart([]) cellstart([:style = stylewidth("20%") + styleheight(30)]) text("User Name") cellend() cellstart([ :style = stylewidth("80%") ]) textbox([:name = "username", :style = stylewidth("100%")]) cellend() rowend() rowstart([]) cellstart([ :style = styleheight(30)]) text("Password") cellend() cellstart([]) textbox([:name = "password" , :type = "password"]) cellend() rowend() rowstart([]) cellstart([ :style = styleheight(30) ]) cellend() cellstart([]) submit([:value = "Login" ]) cellend() rowend() tableend() formend() divend() divend() } Screen Shot:
The response page
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web oUser = new UsersModel oUser.Connect() lResult = oUser.FindWith("username",aPageVars["username"]) new page { if lResult if sha256(aPagevars["password"]+oUser.Salt) = oUser.pwhash text ("Correct Password!") aPageVars["sessionid"] = str2hex(randbytes(32)) oUser.UpdateColumn("sessionid",aPageVars["sessionid"]) cookie("sessionid",aPageVars["sessionid"]) else text ("Bad password!") ok else text("Bad User Name!") ok } oUser.Disconnect() The next code for checking if the user needs to login or not
#!ring -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web oUser = new UsersModel oUser.Connect() lResult = oUser.FindWith("sessionid",aPageVars["sessionid"]) new page { if lResult text("User Name : " + oUser.username ) else text("Please Login First!") ok } oUser.Disconnect() Database, ModelBase & ControllerBase classes
In this section we will see some code from datalib.ring
The next code presents the Database, ModelBase & ControllerBase classes
Import System.Web Class Database cServer = "localhost" cUserName = "root" cPassword = "root" cDatabase = "mahdb" Func Connect con = mysql_init() mysql_connect(con, cServer, cUserName, cPassWord,cDatabase) Func Disconnect mysql_close(con) Func Query cQuery mysql_query(con,cQuery) Func QueryResult return mysql_result(con) Func QueryResultWithColumns # return columns names + query result return mysql_result2(con) Func QueryValue aResult = mysql_result(con) if islist(aResult) and len(aResult) >= 1 aResult = aResult[1] if len(aResult) >= 1 return aResult[1] ok ok return 0 Func EscapeString x if isstring(x) return MySQL_Escape_String(con,x) else return MySQL_Escape_String(con,string(x)) ok Private con = NULL Class ModelBase from Database cTableName = "" cSearchColumn = "name" aColumns = [] aQueryResult = [] ID = 0 # set table name from class name classname = lower(classname(self)) if right(classname,5) = :model cTablename = left(classname,len(classname)-5) ok Func Insert cValues = "" for x in aColumns cValues += "'" + EscapeString(aPageVars[x]) + "'," Next cValues = left(cValues,len(cValues)-1) # remove last comma cColumns = "" for x in aColumns cColumns += x + "," next cColumns = left(cColumns,len(cColumns)-1) query("insert into " + cTableName + "("+cColumns+") values (" + cValues + ")" ) Func Update nID cStr = "" for x in aColumns cStr += x + " = '" + EscapeString(aPageVars[x]) + "' , " # the space after comma is necessary Next cStr = left(cStr,len(cStr)-2) query("update " + cTableName + " set " + cStr + " where id = " + nID ) Func UpdateColumn cColumn,cValue query("update " + cTableName + " set " + cColumn + " = '" + EscapeString(cValue) + "' where id = " + self.ID ) Func Count cValue query("SELECT count(*) FROM " + cTableName + " where "+cSearchColumn+" like '" + EscapeString(cValue) + "%'") return queryValue() Func Read nStart,nRecordsPerPage query("SELECT * FROM "+ cTableName+" limit " + EscapeString(nStart) + "," + EscapeString(nRecordsPerPage) ) aQueryResult = queryResult() Func Search cValue,nStart,nRecordsPerPage query("SELECT * FROM "+ cTableName+" where "+cSearchColumn+" like '" + EscapeString(cValue) + "%'" + " limit " + EscapeString(nStart) + "," + EscapeString(nRecordsPerPage) ) aQueryResult = queryResult() Func Find nID query("select * from " + cTableName + " where id = " + EscapeString(nID) ) aResult = queryResult()[1] # move the result from the array to the object attributes ID = nID cCode = "" for x = 2 to len(aResult) cCode += aColumns[x-1] + " = hex2str('" + str2hex(aResult[x]) + "')" + nl next eval(cCode) Func FindWith cColumn,cValue query("select * from " + cTableName + " where "+cColumn+" = '" + EscapeString(cValue) + "'" ) aResult = queryResult() if len(aResult) > 0 aResult = aResult[1] else return 0 ok # move the result from the array to the object attributes ID = aResult[1] cCode = "" for x = 2 to len(aResult) cCode += aColumns[x-1] + " = hex2str('" + str2hex(aResult[x]) + "')" + nl next eval(cCode) return 1 Func Delete ID query("delete from " + cTableName + " where id = " + EscapeString(ID) ) Func Clear cCode = "" for x in aColumns cCode += x + ' = ""' + nl next eval(cCode) Func LoadModel # create the columns array query("SELECT * FROM "+ cTableName + " limit 0,1") aQueryResult = QueryResultWithColumns()[1] for x = 2 to len(aQueryResult) aColumns + lower(trim(aQueryResult[x])) next # create attribute for each column for x in aColumns addattribute(self,x) next Func Connect Super.Connect() if nLoadModel = 0 nLoadModel = 1 LoadModel() ok private nLoadModel = 0 Class ControllerBase nRecordsPerPage = 5 nRecordsCount = 0 nPagesCount = 0 nActivePage = 0 # Dynamic creation of oView = new tablenameView and oModel = new tablename.Model classname = lower(classname(self)) if right(classname,10) = :controller tablename = left(classname,len(classname)-10) cCode = "oView = new " + tablename+"View" + nl cCode += "oModel = new " + tablename+"Model" + nl eval(cCode) oModel.connect() ok cSearchName = "searchname" cPart = "part" cPageError = "The page number is not correct" cLast = "last" cOperation = "operation" cRecID = "recid" aColumnsNames = ["id"] for t in oModel.aColumns aColumnsNames + t next cMainURL = website + "?" func Routing switch aPageVars[cOperation] on NULL showtable() on :add addrecord() on :save saverecord() on :delete deleterecord() on :edit editrecord() on :update updaterecord() off func ShowTable nRecordsCount = oModel.Count( aPageVars[cSearchName] ) nPagesCount = ceil(nRecordsCount / nRecordsPerPage) if aPageVars[cPart] = cLast aPageVars[cPart] = string(nPagesCount) ok nActivePage = number(aPageVars[cPart]) if nActivePage = 0 nActivePage = 1 ok if ( nActivePage > nPagesCount ) and nRecordsCount > 0 ErrorMsg(cPageError) return ok nStart = (nActivePage-1)*nRecordsPerPage if aPageVars[cSearchName] = NULL oModel.Read( nStart,nRecordsPerPage ) else oModel.Search( aPageVars[cSearchName],nStart,nRecordsPerPage ) ok oView.GridView(self) func AddRecord oModel.clear() oView.FormViewAdd(Self,:save,false) # false mean don't include record id func SaveRecord oModel.Insert() oView.SaveView(self) func EditRecord oModel.Find( aPageVars[cRecID] ) oView.FormViewEdit(Self,:update,true) # true mean include record id func UpdateRecord oModel.update( aPageVars[cRecID] ) oView.UpdateView(self) func DeleteRecord oModel.Delete( aPageVars[cRecID] ) oView.DeleteView() func braceend oModel.Disconnect() WebLib API
In this section we will see the web library functions, classes and methods.
Function | Parameters | Description |
|---|---|---|
LoadVars | None | Save the request parameters and cookies to aPageVars List |
WebPage | None | Create new object from the WebPage Class |
BootStrapWebPage | None | Create new object from the BootStrapWebPage Class |
HTMLSpecialChars | cString | Encode Special characters to HTML equivalent |
Template | cFile,oObject | Execute Ring Code in cFile after accessing oObject using {} |
Alert | cMessage | Generate HTML Web Page that display cMessage using JavaScript Alert() |
HTML2PDF | cString | Generate and Display PDF File from HTML String (cString) |
The Package System.Web contains the next classes
Class Name | Description |
|---|---|
Application | Contains methods for Encoding, Decoding, Cookies & More. |
Page | Contains methods to generate HTML pages. |
ScriptFunctions | Contains methods to generate some JavaScript Functions. |
StyleFunctions | Contains methods to generate CSS. |
PageBuffer | Generate HTML Page in memory (don’t print the output). |
HTML2PDF | Generate PDF File from HTML code. |
BootStrapPage | Using BootStrap Library. |
WebPage | Generate page using objects for each element. |
HtmlPage | Like WebPage but doesn’t print the output to stdout. |
BootStrapWebPage | Generate page using objects, using BootStrap Library. |
ObjsBase | Parent Class for page objects. |
NewObjectsFunctions | Methods to create new objects in the page or element. |
H1 | Wraps HTML H1. |
H2 | Wraps HTML H2. |
H3 | Wraps HTML H3. |
H4 | Wraps HTML H4. |
H5 | Wraps HTML H5. |
H6 | Wraps HTML H6. |
P | Wraps HTML P. |
Link | Wraps HTML link. |
NewLine | Wraps HTML NewLine. |
Div | Wraps HTML Div. |
Form | Wraps HTML Form. |
Input | Wraps HTML Input. |
TextArea | Wraps HTML TextArea. |
Select | Wraps HTML Select. |
Option | Wraps HTML Option. |
Image | Wraps HTML Image. |
UL | Wraps HTML UL. |
LI | Wraps HTML LI. |
Table | Wraps HTML Table. |
TR | Wraps HTML TR. |
TD | Wraps HTML TD. |
TH | Wraps HTML TH. |
Audio | Wraps HTML Audio. |
Video | Wraps HTML Video. |
Nav | Wraps HTML Nav. |
Span | Wraps HTML Span. |
Button | Wraps HTML Button. |
Application Class
Method | Parameters | Description |
|---|---|---|
DecodeString | cString | Decode request parameters |
Decode | cString | Decode multipart/form-data |
GetFileName | aArray,cVar | Get File Name in aArray using cVar |
SetCookie | name,value,expires,path,domain,secure | Set Cookie |
Cookie | name,value | Set Cookie using name and value only |
GetCookies | None | Get Cookies |
URLEncode | cString | URL Encode |
ScriptLibs | None | Add JavaScript Libraries like BootStrap |
None | Print Page Content | |
Style | cStyle | Add cStyle to page CSS content |
StartHTML | None | Add HTTP Header to page content |
Redirect | cLocation | Will redirect the webpage |
NoJavaScript | None | Avoid JavaScript links |
The method DecodeString is used to get HTTP request parameters.
The methods Decode and GetFileName are used for uploading files.
The methods SetCookie, Cookie & GetCookies are used for adding and reading cookies.
The methods StartHTML, ScriptsLibs, Style & Print are used for page structure and JS/CSS support.
The method URLEncode is used to encode a URL to be used in HTML pages.
Page Class
Method | Parameters | Description |
|---|---|---|
text | x | add HTMLSpecialChars(x) to page content (accept strings and numbers) |
html | cString | add html code to page content |
h1 | x | add x to page content between <h1> and </h1> |
h2 | x | add x to page content between <h2> and </h2> |
h3 | x | add x to page content between <h3> and </h3> |
h4 | x | add x to page content between <h4> and </h4> |
h5 | x | add x to page content between <h5> and </h5> |
h6 | x | add x to page content between <h6> and </h6> |
p | aPara | HTML <p> </p>, uses aPara List as Hash to get attributes |
NewLine | None | add <br /> to page content |
AddAttributes | aPara | Convert aPara list as hash to HTML element attributes |
Link | aPara | HTML <a href> and </a>, uses aPara List as Hash to get attributes |
Image | aPara | HTML <img>, uses aPara List as Hash to get attributes |
Button | aPara | HTML <input type=”button”>, uses aPara List as Hash to get attributes |
ButtonLink | aPara | HTML <input type=”button”>, uses link attribute to navigate to link |
Textbox | aPara | HTML <input type=”text”>, uses aPara List as Hash to get attributes |
Editbox | aPara | HTML <textarea> and </textarea>, uses aPara to get attributes |
Combobox | aPara | HTML <select>, uses items attribute as list for <option> |
Listbox | aPara | HTML <select multiple=’multiple’>, uses items attribute for <option> |
ulstart | aPara | HTML <ul> |
ulend | aPara | HTML </ul> |
listart | aPara | HTML <li> |
liend | aPara | HTML </li> |
List2UL | aList | Generate HTML <ul> including items from Ring List items |
DivStart | aPara | HTML <div>, uses aPara List as Hash to get attributes |
NavStart | aPara | HTML <nav>, uses aPara List as Hash to get attributes |
SpanStart | aPara | HTML <span>, uses aPara List as Hash to get attributes |
BoxStart | None | Generate Div with black background to be used as page header |
DivEnd | None | HTML </div> |
NavEnd | None | HTML </nav> |
SpanEnd | None | HTML </span> |
BoxEnd | None | HTML </div>, the same as divend() |
FormStart | cAction | HTML <form>, with cAction as the action attribute or an empty value |
FormPost | cAction | HTML <form method=”post”> , with cAction as the action attribute |
FormEnd | None | HTML </form> |
Submit | aPara | HTML <input type=”submit”> |
Hidden | cName,cValue | HTML <input type=”hidden”> |
FormUpload | x | HTML Form, method=”post” enctype=”multipart/form-data” and x = action |
UploadFile | x | HTML <input type=”file”> and name = x |
Video | aPara | HTML <video> |
Audio | aPara | HTML <audio> |
GetColor | aPara | Select Color |
Radio | aPara | HTML <input type=”radio”> |
Checkbox | aPara | HTML <input type=”checkbox”> |
Spinner | aPara | HTML <input type=”number”> |
Slider | aPara | HTML <input type=”range”> |
TableStart | aPara | HTML <table> |
TableEnd | None | HTML </table> |
RowStart | aPara | HTML <tr> |
RowEnd | None | HTML </tr> |
CellStart | aPara | HTML <td> |
CellEnd | None | HTML </td> |
HeaderStart | aPara | HTML <th> |
HeaderEnd | None | HTML </th> |
theadStart | aPara | HTML <thead> |
theadEnd | None | HTML </thead> |
tbodyStart | aPara | HTML <tbody> |
tbodyEnd | None | HTML </tbody> |
tfootStart | aPara | HTML <tfoot> |
tfootEnd | None | HTML </tfoot> |
aPara in the page methods is a list contains attributes and values. Using aPara we can set values for the next attributes
classname id name align style dir value onclick oncontextmenu ondblclick onmousedown onmouseenter onmouseleave onmousemove onmouseover onmouseout onmouseup onkeydown onkeypress onkeyup onabort onbeforeunload onerror onhashchange onload onpageshow onpagehide onresize onscroll onunload onblur onchange onfocus onfocusin onfocusout oninput oninvalid onreset onsearch onselect onsubmit ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop oncopy oncut onpaste onafterprint onbeforeprint oncanplay oncanplaythrough ondurationchange onemptied onended onloadeddata onloadedmetadata onloadstart onpause onplay onplaying onprogress onratechange onseeked onseeking onstalled onsuspend ontimeupdate onvolumechange onwaiting animationend animationiteration animationstart transitionend onmessage onopen onmousewheel ononline onoffline onpostate onshow onstorage ontoggle onwheel ontouchcancel ontouchend ontouchmove ontouchstart color opacity background backgroundattachment backgroundcolor backgroundimage backgroundposition backgroundrepeat backgroundclip backgroundorigin backgroundsize border borderbottom borderbottomcolor borderbottomleftradius borderbottomrightradius borderbottomstyle borderbottomwidth bordercolor borderimage borderimageoutset borderimagerepeat borderimageslice borderimagesource borderimagewidth borderleft borderleftcolor borderleftstyle borderleftwidth borderradius borderright borderrightcolor borderrightstyle borderrightwidth borderstyle bordertop bordertopcolor bordertopleftradius bordertoprightradius bordertopstyle bordertopwidth borderwidth boxdecorationbreak boxshadow bottom clear clip display float height left margin marginbottom marginleft marginright margintop maxheight maxwidth minheight minwidth overflow overflowx overflowy padding paddingbottom paddingleft paddingright paddingtop position right top visibility width verticalalign zindex aligncontent alignitems alignself flex flexbasis flexdirection flexflow flexgrow flexshrink flexwrap justifycontent order hangingpunctuation hyphens letterspacing linebreak lineheight overflowwrap tabsize textalign textalignlast textcombineupright textindent textjustify texttransform whitespace wordbreak wordspacing wordwrap textdecoration textdecorationcolor textdecorationline textdecorationstyle textshadow textunderlineposition @fontface @fontfeaturevalues font fontfamily fontfeaturesettings fontkerning fontlanguageoverride fontsize fontsizeadjust fontstretch fontstyle fontsynthesis fontvariant fontvariantalternates fontvariantcaps fontvarianteastasian fontvariantligatures fontvariantnumeric fontvariantposition fontweight direction textorientation unicodebidi writingmode bordercollapse borderspacing captionside emptycells tablelayout counterincrement counterreset liststyle liststyleimage liststyleposition liststyletype @keyframes animation animationdelay animationdirection animationduration animationfillmode animationiterationcount animationname animationplaystate animationtimingfunction backfacevisibility perspective perspectiveorigin transform transformorigin transformstyle transition transitionproperty transitionduration transitiontimingfunction transitiondelay boxsizing content cursor imemode navdown navindex navleft navright navup outline outlinecolor outlineoffset outlinestyle outlinewidth resize textoverflow breakafter breakbefore breakinside columncount columnfill columngap columnrule columnrulecolor columnrulestyle columnrulewidth columnspan columnwidth columns widows orphans pagebreakafter pagebreakbefore pagebreakinside marks quotes filter imageorientation imagerendering imageresolution objectfit objectposition mask masktype mark markafter markbefore phonemes rest restafter restbefore voicebalance voiceduration voicepitch voicepitchrange voicerate voicestress voicevolume marqueedirection marqueeplaycount marqueespeed marqueestyle datatoggle dataride datatarget dataslideto dataslide datadismiss dataplacement datacontent datatrigger dataspy dataoffset dataoffsettop ScriptFunctions Class
This class contains methods for adding JavaScript code to the generated web page.
The class methods are merged to the Page class, so we can use the next methods with page objects directly.
Method | Parameters | Description |
|---|---|---|
Script | cCode | Add cCode string between <script> and </script> |
ScriptRedirection | cURL | set window.location to cURL |
ScriptFunc | cFuncName,cCode | Define function cFuncName that contains cCode |
ScriptFuncAlert | cFuncName,cMsg | Define function cFuncName that uses alert() to print cMsg |
ScriptFuncAjax | cFuncName,cLink,cDiv | Define function cFuncName that load cLink in cDiv |
ScriptFuncClean | cFuncName,cDiv | Define function cFuncName that clear the cDiv |
ScriptFuncSelect | cF,aL,cD,cR,cGR,cFC,nTO,cL1,cL2 | Used to Edit/Delete Grid Record |
ScriptScrollFixed | cDiv,nSize | Set cDiv as Fixed Div with Size = nSize |
StyleFunctions Class
This class contains methods for adding CSS to the generated web page.
Like ScriptFunctions Class, The StyleFunctions class methods are merged to the Page class, so we can use the next methods with page objects directly.
Method | Parameters | Description |
|---|---|---|
StyleFloatLeft | None | Return float: left ; |
StyleFloatRight | None | Return float: right ; |
StyleSizeFull | None | Return width: 100% ; height: 100% ; |
Stylecolor | x | Return ” color: ” + x + ” ; “ |
Stylebackcolor | x | Return ” background-color: ” + x + ” ;” |
StyleTextCenter | None | Return “text-align: center ;” |
StyleTextRight | None | Return “text-align: right ;” |
StyleTextLeft | None | Return “text-align: left ;” |
StyleSize | x,y | Return ” width: ” + x + ” ; height: ” + y + ” ;” |
StyleWidth | x | Return ” width: ” + x + ” ;” |
StyleHeight | x | Return ” height: ” + x + ” ;” |
StyleTop | x | Return ” top: ” + x + ” ;” |
StyleLeft | x | Return ” Left: ” + x + ” ;” |
StylePos | x,y | Return ” top: ” + x + ” ;” + ” Left: ” + y + ” ;” |
StyleHorizontalCenter | None | Return ” margin-right:auto ; margin-left:auto; “ |
StyleMarginTop | x | Return ” margin-top: ” + x + ” ;” |
StyleMarginRight | x | Return ” margin-right: ” + x + ” ;” |
StyleMarginLeft | x | Return ” margin-left: ” + x + ” ;” |
StyleDivCenter | nWidth,nHeight | Create Div in the center of the page |
StyleAbsolute | None | Return ” position:absolute ;” |
StyleFixed | None | Return ” position:fixed ;” |
StyleZIndex | x | Return ” z-index: ” + x + ” ;” |
StyleFontSize | x | Return ” font-size: ” + x + ” ;” |
StyleGradient | x | Generate Gradient (x values from 1 to 60) |
StyleTable | None | Set table properties |
StyleTableRows | id | Set different color to even and odd rows in the table |
StyleTableNoBorder | None | Return ” border-style: none;” |
WebPage Class
We use braces to access the active WebPage object attributes
Each one of these attribute will return a new object to access again using braces.
Attribute | Description |
|---|---|
H1 | Wraps HTML H1. |
H2 | Wraps HTML H2. |
H3 | Wraps HTML H3. |
H4 | Wraps HTML H4. |
H5 | Wraps HTML H5. |
H6 | Wraps HTML H6. |
P | Wraps HTML P. |
Link | Wraps HTML link. |
NewLine | Wraps HTML NewLine. |
Div | Wraps HTML Div. |
Form | Wraps HTML Form. |
Input | Wraps HTML Input. |
TextArea | Wraps HTML TextArea. |
Select | Wraps HTML Select. |
Option | Wraps HTML Option. |
Image | Wraps HTML Image. |
UL | Wraps HTML UL. |
LI | Wraps HTML LI. |
Table | Wraps HTML Table. |
TR | Wraps HTML TR. |
TD | Wraps HTML TD. |
TH | Wraps HTML TH. |
Audio | Wraps HTML Audio. |
Video | Wraps HTML Video. |
Nav | Wraps HTML Nav. |
Span | Wraps HTML Span. |
Button | Wraps HTML Button. |
THead | Wraps HTML THEAD. |
TBody | Wraps HTML TBODY. |
TFoot | Wraps HTML TFOOT. |
HtmlPage Class
The same as the WebPage class with the next changes
No output to the stdout
Provide the Output Method to get the output
Syntax:
output() ---> The output as string