Current Version 8.4

Using jQuery Functions

 

Prerequisites

(1) A good understanding of Javascript and jQuery.

(2) Knowledge of the jQuery Widgets :

(3) Familiarity with jQuery Selectors

See https://api.jquery.com/category/selectors/

(4) Familiarity with the DesignBais Basic Functions:

  • REPORT PAGE event - to reset elements on the new OFR page.
  • DBI.G.ID - to get form element IDs.
  • DBI.G.AJXCMD - DRAG, DROP and RESIZE functions.
  • DBMISC event - pre-existing but updated for easier usage.
  • Context Menus - used as an interface to rotate images.

(5) Familiarity with the DesignBais JavaScript Function genericEventCall

This is used to tigger the "dbmisc" event and pass data back to the database. The "dbmisc" event is linked with the database application code PROCESS.EVENT "DBMISC" while the data is returned in PROCESS.PARAMETER.

(6) Familiarity with the CSS Transform Function

This is used to rotate images.

 

Objectives

  • By way of sample forms, investigate the use of the above widgets in a DesignBais form.

 

Analysis

DesignBais includes and utilises the jQuery library. These widgets have always been available. You probably became aware of the functions when we plugged them into Forms Designer.

During the development of the Demo form, it became apparent that a REPORT PAGE event would be necessary and was added. It can also be used to track the displayed page in cases where you wish to return to the same page of an on form report.

The COMMON variable DBAJAXCMD is used to pass javascript / jQuery commands back to the browser. DBI.G.AJXCMD helps with the syntax but your own javascript commands may be issued via this variable - just be aware of our command end marker ";   ".

 

Plan the Tagging of DesignBais Fields for Access by Javascript

We could use "Custom Attributes" to tag fields (as suggested in an earlier blog) but when working with an OFR this could mean a complex grid naming convention for row and column positions. Easier to take advantage of the jQuery class selectors i.e. selecting elements based on their class (DesignBais style or jQuery class).

 

The Demo Form DBDEMO*OFRDRAG

This form contains four on form reports that demonstrate:

  • dragging a Report 1 Description cell to an empty row of Report 2 and moving the data into Report 2.
  • dragging a Report 1 Description cell to the body container of Report 4 and copying data to Report 4.
  • dragging a Report 3 row to a new position within Report 3.
  • resizing Report 1 columns and adding the width change into the next column.
  • dragging Report 3 columns to a new position to re-order the columns.

The form is available in our published DBINET.DEMO account along with the DBLIB routine DBI.I.OFRDRAG containing the supporting code.

 

Construction

1. Add the OFR

Build a normal OFR. The sample uses the data in the demo file DBDEMO.PROD. See the BLD.REP1 internal subroutine.

NB: You will need to track the data in the report so that you can move it to the other reports during the drop function. We use DBOTHER.RECORD(11) for R.REPORT1 data in this example.

2. Set the Description column with the jQuery draggable classes

The jQuery draggable widget will add the classes if you prefer. We are using them in the jQuery selector when setting the draggable widget. The styling also adds our standard dbaisReportBody as per:

OUTPUT.AT<1,ZZ> = 'class="dbaisReportBody ui-draggable ui-draggable-handle"~|padding-left:5px~|alignleft~|cursor:move'

3. Create the Draggable Function for the Description Cells

The jQuery selectors allows for nested references. We are wanting to drag the description cells flagged with the ui-draggable class within the form field R.REPORT1.

The jQuery selector for the cells is 'td[class~="ui-draggable"]' i.e. table data cells with the attribute "class" containing "ui-draggable".

Using DBI.G.ID we can get the DesignBais ID assigned to R.REPORT1:

THIS.NAME = 'R.REPORT1'
CALL DBI.G.ID(THIS.NAME, THIS.TARGET, THIS.ID, THIS.POS)

The full selector becomes:

JQ.SELECT = '#':THIS.ID:' td[class~="ui-draggable"]'
JQ.SELECT = "$('":JQ.SELECT:"')"

Now it is a case of setting up the draggable options and the values required. DBI.G.AJXCMD will put the required JavaScript command together. See the code in DBI.I.OFRDRAG internal subroutine ASSIGN.DRAGGABLE and the jQuery documentation of the options.

We introduced a <div> to the base form with an id="dbdraghelper" which is used to float the dragged cell above the rest of the form.

Don't forget to invoke your ASSIGN.DRAGGABLE after you have built the report.

If you test your form at this point you will be able to drag the description but you have nowhere to drop it.

You will also notice that after paging the report, you will lose the draggable cells.

4. Add REPORT PAGE Event

You may have noticed PROCESS.REPORT<5,nn> at the end of BLD.REP1. If set, you will get a "REPORT PAGE" event in the nominated subroutine.

This is needed so you can invoke ASSIGN.DRAGGABLE to make the description elements on each new page draggable.

5. Add the Target Reports

R.REPORT2 in this example has one empty target row. DBOTHER.RECORD(12) is used to capture the dropped data. See internal subroutine BLD.REP2. The last cell has the ui-droppable class added.

R.REPORT4 has no data initially but DBOTHER.RECORD(14) is used to capture the dropped data. See internal subroutine BLD.REP4. There is no need for any classes to be added as we'll target the report body by ID.

6. Create the Droppable Function

See ASSIGN.DROPPABLE for the R.REPORT2 target.

The jQuery selector for the droppable target cell is similar to the draggable selector 'td[class~="ui-droppable"]' i.e. table data cells with the attribute "class" containing "ui-droppable". In this case only the last empty cell.

Using DBI.G.ID we can get the DesignBais ID assigned to R.REPORT2 detail section:

THIS.NAME = 'R.REPORT2'
THIS.TARGET = "" ;* cleared as it may have been set elsewhere in the code
THIS.ID = "" ;* cleared as it may have been set elsewhere in the code
CALL DBI.G.ID(THIS.NAME, THIS.TARGET, THIS.ID, THIS.POS)

The full selector becomes:

JQ.SELECT = '#':THIS.ID:' td[class~="ui-droppable"]'
JQ.SELECT = "$('":JQ.SELECT:"')"

Now it is a case of setting up the droppable options and the values required. DBI.G.AJXCMD will put the required JavaScript command together. See the code in DBI.I.OFRDRAG internal subroutine ASSIGN.DROPPABLE.

The return event set up is important.

AJX.DATAIN<3,1,-1> = 'drop'
* Get dragged element
DROP.CMDS = 'var draggable = ui.draggable;'
* Set the eventsource to a pipe separated string
* - position 1 = the target report
* - position 2 = the subroutine to call
* - position 3 = use DROP to identify the type of DBMISC event being handled
* - position 4 = the target cell ID
* - position 5 = the dragged element ID
* Trigger drop event in the javascript
DROP.CMDS:= 'var es = "R.REPORT2|DBI.I.OFRDRAG|DROP|" + $(this).attr("id") + "|" + draggable.attr("id");'
DROP.CMDS:= 'genericEventCall(es, "dbmisc");'

Don't forget to invoke your ASSIGN.DROPPABLE after you have built the report.

See REPORT.DROPPABLE for the R.REPORT4 target.

The jQuery selector for the droppable target just uses the R.REPORT4 detail setion.

Using DBI.G.ID we can get the DesignBais ID assigned to R.REPORT4 detail section:

FLD = 'R.REPORT4'
TARG = "D" ;* detail container
ID = ''
CALL DBI.G.ID(FLD,TARG,ID,FPOS)

The full selector becomes:

JQ.SELECT = "$('#":ID:"')"

Now it is a case of setting up the droppable options and the values required. DBI.G.AJXCMD will put the required JavaScript command together. See the code in DBI.I.OFRDRAG internal subroutine ASSIGN.DROPPABLE.

The return event set up is important.

AJX.DATAIN<3,1,-1> = 'drop'
* Get dragged element
DROP.CMDS = 'var draggable = ui.draggable;'
* Set the eventsource to a pipe separated string
* - position 1 = the target report
* - position 2 = the subroutine to call
* - position 3 = use DROP to identify the type of DBMISC event being handled
* - position 4 = the dragged element ID
* Trigger drop event in the javascript
DROP.CMDS:= 'var es = "R.REPORT4|DBI.I.OFRDRAG|DROP|" + draggable.attr("id");'
DROP.CMDS:= 'genericEventCall(es, "dbmisc");'

Don't forget to invoke your REPORT.DROPPABLE after you have built the report.

7. Add the DBMISC Event Logic

As indicated earlier, the EVENTSOURCE will be the first pipe separated segment, the second is the subroutine to be called and the rest are passed in PROCESS.PARAMETER.

The internal subroutine is structured in the same fashion as other DesignBais events.

DBI.G.ID can not only be used to get element ID's from field names but can also get field names from the element ID's.

For OFR cell ID's DBI.G.ID will set DBREPORT.CELL with the row & column.

The process is to extract the field name, update the target report data from the source data and rebuilt the target report. The droppable function will need to be updated as well. This can all be seen in the DBI.I.OFRDRAG routine.

8. Add R.REPORT3 to Re-Order Columns and Drag Rows

We reused the data from R.REPORT1 saved in DBOTHER.RECORD(13). Column details are stored so that they can be easily reordered after a drop event. This report will need a REPORT PAGE event to refresh the draggable and droppable components.

The DRAG.COLUMN internal subroutine shows the logic required to config the header cells. The header elements are targeted both when setting draggable elements and the droppable elements.

The DBMISC event DROP event re-orders the stored column data used to rebuild the report.

The DRAG.ROW internal subroutine targets all rows in the detail section of the report. The DBMISC DRAGROW event reorders the data rows.

9. Allow Resizing of Report 1 Columns

The internal routine ASSIGN.RESIZEABLE walks you through the logic.