PDA

View Full Version : Form field copy killing me!



Ruberto
01-31-2007, 03:27 PM
I am trying to write a script that will copy the values from a number of hidden form widgets and then insert the values in normal widgets for the user to edit. I seem to be going in the right direction but I keep getting an error...
(Firefox)
Error: document.choiceForm.elements[element] has no properties
Source File: http://frankentron.freezope.org/update.html
Line: 37

http://frankentron.freezope.org/update.html

I can't seem to find what is causing this. In IE the error is:
document.choiceForm.elements[...].name' is null or not an object.

When I insert an alert to display the value of the above variable I do not see any null values.
I sure could use some help.

Thanks
Ruberto

Ruberto
01-31-2007, 04:05 PM
I think I fixed it. Really silly of me too. I simply changed the two bottom for loops to use < instead of <=. I guess it's hard to kick a habit..


for(element=0; element<document.choiceForm.length; element++){

for(n=0; n<document.choiceForm.length; n++){

Working alright now, the browser hasn't puked up an error yet.

Twey
01-31-2007, 04:31 PM
document.choiceForm.lengthNever use:
document.myform.myelement... it's very non-standard. Instead, use:
document.forms['myform'].elements['myelement']
I am trying to write a script that will copy the values from a number of hidden form widgets and then insert the values in normal widgets for the user to edit. I seem to be going in the right direction but I keep getting an error... May I ask why you're using hidden form elements rather than just a simple array?

Ruberto
01-31-2007, 05:05 PM
Ok, I will change my sloppy syntax. Thanks for the tip.

The explanation will be a bit long.
The reason for the weird usage of hidden forms elements is because the entire form is created by a Python Script. The Python Script first accesses the DB and gets the schema of the table using information_schema.columns (http://dev.mysql.com/doc/refman/5.0/en/columns-table.html). Then the Script decides the type of HTML form widget for each column based on the DATA_TYPE attribute. Now the script accesses the DB again and returns the values for the current record. These values are encoded into hidden form widgets. The form and its HTML table are dynamically constructed with the proper labels, action, etc. etc.

Here is where it gets tricky. The reason the script cannot just render the record values into the form in the first place is because some tables have columns who's values are in a list resulting from the joining of certain columns in 3 different tables. These lists exist as separate objects within my Zope application server. When the form building script encounters a column with a certain DATA_TYPE it will scan the contents of it's container object to see if there is a list object who's ID matches the name of the column. If one is found the script renders the object and inserts it's HTML into the dynamic form. Other objects it will grab from it's container are WYSIWYG editors and Calendars if that matches corresponding DATA_TYPE. The values of "WYSIWYG" columns is actually in HTML. JS puked when I tried to make such values into an array.



The point of all this is the entire web app only uses a small handful of scripts to manage all of it's DB interface and each script will adapt to changes in the schema of every table. The whole system will scale with the needs of the users. If they want more or less columns in the their tables I can change the DB and it's web interface will reflect the changes without needing modification.

Now I have the fun job of modifying this JS to handle checkboxes and lists!!!
Also, I forgot to mention, the values in the hidden widgets will be used for an undo feature after the form has been submitted.

Twey
01-31-2007, 05:39 PM
The values of "WYSIWYG" columns is actually in HTML. JS puked when I tried to make such values into an array.You'll need to do some cleanup on it first, then. Replace "\n" with r"\n", escape quotes, and you should be fine.

You have tested this without JS enabled, right?

Ruberto
01-31-2007, 06:30 PM
I could try that but it's just much simpler to just triple quote the variable in Python. Afterall, what the WYSIWYG editor thinks is proper HTML and what proper HTML actually is are not very related so I think I'll not tamper with the actual value. It's important to keep the WYSIWYG widget happy.


You have tested this without JS enabled, right?

I'm developing for a local intranet now so I don't need to worry much about peoples browser settings. What I say goes...
However, for the most part, JS isn't being used for very much beyond dynamic CSS stuff. My very unrealistic ideal is to keep all business logic in the app server. But there are times...

Ruberto
01-31-2007, 07:49 PM
Alrighty then, here is the code for the curious, since I cannot leave my test page online. Change MyForm to whatever you called your form.


<SCRIPT LANGUAGE="JavaScript">
<!-- Author: M. A. Ruberto -->
//This section of code will copy the values in hidden fields and insert them-
//into a set of editable fields. Name the fields what you like but make sure
//each hidden field has a corresponding editable field next to it.
function getWidgets() //aka caveman
{
var editFields = new Array()
var hiddenFields = new Array()
var j = 0
var k = 0
//caveman hungry...
for(formItems=0; formItems<document.forms['MyForm'].length; formItems++){
var widgets = document.forms['MyForm'].elements[formItems];
if(widgets.type == "button"){
continue
}//caveman not like button
if(widgets.type == "submit"){
continue
}//caveman not like submit
if(widgets.type != "hidden"){
editFields[k] = widgets.name
k++
}//caveman eat everything he sees
if(widgets.type == "hidden"){
hiddenFields[j] = widgets.name
j++
}//caveman eat the hiding ones too
//burp
}
//alert(editFields.toString())
//alert(hiddenFields.toString())
populateFields(editFields, hiddenFields)
}//caveman throw up!

function populateFields(editFields, hiddenFields){
var thisForm = document.forms['MyForm'];
//lets use the hidden list as an index for main loop
for(field=0; field<=hiddenFields.length; field++){
for(element=0; element<thisForm.length; element++){
if(thisForm.elements[element].name == hiddenFields[field]){
var hiddenVal = thisForm.elements[element].value
}//each time through main loop pick the hiding ones from cavemans puke
}
for(n=0; n<thisForm.length; n++){
if(thisForm.elements[n].name == editFields[field]){
thisForm.elements[n].value = hiddenVal
}//each time through main loop assign the hidden to the visible
}


}
}
</SCRIPT>

Add the following to your <BODY> after the </FORM>:


<script type="text/javascript">
<!--
getWidgets();
//-->
</script>

I'm not done adding the ability to handle checkboxes and lists and probably won't get to finish it today. I'll post that revision when I get around to it. Enjoy!

Here is the new code to allow handling of different types of form elements. I got lazy with multiple selects because I don't really use them anyway. I've tested this with a handful of different form pages and so far it all works well. Replace the populateFields() function with the following code.


function populateFields(editFields, hiddenFields){
var thisForm = document.forms['choiceForm'];
//lets use the hidden list as an index for main loop
for(field=0; field<=hiddenFields.length; field++){
for(element=0; element<thisForm.length; element++){
if(thisForm.elements[element].name == hiddenFields[field]){
var hiddenVal = thisForm.elements[element].value
}//each time through main loop pick the hiding ones from cavemans puke
}
for(n=0; n<thisForm.length; n++){
if(thisForm.elements[n].name == editFields[field]){
var widgetType = thisForm.elements[n].type;
//alert(widgetType)
switch(widgetType){
case "checkbox":
if(hiddenVal == 1){
thisForm.elements[n].click()
}
break
case "select-one":
thisForm.elements[n].selectedIndex = hiddenVal
break
case "select-multiple":
thisForm.elements[n].selectedIndex = hiddenVal
break
case "radio":
if(hiddenVal == 1){
thisForm.elements[n].click()
}
break
default: thisForm.elements[n].value = hiddenVal
}

}//each time through main loop assign the hidden to the visible
}


}
}