Custom field set objects can now populate themselves from submitted form data, so they're ready to do the database writes; I've also framed out the saveToDb() function, and completed one of eight branches that need to be written (integer fields which are based on existing records, i.e. updates to existing integer fields). However, a quick test at the end of the day shows this is not working -- no update is done -- although there's no error. Back to this on Monday...
Data is now being submitted for the new or changed custom fields when a new or edited record is saved.
Next I need to add the code to MdhCustomFieldSet which will populate itself from the submitted data (populateFromFormData). The core issue we have is that we don't know exactly what the actual parameter name will look like; we know it'll be "cf.[parentId].[customFieldId].
", but the last component could be either 0 (for a new record), or another integer (if it's a modification to an existing field). I'm not quite sure how to go about finding an item in the $_REQUEST array under these circumstances.
Made a number of adjustments to the custom field set editing output (and also a couple of tweaks to base MdhField descendant output) to achieve the following:
- Container tags are never self-closed; even empty tags have a single space value, which is then stripped out on submission by JavaScript.
- Custom field editing controls are now included in New Record forms. This didn't happen originally because the first incarnation of the code assumed that data instance objects should not be instantiated if there were no existing parent record.
- The parent MdhRecord object's suffix is now passed into the MdhCustomFieldSet object, and used in the generation of id attributes, keeping these fields consistent with existing regular fields.
- The id attribute of a custom field editing control now consists of: 'cf.' + parent record id + '.' + custom field type id + '.' + custom field data instance record id + parent record suffix (example:
cf.13.2.6.4aa941554358a
). This is plenty of data. The only slight wrinkle is that we must avoid having a table in the db called "cf".
The next stage is making the JS submission code do the following:
- Distinguish between regular fields (which it handles now) and custom fields.
- Ignore custom fields which have no existing data instance AND have no actual submission data (empty string values, after trimming).
- Submit the fields which do have value.
Edit fields are now correctly displaying in the context of the editing of an individual record. Had to tweak the CSS quite a lot, and abandon the idea of floating them as I had originally planned, because both the Opera and Webkit engines had difficulty laying out floated fieldsets with max-width settings on their children. Still, the results are OK even with each fieldset as a separate block, and in fact probably more easily parsable.
Next is writing this data back to the database: first constructing the submission in JS, then having the custom field set object populate itself from the submitted fields, and finally having the custom fieldset write itself out in the form of updates and inserts.
In order to write out the custom fields as form elements, I needed to subclass each of the individual field types, because the standard writeAsFormElement()
methods of the MdhField
descendants are really written for normal fields; custom fields have additional wrinkles. Did that, and tested it, and then implemented the GUI functionality for expanding and collapsing field groups, drawing red lines around "should be set" fields, and laying out the field sets. The next stage is calling this functionality in the edit code of a standard record.
Display of existing custom field values is now working as part of the MdhRecord
object. I've also tested integer and long text fields (which are limited to 8000 characters, but that should be enough). There's a significant performance hit when retrieving a record from the database if you retrieve the custom fields as well, because you have to retrieve the list of field types, and then the list of instances for that document record, so I've made the retrieval of custom field instances an optional parameter on populateFromDb*()
methods, which is false by default. This means they'll only be retrieved when a record is being displayed in full (or edited, although the edit code is not written yet).
I simplified some of the adaptive fields code in order to keep both field definitions and instance data in the same array structure, then started work on reading and rendering fields. I'm able to populate data for a given document record, and spit out readable views of the instance fields that exist. Next, I need to work on the edit view, which will require the creation of a formula for generating form field ids that don't clash with anything else.
It occurred to me that rather than trying to highlight a newly-added record, a simpler thing to do would be to ensure the retrieved table scrolls to its end when a new record is added; it's obvious that the new one is the bottom one, and if it's in view, then it's easy to see where you're up to. Added that through simple JavaScript.
Finished the table row highlighting code by adding a new parameter into the sendRequest
JS function, allowing the passing of a function as a parameter; the function is then called with the incoming XHTML node as a parameter, after the new node has been inserted into the document. The only time highlighting doesn't occur right now is when the whole table is replaced, because a new record has been inserted, but I don't think that's crucial because the record inserted is at the bottom of the current row set, so it's obvious which one it is.
JW wants the active row in the record table to be highlighted, so you can easily find it again when you've viewed a record then collapsed it again. I've done half of this, in that the highlighting works for viewing records; however, when you edit a record, the original row is automatically replaced, so the highlighting is lost. There are two options to get around this:
- The
MdhRecordList
object methodwriteRecAsRow
could have an additional parameter foraddHighlighting
, which would be set to true by the callingsave_rec.php
code. - The AJAX library
sendRequest
function could have an optional parameter for a function to call on completion, which it would have to stash in a global variable, thenonReadyState
could call it at the completion of a transaction, and then set it to null again.
The second of these would be more broadly useful, but more tricky to implement.