There are 3 versions of the exact same application.
All 3 function identically.
Version 1 is BOOKS1.CXP
It uses DCFORM DCTABLE, DCHTML, DCINPUT, DCSUBMIT commands to render the HTML.
Version 2 is BOOKS2.CXP
It uses direct HTML tags to render the HTML.
Version 3 is BOOKS3.CXP
It is similar to BOOKS2.CXP except it uses an array of information to configure the browse columns, thus making redesign simpler and less source code.
The buttons in the headers can be clicked to changed the index order.
Enter text in the Seek box to seek a record based on the controlling index.
Click here to run BOOKS1.CXP:
http://donnay-software.com/ds/books1.cxp
Click here to run BOOKS2.CXP
http://donnay-software.com/ds/books2.cxp
Click here to run BOOKS3.CXP
http://donnay-software.com/ds/books3.cxp
I am still brainstorming how to develop the most productive programming environment for CXP-based applications.
DC* commands can be more productive in some cases, such as the invoice system where working with a grid and a coordinate system makes sense.
In this case, however, I can see advantages to using straight HTML, especially because CXP makes it so easy to combine the HTML and Xbase++ code.
My next venture is to try to create a simpler interface to Jquery.
BOOKS1.CXP (180 lines):
Code: Select all
<%#Code locality="page-global"%>
<%
#command WHAT <wtf,...> => M->cWtf := { <wtf> }
#include "dcdialog.ch"
#include "dccxp.ch"
FUNCTION RenderForm( cPath, oForm )
LOCAL GetList := {}, nRecNo, cOrder, oTable, nRows, nRow, cHtml, ;
aTDoption[8], aTHoption[8], cSeekValue, cAction, cSetOrder, ;
cSeekMessage
PUBLIC cWtf := ''
USE (cPath + '\BOOKS') INDEX (cPath + '\BOOKS') VIA 'FOXCDX'
nRows := 30
cAction := oForm:navigate
cSetOrder := oForm:setorder
cSeekValue := oForm:seekValue
cOrder := oForm:order
nRecNo := Val(oForm:recNo)
cSeekMessage := ''
BEGIN SEQUENCE
IF Empty(cOrder) .AND. Empty(cSetOrder)
BOOKS->(OrdSetFocus(0))
ELSEIF !Empty(cSetOrder)
IF cSetOrder = 'Record'
cSetorder := 0
ENDIF
BOOKS->(OrdSetFocus(cSetOrder))
BREAK
ELSEIF !Empty(cOrder)
BOOKS->(OrdSetFocus(cOrder))
ENDIF
IF !Empty(cSeekValue)
IF !BOOKS->(dbSeek(Upper(Trim(cSeekValue))))
BOOKS->(dbGoTo(nRecNo))
cSeekMessage := Upper(Trim(cSeekValue)) + ' not found!'
ENDIF
ELSEIF nRecNo > 0
BOOKS->(dbGoTo(nRecNo))
ENDIF
IF cAction = 'Top'
BOOKS->(dbGoTop())
ELSEIF cAction = 'Previous'
BOOKS->(dbSkip(-nRows))
ELSEIF cAction = 'Next'
BOOKS->(dbSkip(nRows))
ELSEIF cAction = 'Bottom'
BOOKS->(dbGoBottom())
BOOKS->(dbSkip(-nRows))
ENDIF
END SEQUENCE
DCFORM OBJECT oForm METHOD 'POST' ACTION './Books.cxp?submit'
DCSUBMIT VARNAME 'navigate' VALUE 'Top' PARENT oForm COLSPAN 5
DCSUBMIT VARNAME 'navigate' VALUE 'Previous' PARENT oForm
DCSUBMIT VARNAME 'navigate' VALUE 'Next' PARENT oForm
DCSUBMIT VARNAME 'navigate' VALUE 'Bottom' PARENT oForm
DCHTML ' Seek Value' PARENT oForm
DCINPUT VALUE Trim(Upper(cSeekValue)) SIZE 20 VARNAME 'seekValue' PARENT oForm
DCSUBMIT VARNAME 'seek' VALUE 'Seek' PARENT oForm
DCHTML cSeekMessage PARENT oForm OPTIONS 'style="color:red"'
DCTABLE OBJECT oTable ROWS nRows+1 COLUMNS 8 PARENT oForm BORDER 0 CLASS 'dctable'
aTHOption[1] := 'width=100 '
aTHOption[2] := 'width=400 '
aTHOption[3] := 'width=200 '
aTHOption[4] := 'width=200 '
aTHOption[5] := 'width=50 '
aTHOption[6] := 'width=100 '
aTHOption[7] := 'width=50 '
aTHOption[8] := 'width=50 '
IF BOOKS->(OrdSetFocus())='AUTHOR'
aTHOption[1] += 'style="background-color:red"'
aTDOption[1] := 'style="color:darkred"'
ELSEIF BOOKS->(OrdSetFocus())='TITLE'
aTHOption[2] += 'style="background-color:red"'
aTDOption[2] := 'style="color:darkred"'
ELSEIF BOOKS->(OrdSetFocus())='SUBJECT'
aTHOption[6] += 'style="background-color:red"'
aTDOption[6] := 'style="color:darkred"'
ELSEIF Empty(BOOKS->(OrdSetFocus()))
aTHOption[8] += 'style="background-color:red"'
aTDOption[8] := 'style="color:darkred"'
ENDIF
@ DCHTML_TABLE_HEADER, 1 DCSUBMIT VARNAME 'setorder' VALUE 'Author' PARENT oTable ;
OPTIONS 'style="font-size:20px"' ;
TDOPTION aTHOption[1]
@ DCHTML_TABLE_HEADER, 2 DCSUBMIT VARNAME 'setorder' VALUE 'Title' PARENT oTable ;
OPTIONS 'style="font-size:20px"' ;
TDOPTION aTHOption[2]
@ DCHTML_TABLE_HEADER, 3 DCHTML 'Publisher' PARENT oTable TDOPTION aTHOption[3]
@ DCHTML_TABLE_HEADER, 4 DCHTML 'ISBN' PARENT oTable TDOPTION aTHOption[4]
@ DCHTML_TABLE_HEADER, 5 DCHTML 'Year' PARENT oTable TDOPTION aTHOption[4]
@ DCHTML_TABLE_HEADER, 6 DCSUBMIT VARNAME 'setorder' VALUE 'Subject' PARENT oTable ;
OPTIONS 'style="font-size:20px"' ;
TDOPTION aTHOption[6]
@ DCHTML_TABLE_HEADER, 7 DCHTML 'Pages' PARENT oTable TDOPTION aTHOption[7]
@ DCHTML_TABLE_HEADER, 8 DCSUBMIT VARNAME 'setorder' VALUE 'Record' PARENT oTable ;
OPTIONS 'style="font-size:20px"' ;
TDOPTION aTHOption[8]
nRow := 1
nRecNo := BOOKS->(RecNo())
DO WHILE !BOOKS->(Eof())
IF nRow%2 == 0
@ nRow,1 DCHTML '' TROPTIONS 'style="background-color:lightyellow"' PARENT oTable
ENDIF
@ nRow,1 DCHTML Trim(BOOKS->author) PARENT oTable TDOPTION aTDOption[1]
@ nRow,2 DCHTML Trim(BOOKS->title) PARENT oTable TDOPTION aTDOption[2]
@ nRow,3 DCHTML Trim(BOOKS->publisher) PARENT oTable TDOPTION aTDOption[3]
@ nRow,4 DCHTML Trim(BOOKS->isbn) PARENT oTable TDOPTION aTDOption[4]
@ nRow,5 DCHTML Trim(BOOKS->year) PARENT oTable TDOPTION aTDOption[5]
@ nRow,6 DCHTML Trim(BOOKS->subject) PARENT oTable TDOPTION aTDoption[6]
@ nRow,7 DCHTML Trim(BOOKS->pages) PARENT oTable TDOPTION aTDoption[7]
@ nRow,8 DCHTML BOOKS->(RecNo()) PARENT oTable TDOPTION aTDoption[8]
nRow++
IF nRow > nRows
EXIT
ENDIF
BOOKS->(dbSkip())
ENDDO
BOOKS->(dbSkip())
cOrder := BOOKS->(OrdSetFocus())
DCINPUT VARNAME 'recNo' VALUE Alltrim(Str(nRecNo)) TYPE 'HIDDEN' PARENT oForm
DCINPUT VARNAME 'order' VALUE cOrder TYPE 'HIDDEN' PARENT oForm
BOOKS->(dbCloseArea())
DCREAD HTML TO cHtml
RETURN cHtml
%>
<%#Code locality="page-render"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<link rel="stylesheet" type="text/css" href="donnay.css" />
</head>
<body>
<%
cHtml := RenderForm(::physicalPath, ::httpRequest:form )
? M->cWtf
? cHtml
%>
</body>
</html>
Code: Select all
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<link rel="stylesheet" type="text/css" href="donnay.css" />
</head>
<body>
<%
oForm := ::httpRequest:form
aTDoption := Array(8)
aTHoption := Array(8)
AFill(aTDoption,'')
AFill(aTHoption,'')
cPath := ::physicalPath
USE (cPath + '\BOOKS') INDEX (cPath + '\BOOKS') VIA 'FOXCDX'
nRows := 30
cAction := oForm:navigate
cSetOrder := oForm:setorder
cSeekValue := oForm:seekValue
cOrder := oForm:order
nRecNo := Val(oForm:recNo)
cSeekMessage := ''
BEGIN SEQUENCE
IF Empty(cOrder) .AND. Empty(cSetOrder)
BOOKS->(OrdSetFocus(0))
ELSEIF !Empty(cSetOrder)
IF cSetOrder = 'Record'
cSetorder := 0
ENDIF
BOOKS->(OrdSetFocus(cSetOrder))
BREAK
ELSEIF !Empty(cOrder)
BOOKS->(OrdSetFocus(cOrder))
ENDIF
IF !Empty(cSeekValue)
IF !BOOKS->(dbSeek(Upper(Trim(cSeekValue))))
BOOKS->(dbGoTo(nRecNo))
cSeekMessage := Upper(Trim(cSeekValue)) + ' not found!'
ENDIF
ELSEIF nRecNo > 0
BOOKS->(dbGoTo(nRecNo))
ENDIF
IF cAction = 'Top'
BOOKS->(dbGoTop())
ELSEIF cAction = 'Previous'
BOOKS->(dbSkip(-nRows))
ELSEIF cAction = 'Next'
BOOKS->(dbSkip(nRows))
ELSEIF cAction = 'Bottom'
BOOKS->(dbGoBottom())
BOOKS->(dbSkip(-nRows))
ENDIF
END SEQUENCE
aTHOption[1] := 'width=200 '
aTHOption[2] := 'width=400 '
aTHOption[3] := 'width=200 '
aTHOption[4] := 'width=200 '
aTHOption[5] := 'width=50 '
aTHOption[6] := 'width=150 '
aTHOption[7] := 'width=50 '
aTHOption[8] := 'width=50 '
IF BOOKS->(OrdSetFocus())='AUTHOR'
aTHOption[1] += 'style="background-color:darkred"'
aTDOption[1] := 'style="color:darkred"'
ELSEIF BOOKS->(OrdSetFocus())='TITLE'
aTHOption[2] += 'style="background-color:darkred"'
aTDOption[2] := 'style="color:darkred"'
ELSEIF BOOKS->(OrdSetFocus())='SUBJECT'
aTHOption[6] += 'style="background-color:darkred"'
aTDOption[6] := 'style="color:darkred"'
ELSEIF Empty(BOOKS->(OrdSetFocus()))
aTHOption[8] += 'style="background-color:darkred"'
aTDOption[8] := 'style="color:darkred"'
ENDIF
nRecNo := BOOKS->(RecNo())
nRow := 1
%>
<form method='POST' action= './Books_native.cxp?submit'>
<input name='navigate' value='Top' type='Submit'>
<input name='navigate' value='Previous' type='Submit'>
<input name='navigate' value='Next' type='Submit'>
<input name='navigate' value='Bottom' type='Submit'>
Seek Value
<input name='seekValue' value="@(Trim(Upper(cSeekValue)))" size=20>
<input name='seek' value='Seek' type='Submit'>
<b style="color:red">@(cSeekMessage)</b>
<table border=0 class='dctable'>
<tr>
<th @(aTHOption[1])>
<input name='setorder' type='submit' value='Author' style="font-size:20px">
</th>
<th @(aTHOption[2])>
<input name='setorder' type='submit' value='Title' style="font-size:20px">
</th>
<th @(aTHOption[3])>Publisher</th>
<th @(aTHOption[4])>ISBN</th>
<th @(aTHOption[5])>Year</th>
<th @(aTHOption[6])>
<input name='setorder' type='submit' value='Subject' style="font-size:20px">
</th>
<th @(aTHOption[7])>Pages</th>
<th @(aTHOption[8])>
<input name='setorder' type='submit' value='Record' style="font-size:20px">
</th>
</tr>
<%
DO WHILE !BOOKS->(Eof())
%>
<tr @(IIF(nRow%2 == 0, 'style="background-color:lightyellow"','')) >
<td @(aTDOption[1])> @(Trim(BOOKS->author)) </td>
<td @(aTDOption[2])> @(Trim(BOOKS->title)) </td>
<td @(aTDOption[3])> @(Trim(BOOKS->publisher)) </td>
<td @(aTDOption[4])> @(Trim(BOOKS->isbn)) </td>
<td @(aTDOption[5])> @(Trim(BOOKS->year)) </td>
<td @(aTDOption[6])> @(Trim(BOOKS->subject)) </td>
<td @(aTDOption[7])> @(Trim(BOOKS->pages)) </td>
<td @(aTDOption[2])> @(BOOKS->(RecNo())) </td>
</tr>
<%
nRow++
IF nRow > nRows
EXIT
ENDIF
BOOKS->(dbSkip())
ENDDO
cOrder := BOOKS->(OrdSetFocus())
%>
</table>
<input name='recNo' value=@(Alltrim(Str(nRecNo))) type='HIDDEN'>
<input name='order' value="@(cOrder)" type='HIDDEN'>
</form>
@BOOKS->(dbCloseArea())
</body>
</html>
Code: Select all
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<link rel="stylesheet" type="text/css" href="donnay.css" />
</head>
<body>
<%
nRows := 30
aCols := { ;
{'Author',150,'Author',{||BOOKS->author}}, ;
{'Title',400,'Title',{||BOOKS->title}}, ;
{'Publisher',150,nil,{||BOOKS->publisher}}, ;
{'ISBN',150,nil,{||BOOKS->isbn}}, ;
{'Year',50,nil,{||BOOKS->year}}, ;
{'Subject',150,'Subject',{||BOOKS->subject}}, ;
{'Pages',50,nil,{||BOOKS->pages}}, ;
{'Record',50,'',{||BOOKS->(RecNo())}} }
cDatabase := 'BOOKS'
cDbe := 'FOXCDX'
oForm := ::httpRequest:form
aTDoption := Array(Len(aCols))
aTHoption := Array(Len(aCols))
AFill(aTDoption,'')
AFill(aTHoption,'')
cPath := ::physicalPath
USE (cPath + '\' + cDatabase) INDEX (cPath + '\' + cDatabase) VIA (cDbe) NEW
cAlias := Alias()
cAction := oForm:navigate
cSetOrder := oForm:setorder
cSeekValue := oForm:seekValue
cOrder := oForm:order
nRecNo := Val(oForm:recNo)
cSeekMessage := ''
BEGIN SEQUENCE
IF Empty(cOrder) .AND. Empty(cSetOrder)
(cAlias)->(OrdSetFocus(0))
ELSEIF !Empty(cSetOrder)
IF cSetOrder = 'Record'
cSetorder := 0
ENDIF
(cAlias)->(OrdSetFocus(cSetOrder))
BREAK
ELSEIF !Empty(cOrder)
(cAlias)->(OrdSetFocus(cOrder))
ENDIF
IF !Empty(cSeekValue)
IF !(cAlias)->(dbSeek(Upper(Trim(cSeekValue))))
dbGoTo(nRecNo)
cSeekMessage := Upper(Trim(cSeekValue)) + ' not found!'
ENDIF
ELSEIF nRecNo > 0
(cAlias)->(dbGoTo(nRecNo))
ENDIF
IF cAction = 'Top'
(cAlias)->(dbGoTop())
ELSEIF cAction = 'Previous'
(cAlias)->(dbSkip(-nRows))
ELSEIF cAction = 'Next'
(cAlias)->(dbSkip(nRows))
ELSEIF cAction = 'Bottom'
(cAlias)->(dbGoBottom())
(cAlias)->(dbSkip(-nRows))
ENDIF
END SEQUENCE
FOR i := 1 TO Len(aCols)
aTHOption[i] := 'width=' + Alltrim(Str(aCols[i,2]))
IF !(aCols[i,3]==nil) .AND. (cAlias)->(OrdSetFocus()) == Upper(aCols[i,3])
aTHOption[i] += ' style="background-color:darkred"'
aTDOption[i] := ' style="color:darkred"'
ENDIF
NEXT
nRecNo := RecNo()
nRow := 1
%>
<form method='POST' action= './books3.cxp?submit'>
<input name='navigate' value='Top' type='Submit'>
<input name='navigate' value='Previous' type='Submit'>
<input name='navigate' value='Next' type='Submit'>
<input name='navigate' value='Bottom' type='Submit'>
Seek Value
<input name='seekValue' value="@(Trim(Upper(cSeekValue)))" size=20>
<input name='seek' value='Seek' type='Submit'>
<b style="color:red">@(cSeekMessage)</b>
<table border=0 class='dctable'>
<tr>
@FOR i := 1 TO Len(aCols)
<th @(aTHOption[i])>
@IF !(aCols[i,3])==nil
<input name='setorder' type='submit' value=@(aCols[i,1]) style="font-size:20px">
@ELSE
@(aCols[i,1])
@ENDIF
</th>
@NEXT
</tr>
<%
DO WHILE (cAlias)->(!Eof())
%>
<tr @(IIF(nRow%2 == 0, 'style="background-color:lightyellow"','')) >
<% FOR i := 1 TO Len(aCols) %>
<% cData := Eval(aCols[i,4]) %>
<td @(aTDOption[i])> @(cData) </td>
<% NEXT %>
</tr>
<%
nRow++
IF nRow > nRows
EXIT
ENDIF
(cAlias)->(dbSkip())
ENDDO
cOrder := (cAlias)->(OrdSetFocus())
%>
</table>
<input name='recNo' value=@(Alltrim(Str(nRecNo))) type='HIDDEN'>
<input name='order' value="@(cOrder)" type='HIDDEN'>
</form>
@((cAlias)->(dbCloseArea()))
</body>
</html>