Related to 18470: Performance: generate smaller javascript for a window, improve view generation performance
authorMartin Taal <martin.taal@openbravo.com>
Fri, 09 Sep 2011 15:34:14 +0200
changeset 13708 efc85c801356
parent 13707 7fc808fb56f4
child 13709 ab2cb32381f1
Related to 18470: Performance: generate smaller javascript for a window, improve view generation performance
modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml
modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE_DEPENDENCY.xml
modules/org.openbravo.client.application/src/org/openbravo/client/application/personalization/PersonalizationActionHandler.java
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-standard-view-window.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-field.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-grid.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-personalization-form.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFormComponent.java
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewGridComponent.java
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-grid.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-manager.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/classic/ob-classic-compatibility.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-date.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-list.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-minidaterange.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-number.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-section.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-statusbar.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-attachments.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-linked-items.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-notes.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-tab.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-application-menu.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quickrun-widget.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-user-profile-widget.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-popups.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-toolbar.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization-treegrid.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form-toolbar-button.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-keyboard-manager.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-property-store.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-recent-utilities.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml	Fri Sep 09 15:34:14 2011 +0200
@@ -170,7 +170,7 @@
 <!--FF8081812E9F4334012E9F4855820012-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
 <!--FF8081812E9F4334012E9F4855820012-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
 <!--FF8081812E9F4334012E9F4855820012-->  <VALUE><![CDATA[OBUIAPP_RecentDocumentsList]]></VALUE>
-<!--FF8081812E9F4334012E9F4855820012-->  <NAME><![CDATA[OBUIAPP_RecentDocumentsList]]></NAME>
+<!--FF8081812E9F4334012E9F4855820012-->  <NAME><![CDATA[Recent Documents List Setting]]></NAME>
 <!--FF8081812E9F4334012E9F4855820012-->  <DESCRIPTION><![CDATA[Recent documents opened by the user]]></DESCRIPTION>
 <!--FF8081812E9F4334012E9F4855820012-->  <AD_REFERENCE_ID><![CDATA[A26BA480E2014707B47257024C3CBFF7]]></AD_REFERENCE_ID>
 <!--FF8081812E9F4334012E9F4855820012-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
@@ -232,7 +232,7 @@
 <!--FF80818132443EBA01324440CCE80007-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
 <!--FF80818132443EBA01324440CCE80007-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
 <!--FF80818132443EBA01324440CCE80007-->  <VALUE><![CDATA[OBUIAPP_DefaultSavedView]]></VALUE>
-<!--FF80818132443EBA01324440CCE80007-->  <NAME><![CDATA[OBUIAPP_DefaultSavedView]]></NAME>
+<!--FF80818132443EBA01324440CCE80007-->  <NAME><![CDATA[Default View Setting]]></NAME>
 <!--FF80818132443EBA01324440CCE80007-->  <DESCRIPTION><![CDATA[The id of the default view for the user]]></DESCRIPTION>
 <!--FF80818132443EBA01324440CCE80007-->  <AD_REFERENCE_ID><![CDATA[A26BA480E2014707B47257024C3CBFF7]]></AD_REFERENCE_ID>
 <!--FF80818132443EBA01324440CCE80007-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE_DEPENDENCY.xml	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE_DEPENDENCY.xml	Fri Sep 09 15:34:14 2011 +0200
@@ -1,12 +1,13 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <data>
-<!--76A793FCC33848C1835159B8E6C5FCAB--><OBCLKER_TEMPLATE_DEPENDENCY>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <OBCLKER_TEMPLATE_DEPENDENCY_ID><![CDATA[76A793FCC33848C1835159B8E6C5FCAB]]></OBCLKER_TEMPLATE_DEPENDENCY_ID>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <OBCLKER_TEMPLATE_ID><![CDATA[C1D176407A354A40815DC46D24D70EB8]]></OBCLKER_TEMPLATE_ID>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <DEPENDSON_TEMPLATE_ID><![CDATA[33E04D0799794C6F95F05149D2E04E78]]></DEPENDSON_TEMPLATE_ID>
-<!--76A793FCC33848C1835159B8E6C5FCAB-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
-<!--76A793FCC33848C1835159B8E6C5FCAB--></OBCLKER_TEMPLATE_DEPENDENCY>
+<!--FF808181324E2FEC01324E3F2E620015--><OBCLKER_TEMPLATE_DEPENDENCY>
+<!--FF808181324E2FEC01324E3F2E620015-->  <OBCLKER_TEMPLATE_DEPENDENCY_ID><![CDATA[FF808181324E2FEC01324E3F2E620015]]></OBCLKER_TEMPLATE_DEPENDENCY_ID>
+<!--FF808181324E2FEC01324E3F2E620015-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--FF808181324E2FEC01324E3F2E620015-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--FF808181324E2FEC01324E3F2E620015-->  <OBCLKER_TEMPLATE_ID><![CDATA[B5124C0A450D4D3A867AEAC7DF64D6F0]]></OBCLKER_TEMPLATE_ID>
+<!--FF808181324E2FEC01324E3F2E620015-->  <DEPENDSON_TEMPLATE_ID><![CDATA[33E04D0799794C6F95F05149D2E04E78]]></DEPENDSON_TEMPLATE_ID>
+<!--FF808181324E2FEC01324E3F2E620015-->  <DESCRIPTION><![CDATA[Field Template]]></DESCRIPTION>
+<!--FF808181324E2FEC01324E3F2E620015-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--FF808181324E2FEC01324E3F2E620015--></OBCLKER_TEMPLATE_DEPENDENCY>
 
 </data>
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/personalization/PersonalizationActionHandler.java	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/personalization/PersonalizationActionHandler.java	Fri Sep 09 15:34:14 2011 +0200
@@ -26,6 +26,7 @@
 import org.codehaus.jettison.json.JSONObject;
 import org.openbravo.base.exception.OBException;
 import org.openbravo.client.application.UIPersonalization;
+import org.openbravo.client.application.window.OBViewFieldHandler;
 import org.openbravo.client.application.window.OBViewFormComponent;
 import org.openbravo.client.kernel.BaseActionHandler;
 import org.openbravo.dal.core.OBContext;
@@ -61,6 +62,9 @@
   @Inject
   private OBViewFormComponent viewFormComponent;
 
+  @Inject
+  private OBViewFieldHandler fieldHandler;
+
   protected JSONObject execute(Map<String, Object> parameters, String data) {
 
     try {
@@ -94,7 +98,8 @@
       } else if (action.equals(ACTION_FORM)) {
         viewFormComponent.setParameters(parameters);
         viewFormComponent.setTemplateId(TEMPLATE_ID);
-        viewFormComponent.setTab(OBDal.getInstance().get(Tab.class, tabId));
+        fieldHandler.setTab(OBDal.getInstance().get(Tab.class, tabId));
+        viewFormComponent.setFieldHandler(fieldHandler);
         final String formJS = viewFormComponent.generate();
         final JSONObject formProps = new JSONObject(formJS);
         return formProps;
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-standard-view-window.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-standard-view-window.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -17,10 +17,9 @@
  * Contributor(s):  ______________________________________.
  ************************************************************************
 */
+// contains the code for creating a class reflecting the standard window
+// tell the view manager what got loaded...
 -->
-// contains the code for creating a class reflecting the standard window
-//jslint
-// tell the view manager what got loaded...
 OB.Layout.ViewManager.loadedWindowClassName = '${data.windowClientClassName?js_string}';
 
 isc.ClassFactory.defineClass('${data.windowClientClassName?js_string}', isc.OBStandardWindow).addProperties({
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-field.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-field.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -17,93 +17,130 @@
  * Contributor(s):  ______________________________________.
  ************************************************************************
 */
+
+Note, the below template contains many if statements to minimize the output if
+the outputted value is already covered by a default.
 -->
 
-<#macro createField fieldDefinition>
-    {
-        name: '${fieldDefinition.name?js_string}',
-        type: '${fieldDefinition.type}',
-        <#if fieldDefinition.required>
-        required: ${fieldDefinition.required?string},
+<#macro createField field>
+{
+<@compress single_line=true>
+    name: '${field.name?js_string}',
+    <#if field.label != ''>
+        title: '${field.label?js_string}',
+    </#if>
+    <#if field.required>
+        required: ${field.required?string},
+    </#if>
+    <#if field.readOnly>
+        disabled: true,
+    </#if>
+    <#if !field.updatable>
+        updatable: false,
+    </#if>
+    <#if field.sessionProperty>
+        sessionProperty: true,
+    </#if>
+    <#if field.parentProperty>
+        parentProperty: true,
+    </#if>
+    <#if field.showColSpan>
+        colSpan: ${field.colSpan},
+    </#if>
+    <#if field.rowSpan != 1>
+        rowSpan: ${field.rowSpan},
+    </#if>
+    <#if field.showStartRow>
+        startRow: ${field.startRow?string},
+    </#if>
+    <#if field.showEndRow>
+        endRow: ${field.endRow?string},
+    </#if>
+    <#if !field.personalizable>
+        personalizable: false,
+    </#if>
+    <#if field.hasDefaultValue>
+        hasDefaultValue: true,
+    </#if>
+</@compress>
+    <#if field.standardField>
+<@compress single_line=true>
+        <#if field.columnName != ''>
+            columnName: '${field.columnName?string}',
         </#if>
-        <#if fieldDefinition.readOnly>
-        disabled: true,
+        <#if field.inpColumnName != ''>
+            inpColumnName: '${field.inpColumnName?string}',
         </#if>
-        <#if !fieldDefinition.updatable>
-        updatable: false,
+        <#if field.referencedKeyColumnName != ''>
+            referencedKeyColumnName: '${field.referencedKeyColumnName?string}',
         </#if>
-        <#if fieldDefinition.sessionProperty>
-        sessionProperty: true,
+        <#if field.targetEntity != ''>
+            targetEntity: '${field.targetEntity?string}',
         </#if>
-        <#if fieldDefinition.parentProperty>
-        parentProperty: true,
+        <#if !field.displayed>
+            displayed: false,
         </#if>
-        <#if fieldDefinition.colSpan != 1>
-        colSpan: ${fieldDefinition.colSpan},
-        </#if>
-        <#if fieldDefinition.rowSpan != 1>
-        rowSpan: ${fieldDefinition.rowSpan},
-        </#if>
-        <#if fieldDefinition.startRow>
-        startRow: true,
-        </#if>
-        <#if fieldDefinition.endRow>
-        endRow: true,
-        </#if>
-        <#if !fieldDefinition.personalizable>
-        personalizable: false,
-        </#if>
-        <#if fieldDefinition.hasDefaultValue>
-        hasDefaultValue: true,
-        </#if>
-        <#if fieldDefinition.standardField>
-        columnName: '${fieldDefinition.columnName?string}',
-        inpColumnName: '${fieldDefinition.inpColumnName?string}',
-        <#if fieldDefinition.referencedKeyColumnName != ''>
-        referencedKeyColumnName: '${fieldDefinition.referencedKeyColumnName?string}',
-        </#if>
-        <#if fieldDefinition.targetEntity != ''>
-        targetEntity: '${fieldDefinition.targetEntity?string}',
-        </#if>
-        <#if !fieldDefinition.displayed>
-        visible: false,
-        displayed: false,
-        alwaysTakeSpace: false,
-        </#if>
-        <#if fieldDefinition.redrawOnChange && fieldDefinition.displayed>
+        <#if field.redrawOnChange && field.displayed>
             redrawOnChange: true,
         </#if>
-        <#if fieldDefinition.showIf != "" && fieldDefinition.displayed>
-          showIf: function(item, value, form, currentValues, context) {
-            return (${fieldDefinition.showIf});          
-          },          
-          </#if>
-          <#if fieldDefinition.searchField>
-          displayField: '${fieldDefinition.name?js_string}._identifier',
-          valueField: '${fieldDefinition.name?js_string}',
-          showPickerIcon: ${(!fieldDefinition.parentProperty)?string},
-          </#if>
-          <#if fieldDefinition.firstFocusedField>
-          firstFocusedField: true,
-          </#if>
+        <#if field.showIf != "" && field.displayed>
+            showIf: function(item, value, form, currentValues, context) {
+                return (${field.showIf});          
+            },          
         </#if>
-        <#if fieldDefinition.type = "OBSectionItem" || fieldDefinition.type = "OBNoteSectionItem" || fieldDefinition.type = "OBLinkedItemSectionItem"  || fieldDefinition.type = "OBAttachmentsSectionItem" || fieldDefinition.type = "OBAuditSectionItem">
-          <#if !fieldDefinition.displayed>
-          visible: false,
-          </#if>
-        <#if fieldDefinition.expanded>
-        sectionExpanded: ${fieldDefinition.expanded?string},
+        <#if field.searchField>
+            displayField: '${field.name?js_string}._identifier',
+            <#if field.parentProperty>
+                showPickerIcon: ${(!field.parentProperty)?string},
+            </#if>
         </#if>
-        defaultValue: '${fieldDefinition.label?js_string}',
-        <#if fieldDefinition.hasChildren>
-        itemIds: [
-        <#list fieldDefinition.children as childField>
-        '${childField.name?js_string}'<#if childField_has_next>,</#if>
-        </#list>
-        ],
+        <#if field.firstFocusedField>
+            firstFocusedField: true,
         </#if>
+</@compress>
+    </#if>
+    <#if field.type = "OBSectionItem" || field.type = "OBNoteSectionItem" || field.type = "OBLinkedItemSectionItem"  || field.type = "OBAttachmentsSectionItem" || field.type = "OBAuditSectionItem">
+<@compress single_line=true>
+        <#if !field.displayed>
+            displayed: false,
         </#if>
-        ${fieldDefinition.fieldProperties}
-        title: '${fieldDefinition.label?js_string}'
-    }
-</#macro>
+        <#if field.expanded>
+            sectionExpanded: ${field.expanded?string},
+        </#if>
+        <#if field.label != ''>
+            defaultValue: '${field.label?js_string}',
+        </#if>
+        <#if field.hasChildren>
+            itemIds: [
+            <#list field.children as childField>
+            '${childField.name?js_string}'<#if childField_has_next>,</#if>
+            </#list>
+            ],
+        </#if>
+</@compress>
+    </#if>
+    ${field.fieldProperties}
+    <#if field.isGridProperty>
+<@compress single_line=true>
+        gridProps: {
+            sortNum: ${field.gridSort?string},
+            <#if field.autoExpand>
+                autoExpand: ${field.autoExpand?string},
+            </#if>
+            <#if field.cellAlign??>
+                cellAlign: '${field.cellAlign?js_string}',
+            </#if>
+            showIf: '${field.showInitiallyInGrid?string}'<#if field.gridEditorFieldProperties != "">,</#if>
+            <#if field.gridEditorFieldProperties != "">
+                editorProperties: {
+                  ${field.gridEditorFieldProperties}
+                }
+            </#if>
+            ${field.gridFieldProperties}
+            ${field.filterEditorProperties}
+        },
+</@compress>
+    </#if>
+    type: '${field.type}'
+}
+</#macro>
\ No newline at end of file
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -19,38 +19,23 @@
 */
 -->
 {
-    // use theFields instead of fields, when the form
-    // gets created, initialized, the datasource is
-    // set (ob-standard-view.js buildStructure) 
-    // causing re-initialization of the fields,
-    // removing the current ones and recreating new ones
-    // by using theFields, the form initially does not
-    // have fields, which prevents this initial destroy step
-    // Note: this.prepareFormFields is defined in ob-standard-view
-    theFields: this.prepareFormFields([
-    <#list data.fields as field>
-      <@createField field/><#if field_has_next>,</#if>
-    </#list>    
-    ]),
-
-    statusBarFields: [
-    <#list data.statusBarFields as sbf>
-      '${sbf?js_string}'<#if sbf_has_next>,</#if>
-    </#list>
-    ],
-
+    // this this is the view
+    statusBarFields: this.statusBarFields,
+    
+<#--
     // except for the fields all other form properties should be added to the formProperties
     // the formProperties are re-used for inline grid editing
+-->
     obFormProperties: {
       onFieldChanged: function(form, item, value) {
         var f = form || this,
             context = this.view.getContextInfo(false, true),
             currentValues = f.view.getCurrentValues(), otherItem;
-        <#list data.fields as field>
+        <#list data.fieldHandler.fields as field>
         <#if field.readOnlyIf != "">
-            f.handleOtherItem('${field.name}', ${field.readOnlyIf});
+            f.disableItem('${field.name}', ${field.readOnlyIf});
         </#if>
         </#list>
       }
     }
-}
+}
\ No newline at end of file
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-grid.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-grid.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -21,96 +21,23 @@
 
 isc.OBViewGrid.create({
     uiPattern: '${data.uiPattern}', 
-    fields:[
-    <#list data.fields as field>
-        { 
-        autoExpand: ${field.autoExpand}, type: '${field.type}',
-        <#if field.cellAlign??>
-        cellAlign: '${field.cellAlign?js_string}',
-        </#if>
-        editorProperties: {
-          ${field.gridEditorFieldProperties}
-          // note need to be repeated for editor fields
-          , columnName: '${field.columnName?js_string}'
-          , inpColumnName: '${field.inpColumnName?js_string}'
-          , referencedKeyColumnName: '${field.referencedKeyColumnName?js_string}'        
-          , targetEntity: '${field.targetEntity?js_string}'
-          , disabled: ${field.readOnly?string}
-          , readonly: ${field.readOnly?string}
-          , updatable: ${field.updatable?string}
-          <#if field.redrawOnChange?string = "true" >
-          , redrawOnChange: true
-          </#if>
-          <#if field.firstFocusedField>
-          , firstFocusedField: true
-          </#if>          
-          <#if field.showIf != "">
-          , showIf: function(item, value, form, currentValues) {
-              currentValues = currentValues || form.view.getCurrentValues();
-              var context = form.view.getContextInfo(false, true);
-              return context && (${field.showIf});
-            }
-          </#if>
-          
-        }
-        ${field.gridFieldProperties}
-        ${field.filterEditorProperties}
-        , title: '${field.title?js_string}'
-        , prompt: '${field.title?js_string}'
-        , required: ${field.required?string}
-        , escapeHTML: true
-        , showIf: '${field.initialShow?string}'
-        , columnName: '${field.columnName?js_string}'
-        , inpColumnName: '${field.inpColumnName?js_string}'
-        , referencedKeyColumnName: '${field.referencedKeyColumnName?js_string}'        
-        , targetEntity: '${field.targetEntity?js_string}'
-       }
-       <#if field_has_next>,</#if>
-    </#list>
-    <#list data.auditFields as field>
-     ,
-       { 
-        autoExpand: false, type: '${field.type}',
-        editorProperties: {
-          width: '*'
-          , columnName: '${field.columnName?js_string}'
-          , targetEntity: '${field.targetEntity?js_string}'
-          , disabled: true
-          , updatable: false
-        }
-        , showHover: false, 
-        width: isc.OBGrid.getDefaultColumnWidth(30), 
-        name: '${field.columnName?js_string}', 
-        canExport: true, 
-        canHide: true, 
-        editorType: '${field.editorType?js_string}',
-        filterEditorType: '${field.filterEditorType?js_string}',
-        ${field.displayFieldJS}
-         filterOnKeypress: true, canFilter:true, required: false
-        , title: '${field.title?js_string}'
-        , prompt: '${field.title?js_string}'
-        , escapeHTML: true
-        , showIf: 'false'
-        , columnName: '${field.columnName?js_string}'
-        , inpColumnName: ''
-        , targetEntity: '${field.targetEntity?js_string}'
-       }
-    </#list>
-    ],
-    autoExpandFieldNames:[
-    <#list data.autoExpandFields as field>
-        '${field}'<#if field_has_next>,</#if>
-    </#list>
-    ],
-    whereClause: '${data.whereClause?js_string}',
-    orderByClause: '${data.orderByClause?js_string}',
-    sortField: '${data.sortField?js_string}',
-    filterClause: '${data.filterClause?js_string}',
-    filterName: '${data.filterName?js_string}',
+     
+    <#if data.whereClause != "">
+        whereClause: '${data.whereClause?js_string}',
+    </#if>
+    <#if data.orderByClause != "">
+        orderByClause: '${data.orderByClause?js_string}',
+    </#if>
+    <#if data.sortField != "">
+        sortField: '${data.sortField?js_string}',
+    </#if>
+    <#if data.filterClause != "">
+        filterClause: '${data.filterClause?js_string}',
+    </#if>
+    <#if data.filterName != "">
+        filterName: '${data.filterName?js_string}',
+    </#if>
     
-    foreignKeyFieldNames:[
-    <#list data.foreignKeyFields as field>
-        '${field}'<#if field_has_next>,</#if>
-    </#list>
-    ]
+    // the this is the view instance
+    fields: this.gridFields
 })
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-personalization-form.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-personalization-form.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -20,56 +20,58 @@
 -->
 {
     fields: [
-    <#list data.fields as fieldDefinition>
+    <#list data.fieldHandler.fields as field>
       {
-        name: '${fieldDefinition.name?js_string}',
-        title: '${fieldDefinition.label?js_string}',
-        type: '${fieldDefinition.type}',
-        colSpan: ${fieldDefinition.colSpan},
-        rowSpan: ${fieldDefinition.rowSpan},
-        startRow: ${fieldDefinition.startRow?string},
-        endRow: ${fieldDefinition.endRow?string},
-        personalizable: ${fieldDefinition.personalizable?string},
+        name: '${field.name?js_string}',
+        title: '${field.label?js_string}',
+        type: '${field.type}',
+        colSpan: ${field.colSpan},
+        rowSpan: ${field.rowSpan},
+        startRow: ${field.startRow?string},
+        endRow: ${field.endRow?string},
+        personalizable: ${field.personalizable?string},
         isPreviewFormItem: true,
         disabled: true,
         showDisabled: false,
-        <#if !fieldDefinition.displayed>
+        <#if !field.displayed>
         width: '',
         <#else>
         width: '*',
         </#if>
-        <#if fieldDefinition.showIf != "" && fieldDefinition.displayed>
+        <#if field.showIf != "" && field.displayed>
           hasShowIf: true,            
         </#if>
-        <#if fieldDefinition.standardField>
-            <#if !fieldDefinition.displayed>
+        <#if field.standardField>
+            <#if !field.displayed>
                 alwaysTakeSpace: false,
                 displayed: false,
             </#if>
-            required: ${fieldDefinition.required?string},
-            hasDefaultValue: ${fieldDefinition.hasDefaultValue?string},
-            <#if fieldDefinition.searchField>
-                showPickerIcon: ${(!fieldDefinition.parentProperty)?string},
+            required: ${field.required?string},
+            hasDefaultValue: ${field.hasDefaultValue?string},
+            <#if field.searchField>
+                showPickerIcon: ${(!field.parentProperty)?string},
             </#if>
         </#if>
-        <#if fieldDefinition.type = "OBSectionItem" || fieldDefinition.type = "OBNoteSectionItem" || fieldDefinition.type = "OBLinkedItemSectionItem"  || fieldDefinition.type = "OBAttachmentsSectionItem" || fieldDefinition.type = "OBAuditSectionItem">
-          <#if !fieldDefinition.displayed>
+        <#if field.type = "OBSectionItem" || field.type = "OBNoteSectionItem" || field.type = "OBLinkedItemSectionItem"  || field.type = "OBAttachmentsSectionItem" || field.type = "OBAuditSectionItem">
+          <#if !field.displayed>
           visible: false,
           </#if>
-          defaultValue: '${fieldDefinition.label?js_string}',
+          <#if field.hasChildren>
           itemIds: [
-            <#list fieldDefinition.children as childField>
+            <#list field.children as childField>
                 '${childField.name?js_string}'<#if childField_has_next>,</#if>
             </#list>
-            ]
+            ],
+          </#if>
+          defaultValue: '${field.label?js_string}'
         </#if>
     }
-      <#if fieldDefinition_has_next>,</#if>
+      <#if field_has_next>,</#if>
     </#list>    
     ],
 
     statusBarFields: [
-    <#list data.statusBarFields as sbf>
+    <#list data.fieldHandler.statusBarFields as sbf>
       '${sbf?js_string}'<#if sbf_has_next>,</#if>
     </#list>
     ]
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl	Fri Sep 09 15:34:14 2011 +0200
@@ -32,12 +32,19 @@
         moduleId: '${tabComponent.moduleId}',
     </#if>
     
-    defaultEditMode: ${tabComponent.defaultEditMode},
+    <#if tabComponent.defaultEditMode>
+    defaultEditMode: ${tabComponent.defaultEditMode?string},
+    </#if> 
     mapping250: '${tabComponent.mapping250?js_string}',
-    isAcctTab: ${tabComponent.acctTab?string}, 
+    <#if tabComponent.acctTab>
+    isAcctTab: ${tabComponent.acctTab?string},
+    </#if> 
+    <#if tabComponent.trlTab>
     isTrlTab: ${tabComponent.trlTab?string},
+    </#if> 
     
     standardProperties:{
+<@compress single_line=true>
       inpTabId: '${tabComponent.tabId}',
       inpwindowId: '${tabComponent.windowId}',
       inpTableId: '${tabComponent.tableId?js_string}',
@@ -46,10 +53,12 @@
       inpKeyName: '${tabComponent.keyInpName?js_string}',
       keyColumnName: '${tabComponent.keyColumnName?js_string}',
       keyPropertyType: '${tabComponent.keyPropertyType?js_string}'      
+</@compress>
     },
      
     actionToolbarButtons: [
     <#list tabComponent.buttonFields as field>
+<@compress single_line=true>
       {id: '${field.id?js_string}', 
        title: '${field.label?js_string}',
        obManualURL: '${field.url?js_string}',
@@ -75,25 +84,59 @@
        </#if>
        autosave: ${field.autosave?string}
       }<#if field_has_next>,</#if>
+</@compress>
     </#list>],
     
     showParentButtons: ${tabComponent.showParentButtons?string},
     
     buttonsHaveSessionLogic: ${tabComponent.buttonSessionLogic?string},
     
+    fields: [
+    <#list tabComponent.fieldHandler.fields as field>
+      <@createField field/><#if field_has_next>,</#if>
+    </#list>    
+    ],
+    
+    statusBarFields: [
+<@compress single_line=true>
+    <#list tabComponent.fieldHandler.statusBarFields as sbf>
+      '${sbf?js_string}'<#if sbf_has_next>,</#if>
+    </#list>
+</@compress>
+    ],
+    
+    initialPropertyToColumns:[
+    <#list tabComponent.otherFields as field>
+<@compress single_line=true>
+        {
+            property: '${field.propertyName?js_string}',
+            inpColumn: '${field.inpColumnName?js_string}', 
+            dbColumn: '${field.dbColumnName?js_string}',
+            <#if field.session>
+                sessionProperty: ${field.session?string},
+            </#if>
+            type: '${field.type?js_string}'
+        }<#if field_has_next>,</#if>
+</@compress>
+    </#list>
+    ],
+    
     iconToolbarButtons: [
     <#list tabComponent.iconButtons as button>
+<@compress single_line=true>
       {
         action: function(){ ${button.action} },
         buttonType: '${button.type?js_string}',
         prompt: '${button.label?js_string}'
       }<#if button_has_next>,</#if>
+</@compress>
     </#list>],
     
     <#if tabComponent.childTabs?size &gt; 0>
         hasChildTabs: true,
     </#if>
     initWidget: function() {
+        this.prepareFields();
         this.dataSource = ${tabComponent.dataSourceJavaScript};
         this.viewForm = isc.OBViewForm.create(${tabComponent.viewForm}); 
         this.viewGrid = ${tabComponent.viewGrid};
@@ -108,4 +151,4 @@
         );
         </#list>
     }
-</#macro>  
+</#macro>
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFormComponent.java	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFormComponent.java	Fri Sep 09 15:34:14 2011 +0200
@@ -18,30 +18,9 @@
  */
 package org.openbravo.client.application.window;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-import org.openbravo.base.model.Property;
-import org.openbravo.base.model.domaintype.ForeignKeyDomainType;
-import org.openbravo.client.application.ApplicationUtils;
-import org.openbravo.client.application.DynamicExpressionParser;
 import org.openbravo.client.kernel.BaseTemplateComponent;
-import org.openbravo.client.kernel.KernelUtils;
 import org.openbravo.client.kernel.Template;
-import org.openbravo.client.kernel.reference.FKSearchUIDefinition;
-import org.openbravo.client.kernel.reference.UIDefinition;
-import org.openbravo.client.kernel.reference.UIDefinitionController;
 import org.openbravo.dal.service.OBDal;
-import org.openbravo.data.Sqlc;
-import org.openbravo.model.ad.ui.Element;
-import org.openbravo.model.ad.ui.Field;
-import org.openbravo.model.ad.ui.FieldGroup;
-import org.openbravo.model.ad.ui.Tab;
 
 /**
  * The backing bean for generating the OBViewForm client-side representation.
@@ -53,1184 +32,17 @@
 public class OBViewFormComponent extends BaseTemplateComponent {
 
   private static final String TEMPLATE_ID = "C1D176407A354A40815DC46D24D70EB8";
-  private static Logger log = Logger.getLogger(OBViewFormComponent.class);
 
   private String parentProperty;
 
-  private static final long ONE_COLUMN_MAX_LENGTH = 60;
-  private static final String TEXT_AD_REFERENCE_ID = "14";
-  private static final String IMAGEBLOB_AD_REFERENCE_ID = "4AA6C3BE9D3B4D84A3B80489505A23E5";
+  private String templateId = TEMPLATE_ID;
 
-  private static final String AUDIT_GROUP_ID = "1000100001";
-  private static final String MORE_INFO_GROUP_ID = "402880E72F1C15A5012F1C7AA98B00E8";
-
-  private Tab tab;
-  private List<String> statusBarFields = new ArrayList<String>();
-
-  private String templateId = TEMPLATE_ID;
+  private OBViewFieldHandler fieldHandler;
 
   protected Template getComponentTemplate() {
     return OBDal.getInstance().get(Template.class, templateId);
   }
 
-  public Tab getTab() {
-    return tab;
-  }
-
-  public void setTab(Tab tab) {
-    this.tab = tab;
-  }
-
-  public List<OBViewFieldDefinition> getFields() {
-
-    final List<OBViewFieldDefinition> fields = new ArrayList<OBViewFieldDefinition>();
-    final List<Field> adFields = new ArrayList<Field>(tab.getADFieldList());
-    Collections.sort(adFields, new FormFieldComparator());
-
-    final List<Field> fieldsInDynamicExpression = new ArrayList<Field>();
-    final Map<Field, String> displayLogicMap = new HashMap<Field, String>();
-    final Map<Field, String> readOnlyLogicMap = new HashMap<Field, String>();
-
-    // Processing dynamic expressions (display logic)
-    for (Field f : adFields) {
-      if (f.getDisplayLogic() == null || f.getDisplayLogic().equals("") || !f.isActive()
-          || !f.isDisplayed()) {
-        continue;
-      }
-
-      final DynamicExpressionParser parser = new DynamicExpressionParser(f.getDisplayLogic(), tab);
-      displayLogicMap.put(f, parser.getJSExpression());
-
-      log.debug(f.getTab().getId() + " - " + f.getName() + " >>> " + parser.getJSExpression());
-
-      for (Field fieldExpression : parser.getFields()) {
-        if (!fieldsInDynamicExpression.contains(fieldExpression)) {
-          fieldsInDynamicExpression.add(fieldExpression);
-        }
-      }
-    }
-
-    // Processing dynamic expression (read-only logic)
-    for (Field f : adFields) {
-      if (f.getColumn().getReadOnlyLogic() == null || f.getColumn().getReadOnlyLogic().equals("")
-          || !f.isActive() || !f.getColumn().isActive()) {
-        continue;
-      }
-
-      final DynamicExpressionParser parser = new DynamicExpressionParser(f.getColumn()
-          .getReadOnlyLogic(), tab);
-      readOnlyLogicMap.put(f, parser.getJSExpression());
-
-      log.debug(f.getTab().getId() + " - " + f.getName() + " >>> " + parser.getJSExpression());
-
-      for (Field fieldExpression : parser.getFields()) {
-        if (!fieldsInDynamicExpression.contains(fieldExpression)) {
-          fieldsInDynamicExpression.add(fieldExpression);
-        }
-      }
-    }
-
-    // Processing audit fields: if there's field for audit, don't put it in the "more info" section
-    boolean hasCreatedField = false, hasCreatedByField = false, hasUpdatedField = false, hasUpdatedByField = false;
-    for (Field f : adFields) {
-      String dbColName = f.getColumn().getDBColumnName().toLowerCase();
-      if (!dbColName.startsWith("created") && !dbColName.startsWith("updated")) {
-        continue;
-      }
-      if (f.isActive() && f.getColumn().isActive() && (f.isDisplayed() || f.isShownInStatusBar())) {
-        if ("created".equals(dbColName)) {
-          hasCreatedField = true;
-        } else if ("createdby".equals(dbColName)) {
-          hasCreatedByField = true;
-        } else if ("updated".equals(dbColName)) {
-          hasUpdatedField = true;
-        } else if ("updatedby".equals(dbColName)) {
-          hasUpdatedByField = true;
-        }
-      }
-    }
-    List<OBViewFieldDefinition> auditFields = new ArrayList<OBViewFieldDefinition>();
-
-    if (!hasCreatedField) {
-      OBViewFieldAudit audit = new OBViewFieldAudit("creationDate", OBViewUtil.createdElement);
-      auditFields.add(audit);
-    }
-    if (!hasCreatedByField) {
-      OBViewFieldAudit audit = new OBViewFieldAudit("createdBy", OBViewUtil.createdByElement);
-      auditFields.add(audit);
-    }
-    if (!hasUpdatedField) {
-      OBViewFieldAudit audit = new OBViewFieldAudit("updated", OBViewUtil.updatedElement);
-      auditFields.add(audit);
-    }
-    if (!hasUpdatedByField) {
-      OBViewFieldAudit audit = new OBViewFieldAudit("updatedBy", OBViewUtil.updatedByElement);
-      auditFields.add(audit);
-    }
-
-    OBViewFieldGroup currentFieldGroup = null;
-    FieldGroup currentADFieldGroup = null;
-    int colNum = 1;
-    for (Field field : adFields) {
-
-      if (field.getColumn() == null || !field.isActive() || !field.isDisplayed()
-          || ApplicationUtils.isUIButton(field)) {
-        continue;
-      }
-
-      final Property property = KernelUtils.getInstance().getPropertyFromColumn(field.getColumn(),
-          false);
-
-      final OBViewField viewField = new OBViewField();
-      viewField.setField(field);
-      viewField.setProperty(property);
-      viewField.setRedrawOnChange(fieldsInDynamicExpression.contains(field));
-      viewField.setShowIf(displayLogicMap.get(field) != null ? displayLogicMap.get(field) : "");
-      viewField.setReadOnlyIf(readOnlyLogicMap.get(field) != null ? readOnlyLogicMap.get(field)
-          : "");
-      // Positioning some fields in odd-columns
-      if (colNum % 2 == 0 && (field.isStartinoddcolumn() || viewField.getColSpan() == 2)) {
-        final OBViewFieldSpacer spacer = new OBViewFieldSpacer();
-        fields.add(spacer);
-        colNum++;
-        if (colNum > 4) {
-          colNum = 1;
-        }
-      }
-
-      // change in fieldgroup
-      if (field.getFieldGroup() != null && field.getFieldGroup() != currentADFieldGroup) {
-        // start of a fieldgroup use it
-        final OBViewFieldGroup viewFieldGroup = new OBViewFieldGroup();
-        fields.add(viewFieldGroup);
-        viewFieldGroup.setFieldGroup(field.getFieldGroup());
-
-        currentFieldGroup = viewFieldGroup;
-        currentADFieldGroup = field.getFieldGroup();
-        colNum = 1;
-      }
-
-      fields.add(viewField);
-
-      if (currentFieldGroup != null) {
-        currentFieldGroup.addChild(viewField);
-      }
-
-      colNum += viewField.getColSpan();
-      if (colNum > 4) {
-        colNum = 1;
-      }
-    }
-
-    // Add audit info
-    if (!auditFields.isEmpty()) {
-      final OBViewFieldGroup viewFieldGroup = new OBViewFieldGroup();
-      viewFieldGroup.setType("OBAuditSectionItem");
-      viewFieldGroup.setPersonalizable(false);
-      fields.add(viewFieldGroup);
-      viewFieldGroup.setFieldGroup(OBDal.getInstance().get(FieldGroup.class, AUDIT_GROUP_ID));
-      // itemIds are hardcoded in the field type
-      // viewFieldGroup.addChildren(auditFields);
-      fields.addAll(auditFields);
-    }
-
-    // add the notes part
-    final OBViewFieldDefinition notesCanvasFieldDefinition = new NotesCanvasField();
-    final NotesField notesField = new NotesField();
-    // itemIds are hardcoded in the field type
-    // notesField.setChildField(notesCanvasFieldDefinition);
-    fields.add(notesField);
-    fields.add(notesCanvasFieldDefinition);
-
-    // add the linked items part
-    final OBViewFieldDefinition linkedItemsCanvasFieldDefinition = new LinkedItemsCanvasField();
-    final LinkedItemsField linkedItemsField = new LinkedItemsField();
-    // itemIds are hardcoded in the field type
-    // linkedItemsField.setChildField(linkedItemsCanvasFieldDefinition);
-    fields.add(linkedItemsField);
-    fields.add(linkedItemsCanvasFieldDefinition);
-
-    // add the attachments part
-    final AttachmentsCanvasField attachmentsCanvas = new AttachmentsCanvasField();
-    final AttachmentsField attachmentDefinition = new AttachmentsField();
-    // itemIds are hardcoded in the field type
-    // attachmentDefinition.setChildField(attachmentsCanvas);
-    fields.add(attachmentDefinition);
-    fields.add(attachmentsCanvas);
-
-    // add status bar fields
-    processStatusBarFields(fields, adFields);
-
-    return fields;
-  }
-
-  public List<String> getStatusBarFields() {
-    if (statusBarFields == null) {
-      log.warn("Calling getStatusBarFields without initializing fields cache");
-      return Collections.emptyList();
-    }
-    return statusBarFields;
-  }
-
-  private void processStatusBarFields(List<OBViewFieldDefinition> fields, List<Field> adFields) {
-    for (Field field : adFields) {
-
-      if (field.isShownInStatusBar() == null || !field.isShownInStatusBar()) {
-        continue;
-      }
-
-      final Property property = KernelUtils.getInstance().getPropertyFromColumn(field.getColumn(),
-          false);
-
-      statusBarFields.add(property.getName());
-
-      if (field.isDisplayed()) {
-        continue;
-      }
-
-      final OBViewField viewField = new OBViewField();
-      viewField.setField(field);
-      viewField.setProperty(property);
-      viewField.setRedrawOnChange(false);
-      viewField.setShowIf("");
-      viewField.setReadOnlyIf("");
-
-      fields.add(viewField);
-    }
-  }
-
-  private interface OBViewFieldDefinition {
-    public String getLabel();
-
-    public String getName();
-
-    public String getType();
-
-    public boolean getSessionProperty();
-
-    public boolean getStandardField();
-
-    public boolean getPersonalizable();
-
-    public String getFieldProperties();
-
-    public String getInpColumnName();
-
-    public String getReferencedKeyColumnName();
-
-    public String getTargetEntity();
-
-    public boolean getStartRow();
-
-    public boolean getEndRow();
-
-    public long getColSpan();
-
-    public long getRowSpan();
-
-    public boolean getReadOnly();
-
-    public boolean getRequired();
-
-    public boolean getUpdatable();
-
-    public boolean getParentProperty();
-
-    public boolean getRedrawOnChange();
-
-    public String getShowIf();
-
-    public String getReadOnlyIf();
-
-    public boolean isDisplayed();
-
-    public boolean getHasDefaultValue();
-  }
-
-  public class OBViewFieldAudit implements OBViewFieldDefinition {
-    private String name;
-    private String refType;
-    private String refEntity;
-    private Element element;
-
-    public OBViewFieldAudit(String type, Element element) {
-      name = type;
-      this.element = element;
-
-      if (type.endsWith("By")) {
-        // User search
-        refType = "30";
-        refEntity = "User";
-      } else {
-        // Date time
-        refType = "16";
-        refEntity = "";
-      }
-    }
-
-    @Override
-    public String getLabel() {
-      return OBViewUtil.getLabel(element, element.getADElementTrlList());
-    }
-
-    public boolean getSessionProperty() {
-      return false;
-    }
-
-    @Override
-    public String getName() {
-      return name;
-    }
-
-    @Override
-    public String getType() {
-      return "_id_" + refType;
-    }
-
-    @Override
-    public boolean getStandardField() {
-      return true;
-    }
-
-    @Override
-    public String getFieldProperties() {
-      return "";
-    }
-
-    @Override
-    public String getInpColumnName() {
-      return "";
-    }
-
-    @Override
-    public String getReferencedKeyColumnName() {
-      return "";
-    }
-
-    public boolean getHasDefaultValue() {
-      return false;
-    }
-
-    @Override
-    public String getTargetEntity() {
-      return refEntity;
-    }
-
-    @Override
-    public boolean getStartRow() {
-      return false;
-    }
-
-    @Override
-    public boolean getEndRow() {
-      return false;
-    }
-
-    @Override
-    public long getColSpan() {
-      return 1;
-    }
-
-    @Override
-    public long getRowSpan() {
-      return 1;
-    }
-
-    @Override
-    public boolean getReadOnly() {
-      return true;
-    }
-
-    @Override
-    public boolean getUpdatable() {
-      return false;
-    }
-
-    public boolean getPersonalizable() {
-      return false;
-    }
-
-    @Override
-    public boolean getParentProperty() {
-      return false;
-    }
-
-    @Override
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    @Override
-    public String getShowIf() {
-      return "";
-    }
-
-    @Override
-    public String getReadOnlyIf() {
-      return "";
-    }
-
-    public boolean getRequired() {
-      return false;
-    }
-
-    public String getColumnName() {
-      return "";
-    }
-
-    public boolean isFirstFocusedField() {
-      return false;
-    }
-
-    public boolean isSearchField() {
-      return !refEntity.isEmpty();
-    }
-
-    public boolean isDisplayed() {
-      return true;
-    }
-  }
-
-  public class OBViewField implements OBViewFieldDefinition {
-    private Field field;
-    private Property property;
-    private String label;
-    private UIDefinition uiDefinition;
-    private Boolean getParentProperty = null;
-    private boolean redrawOnChange = false;
-    private String showIf = "";
-    private String readOnlyIf = "";
-
-    /**
-     * @deprecated use {@link #setRedrawOnChange(boolean)}
-     */
-    @Deprecated
-    public void setReadrawOnChange(boolean value) {
-      this.setRedrawOnChange(value);
-    }
-
-    public boolean getSessionProperty() {
-      return property.isStoredInSession();
-    }
-
-    public boolean getReadOnly() {
-      return getParentProperty() || field.isReadOnly();
-    }
-
-    public boolean getUpdatable() {
-      return property.isUpdatable();
-    }
-
-    public boolean getPersonalizable() {
-      return true;
-    }
-
-    public boolean getParentProperty() {
-      if (getParentProperty == null) {
-        if (OBViewFormComponent.this.getParentProperty() == null) {
-          getParentProperty = false;
-        } else {
-          getParentProperty = OBViewFormComponent.this.getParentProperty().equals(
-              property.getName());
-        }
-      }
-      return getParentProperty;
-    }
-
-    public boolean isSearchField() {
-      return uiDefinition instanceof FKSearchUIDefinition;
-    }
-
-    public boolean isFirstFocusedField() {
-      Boolean focused = field.isFirstFocusedField();
-      Boolean displayed = field.isDisplayed();
-      return focused != null && focused && displayed != null && displayed;
-    }
-
-    public String getType() {
-      return getUIDefinition().getName();
-    }
-
-    public boolean getHasDefaultValue() {
-      return field.getColumn().getDefaultValue() != null;
-    }
-
-    public String getFieldProperties() {
-
-      String jsonString = getUIDefinition().getFieldProperties(field).trim();
-      if (jsonString == null || jsonString.trim().length() == 0) {
-        return "";
-      }
-      // strip the first and last { }
-      if (jsonString.startsWith("{") && jsonString.endsWith("}")) {
-        // note -2 is done because the first substring takes of 1 already
-        return jsonString.substring(1).substring(0, jsonString.length() - 2) + ",";
-      } else if (jsonString.equals("{}")) {
-        return "";
-      }
-      // be lenient just return the string as it is...
-      return jsonString + (jsonString.trim().endsWith(",") ? "" : ",");
-    }
-
-    private UIDefinition getUIDefinition() {
-      if (uiDefinition != null) {
-        return uiDefinition;
-      }
-      uiDefinition = UIDefinitionController.getInstance().getUIDefinition(property.getColumnId());
-      return uiDefinition;
-    }
-
-    public String getName() {
-      return property.getName();
-    }
-
-    public String getColumnName() {
-      return property.getColumnName();
-    }
-
-    public String getInpColumnName() {
-      return "inp" + Sqlc.TransformaNombreColumna(property.getColumnName());
-    }
-
-    public String getReferencedKeyColumnName() {
-      if (property.isOneToMany() || property.isPrimitive()) {
-        return "";
-      }
-      Property prop;
-      if (property.getReferencedProperty() == null) {
-        prop = property.getTargetEntity().getIdProperties().get(0);
-      } else {
-        prop = property.getReferencedProperty();
-      }
-      return prop.getColumnName();
-    }
-
-    public String getTargetEntity() {
-      if (property.isOneToMany() || property.isPrimitive()) {
-        return "";
-      }
-      return property.getTargetEntity().getName();
-    }
-
-    public String getLabel() {
-      // compute the label
-      if (label == null) {
-        label = OBViewUtil.getLabel(field);
-      }
-      return label;
-    }
-
-    public void setLabel(String label) {
-      this.label = label;
-    }
-
-    public Field getField() {
-      return field;
-    }
-
-    public void setField(Field field) {
-      this.field = field;
-    }
-
-    public boolean getStandardField() {
-      return true;
-    }
-
-    public Property getProperty() {
-      return property;
-    }
-
-    public void setProperty(Property property) {
-      this.property = property;
-    }
-
-    public boolean getRequired() {
-      // booleans are never required as their input only allows 2 values
-      if (property.isBoolean()) {
-        return false;
-      }
-
-      if (field.getColumn() != null) {
-        // Taking value from AD definition, mandatoriness of a column can be different in AD and in
-        // memory model, because memory model sets mandatoriness regarding physical DB definition.
-        return field.getColumn().isMandatory();
-      } else {
-        return property.isMandatory();
-      }
-    }
-
-    public int getLength() {
-      return property.getFieldLength();
-    }
-
-    public boolean getForeignKeyField() {
-      return property.getDomainType() instanceof ForeignKeyDomainType;
-    }
-
-    public String getDataSourceId() {
-      return property.getTargetEntity().getName();
-    }
-
-    public long getColSpan() {
-      if (field.getObuiappColspan() != null) {
-        return field.getObuiappColspan();
-      }
-      return field.getDisplayedLength() > ONE_COLUMN_MAX_LENGTH
-          || (getRowSpan() == 2 && !property.getDomainType().getReference().getId()
-              .equals(IMAGEBLOB_AD_REFERENCE_ID)) ? 2 : 1;
-    }
-
-    public boolean getEndRow() {
-      return false;
-    }
-
-    public long getRowSpan() {
-      if (field.getObuiappRowspan() != null) {
-        return field.getObuiappRowspan();
-      }
-      if (property.getDomainType().getReference().getId().equals(TEXT_AD_REFERENCE_ID)) {
-        return 2;
-      }
-      if (property.getDomainType().getReference().getId().equals(IMAGEBLOB_AD_REFERENCE_ID)) {
-        return 2;
-      }
-      return 1;
-    }
-
-    public boolean getStartRow() {
-      return field.isStartnewline();
-    }
-
-    public void setRedrawOnChange(boolean redrawOnChange) {
-      this.redrawOnChange = redrawOnChange;
-    }
-
-    public boolean getRedrawOnChange() {
-      return redrawOnChange;
-    }
-
-    public void setShowIf(String showIf) {
-      this.showIf = showIf;
-    }
-
-    public String getShowIf() {
-      return showIf;
-    }
-
-    public void setReadOnlyIf(String readOnlyExpression) {
-      this.readOnlyIf = readOnlyExpression;
-    }
-
-    public String getReadOnlyIf() {
-      return readOnlyIf;
-    }
-
-    public boolean isDisplayed() {
-      return field.isDisplayed() != null && field.isDisplayed();
-    }
-  }
-
-  public class DefaultVirtualField implements OBViewFieldDefinition {
-    public boolean getRequired() {
-      return false;
-    }
-
-    public boolean getSessionProperty() {
-      return false;
-    }
-
-    public String getFieldProperties() {
-      return "";
-    }
-
-    public boolean getHasDefaultValue() {
-      return false;
-    }
-
-    public boolean getReadOnly() {
-      return false;
-    }
-
-    public boolean getUpdatable() {
-      return true;
-    }
-
-    public boolean getParentProperty() {
-      return false;
-    }
-
-    public boolean getPersonalizable() {
-      return false;
-    }
-
-    public String getInpColumnName() {
-      return "";
-    }
-
-    public String getReferencedKeyColumnName() {
-      return "";
-    }
-
-    public String getTargetEntity() {
-      return "";
-    }
-
-    public long getColSpan() {
-      return 4;
-    }
-
-    public boolean getEndRow() {
-      return true;
-    }
-
-    public long getRowSpan() {
-      return 1;
-    }
-
-    public boolean getStartRow() {
-      return true;
-    }
-
-    public boolean getStandardField() {
-      return false;
-    }
-
-    public String getLabel() {
-      return "";
-    }
-
-    public String getName() {
-      return "";
-    }
-
-    public String getType() {
-      return "";
-    }
-
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    public String getShowIf() {
-      return "";
-    }
-
-    public String getReadOnlyIf() {
-      return "";
-    }
-
-    public boolean isDisplayed() {
-      return true;
-    }
-  }
-
-  public class OBViewFieldGroup extends DefaultVirtualField {
-
-    private boolean expanded = true;
-    private String type;
-    private FieldGroup fieldGroup;
-    private String label;
-    private List<OBViewFieldDefinition> children = new ArrayList<OBViewFieldDefinition>();
-    private boolean personalizable = true;
-
-    public OBViewFieldGroup() {
-      type = "OBSectionItem";
-    }
-
-    public boolean getPersonalizable() {
-      return personalizable;
-    }
-
-    public String getLabel() {
-      // compute the label
-      if (label == null) {
-        label = OBViewUtil.getLabel(fieldGroup, fieldGroup.getADFieldGroupTrlList());
-      }
-      return label;
-    }
-
-    public void setLabel(String label) {
-      this.label = label;
-    }
-
-    public FieldGroup getFieldGroup() {
-      return fieldGroup;
-    }
-
-    public void setFieldGroup(FieldGroup fieldGroup) {
-      if (AUDIT_GROUP_ID.equals(fieldGroup.getId())
-          || MORE_INFO_GROUP_ID.equals(fieldGroup.getId())) {
-        expanded = false;
-      }
-
-      this.fieldGroup = fieldGroup;
-    }
-
-    public void addChild(OBViewFieldDefinition viewFieldDefinition) {
-      children.add(viewFieldDefinition);
-    }
-
-    public void addChildren(List<OBViewFieldDefinition> viewFieldDefinitions) {
-      children.addAll(viewFieldDefinitions);
-    }
-
-    public boolean getHasChildren() {
-      return !getChildren().isEmpty();
-    }
-
-    public List<OBViewFieldDefinition> getChildren() {
-      return children;
-    }
-
-    public String getType() {
-      return type;
-    }
-
-    public void setType(String type) {
-      this.type = type;
-    }
-
-    public String getName() {
-      return fieldGroup.getId();
-    }
-
-    public boolean getExpanded() {
-      return expanded;
-    }
-
-    public void setExpanded(boolean expanded) {
-      this.expanded = expanded;
-    }
-
-    public boolean isDisplayed() {
-      for (OBViewFieldDefinition child : children) {
-        if (child.isDisplayed()) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    public void setPersonalizable(boolean personalizable) {
-      this.personalizable = personalizable;
-    }
-  }
-
-  public class AttachmentsCanvasField extends DefaultVirtualField {
-
-    public String getName() {
-      return "_attachments_Canvas";
-    }
-
-    public String getType() {
-      return "OBAttachmentCanvasItem";
-    }
-
-  }
-
-  public class AttachmentsField extends DefaultVirtualField {
-
-    private OBViewFieldDefinition childField;
-
-    public String getLabel() {
-      // is set at runtime
-      return "dummy";
-    }
-
-    public boolean getEndRow() {
-      return true;
-    }
-
-    public List<OBViewFieldDefinition> getChildren() {
-      return Collections.singletonList(childField);
-
-    }
-
-    public String getType() {
-      return "OBAttachmentsSectionItem";
-    }
-
-    public boolean getStartRow() {
-      return true;
-    }
-
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    public String getName() {
-      return "_attachments_";
-    }
-
-    public OBViewFieldDefinition getChildField() {
-      return childField;
-    }
-
-    public void setChildField(OBViewFieldDefinition childField) {
-      this.childField = childField;
-    }
-
-    public boolean isExpanded() {
-      return false;
-    }
-  }
-
-  public class LinkedItemsField extends DefaultVirtualField {
-
-    private OBViewFieldDefinition childField;
-
-    public String getLabel() {
-      // is set at runtime
-      return "dummy";
-    }
-
-    public boolean getEndRow() {
-      return true;
-    }
-
-    public List<OBViewFieldDefinition> getChildren() {
-      return Collections.singletonList(childField);
-
-    }
-
-    public String getType() {
-      return "OBLinkedItemSectionItem";
-    }
-
-    public boolean getStartRow() {
-      return true;
-    }
-
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    public String getName() {
-      return "_linkedItems_";
-    }
-
-    public OBViewFieldDefinition getChildField() {
-      return childField;
-    }
-
-    public void setChildField(OBViewFieldDefinition childField) {
-      this.childField = childField;
-    }
-
-    public boolean isExpanded() {
-      return false;
-    }
-  }
-
-  private class LinkedItemsCanvasField extends DefaultVirtualField {
-
-    public String getLabel() {
-      // is set at runtime
-      return "dummy";
-    }
-
-    @SuppressWarnings("unused")
-    public List<OBViewFieldDefinition> getChildren() {
-      return Collections.emptyList();
-    }
-
-    public String getType() {
-      return "OBLinkedItemCanvasItem";
-    }
-
-    public String getName() {
-      return "_linkedItems_Canvas";
-    }
-  }
-
-  public class NotesField extends DefaultVirtualField {
-
-    private OBViewFieldDefinition childField;
-
-    public String getLabel() {
-      // is set at runtime
-      return "dummy";
-    }
-
-    public boolean getEndRow() {
-      return true;
-    }
-
-    public List<OBViewFieldDefinition> getChildren() {
-      return Collections.singletonList(childField);
-
-    }
-
-    public String getType() {
-      return "OBNoteSectionItem";
-    }
-
-    public boolean getStartRow() {
-      return true;
-    }
-
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    public String getName() {
-      return "_notes_";
-    }
-
-    public OBViewFieldDefinition getChildField() {
-      return childField;
-    }
-
-    public void setChildField(OBViewFieldDefinition childField) {
-      this.childField = childField;
-    }
-
-    public boolean isExpanded() {
-      return false;
-    }
-  }
-
-  private class NotesCanvasField extends DefaultVirtualField {
-
-    public String getLabel() {
-      // is set at runtime
-      return "dummy";
-    }
-
-    @SuppressWarnings("unused")
-    public List<OBViewFieldDefinition> getChildren() {
-      return Collections.emptyList();
-    }
-
-    public String getType() {
-      return "OBNoteCanvasItem";
-    }
-
-    public String getName() {
-      return "_notes_Canvas";
-    }
-
-  }
-
-  public class OBViewFieldSpacer implements OBViewFieldDefinition {
-    public boolean getRequired() {
-      return false;
-    }
-
-    public boolean getSessionProperty() {
-      return false;
-    }
-
-    public boolean getPersonalizable() {
-      return false;
-    }
-
-    public boolean getHasDefaultValue() {
-      return false;
-    }
-
-    public long getColSpan() {
-      return 1;
-    }
-
-    public boolean getEndRow() {
-      return false;
-    }
-
-    public boolean getReadOnly() {
-      return false;
-    }
-
-    public boolean getUpdatable() {
-      return true;
-    }
-
-    public boolean getParentProperty() {
-      return false;
-    }
-
-    public String getFieldProperties() {
-      return "";
-    }
-
-    public String getInpColumnName() {
-      return "";
-    }
-
-    public String getLabel() {
-      return "";
-    }
-
-    public String getName() {
-      return "";
-    }
-
-    public String getReferencedKeyColumnName() {
-      return "";
-    }
-
-    public String getTargetEntity() {
-      return "";
-    }
-
-    public long getRowSpan() {
-      return 1;
-    }
-
-    public boolean getStandardField() {
-      return false;
-    }
-
-    public boolean getStartRow() {
-      return false;
-    }
-
-    public String getType() {
-      return "spacer";
-    }
-
-    public boolean getRedrawOnChange() {
-      return false;
-    }
-
-    public String getShowIf() {
-      return "";
-    }
-
-    public String getReadOnlyIf() {
-      return "";
-    }
-
-    public boolean isDisplayed() {
-      return true;
-    }
-
-  }
-
-  public static class FormFieldComparator implements Comparator<Field> {
-
-    /**
-     * Fields with null sequence number are in the bottom of the form. In case multiple null
-     * sequences, it is sorted by field UUID.
-     */
-    @Override
-    public int compare(Field arg0, Field arg1) {
-      Long arg0Position = arg0.getSequenceNumber();
-      Long arg1Position = arg1.getSequenceNumber();
-
-      if (arg0Position == null && arg1Position == null) {
-        return arg0.getId().compareTo(arg1.getId());
-      } else if (arg0Position == null) {
-        return 1;
-      } else if (arg1Position == null) {
-        return -1;
-      }
-
-      return (int) (arg0Position - arg1Position);
-    }
-
-  }
-
   public String getParentProperty() {
     return parentProperty;
   }
@@ -1242,4 +54,12 @@
   public void setTemplateId(String templateId) {
     this.templateId = templateId;
   }
+
+  public OBViewFieldHandler getFieldHandler() {
+    return fieldHandler;
+  }
+
+  public void setFieldHandler(OBViewFieldHandler fieldHandler) {
+    this.fieldHandler = fieldHandler;
+  }
 }
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewGridComponent.java	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewGridComponent.java	Fri Sep 09 15:34:14 2011 +0200
@@ -18,32 +18,17 @@
  */
 package org.openbravo.client.application.window;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.openbravo.base.model.Entity;
 import org.openbravo.base.model.ModelProvider;
-import org.openbravo.base.model.Property;
-import org.openbravo.client.application.ApplicationUtils;
-import org.openbravo.client.application.DynamicExpressionParser;
+import org.openbravo.client.application.window.OBViewFieldHandler.OBViewField;
+import org.openbravo.client.application.window.OBViewFieldHandler.OBViewFieldDefinition;
 import org.openbravo.client.kernel.BaseTemplateComponent;
-import org.openbravo.client.kernel.KernelUtils;
 import org.openbravo.client.kernel.RequestContext;
 import org.openbravo.client.kernel.Template;
-import org.openbravo.client.kernel.reference.StringUIDefinition;
-import org.openbravo.client.kernel.reference.UIDefinition;
-import org.openbravo.client.kernel.reference.UIDefinitionController;
 import org.openbravo.dal.core.DalUtil;
 import org.openbravo.dal.core.OBContext;
 import org.openbravo.dal.service.OBDal;
-import org.openbravo.data.Sqlc;
 import org.openbravo.erpCommon.utility.Utility;
-import org.openbravo.model.ad.ui.Element;
-import org.openbravo.model.ad.ui.Field;
 import org.openbravo.model.ad.ui.Tab;
 import org.openbravo.model.common.order.Order;
 import org.openbravo.model.common.order.OrderLine;
@@ -58,16 +43,12 @@
 public class OBViewGridComponent extends BaseTemplateComponent {
 
   private static final String TEMPLATE_ID = "91DD63545B674BE8801E1FA4F48FF4C6";
-  private static Long ZERO = new Long(0);
 
   private boolean applyTransactionalFilter = false;
   private Tab tab;
   private Entity entity;
-  private List<LocalField> fields = null;
 
-  private final List<Field> fieldsInDynamicExpression = new ArrayList<Field>();
-  private final Map<Field, String> displayLogicMap = new HashMap<Field, String>();
-  private final Map<Field, String> readOnlyLogicMap = new HashMap<Field, String>();
+  private OBViewTab viewTab;
 
   protected Template getComponentTemplate() {
     return OBDal.getInstance().get(Template.class, TEMPLATE_ID);
@@ -103,11 +84,15 @@
     }
 
     long lowestSortno = Long.MAX_VALUE;
-    LocalField sortByField = null;
-    for (LocalField localField : getFields()) {
-      final Long recordSortno = localField.getField().getRecordSortNo();
-      if (localField.isInitialShow() && recordSortno != null && recordSortno < lowestSortno) {
-        sortByField = localField;
+    OBViewField sortByField = null;
+    for (OBViewFieldDefinition localField : getViewTab().getFieldHandler().getFields()) {
+      if (!(localField instanceof OBViewField)) {
+        continue;
+      }
+      final OBViewField viewField = (OBViewField) localField;
+      final Long recordSortno = viewField.getField().getRecordSortNo();
+      if (viewField.isShowInitiallyInGrid() && recordSortno != null && recordSortno < lowestSortno) {
+        sortByField = viewField;
       }
     }
     if (sortByField != null && sortByField.getProperty() != null) {
@@ -122,9 +107,13 @@
       return OrderLine.PROPERTY_LINENO;
     }
 
-    for (LocalField localField : getFields()) {
-      if (localField.getProperty() != null && localField.getProperty().isIdentifier()) {
-        return localField.getProperty().getName();
+    for (OBViewFieldDefinition localField : getViewTab().getFieldHandler().getFields()) {
+      if (!(localField instanceof OBViewField)) {
+        continue;
+      }
+      final OBViewField viewField = (OBViewField) localField;
+      if (viewField.getProperty() != null && viewField.getProperty().isIdentifier()) {
+        return viewField.getProperty().getName();
       }
     }
     return "";
@@ -192,466 +181,6 @@
     return tab.getUIPattern();
   }
 
-  public List<String> getForeignKeyFields() {
-    final List<String> fkFields = new ArrayList<String>();
-    for (LocalField field : getFields()) {
-      if (!field.getProperty().isPrimitive()) {
-        fkFields.add(field.getProperty().getName());
-      }
-    }
-    return fkFields;
-  }
-
-  public List<String> getAutoExpandFields() {
-    List<LocalField> autoExpandFields = new ArrayList<LocalField>();
-    for (LocalField field : getFields()) {
-      if (new Boolean(field.getAutoExpand())) {
-        autoExpandFields.add(field);
-      }
-    }
-    Collections.sort(autoExpandFields, new LengthComparator());
-    List<String> autoExpandFieldsStr = new ArrayList<String>();
-    for (LocalField field : autoExpandFields) {
-      autoExpandFieldsStr.add(field.getProperty().getName());
-    }
-    return autoExpandFieldsStr;
-  }
-
-  private class LengthComparator implements Comparator<LocalField> {
-    @Override
-    public int compare(LocalField o1, LocalField o2) {
-      return o2.getLength().compareTo(o1.getLength());
-    }
-  }
-
-  public List<LocalField> getFields() {
-    if (fields != null) {
-      return fields;
-    }
-    fields = new ArrayList<LocalField>();
-    final List<String> windowEntities = getWindowEntities();
-    final List<Field> sortedFields = new ArrayList<Field>(tab.getADFieldList());
-    Collections.sort(sortedFields, new GridFieldComparator());
-
-    // Processing dynamic expressions (display logic)
-    for (Field f : sortedFields) {
-      if (f.getDisplayLogic() == null || f.getDisplayLogic().equals("") || !f.isActive()
-          || !f.isDisplayed()) {
-        continue;
-      }
-
-      final DynamicExpressionParser parser = new DynamicExpressionParser(f.getDisplayLogic(), tab);
-      displayLogicMap.put(f, parser.getJSExpression());
-
-      for (Field fieldExpression : parser.getFields()) {
-        if (!fieldsInDynamicExpression.contains(fieldExpression)) {
-          fieldsInDynamicExpression.add(fieldExpression);
-        }
-      }
-    }
-
-    // first add the grid fields
-    for (Field fld : sortedFields) {
-      if (fld.isActive() && fld.isShowInGridView()) {
-        final Property prop = KernelUtils.getInstance().getPropertyFromColumn(fld.getColumn());
-        if (prop.isParent() && windowEntities.contains(prop.getTargetEntity().getName())) {
-          continue;
-        }
-        if (prop.isId()) {
-          continue;
-        }
-        if (ApplicationUtils.isUIButton(fld)) {
-          continue;
-        }
-        // these are currently also ignored
-        if (fld.getGridPosition() == null && fld.getSequenceNumber() == null) {
-          continue;
-        }
-
-        fields.add(createLocalField(fld, prop, true));
-      }
-    }
-
-    // Processing dynamic expression (read-only logic)
-    for (Field f : sortedFields) {
-      if (f.getColumn().getReadOnlyLogic() == null || f.getColumn().getReadOnlyLogic().equals("")
-          || !f.isActive() || !f.getColumn().isActive()) {
-        continue;
-      }
-
-      final DynamicExpressionParser parser = new DynamicExpressionParser(f.getColumn()
-          .getReadOnlyLogic(), tab);
-      readOnlyLogicMap.put(f, parser.getJSExpression());
-
-      for (Field fieldExpression : parser.getFields()) {
-        if (!fieldsInDynamicExpression.contains(fieldExpression)) {
-          fieldsInDynamicExpression.add(fieldExpression);
-        }
-      }
-    }
-
-    // and add the non grid fields
-    for (Field fld : sortedFields) {
-      if (fld.isActive() && !fld.isShowInGridView()) {
-        final Property prop = KernelUtils.getInstance().getPropertyFromColumn(fld.getColumn());
-        if (prop.isParent() && windowEntities.contains(prop.getTargetEntity().getName())) {
-          continue;
-        }
-        if (prop.isId()) {
-          continue;
-        }
-        if (ApplicationUtils.isUIButton(fld)) {
-          continue;
-        }
-        fields.add(createLocalField(fld, prop, false));
-      }
-    }
-
-    return fields;
-  }
-
-  public List<AuditLocalField> getAuditFields() {
-    boolean hasCreatedField = false, hasCreatedByField = false, hasUpdatedField = false, hasUpdatedByField = false;
-    for (Field f : tab.getADFieldList()) {
-      String dbColName = f.getColumn().getDBColumnName().toLowerCase();
-      if (!dbColName.startsWith("created") && !dbColName.startsWith("updated")) {
-        continue;
-      }
-      if (f.isActive() && f.getColumn().isActive() && (f.isDisplayed() || f.isShownInStatusBar())) {
-        if ("created".equals(dbColName)) {
-          hasCreatedField = true;
-        } else if ("createdby".equals(dbColName)) {
-          hasCreatedByField = true;
-        } else if ("updated".equals(dbColName)) {
-          hasUpdatedField = true;
-        } else if ("updatedby".equals(dbColName)) {
-          hasUpdatedByField = true;
-        }
-      }
-    }
-
-    List<AuditLocalField> auditFields = new ArrayList<OBViewGridComponent.AuditLocalField>();
-
-    if (!hasCreatedField) {
-      AuditLocalField created = new AuditLocalField("creationDate", OBViewUtil.createdElement);
-      auditFields.add(created);
-    }
-
-    if (!hasCreatedByField) {
-      AuditLocalField createdBy = new AuditLocalField("createdBy", OBViewUtil.createdByElement);
-      auditFields.add(createdBy);
-    }
-
-    if (!hasUpdatedField) {
-      AuditLocalField updated = new AuditLocalField("updated", OBViewUtil.updatedElement);
-      auditFields.add(updated);
-    }
-
-    if (!hasUpdatedByField) {
-      AuditLocalField updatedBy = new AuditLocalField("updatedBy", OBViewUtil.updatedByElement);
-      auditFields.add(updatedBy);
-    }
-    return auditFields;
-  }
-
-  private LocalField createLocalField(Field fld, Property prop, boolean showInitially) {
-    final LocalField localField = new LocalField();
-    localField.setField(fld);
-    localField.setProperty(prop);
-    localField.setUIDefinition(UIDefinitionController.getInstance().getUIDefinition(
-        prop.getColumnId()));
-    if (!prop.isPrimitive()) {
-      localField.setName(prop.getName() + "." + JsonConstants.IDENTIFIER);
-    } else {
-      localField.setName(prop.getName());
-    }
-    localField.setTitle(OBViewUtil.getLabel(fld));
-    localField.setInitialShow(showInitially);
-    localField.setRedrawOnChange(fieldsInDynamicExpression.contains(fld));
-    localField.setShowIf(displayLogicMap.get(fld) != null ? displayLogicMap.get(fld) : "");
-
-    return localField;
-  }
-
-  public class LocalField {
-    private String name;
-    private Field field;
-    private String title;
-    private Property property;
-    private UIDefinition uiDefinition;
-    private boolean initialShow;
-    private String showIf;
-    private boolean redrawOnChange;
-
-    public boolean isFirstFocusedField() {
-      Boolean focused = field.isFirstFocusedField();
-      Boolean displayed = field.isDisplayed();
-      return focused != null && focused && displayed != null && displayed;
-    }
-
-    public String getColumnName() {
-      return property.getColumnName();
-    }
-
-    public boolean isRequired() {
-      // return true;
-      // booleans are never required as their input only allows 2 values
-      if (property.isBoolean()) {
-        return false;
-      }
-
-      if (field.getColumn() != null) {
-        // Taking value from AD definition, mandatoriness of a column can be different in AD and in
-        // memory model, because memory model sets mandatoriness regarding physical DB definition.
-        return field.getColumn().isMandatory();
-      } else {
-        return property.isMandatory();
-      }
-    }
-
-    public boolean isReadOnly() {
-      return field.isReadOnly();
-    }
-
-    public boolean isUpdatable() {
-      return property.isUpdatable();
-    }
-
-    public String getInpColumnName() {
-      return "inp" + Sqlc.TransformaNombreColumna(property.getColumnName());
-    }
-
-    public String getReferencedKeyColumnName() {
-      if (property.isOneToMany() || property.isPrimitive()) {
-        return "";
-      }
-      Property prop;
-      if (property.getReferencedProperty() == null) {
-        prop = property.getTargetEntity().getIdProperties().get(0);
-      } else {
-        prop = property.getReferencedProperty();
-      }
-      return prop.getColumnName();
-    }
-
-    /**
-     * @deprecated use {@link #getGridFieldProperties()}
-     */
-    @Deprecated
-    public String getFieldProperties() {
-      return getGridFieldProperties();
-    }
-
-    public String getGridFieldProperties() {
-      return uiDefinition.getGridFieldProperties(field);
-    }
-
-    public String getTargetEntity() {
-      if (property.getTargetEntity() == null) {
-        return "";
-      }
-      return property.getTargetEntity().getName();
-    }
-
-    public String getGridEditorFieldProperties() {
-      String props = uiDefinition.getGridEditorFieldProperties(field).trim();
-      if (props.startsWith("{")) {
-        props = props.substring(1, props.length() - 1);
-      }
-      if (props.trim().endsWith(",")) {
-        return props.trim().substring(0, props.trim().length() - 1);
-      }
-      if (props.trim().length() == 0) {
-        // return at least a dummy property
-        return "_d: ''";
-      }
-      return props.trim();
-    }
-
-    public String getFilterEditorProperties() {
-      return uiDefinition.getFilterEditorProperties(field);
-    }
-
-    // can the column be auto expanded to fill any remaining space
-    public String getAutoExpand() {
-      return (Boolean.toString(!name.equalsIgnoreCase("documentno")
-          && (uiDefinition instanceof StringUIDefinition || !property.isPrimitive())));
-    }
-
-    public String getName() {
-      return name;
-    }
-
-    public void setName(String name) {
-      this.name = name;
-    }
-
-    public String getTitle() {
-      return title;
-    }
-
-    public void setTitle(String title) {
-      this.title = title;
-    }
-
-    public UIDefinition getUIDefinition() {
-      return uiDefinition;
-    }
-
-    public void setUIDefinition(UIDefinition typeDefinition) {
-      this.uiDefinition = typeDefinition;
-    }
-
-    public String getType() {
-      return uiDefinition.getName();
-    }
-
-    public Field getField() {
-      return field;
-    }
-
-    public void setField(Field field) {
-      this.field = field;
-    }
-
-    public Property getProperty() {
-      return property;
-    }
-
-    public void setProperty(Property property) {
-      this.property = property;
-    }
-
-    public boolean isInitialShow() {
-      return initialShow;
-    }
-
-    public void setInitialShow(boolean initialShow) {
-      this.initialShow = initialShow;
-    }
-
-    public String getShowIf() {
-      return showIf;
-    }
-
-    public void setShowIf(String showIf) {
-      this.showIf = showIf;
-    }
-
-    public boolean isRedrawOnChange() {
-      return redrawOnChange;
-    }
-
-    public void setRedrawOnChange(boolean redrawOnChange) {
-      this.redrawOnChange = redrawOnChange;
-    }
-
-    public Long getLength() {
-      return field.getDisplayedLength();
-    }
-
-    public String getCellAlign() {
-      return uiDefinition.getCellAlign();
-    }
-  }
-
-  public class AuditLocalField extends LocalField {
-
-    private String refType;
-    private String refEntity;
-    private String name;
-    private Element element;
-
-    public AuditLocalField(String type, Element element) {
-      name = type;
-      this.element = element;
-      if (type.endsWith("By")) {
-        // User search
-        refType = "30";
-        refEntity = "User";
-      } else {
-        // Date time
-        refType = "16";
-        refEntity = "";
-      }
-    }
-
-    @Override
-    public String getColumnName() {
-      return name;
-    }
-
-    @Override
-    public String getTargetEntity() {
-      return refEntity;
-    }
-
-    @Override
-    public String getTitle() {
-      return OBViewUtil.getLabel(element, element.getADElementTrlList());
-    }
-
-    @Override
-    public String getType() {
-      return "_id_" + refType;
-    }
-
-    public String getEditorType() {
-      if ("30".equals(refType)) {
-        return "OBSearchItem";
-      } else {
-        return "OBDateItem";
-      }
-    }
-
-    public String getFilterEditorType() {
-      if ("30".equals(refType)) {
-        return "OBFKFilterTextItem";
-      } else {
-        return "OBMiniDateRangeItem";
-      }
-    }
-
-    public String getDisplayFieldJS() {
-      if ("30".equals(refType)) {
-        return "displayField: '" + name + "._identifier',valueField: '" + name + "',";
-      } else {
-        return "";
-      }
-    }
-
-  }
-
-  private class GridFieldComparator implements Comparator<Field> {
-
-    @Override
-    public int compare(Field arg0, Field arg1) {
-      Long arg0Position = (arg0.getGridPosition() != null ? arg0.getGridPosition() : arg0
-          .getSequenceNumber());
-      Long arg1Position = (arg1.getGridPosition() != null ? arg1.getGridPosition() : arg1
-          .getSequenceNumber());
-
-      if (arg0Position == null && arg1Position == null) {
-        return arg0.getId().compareTo(arg1.getId());
-      } else if (arg0Position == null) {
-        return 1;
-      } else if (arg1Position == null) {
-        return -1;
-      }
-
-      return (int) (arg0Position - arg1Position);
-    }
-
-  }
-
-  private List<String> getWindowEntities() {
-    final List<String> windowEntities = new ArrayList<String>();
-    for (Tab localTab : tab.getWindow().getADTabList()) {
-      windowEntities.add(localTab.getTable().getName());
-    }
-    return windowEntities;
-  }
-
   public boolean isApplyTransactionalFilter() {
     return applyTransactionalFilter;
   }
@@ -660,4 +189,12 @@
     this.applyTransactionalFilter = applyTransactionalFilter;
   }
 
+  public OBViewTab getViewTab() {
+    return viewTab;
+  }
+
+  public void setViewTab(OBViewTab viewTab) {
+    this.viewTab = viewTab;
+  }
+
 }
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java	Fri Sep 09 15:34:14 2011 +0200
@@ -21,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -32,7 +33,6 @@
 import org.openbravo.base.model.Property;
 import org.openbravo.client.application.ApplicationUtils;
 import org.openbravo.client.application.DynamicExpressionParser;
-import org.openbravo.client.application.window.OBViewFormComponent.FormFieldComparator;
 import org.openbravo.client.kernel.BaseTemplateComponent;
 import org.openbravo.client.kernel.Component;
 import org.openbravo.client.kernel.ComponentProvider;
@@ -77,6 +77,9 @@
   private boolean isRootTab;
 
   @Inject
+  private OBViewFieldHandler fieldHandler;
+
+  @Inject
   @ComponentProvider.Qualifier(DataSourceConstants.DS_COMPONENT_TYPE)
   private ComponentProvider componentProvider;
 
@@ -93,13 +96,25 @@
     return OBDal.getInstance().get(Template.class, TEMPLATE_ID);
   }
 
+  public OBViewFieldHandler getFieldHandler() {
+    return fieldHandler;
+  }
+
+  public List<OtherField> getOtherFields() {
+    final List<OtherField> otherFields = new ArrayList<OBViewTab.OtherField>();
+    for (Field fld : fieldHandler.getIgnoredFields()) {
+      otherFields.add(new OtherField(fld.getColumn()));
+    }
+    return otherFields;
+  }
+
   public void addChildTabComponent(OBViewTab childTabComponent) {
     childTabComponent.setParentTabComponent(this);
     childTabs.add(childTabComponent);
   }
 
-  public String getDefaultEditMode() {
-    return tab.isDefaultEditMode() == null ? "false" : Boolean.toString(tab.isDefaultEditMode());
+  public boolean getDefaultEditMode() {
+    return tab.isDefaultEditMode() == null ? false : tab.isDefaultEditMode();
   }
 
   public String getMapping250() {
@@ -202,8 +217,8 @@
 
     final OBViewFormComponent viewFormComponent = createComponent(OBViewFormComponent.class);
     viewFormComponent.setParameters(getParameters());
-    viewFormComponent.setTab(tab);
     viewFormComponent.setParentProperty(getParentProperty());
+    viewFormComponent.setFieldHandler(fieldHandler);
     return viewFormComponent.generate();
   }
 
@@ -214,6 +229,7 @@
     final OBViewGridComponent viewGridComponent = createComponent(OBViewGridComponent.class);
     viewGridComponent.setParameters(getParameters());
     viewGridComponent.setTab(tab);
+    viewGridComponent.setViewTab(this);
     viewGridComponent.setApplyTransactionalFilter(isRootTab()
         && this.tab.getWindow().getWindowType().equals("T"));
     return viewGridComponent.generate();
@@ -237,6 +253,7 @@
 
   public void setTab(Tab tab) {
     this.tab = tab;
+    fieldHandler.setTab(tab);
   }
 
   public boolean isTabSet() {
@@ -286,11 +303,11 @@
     this.tabTitle = tabTitle;
   }
 
-  public boolean isAcctTab() {
+  public boolean getAcctTab() {
     return tab.isAccountingTab();
   }
 
-  public boolean isTrlTab() {
+  public boolean getTrlTab() {
     return tab.isTranslationTab();
   }
 
@@ -570,4 +587,55 @@
     return tab.isShowParentsButtons();
   }
 
+  private class FormFieldComparator implements Comparator<Field> {
+
+    /**
+     * Fields with null sequence number are in the bottom of the form. In case multiple null
+     * sequences, it is sorted by field UUID.
+     */
+    @Override
+    public int compare(Field arg0, Field arg1) {
+      Long arg0Position = arg0.getSequenceNumber();
+      Long arg1Position = arg1.getSequenceNumber();
+
+      if (arg0Position == null && arg1Position == null) {
+        return arg0.getId().compareTo(arg1.getId());
+      } else if (arg0Position == null) {
+        return 1;
+      } else if (arg1Position == null) {
+        return -1;
+      }
+
+      return (int) (arg0Position - arg1Position);
+    }
+
+  }
+
+  public class OtherField {
+    private Property property;
+
+    private OtherField(Column col) {
+      this.property = KernelUtils.getInstance().getPropertyFromColumn(col, false);
+    }
+
+    public String getPropertyName() {
+      return property.getName();
+    }
+
+    public String getInpColumnName() {
+      return "inp" + Sqlc.TransformaNombreColumna(property.getColumnName());
+    }
+
+    public String getDbColumnName() {
+      return property.getColumnName();
+    }
+
+    public String getType() {
+      return UIDefinitionController.getInstance().getUIDefinition(property.getColumnId()).getName();
+    }
+
+    public boolean getSession() {
+      return property.isStoredInSession();
+    }
+  }
 }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-grid.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-grid.js	Fri Sep 09 15:34:14 2011 +0200
@@ -206,8 +206,9 @@
   },
   
   cellClick: function (record, rowNum, colNum) {
-    var i, tabId, field = this.getField(colNum);
-    for (i = 0; i < OB.AlertManagement.alertRules.length; i++) {
+    var i, tabId, field = this.getField(colNum),
+      length = OB.AlertManagement.alertRules.length;
+    for (i = 0; i < length; i++) {
       if (OB.AlertManagement.alertRules[i].alertRuleId === record.alertRule) {
         tabId = OB.AlertManagement.alertRules[i].tabId;
       }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-manager.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/alert-management/ob-alert-manager.js	Fri Sep 09 15:34:14 2011 +0200
@@ -70,12 +70,12 @@
     },
 
     _notify : function(rpcResponse, data, rpcRequest) {
-      var i;
+      var i, length = OB.AlertManager.listeners.length;
       // store info for new listeners
       OB.AlertManager.lastResponse = rpcResponse;
       OB.AlertManager.lastData = data;
       OB.AlertManager.lastRequest = rpcRequest;
-      for (i = 0; i < OB.AlertManager.listeners.length; i++) {
+      for (i = 0; i < length; i++) {
         OB.AlertManager.listeners[i](rpcResponse, data, rpcRequest);
       }
       isc.Timer.setTimeout(OB.AlertManager.call, OB.AlertManager.delay);
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/classic/ob-classic-compatibility.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/classic/ob-classic-compatibility.js	Fri Sep 09 15:34:14 2011 +0200
@@ -153,12 +153,12 @@
       // parameters to communicate with the classic OB class
       //
       function getXHRParamsObj(/* String */action, /* Object */ formObject){
-        var paramsObj = {}, i;
+        var paramsObj = {}, i, length = formObject.elements.length;
 
         paramsObj.Command = action;
         paramsObj.IsAjaxCall = '1';
 
-        for (i = 0; i < formObject.elements.length; i++) {
+        for (i = 0; i < length; i++) {
           if (formObject.elements[i].type) {
           var param =  inputValueForms(formObject.elements[i].name, formObject.elements[i]);
 
@@ -233,9 +233,10 @@
       getMDIKS: function(){
         var key, auxKey, action, funcParam, keyMap,
             ClassicKeyJSON = [],
-            LKS = O.KeyboardManager.Shortcuts, i;
+            LKS = O.KeyboardManager.Shortcuts, i,
+            length = LKS.list.length;
 
-        for (i = 0; i < LKS.list.length; i++) {
+        for (i = 0; i < length; i++) {
           auxKey = '';
           if (LKS.list[i].isGlobal) {
             if (LKS.list[i].keyComb.ctrl === true) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-date.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-date.js	Fri Sep 09 15:34:14 2011 +0200
@@ -52,11 +52,15 @@
   dateParts : [],
 
   doInit: function() {
-    var i, dateFormatUpper, index = 0, currentTime;
+    var i, dateFormatUpper, index = 0, 
+      length, currentTime;
+    
     dateFormatUpper = this.dateFormat.toUpperCase();
+    length = dateFormatUpper.length;
     this.dateSeparator = this.dateFormat.toUpperCase().replace(/D/g, '')
         .replace(/M/g, '').replace(/Y/g, '').substr(0, 1);
-    for (i = 0; i < dateFormatUpper.length; i++) {
+    
+    for (i = 0; i < length; i++) {
       if (this.isSeparator(dateFormatUpper, i)) {
         index++;
       } else {
@@ -87,11 +91,13 @@
   },
   
   parseValue: function() {
-    var i, str = this.blurValue(), parts = [ '', '', '' ], partIndex = 0, result;
+    var i, str = this.blurValue(), 
+      length = str.length, 
+      parts = [ '', '', '' ], partIndex = 0, result;
     if (!str || isc.isA.Date(str)) {
       return str;
     }
-    for (i = 0; i < str.length; i++) {
+    for (i = 0; i < length; i++) {
       if (this.isNumber(str, i)) {
         if (this.reachedLength(parts[partIndex], partIndex)) {
           partIndex++;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-list.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-list.js	Fri Sep 09 15:34:14 2011 +0200
@@ -95,9 +95,10 @@
   },
 
   setEntries: function(entries) {
-    var valueField = this.getValueFieldName(), valueMap = {};
+    var length = entries.length,
+      valueField = this.getValueFieldName(), valueMap = {};
     this.entries = [];
-    for (i = 0; i < entries.length; i++) {
+    for (i = 0; i < length; i++) {
       id = entries[i][OB.Constants.ID] || '';
       identifier = entries[i][OB.Constants.IDENTIFIER] || '';
       valueMap[id] = identifier;
@@ -109,8 +110,8 @@
 
   setEntry: function(id, identifier) {
     var i, entries = this.entries || [], entry = {}, valueField = this
-        .getValueFieldName();
-    for (i = 0; i < entries.length; i++) {
+        .getValueFieldName(), length = entries.length;
+    for (i = 0; i < length; i++) {
       if (entries[i][valueField] === id) {
         return;
       }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-minidaterange.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-minidaterange.js	Fri Sep 09 15:34:14 2011 +0200
@@ -315,14 +315,15 @@
   },
   
   updateStoredDates: function() {
-    var value = this.rangeItemValue, i;
+    var value = this.rangeItemValue, i, newValue, length;
     
     if (value) {
       if (isc.DataSource.isAdvancedCriteria(value)) {
         // value has come back as an AdvancedCriteria!
-        var newValue = {};
-
-        for (i = 0; i < value.criteria.length; i++) {
+        newValue = {};
+        length = value.criteria.length;
+          
+        for (i = 0; i < length; i++) {
           var criterion = value.criteria[i];
           if (criterion.operator === 'greaterThan'
               || criterion.operator === 'greaterOrEqual') {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-number.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-number.js	Fri Sep 09 15:34:14 2011 +0200
@@ -36,12 +36,14 @@
   doBlurLogic: true,
   
   init: function(){
+    var length = this.validators.length;
+    
     this.setKeyPressFilter(this.keyPressFilterNumeric);
     this.typeInstance = SimpleType.getType(this.type);
     var newValidators = [], i;
     // get rid of the isFloat validators, as we have 
     // specific validation based on the format definition
-    for (i = 0; i < this.validators.length; i++) {
+    for (i = 0; i < length; i++) {
       if (this.validators[i].type !== 'isFloat') {
         newValidators.push(this.validators[i]);
       }
@@ -531,10 +533,11 @@
   },
   
   buildValueExpressions: function(criterion) {
-    var i = 0, criteria;
+    var i = 0, criteria, length;
     if (criterion && criterion.criteria) {
       criterion = isc.clone(criterion);
-      for (i = 0; i < criterion.criteria.length; i++) {
+      length = criterion.criteria.length;
+      for (i = 0; i < length; i++) {
         criteria = criterion.criteria[i];
         if (criteria.start) {
           criteria.start = this.convertToStringValue(criteria.start);
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-section.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-section.js	Fri Sep 09 15:34:14 2011 +0200
@@ -29,13 +29,19 @@
   // visual state of disabled or non-disabled stays the same now
   showDisabled: false,
 
+  // some defaults, note if this changes then also the 
+  // field generation logic needs to be checked
+  colSpan: 4, 
+  startRow: true, 
+  endRow: true,
+  
   canTabToHeader: true,
   
   alwaysTakeSpace: false,
 
   setSectionItemInContent: function(form) {
-    var i = 0;
-    for (i = 0; i < this.itemIds.length; i++) {
+    var i = 0, length = this.itemIds.length;
+    for (i = 0; i < length; i++) {
       if (form.getItem(this.itemIds[i])) {
         form.getItem(this.itemIds[i]).section = this;
       }
@@ -50,9 +56,9 @@
   // Update the property alwaysTakeSpace when collapsing/expanding a section
   // Note: The hidden fields are not updated, they always have alwaysTakeSpace to false
   updateAlwaysTakeSpace: function(flag) {
-    var i, f = this.form, item;
+    var i, f = this.form, item, length = this.itemIds.length;
 
-    for(i = 0; i < this.itemIds.length; i++) {
+    for(i = 0; i < length; i++) {
       item = f.getItem(this.itemIds[i]);
       if (item) {
         // note different cases can occur, these properties may be set, maybe
@@ -109,8 +115,8 @@
   },
 
   setNewFocusItemExpanding: function(){
-    var newFocusItem = null, i;
-    for (i = 0; i < this.itemIds.length; i++) {
+    var newFocusItem = null, i, length = this.itemIds.length;
+    for (i = 0; i < length; i++) {
       var itemName = this.itemIds[i], item = this.form.getItem(itemName);
       // isFocusable is a method added in ob-smartclient.js
       if (item.isFocusable()) {
@@ -128,13 +134,15 @@
   },
 
   showIf: function(item, value, form, values) {
-    var i, field;
+    var i, field, length;
 
     if(!this.itemIds) {
       return false;
     }
-
-    for (i = 0; i < this.itemIds.length; i++) {
+    
+    length = this.itemIds.length;
+    
+    for (i = 0; i < length; i++) {
       field = form.getItem(this.itemIds[i]);
 
       if(!field || (item.visible === false || item.displayed === false || item.hiddenInForm === true)) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-statusbar.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-statusbar.js	Fri Sep 09 15:34:14 2011 +0200
@@ -75,7 +75,7 @@
   },
 
   doAction : function() {
-    var rowNum, newRowNum, newRecord, theButtonBar, i;
+    var rowNum, newRowNum, newRecord, theButtonBar, i, length;
     if (this.buttonType === 'previous') {
       this.view.editNextPreviousRecord(false);
     } else if (this.buttonType === 'maximize') {
@@ -96,7 +96,8 @@
     } else if (this.buttonType === 'maximizeRestore') {
       theButtonBar = this.view.statusBar.buttonBar;
       if (theButtonBar.members) {
-        for (i = 0; i < theButtonBar.members.length; i++) {
+        length = theButtonBar.members.length;
+        for (i = 0; i < length; i++) {
           if (theButtonBar.members[i].buttonType === 'maximize' && !theButtonBar.members[i].isDisabled() && theButtonBar.members[i].isVisible()) {
             theButtonBar.members[i].action();
             break;
@@ -189,6 +190,9 @@
   },
   
   addCreateButtons: function() {
+    var buttonSpacer = isc.HLayout.create( {
+        width : this.iconButtonGroupSpacerWidth
+      }), i, length;
 
     this.previousButton = isc.OBStatusBarIconButton.create( {
       view : this.view,
@@ -196,29 +200,34 @@
       keyboardShortcutId : 'StatusBar_Previous',
       prompt : OB.I18N.getLabel('OBUIAPP_PREVIOUSBUTTON')
     });
+    
     this.nextButton = isc.OBStatusBarIconButton.create( {
       view : this.view,
       buttonType : 'next',
       keyboardShortcutId : 'StatusBar_Next',
       prompt : OB.I18N.getLabel('OBUIAPP_NEXTBUTTON')
     });
+    
     this.closeButton = isc.OBStatusBarIconButton.create( {
       view : this.view,
       buttonType : 'close',
       keyboardShortcutId : 'StatusBar_Close',
       prompt : OB.I18N.getLabel('OBUIAPP_CLOSEBUTTON')
     });
+    
     this.maximizeButton = isc.OBStatusBarIconButton.create( {
       view : this.view,
       buttonType : 'maximize',
       prompt : OB.I18N.getLabel('OBUIAPP_MAXIMIZEBUTTON')
     });
+    
     this.restoreButton = isc.OBStatusBarIconButton.create( {
       visibility : 'hidden',
       view : this.view,
       buttonType : 'restore',
       prompt : OB.I18N.getLabel('OBUIAPP_RESTOREBUTTON')
     });
+    
     this.maximizeRestoreButton = isc.OBStatusBarIconButton.create( { // Only for implement 'StatusBar_Maximize-Restore' keyboard shortcut
       visibility : 'hidden',
       view : this.view,
@@ -227,13 +236,10 @@
       keyboardShortcutId : 'StatusBar_Maximize-Restore'
     });
 
-    var buttonSpacer = isc.HLayout.create( {
-      width : this.iconButtonGroupSpacerWidth
-    }), i;
-
     this.buttonBar.addMembers( [ this.previousButton, this.nextButton, buttonSpacer,
         this.maximizeButton, this.restoreButton, this.closeButton, this.maximizeRestoreButton ]);
-    for (i = 0; i < this.buttonBar.members.length; i++) {
+    length = this.buttonBar.members.length;
+    for (i = 0; i < length; i++) {
       if (this.buttonBar.members[i].buttonType) {
         OB.TestRegistry.register(
             'org.openbravo.client.application.statusbar.button.' + this.buttonBar.members[i].buttonType + '.' + this.view.tabId,
@@ -277,8 +283,10 @@
   },
 
   disableShortcuts: function(){
+    var length;
     if (this.buttonBar.members) {
-      for (i = 0; i < this.buttonBar.members.length; i++) {
+      length = this.buttonBar.members.length;
+      for (i = 0; i < length; i++) {
         if (this.buttonBar.members[i].disableShortcut) {
           this.buttonBar.members[i].disableShortcut();
         }
@@ -321,13 +329,14 @@
   },
 
   updateContentTitle: function(arrayTitleField, message) {
-    var msg = '', i;
+    var msg = '', i, length;
     if (!isc.Page.isRTL()) { // LTR mode
       if (this.statusCode) {
         msg += '<span class="' + (this.statusLabelStyle?this.statusLabelStyle:'') + '">' + OB.I18N.getLabel(this.statusCode) + '</span>';
       }
       if (arrayTitleField) {
-        for (i = 0; i < arrayTitleField[0].length; i++) {
+        length = arrayTitleField[0].length;
+        for (i = 0; i < length; i++) {
           if (i !== 0 || this.statusCode) {
             msg += '<span class="' + (this.separatorLabelStyle?this.separatorLabelStyle:'') + '">' + '&nbsp;&nbsp;|&nbsp;&nbsp;' + '</span>';
           }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-attachments.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-attachments.js	Fri Sep 09 15:34:14 2011 +0200
@@ -99,6 +99,12 @@
 
 isc.OBAttachmentCanvasItem.addProperties({
 
+  // some defaults, note if this changes then also the 
+  // field generation logic needs to be checked
+  colSpan: 4, 
+  startRow: true, 
+  endRow: true,
+
   canFocus: true,
   
   // setting width/height makes the canvasitem to be hidden after a few
@@ -208,12 +214,15 @@
   },
   
   fileExists: function(fileName, attachments){
-	var i;
+    var i, length;
+   
     if(!attachments || attachments.length === 0){
       return false;
     }
-    for(i=0; i < attachments.length; i++){
-      if(attachments[i].name === fileName){
+    
+    length = attachments.length;
+    for( i = 0; i < length; i++){
+      if (attachments[i].name === fileName) {
         return true;
       }
     }
@@ -368,64 +377,64 @@
     };
     
     var removeActions = function(){
-      var i;
-      var d = {
-        Command: 'DELETE',
-        tabId: this.canvas.tabId,
-        buttonId: this.canvas.ID,
-        recordIds: this.canvas.recordId,
-        attachId: this.attachmentId
+      var i, length, d = {
+          Command: 'DELETE',
+          tabId: this.canvas.tabId,
+          buttonId: this.canvas.ID,
+          recordIds: this.canvas.recordId,
+          attachId: this.attachmentId
+        }, canvas = this.canvas;
+
+      isc.confirm(OB.I18N.getLabel('OBUIAPP_ConfirmRemove'), function(clickedOK){
+          if(clickedOK){
+            OB.RemoteCallManager.call('org.openbravo.client.application.window.AttachmentsAH', {}, d, function(response, data, request){
+              canvas.fillAttachments(data.attachments);
+            });
+          }
+        },{title: OB.I18N.getLabel('OBUIAPP_ConfirmRemoveTitle')});
       };
-      var canvas = this.canvas;
-      isc.confirm(OB.I18N.getLabel('OBUIAPP_ConfirmRemove'), function(clickedOK){
-        if(clickedOK){
-          OB.RemoteCallManager.call('org.openbravo.client.application.window.AttachmentsAH', {}, d, function(response, data, request){
-              canvas.fillAttachments(data.attachments);
-          });
-        }
-      },{title: OB.I18N.getLabel('OBUIAPP_ConfirmRemoveTitle')});
-    };
     
-    for(i=0; i < attachments.length; i++){
-      var attachment = attachments[i];
-      var buttonLayout = isc.HLayout.create();
-      var attachmentLabel = isc.Label.create({
-        contents: attachment.name,
-        className: 'OBNoteListGrid',
-        width: '200px',
-        height: 20,
-        wrap: false
-      });
-      var creationDate = OB.Utilities.getTimePassedInterval(attachment.age);
-      var attachmentBy = isc.Label.create({
-        height:  1,
-        className: 'OBNoteListGridAuthor',
-        width: '200px',
-        contents: creationDate+" "+OB.I18N.getLabel('OBUIAPP_AttachmentBy')+" "+attachment.updatedby
-      });
-      var downloadAttachment = isc.OBLinkButtonItem.create({
-        title: '[ '+OB.I18N.getLabel('OBUIAPP_AttachmentDownload')+' ]',
-        width: '30px',
-        attachmentName: attachment.name,
-        attachId: attachment.id,
-        action: downloadActions
-      });
-      downloadAttachment.height=0;
-      var removeAttachment = isc.OBLinkButtonItem.create({
-        title: '[ '+OB.I18N.getLabel('OBUIAPP_AttachmentRemove')+' ]',
-        width: '30px',
-        attachmentName: attachment.name,
-        attachmentId: attachment.id,
-        canvas: this,
-        action: removeActions
-      });
-      buttonLayout.addMember(attachmentLabel);
-      buttonLayout.addMember(attachmentBy);
-      buttonLayout.addMember(downloadAttachment);
-      buttonLayout.addMember(removeAttachment);
-      this.addMember(buttonLayout);
-    }
-  },
+      length = attachments.length;
+      for(i=0; i < attachments.length; i++){
+        var attachment = attachments[i];
+        var buttonLayout = isc.HLayout.create();
+        var attachmentLabel = isc.Label.create({
+          contents: attachment.name,
+          className: 'OBNoteListGrid',
+          width: '200px',
+          height: 20,
+          wrap: false
+        });
+        var creationDate = OB.Utilities.getTimePassedInterval(attachment.age);
+        var attachmentBy = isc.Label.create({
+          height:  1,
+          className: 'OBNoteListGridAuthor',
+          width: '200px',
+          contents: creationDate+" "+OB.I18N.getLabel('OBUIAPP_AttachmentBy')+" "+attachment.updatedby
+        });
+        var downloadAttachment = isc.OBLinkButtonItem.create({
+          title: '[ '+OB.I18N.getLabel('OBUIAPP_AttachmentDownload')+' ]',
+          width: '30px',
+          attachmentName: attachment.name,
+          attachId: attachment.id,
+          action: downloadActions
+        });
+        downloadAttachment.height=0;
+        var removeAttachment = isc.OBLinkButtonItem.create({
+          title: '[ '+OB.I18N.getLabel('OBUIAPP_AttachmentRemove')+' ]',
+          width: '30px',
+          attachmentName: attachment.name,
+          attachmentId: attachment.id,
+          canvas: this,
+          action: removeActions
+        });
+        buttonLayout.addMember(attachmentLabel);
+        buttonLayout.addMember(attachmentBy);
+        buttonLayout.addMember(downloadAttachment);
+        buttonLayout.addMember(removeAttachment);
+        this.addMember(buttonLayout);
+      }
+    },
   
   // ensure that the view gets activated
   focusChanged: function(){
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-linked-items.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-linked-items.js	Fri Sep 09 15:34:14 2011 +0200
@@ -393,6 +393,12 @@
 
 isc.OBLinkedItemCanvasItem.addProperties({
 
+  // some defaults, note if this changes then also the 
+  // field generation logic needs to be checked
+  colSpan: 4, 
+  startRow: true, 
+  endRow: true,
+
   canFocus: true,
   
   // setting width/height makes the canvasitem to be hidden after a few
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-notes.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form-notes.js	Fri Sep 09 15:34:14 2011 +0200
@@ -31,6 +31,12 @@
 
   overflow : 'hidden',
 
+  // some defaults, note if this changes then also the 
+  // field generation logic needs to be checked
+  colSpan: 4, 
+  startRow: true, 
+  endRow: true,
+
   canFocus : true,
 
   prompt : OB.I18N.getLabel('OBUIAPP_NotesPrompt'),
@@ -356,6 +362,12 @@
 
 isc.OBNoteCanvasItem.addProperties({
 
+  // some defaults, note if this changes then also the 
+  // field generation logic needs to be checked
+  colSpan: 4, 
+  startRow: true, 
+  endRow: true,
+
   canFocus : true,
 
   // setting width/height makes the canvasitem to be hidden after a few
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Fri Sep 09 15:34:14 2011 +0200
@@ -83,34 +83,20 @@
 
   initWidget: function() {
     this._preventFocusChanges = true;
-    var length, i, item;
+
     // add the obFormProperties to ourselves, the obFormProperties
     // are re-used for inline grid editing
     isc.addProperties(this, this.obFormProperties);
-
-    // is used to keep track of the original simple objects
-    // used to create fields
-    // note fields can be in fields or theFields
-    this._originalFields = isc.shallowClone(this.fields || this.theFields);
     
     this.Super('initWidget', arguments);
 
-    length = this.getItems().length;
-
-    for(i = 0; i < length; i++) {
-      item = this.getItem(i);
-      if(item && item.firstFocusedField) {
-        this.firstFocusedField = item.name;
-        break;
-      }
-    }
-
     delete this._preventFocusChanges;
   },
-
+  
   getStatusBarFields: function() {
-    var statusBarFields = [[],[]], i, item, value, tmpValue;
-    for(i = 0; i < this.statusBarFields.length; i++) {
+    var statusBarFields = [[],[]], i, item, value, tmpValue,
+      length = this.statusBarFields.length;
+    for(i = 0; i < length; i++) {
       item = this.getItem(this.statusBarFields[i]);
       value = item.getDisplayValue();
       if(item && value !== null && value !== '') {
@@ -433,10 +419,12 @@
   },
   
   getFieldFromInpColumnName: function(inpColumnName) {
-    var i;
+    var i, length;
+    
     if (!this.fieldsByInpColumnName) {
       var localResult = [], fields = this.getFields();
-      for (i = 0; i < fields.length; i++) {
+      length = fields.length;
+      for (i = 0; i < length; i++) {
         if (fields[i].inpColumnName) {
           localResult[fields[i].inpColumnName.toLowerCase()] = fields[i];
         }
@@ -447,9 +435,12 @@
   },
   
   getFieldFromColumnName: function(columnName) {
-    var i;
+    var i, length;
     if (!this.fieldsByColumnName) {
       var localResult = [], fields = this.getFields();
+      
+      length = fields.length;
+
       for (i = 0; i < fields.length; i++) {
         if (fields[i].columnName) {
           localResult[fields[i].columnName.toLowerCase()] = fields[i];
@@ -461,7 +452,7 @@
   },
   
   setFields: function(){
-    var i, item;
+    var i, item, length = this.getItems().length;
     
     // is used in various places, prevent focus and scroll events
     this._preventFocusChanges = true;
@@ -470,7 +461,7 @@
     this.fieldsByInpColumnName = null;
     this.fieldsByColumnName = null;
 
-    for (i = 0; i < this.getItems().length; i++) {
+    for (i = 0; i < length; i++) {
       item = this.getItem(i);
       if(item && item.setSectionItemInContent) {
         item.setSectionItemInContent(this);
@@ -480,12 +471,15 @@
   },
   
   retrieveInitialValues: function(isNew){
+    var parentId = this.view.getParentId(), i, fldNames = [], 
+      requestParams, allProperties, parentColumn, me = this, 
+      mode, length = this.getFields().length;
+    
     this.setParentDisplayInfo();
     
-    var parentId = this.view.getParentId(), i, fldNames = [], requestParams, parentColumn, me = this, mode;
-    // note also in this case initial vvalues are passed in as in case of grid
+    // note also in this case initial values are passed in as in case of grid
     // editing the unsaved/error values from a previous edit session are maintained
-    var allProperties = this.view.getContextInfo(false, true, false, true);
+    allProperties = this.view.getContextInfo(false, true, false, true);
     
     if (isNew) {
       mode = 'NEW';
@@ -499,14 +493,16 @@
       TAB_ID: this.view.tabId,
       ROW_ID: this.getValue(OB.Constants.ID)
     };
+    
     if (parentId && isNew && this.view.parentProperty) {
       parentColumn = this.view.getPropertyDefinition(this.view.parentProperty).inpColumn;
       requestParams[parentColumn] = parentId;
     }
+    
     allProperties._entityName = this.view.entity;
     
     // only put the visible field names in the call
-    for (i = 0; i < this.getFields().length; i++) {
+    for (i = 0; i < length; i++) {
       if (this.getFields()[i].inpColumnName) {
         fldNames.push(this.getFields()[i].inpColumnName);
       }
@@ -554,11 +550,11 @@
   },
   
   rememberValues: function() {
-    var i, flds = this.getFields();
+    var i, flds = this.getFields(), length = flds.length;
     this.Super('rememberValues', arguments);
     
     // also remember the valuemaps
-    for (i = 0; i < flds.length; i++) {
+    for (i = 0; i < length; i++) {
       if (flds[i].valueMap) {
         flds[i]._rememberedValueMap = flds[i].valueMap;
       }
@@ -568,14 +564,15 @@
   // used in grid editing, when an edit is discarded then the canFocus needs to be
   // reset
   resetCanFocus: function() {
-    var i;
-    for (i = 0; i < this.getItems().length; i++) {
+    var i, length = this.getItems().length;
+    for (i = 0; i < length; i++) {
       delete this.getItems()[i].canFocus;
     }
   },
   
   processFICReturn: function(response, data, request, editValues, editRow){
-    var modeIsNew = request.params.MODE === 'NEW', noErrors, errorSolved;
+    var length, modeIsNew = request.params.MODE === 'NEW', 
+      noErrors, errorSolved;
 
     delete this.contextInfo;
 
@@ -691,12 +688,15 @@
     // on field changed may have made the focused item non-editable
     // this is handled in setdisabled restore focus item's call
     this.setDisabled(false);
+    
+    length = this.getFields().length;
 
     if (this.validateAfterFicReturn) {
       delete this.validateAfterFicReturn;
       // only validate the fields which have errors or which have changed
       noErrors = true;
-      for (i = 0; i < this.getFields().length; i++) {
+      
+      for (i = 0; i < length; i++) {
         if (this.getFields()[i]._changedByFic || this.hasFieldErrors(this.getFields()[i].name)) {
           errorSolved = this.getFields()[i].validate();
           noErrors = noErrors && errorSolved;
@@ -711,12 +711,12 @@
       }
     }
 
-    for (i = 0; i < this.getFields().length; i++) {
+    for (i = 0; i < length; i++) {
       delete this.getFields()[i]._changedByFic;
     }
 
     // refresh WidgetInForm fields if present (as they might depend on data of current record) 
-    for (i = 0; i < this.getFields().length; i++) {
+    for (i = 0; i < length; i++) {
       var locField  = this.getFields()[i];
       if (locField.hasOwnProperty("widgetClassId")) {
         locField.refresh();
@@ -746,14 +746,16 @@
     }
 
     if(data.jscode) {
-      for(i = 0; i < data.jscode.length; i++) {
+      length = data.jscode.length;
+      for(i = 0; i < length; i++) {
         eval(data.jscode[i]);
       }
     }
   },
   
   setDisabled: function(state) {
-    var previousAllItemsDisabled = this.allItemsDisabled || false, i;
+    var previousAllItemsDisabled = this.allItemsDisabled || false, 
+      i, length;
     this.allItemsDisabled = state;
 
     if (previousAllItemsDisabled !== this.allItemsDisabled) {
@@ -769,7 +771,8 @@
           this.setHandleDisabled(state);
           this.view.viewGrid.refreshEditRow();
           // reset the canfocus
-          for (i = 0; i < this.getFields().length; i++) {
+          length = this.getFields().length;
+          for (i = 0; i < length; i++) {
             delete this.getFields()[i].canFocus;
           }
           
@@ -908,13 +911,13 @@
   
   setColumnValuesInEditValues: function(columnName, columnValue, editValues){
     // Modifications in this method should go also in processColumnValue because both almost do the same
-    var assignClassicValue;
-    var typeInstance;
+    var assignClassicValue, typeInstance, length;
 
     // no editvalues even anymore, go away
     if (!editValues) {
       return;
     }
+    
     var id, identifier, field = this.getFieldFromColumnName(columnName), i, valueMap = {}, 
       entries = columnValue.entries;
     var prop = this.view.getPropertyFromDBColumnName(columnName);
@@ -925,7 +928,8 @@
     }
     
     if (entries) {
-      for (i = 0; i < entries.length; i++) {
+      length = entries.length;
+      for (i = 0; i < length; i++) {
         id = entries[i][OB.Constants.ID] || '';
         identifier = entries[i][OB.Constants.IDENTIFIER] || '';
         valueMap[id] = identifier;
@@ -997,6 +1001,8 @@
   
   // called explicitly onblur and when non-editable fields change
   handleItemChange: function(item){
+    var i, length;
+    
     // is used to prevent infinite loops during save
     delete this.saveFocusItemChanged;
 
@@ -1007,8 +1013,8 @@
 
       this.onFieldChanged(item.form, item, item.getValue());
 
-      var i;
-      for (i = 0; i < this.dynamicCols.length; i++) {
+      length = this.dynamicCols.length;
+      for (i = 0; i < length; i++) {
         if (this.dynamicCols[i] === item.inpColumnName) {
           item._hasChanged = false;
           this.inFicCall = true;
@@ -1105,10 +1111,10 @@
   },
   
   undo: function(){
-    var i, flds = this.getFields();
+    var i, flds = this.getFields(), length = flds.length;
     
     // also restore the valuemaps
-    for (i = 0; i < flds.length; i++) {
+    for (i = 0; i < length; i++) {
       if (flds[i]._rememberedValueMap) {
         flds[i].valueMap = flds[i]._rememberedValueMap;
       }
@@ -1468,7 +1474,7 @@
     // To be implemented dynamically
   },
 
-  handleOtherItem: function(otherName, condition) {
+  disableItem: function(otherName, condition) {
     var otherItem = this.getItem(otherName);
     if (otherItem && otherItem.disable && otherItem.enable) {
       if (this.readOnly) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-grid.js	Fri Sep 09 15:34:14 2011 +0200
@@ -96,11 +96,12 @@
   focusInFirstFilterEditor: function() {
     if (this.getFilterEditor()) { // there is a filter editor
       var object = this.getFilterEditor().getEditForm(),
-        items, item, i;
+        items, item, i, length;
 
       // compute a focusable item
       items = object.getItems();
-      for (i = 0; i < items.length; i++) {
+      length = items.length;
+      for (i = 0; i < length; i++) {
         item = items[i];
         if (item.getCanFocus() && !item.isDisabled()) {
           this.focusInFilterEditor(item);
@@ -156,12 +157,14 @@
   
   initWidget: function(){
     // prevent the value to be displayed in case of a link
-    var i, thisGrid = this, field, formatCellValueFunction = function(value, record, rowNum, colNum, grid){
-      return '';
-    };
+    var i, thisGrid = this, field, 
+      formatCellValueFunction = function(value, record, rowNum, colNum, grid){
+        return '';
+      };
 
     if (this.fields) {
-      for (i = 0; i < this.fields.length; i++) {
+      length = this.fields.length;
+      for (i = 0; i < length; i++) {
         field = this.fields[i];
 
         if (!field.filterEditorProperties) {
@@ -257,7 +260,7 @@
         if (internCriteria && this.getEditForm()) {
           // now remove anything which is not a field
           // otherwise smartclient will keep track of them and send them again
-          var fields = this.getEditForm().getFields();
+          var fields = this.getEditForm().getFields(), length = fields.length;
           for (i = internCriteria.length - 1; i >=0; i--) {
             prop = internCriteria[i].fieldName;
             // happens when the internCriteria[i], is again an advanced criteria
@@ -270,7 +273,7 @@
               prop = prop.substring(0, index);
             }
             var fnd = false, j;
-            for (j = 0; j < fields.length; j++) {
+            for (j = 0; j < length; j++) {
               if (fields[j].displayField === fullPropName) {
                 fnd = true;
                 break;
@@ -333,26 +336,30 @@
   
   //  http://forums.smartclient.com/showthread.php?p=72177#post72177
   destroy: function() {
-    var i, components;
+    var i, components, length;
     this.Super('destroy', arguments);
     
     components = this.getRecordComponentPool();
     if (components) {
-      for (i = 0; i < components.length; i++) {
+      length = components.length;
+      for (i = 0; i < length; i++) {
         components[i].destroy();
       }
     }
   },
   
   clearFilter: function(keepFilterClause, noPerformAction){
-    var i = 0, fld;
+    var i = 0, fld, length;
     if (!keepFilterClause) {
       delete this.filterClause;
     }
     this.forceRefresh = true;
     this.filterEditor.getEditForm().clearValues();
+    
     // clear the date values in a different way
-    for (i = 0; i < this.filterEditor.getEditForm().getFields().length; i++) {
+    length = this.filterEditor.getEditForm().getFields().length;
+    
+    for (i = 0; i < length; i++) {
       fld = this.filterEditor.getEditForm().getFields()[i];
       if (fld.clearDateValues) {
         fld.clearDateValues();
@@ -449,11 +456,12 @@
   },
   
   isGridFilteredWithCriteria: function(criteria) {
-    var i;
+    var i, length;
     if (!criteria) {
       return false;
     }
-    for (i = 0; i < criteria.length; i++) {
+    length = criteria.length;
+    for (i = 0; i < length; i++) {
       var criterion = criteria[i];
       var prop = criterion.fieldName;
       var fullPropName = prop;
@@ -549,11 +557,12 @@
   //= getErrorRows =
   // Returns all the rows that have errors.
   getErrorRows: function(){
-    var editRows, errorRows = [], i;
+    var editRows, errorRows = [], i, length;
 
     if (this.hasErrors()) {
       editRows = this.getAllEditRows(true);
-      for (i = 0; i < editRows.length; i++) {
+      length = editRows.length;
+      for (i = 0; i < length; i++) {
         if (this.rowHasErrors(editRows[i])) {
           errorRows.push(editRows[i]);
         }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Fri Sep 09 15:34:14 2011 +0200
@@ -39,11 +39,6 @@
   // and the grid and other related components.
   view: null,
   
-  // ** {{{ foreignKeyFieldNames }}} **
-  // The list of fields which are foreign keys, these require custom
-  // filtering.
-  foreignKeyFieldNames: [],
-  
   // ** {{{ editGrid }}} **
   // Controls if an edit link column is created in the grid, set to false to
   // prevent this.
@@ -196,7 +191,8 @@
     },
 
     transformData: function(newData, dsResponse) {
-      var i;
+      var i, length;
+      
       // only do this stuff for fetch operations, in other cases strange things
       // happen as update/delete operations do not return the totalRows parameter
       if (dsResponse && dsResponse.context && dsResponse.context.operationType !== 'fetch') {
@@ -204,7 +200,8 @@
       }
       // correct the length if there is already data in the localData array
       if (this.localData) {
-        for (i = dsResponse.endRow + 1; i < this.localData.length; i++) {
+        length = this.localData.length;
+        for (i = dsResponse.endRow + 1; i < length; i++) {
           if (!Array.isLoading(this.localData[i]) && this.localData[i]) {
             dsResponse.totalRows = i + 1;
           } else {
@@ -340,7 +337,7 @@
   },
 
   draw: function() {
-    var drawnBefore = this.isDrawn(), form, item;
+    var drawnBefore = this.isDrawn(), form, item, length;
     this.Super('draw', arguments);
     // set the focus in the filter editor
     if (this.view && this.view.isActiveView() && !drawnBefore && this.isVisible() &&
@@ -352,8 +349,9 @@
       // to give everyone time to be ready
       if (!form.getFocusItem()) {
         items = form.getItems();
+        length = items.length;
 
-        for (i = 0; i < items.length; i++) {
+        for (i = 0; i < length; i++) {
           item = items[i];
           if (item.getCanFocus() && !item.isDisabled()) {
             item.delayCall('focusInItem', null, 100);
@@ -454,7 +452,8 @@
   },
  
   setView: function(view){
-    var dataPageSizeaux;
+    var dataPageSizeaux, length;
+    
     this.view = view;
     this.editFormDefaults.view = view;
     if (this.view.standardWindow.viewState && this.view.standardWindow.viewState[this.view.tabId]) {
@@ -480,9 +479,11 @@
     
     // if there is no autoexpand field then just divide the space
     if (!this.getAutoFitExpandField()) {
+      length = this.fields.length;
+      
       // nobody, then give all the fields a new size, dividing
       // the space among them
-      for (i = 0; i < this.fields.length; i++) {
+      for (i = 0; i < length; i++) {
         // ignore the first 2 fields, the checkbox and edit/form
         // buttons
         if (i > 1) {
@@ -963,7 +964,8 @@
   },
     
   convertCriteria: function(criteria){
-    var selectedValues, prop, fld, value, i, criterion, fldName;
+    var selectedValues, prop, fld, value, i, 
+      criterion, fldName, length;
 
     if (!criteria) {
       criteria = {
@@ -998,7 +1000,8 @@
       delete this.forceRefresh;
     } else {
       // remove the _dummy
-      for (i = 0; i < criteria.criteria.length; i++) {
+      length = criteria.criteria.length;
+      for (i = 0; i < length; i++) {
         if (criteria.criteria[i].fieldName === isc.OBRestDataSource.DUMMY_CRITERION_NAME) {
           criteria.criteria.removeAt(i);
           break;
@@ -1024,7 +1027,8 @@
       
       var fnd = false;
       var innerCriteria = criteria.criteria;
-      for (i = 0; i < innerCriteria.length; i++) {
+      length = innerCriteria.length;
+      for (i = 0; i < length; i++) {
         criterion = innerCriteria[i];
         fldName = criterion.fieldName;
         if (fldName === this.view.parentProperty) {
@@ -1127,10 +1131,11 @@
   },
   
   // determine which field can be autoexpanded to use extra space
-  getAutoFitExpandField: function() {
-    var ret, i;
-    for (i = 0; i < this.autoExpandFieldNames.length; i++) {
-      var field = this.getField(this.autoExpandFieldNames[i]);
+  getAutoFitExpandField: function() {    
+    var ret, i, length;
+    length = this.view.autoExpandFieldNames.length;
+    for (i = 0; i < length; i++) {
+      var field = this.getField(this.view.autoExpandFieldNames[i]);
       if (field && field.name) {
         return field.name;
       }
@@ -1138,7 +1143,7 @@
     ret = this.Super('getAutoFitExpandField', arguments);    
     return ret;
   },
-
+  
   recordClick: function(viewer, record, recordNum, field, fieldNum, value, rawValue){
     var textDeselectInterval = setInterval(function() { //To ensure that if finally a double click (recordDoubleClick) is executed, no work is highlighted/selected
       if (document.selection && document.selection.empty) {
@@ -1586,11 +1591,11 @@
   // +++++++++++++++++ functions for grid editing +++++++++++++++++
 
   startEditing: function (rowNum, colNum, suppressFocus, eCe, suppressWarning) {
-    var i, ret;
+    var i, ret, length = this.getFields().length;
     // if a row is set and not a col then check if we should focus in the
     // first error field
     if ((rowNum || rowNum === 0) && (!colNum && colNum !== 0) && this.rowHasErrors(rowNum))  {
-      for (i = 0; i < this.getFields().length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.cellHasErrors(rowNum, i)) {
          colNum = i;
          break; 
@@ -1602,7 +1607,7 @@
       this.forceFocusColumn = this.getField(colNum).name;
     } else {
       // set the first focused column
-      for (i = 0; i < this.getFields().length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.getFields()[i].editorProperties && this.getFields()[i].editorProperties.firstFocusedField) {
           colNum = i;
         }
@@ -1737,8 +1742,9 @@
   },
 
   undoEditSelectedRows: function(){
-    var selectedRecords = this.getSelectedRecords(), toRemove = [], i;
-    for (i = 0; i < selectedRecords.length; i++) {
+    var selectedRecords = this.getSelectedRecords(), 
+      toRemove = [], i, length = selectedRecords.length;
+    for (i = 0; i < length; i++) {
       var rowNum = this.getRecordIndex(selectedRecords[i]);
       var record = selectedRecords[i];
       this.Super('discardEdits', [rowNum, false, false, isc.ListGrid.PROGRAMMATIC]);
@@ -1900,7 +1906,7 @@
   // is the last being edited
   // also sets a flag which is used in canEditCell   
   getNextEditCell: function (rowNum, colNum, editCompletionEvent) {
-    var ret, i;
+    var ret, i, length = this.getFields().length;
     this._inGetNextEditCell = true;
     // past the last row
     if (editCompletionEvent === isc.ListGrid.ENTER_KEYPRESS && rowNum === (this.getTotalRows() - 1)) {
@@ -1908,7 +1914,7 @@
       ret = this.findNextEditCell(rowNum + 1, 0, 1, true, true);
 
       // force the focus column in the first focus field
-      for (i = 0; i < this.getFields().length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.getFields()[i].editorProperties && this.getFields()[i].editorProperties.firstFocusedField) {
           this.forceFocusColumn = this.getFields()[i].name;
           break;
@@ -2133,11 +2139,12 @@
   },
 
   refreshEditRow: function(){
-    var editRow = this.view.viewGrid.getEditRow(), i;
+    var editRow = this.view.viewGrid.getEditRow(), i, length;
     if (editRow || editRow === 0) {
       // don't refresh the frozen fields, this give strange
       // styling issues in chrome
-      for (i = 0; i < this.view.viewGrid.fields.length; i++) {
+      length = this.view.viewGrid.fields.length;
+      for (i = 0; i < length; i++) {
         if (!this.fieldIsFrozen(i)) {
           this.view.viewGrid.refreshCell(editRow, i, true);
         }
@@ -2253,8 +2260,8 @@
   },
 
   allSelectedRecordsWritable: function() {
-    var i;
-    for (i = 0; i < this.getSelectedRecords().length; i++) {
+    var i, length = this.getSelectedRecords().length;
+    for (i = 0; i < length; i++) {
       var record = this.getSelectedRecords()[i];
       if (!this.isWritable(record) || record._new) {
         return false;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Fri Sep 09 15:34:14 2011 +0200
@@ -183,6 +183,8 @@
   propertyToColumns:[],
 
   initWidget: function(properties){
+    var length;
+    
     this.messageBar = isc.OBMessageBar.create({
       visibility: 'hidden',
       view: this
@@ -201,7 +203,8 @@
     var i, actionButton;
     
     if (this.actionToolbarButtons) {
-      for (i = 0; i < this.actionToolbarButtons.length; i++) {
+      length = this.actionToolbarButtons.length;
+      for (i = 0; i < length; i++) {
         actionButton = isc.OBToolbarActionButton.create(this.actionToolbarButtons[i]);
         actionButton.contextView = this;
         rightMemberButtons.push(actionButton);
@@ -210,7 +213,8 @@
     
     // Look for specific toolbar buttons for this tab
     if (this.iconToolbarButtons) {
-      for (i = 0; i < this.iconToolbarButtons.length; i++) {
+      length = this.iconToolbarButtons.length;
+      for (i = 0; i < length; i++) {
         // note create a somewhat unique id by concatenating the tabid and the index
         OB.ToolbarRegistry.registerButton(this.tabId + '_' + i, isc.OBToolbarIconButton, this.iconToolbarButtons[i], 200 + (i * 10), this.tabId);
       }
@@ -240,6 +244,7 @@
   },
   
   buildStructure: function(){
+    var length, i, fld;
     this.createMainParts();
     this.createViewStructure();
     if (this.childTabSet && this.childTabSet.tabs.length === 0) {
@@ -257,19 +262,17 @@
     }
     
     if (this.viewForm) {
-      this.prepareViewFields(this.viewForm.theFields);
-      
       // setDataSource executes setFields which replaces the current fields
       // We don't want to destroy the associated DataSource objects
       this.viewForm.destroyItemObjects = false;
       
-      // initially the viewForm.fields is not set, the fields are
-      // in this.viewForm.theFields, this to prevent too early creation of fields
-      // i.e. they are recreated when setting the datasource, as is done
-      // here.
-      // make sure the fields are set now
-      this.viewForm.fields = this.viewForm.theFields;
-      this.viewForm.setDataSource(this.dataSource, this.viewForm.theFields);
+      // is used to keep track of the original simple objects
+      // used to create fields
+      this.viewForm._originalFields = isc.clone(this.formFields);
+      this.viewForm.fields = this.formFields;
+      this.viewForm.firstFocusedField = this.firstFocusedField;
+      
+      this.viewForm.setDataSource(this.dataSource, this.formFields);
       this.viewForm.isViewForm = true;
       this.viewForm.destroyItemObjects = true;
     }
@@ -524,6 +527,8 @@
   // this
   // parent.
   addChildView: function(childView){
+    var length;
+    
     if ((childView.isTrlTab && OB.PropertyStore.get('ShowTrl', this.windowId) !== 'Y') ||
         (childView.isAcctTab && OB.PropertyStore.get('ShowAcct', this.windowId) !== 'Y')){
       return;
@@ -534,7 +539,8 @@
     // Add buttons in parent to child. Note that currently it is only added one level.
     var i;
     if (this.actionToolbarButtons && this.actionToolbarButtons.length>0 && childView.showParentButtons){
-      for (i = 0; i < this.actionToolbarButtons.length; i++) {
+      length = this.actionToolbarButtons.length;
+      for (i = 0; i < length; i++) {
         actionButton = isc.OBToolbarActionButton.create(isc.addProperties({}, this.actionToolbarButtons[i], {baseStyle: 'OBToolbarTextButtonParent'}));
         actionButton.contextView = this; // Context is still parent view
         actionButton.toolBar = childView.toolBar;
@@ -786,9 +792,10 @@
   },
 
   refreshChildViews: function() {
-    var i;
+    var i, length;
     if (this.childTabSet) {
-      for (i = 0; i < this.childTabSet.tabs.length; i++) {
+      length = this.childTabSet.tabs.length;
+      for (i = 0; i < length; i++) {
         tabViewPane = this.childTabSet.tabs[i].pane;
         // force a refresh, only the visible ones will really 
         // be refreshed
@@ -1041,6 +1048,8 @@
   // function is called with a small delay to handle the case that a user
   // navigates quickly over a grid
   delayedRecordSelected: function() {
+    var length;
+    
     // is actually a different parent selected, only then refresh children
     var differentRecordId = !this.lastRecordSelected || !this.viewGrid.getSelectedRecord() ||
       this.viewGrid.getSelectedRecord().id !== this.lastRecordSelected.id;
@@ -1055,7 +1064,8 @@
 
     // refresh the tabs
     if (this.childTabSet && (differentRecordId || !this.isOpenDirectModeParent)) {
-      for (i = 0; i < this.childTabSet.tabs.length; i++) {
+      length = this.childTabSet.tabs.length;
+      for (i = 0; i < length; i++) {
         tabViewPane = this.childTabSet.tabs[i].pane;
 
         if (!selectedRecordId || !this.isOpenDirectModeParent || selectedRecordId !== tabViewPane.parentRecordId) {
@@ -1068,8 +1078,11 @@
 
   // set childs to refresh when they are made visible
   setChildsToRefresh: function() {
+    var length;
+    
     if (this.childTabSet) {
-      for (i = 0; i < this.childTabSet.tabs.length; i++) {
+      length = this.childTabSet.tabs.length;
+      for (i = 0; i < length; i++) {
         if (!this.childTabSet.tabs[i].pane.isVisible()) {
           this.childTabSet.tabs[i].pane.refreshContents = true;  
         }
@@ -1176,7 +1189,8 @@
       tab = this.tab;
       tabSet = this.parentTabSet;
 
-      if (this.parentView.viewGrid.getSelectedRecords().length !== 1) {
+      if (!this.parentView.viewGrid.getSelectedRecords() || 
+          this.parentView.viewGrid.getSelectedRecords().length !== 1) {
         title = this.originalTabTitle;
       } else if (this.recordCount) {
         title = this.originalTabTitle + ' (' + this.recordCount + ')';
@@ -1184,6 +1198,12 @@
         title = this.originalTabTitle;
       }
     }
+    
+    // happens when a tab gets closed
+    if (!tab) {
+      return;
+    }
+    
     if (title) {
       
       // show a prompt with the title info
@@ -1312,7 +1332,8 @@
   },
 
   hasNotChanged: function() {
-    var view = this, form = view.viewForm, grid = view.viewGrid, hasErrors = false, editRow, i;
+    var view = this, form = view.viewForm, length, selectedRecords,
+      grid = view.viewGrid, allRowsHaveErrors, hasErrors = false, editRow, i;
     if (view.isShowingForm) {
       if(form.isNew) {
         return false;
@@ -1324,8 +1345,10 @@
       form = grid.getEditForm();
       return !form.isNew && !hasErrors && (form.isSaving || form.readOnly || !view.hasValidState() || !form.hasChanged);
     } else {
-      var selectedRecords = grid.getSelectedRecords(), allRowsHaveErrors = true;
-      for (i = 0; i < selectedRecords.length; i++) {
+      selectedRecords = grid.getSelectedRecords();
+      allRowsHaveErrors = true;
+      length = selectedRecords.length;
+      for (i = 0; i < length; i++) {
         var rowNum = grid.getRecordIndex(selectedRecords[i]);
         allRowsHaveErrors = allRowsHaveErrors && grid.rowHasErrors(rowNum);
       }
@@ -1362,59 +1385,65 @@
       }
     
       var callback = function(ok){
-        var i, doUpdateTotalRows, data, deleteData, error, recordInfos = [], removeCallBack = function(resp, data, req){
-          var localData = resp.dataObject || resp.data || data, i, updateTotalRows;
-          if (!localData) {
-            // bail out, an error occured which should be displayed to the user now
-            return;
-          }
-          var status = resp.status;
-          if (localData && localData.hasOwnProperty('status')) {
-            status = localData.status;
-          }
-          if (localData && localData.response && localData.response.hasOwnProperty('status')) {
-            status = localData.response.status;
-          }
-          if (status === isc.RPCResponse.STATUS_SUCCESS) {
-            if (view.isShowingForm) {
-              view.switchFormGridVisibility();
+        var i, doUpdateTotalRows, data, deleteData, error, 
+          recordInfos = [], 
+          removeCallBack = function(resp, data, req){
+            var length,
+              localData = resp.dataObject || resp.data || data, 
+              i, updateTotalRows;
+            
+            if (!localData) {
+              // bail out, an error occured which should be displayed to the user now
+              return;
             }
-            view.messageBar.setMessage(isc.OBMessageBar.TYPE_SUCCESS, null, OB.I18N.getLabel('OBUIAPP_DeleteResult', [deleteCount]));
-            if (deleteData) {
-              // note totalrows is used when inserting a new row, to determine after which
-              // record to add a new row
-              updateTotalRows = (view.viewGrid.data.getLength() === view.viewGrid.data.totalRows);
-              // deleteData is computed below
-              for (i = 0 ; i < deleteData.ids.length; i++) {
-                recordInfos.push({id: deleteData.ids[i]});
+            var status = resp.status;
+            if (localData && localData.hasOwnProperty('status')) {
+              status = localData.status;
+            }
+            if (localData && localData.response && localData.response.hasOwnProperty('status')) {
+              status = localData.response.status;
+            }
+            if (status === isc.RPCResponse.STATUS_SUCCESS) {
+              if (view.isShowingForm) {
+                view.switchFormGridVisibility();
               }
-              view.viewGrid.data.handleUpdate('remove', recordInfos);
-              if (updateTotalRows) {
+              view.messageBar.setMessage(isc.OBMessageBar.TYPE_SUCCESS, null, OB.I18N.getLabel('OBUIAPP_DeleteResult', [deleteCount]));
+              if (deleteData) {
+                // note totalrows is used when inserting a new row, to determine after which
+                // record to add a new row
+                updateTotalRows = (view.viewGrid.data.getLength() === view.viewGrid.data.totalRows);
+                // deleteData is computed below
+                length = deleteData.ids.length;
+                for (i = 0 ; i < length; i++) {
+                  recordInfos.push({id: deleteData.ids[i]});
+                }
+                view.viewGrid.data.handleUpdate('remove', recordInfos);
+                if (updateTotalRows) {
+                  view.viewGrid.data.totalRows = view.viewGrid.data.getLength();
+                }
+              } else if (doUpdateTotalRows) {
                 view.viewGrid.data.totalRows = view.viewGrid.data.getLength();
               }
-            } else if (doUpdateTotalRows) {
-              view.viewGrid.data.totalRows = view.viewGrid.data.getLength();
-            }
-            view.viewGrid.updateRowCountDisplay();
-            view.refreshChildViews();
-            view.refreshParentRecord();
-          } else {
-            // get the error message from the dataObject 
-            if (localData.response && localData.response.error && localData.response.error.message) {
-              error = localData.response.error;
-              if (error.type && error.type === 'user') {
-                view.messageBar.setLabel(isc.OBMessageBar.TYPE_ERROR, null, error.message, error.params);
-              } else if (error.message && error.params) {
+              view.viewGrid.updateRowCountDisplay();
+              view.refreshChildViews();
+              view.refreshParentRecord();
+            } else {
+              // get the error message from the dataObject 
+              if (localData.response && localData.response.error && localData.response.error.message) {
+                error = localData.response.error;
+                if (error.type && error.type === 'user') {
                   view.messageBar.setLabel(isc.OBMessageBar.TYPE_ERROR, null, error.message, error.params);
-              } else if (error.message) {
-                view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, error.message);
-              } else {
-                view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, OB.I18N.getLabel('OBUIAPP_DeleteResult', [0]));
+                } else if (error.message && error.params) {
+                    view.messageBar.setLabel(isc.OBMessageBar.TYPE_ERROR, null, error.message, error.params);
+                } else if (error.message) {
+                  view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, error.message);
+                } else {
+                  view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, OB.I18N.getLabel('OBUIAPP_DeleteResult', [0]));
+                }
               }
             }
-          }
-        };
-        
+          };
+      
         if (ok) {
           var selection = view.viewGrid.getSelection().duplicate();
           // deselect the current records
@@ -1424,7 +1453,8 @@
             deleteData = {};
             deleteData.entity = view.entity;
             deleteData.ids = [];
-            for (i = 0; i < selection.length; i++) {
+            length = selection.length;
+            for (i = 0; i < length; i++) {
               deleteData.ids.push(selection[i][OB.Constants.ID]);
             }
             OB.RemoteCallManager.call('org.openbravo.client.application.MultipleDeleteActionHandler', deleteData, {}, removeCallBack, {
@@ -1462,7 +1492,7 @@
   },
 
   undo: function(){
-    var view = this, callback, form, grid, errorRows, i;
+    var view = this, callback, form, grid, errorRows, i, length;
     view.messageBar.hide(true);
     if (this.isEditingGrid) {
       grid = view.viewGrid;
@@ -1472,7 +1502,8 @@
       // undo edit in all records with errors
       if (grid.hasErrors()) {
         errorRows = grid.getErrorRows();
-        for (i = 0; i < errorRows.length; i++){
+        length = errorRows.length;
+        for (i = 0; i < length; i++){
           grid.selectRecord(grid.getRecord(errorRows[i]));
         }
         grid.undoEditSelectedRows();
@@ -1604,10 +1635,12 @@
     var contextInfo = {}, addProperty, rowNum;
     // if classicmode is undefined then both classic and new props are used
     var classicModeUndefined = (typeof classicMode === 'undefined');
+    var value, field, record, form, component, propertyObj, 
+      type, length;
+
     if (classicModeUndefined) {
       classicMode = true;
     }
-    var value, field, record, form, component, propertyObj, type;
 
     // a special case, the editform has been build but it is not present yet in the
     // form, so isEditingGrid is true but the edit form is not there yet, in that 
@@ -1646,7 +1679,8 @@
         record[OB.Constants.ID] = this.viewGrid.getSelectedRecord()[OB.Constants.ID];
       }
       
-      for (i = 0; i < properties.length; i++) {
+      length = properties.length;
+      for (i = 0; i < length; i++) {
         propertyObj = properties[i];
         value = record[propertyObj.property];
         field = component.getField(propertyObj.property);
@@ -1654,7 +1688,7 @@
         if (addProperty) {
           if (classicMode) {
             if (propertyObj.type && convertToClassicFormat) {
-              type = SimpleType.getType(propertyObj.type);
+              type = isc.SimpleType.getType(propertyObj.type);
               if (type.createClassicString) {
                 contextInfo[properties[i].inpColumn] = type.createClassicString(value);
               } else {
@@ -1712,8 +1746,8 @@
   },
   
   getPropertyDefinition: function(property) {
-    var properties = this.propertyToColumns, i;
-    for (i = 0; i < properties.length; i++) {
+    var properties = this.propertyToColumns, i, length = properties.length;
+    for (i = 0; i < length; i++) {
       if (property === properties[i].property) {
         return properties[i];
       }
@@ -1761,9 +1795,43 @@
     return this.standardWindow.getFormPersonalization(this);
   },
   
+  // TODO: consider caching the prepared fields on
+  // class level, the question is if it is faster
+  // as then a clone action needs to be done
+  prepareFields: function() {
+    // first compute the gridfields and then the formfields
+    this.prepareViewFields(this.fields);
+    this.gridFields = this.prepareGridFields(this.fields);
+    this.formFields = this.prepareFormFields(this.fields);
+  },
+  
   prepareFormFields: function(fields) {
-    var i, length = fields.length, fld,
-      showIfFunction = function(item, value, form, values) {
+    var i, length = fields.length, result = [];
+    
+    for (i = 0; i < length; i++) {
+      fld = isc.shallowClone(fields[i]);
+      result.push(this.setFieldFormProperties(fld));
+
+      if(fld.firstFocusedField) {
+        this.firstFocusedField = fld.name;
+      }
+    }
+    
+    return result;
+  },
+  
+  setFieldFormProperties: function(fld) {
+    if (fld.displayed === false) {
+      fld.visible = false;
+      fld.alwaysTakeSpace = false;
+    }
+
+    if (!fld.width) {
+      fld.width = '*';
+    }
+    if (fld.showIf && !fld.originalShowIf) {
+      fld.originalShowIf = fld.showIf;
+      fld.showIf = function(item, value, form, values) {
         var currentValues = values || form.view.getCurrentValues(),
         context = form.getCachedContextInfo();
 
@@ -1772,24 +1840,17 @@
         return !this.hiddenInForm && context && 
           this.originalShowIf(item, value, form, currentValues, context);
       };
-    
-    for (i = 0; i < length; i++) {
-      fld = fields[i];
-      if (fld.showIf && !fld.originalShowIf) {
-        fld.originalShowIf = fld.showIf;
-        fld.showIf = showIfFunction;
-      }
-      if (!fld.width) {
-        fld.width = '*';
-      }
     }
-    return fields;
+    return fld;
   },
   
   // prepare stuff on view level
   prepareViewFields: function(fields) {
     var i, length = fields.length, fld;
     
+    // start with the initial ones
+    this.propertyToColumns = this.initialPropertyToColumns.duplicate();
+    
     this.propertyToColumns.push({
         property: this.standardProperties.keyProperty,
         dbColumn: this.standardProperties.keyColumnName,
@@ -1811,6 +1872,114 @@
         });
       }
     }
+  },
+  
+  prepareGridFields: function(fields) {
+    var result = [], i, length = fields.length, fld, type,
+      expandFieldNames, hoverFunction;
+    
+    hoverFunction = function(record, value, rowNum, colNum, grid) {
+      return grid.getDisplayValue(colNum, record[(this.displayField ? this.displayField : this.name)]);
+    };
+    
+    for (i = 0; i < length; i++) {
+      fld = fields[i];
+      if (!fld.gridProps) {
+        continue;
+      }
+      fld = isc.shallowClone(fields[i]);
+      
+      if (fld.showHover) {
+        fld.hoverHTML = hoverFunction;
+      }
+      
+      if (fld.gridProps.length) {
+        fld.gridProps.width = isc.OBGrid.getDefaultColumnWidth(fld.gridProps.length);
+      }
+      
+      isc.addProperties(fld, fld.gridProps);
+      
+      if (!fld.width) {
+        fld.width = isc.OBGrid.getDefaultColumnWidth(30);
+      }
+            
+      fld.canExport = (fld.canExport === false ? false : true);
+      fld.canHide = (fld.canHide === false ? false : true);
+      fld.canFilter = (fld.canFilter === false ? false : true);
+      fld.filterOnKeypress = (fld.filterOnKeypress === false ? false : true); 
+      fld.escapeHTML = (fld.escapeHTML === false ? false : true);
+      fld.prompt = fld.title;
+      fld.editorProperties = isc.addProperties({}, fld, isc.shallowClone(fld.editorProperties));      
+      this.setFieldFormProperties(fld.editorProperties);
+
+      type = isc.SimpleType.getType(fld.type);
+      if (type.editorType) {
+        fld.editorType = type.editorType;
+      }
+      if (type.filterEditorType) {
+        fld.filterEditorType = type.filterEditorType;
+      }
+      // don't set it if explicitly set to null
+      if (fld.foreignKeyField && !fld.displayField && fld.displayField !== null) {
+        fld.displayField = fld.name + '.' + OB.Constants.IDENTIFIER;
+      }
+      
+      result.push(fld);
+    }
+    
+    // sort according to length, for the autoexpandfieldnames
+    result.sort(function(v1, v2) {
+      var t1 = v1.length, t2 = v2.length;
+      if (!t1 && !t2) {
+        return 0;
+      }
+      if (!t1) {
+        return -1;
+      }
+      if (!t2) {
+        return 1;
+      }
+      if (t1 < t2) {
+        return -1;
+      } else if (t1 === t2) {
+        return 0;
+      }
+      return 1;
+    });
+    
+    this.autoExpandFieldNames = [];
+    length = result.length;
+    for (i = 0; i < length; i++) {
+      if (result[i].autoExpand) {
+        this.autoExpandFieldNames.push(result[i].name);
+      }
+    }
+        
+    // sort according to the sortnum
+    // that's how they are displayed
+    result.sort(function(v1, v2) {
+      var t1 = v1.sortNum, t2 = v2.sortNum;
+      if (!t1 && !t2) {
+        return 0;
+      }
+      if (!t1) {
+        return -1;
+      }
+      if (!t2) {
+        return 1;
+      }
+      if (t1 < t2) {
+        return -1;
+      } else if (t1 === t2) {
+        return 0;
+      }
+      return 1;
+    });
+    
+    
+    
+    return result;
   }
+  
 });
 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Fri Sep 09 15:34:14 2011 +0200
@@ -106,7 +106,7 @@
   
   // set window specific user settings, purposely set on class level
   setWindowSettings: function(data) {
-    var i, defaultView, persDefaultValue, views;
+    var i, defaultView, persDefaultValue, views, length;
 
     if (data && data.personalization) {
       if (data.personalization.forms) {
@@ -120,8 +120,9 @@
       // returned in order of prio, then do sort by name
       if (this.getClass().personalization.views) {
         views = this.getClass().personalization.views;
+        length = views.length;
         if (persDefaultValue) {
-          for (i = 0; i < views.length; i++) {
+          for (i = 0; i < length; i++) {
             if (persDefaultValue === views[i].personalizationId) {
               defaultView = views[i];
               break;
@@ -129,7 +130,7 @@
           }
         }
         if (!defaultView) {
-          for (i = 0; i < views.length; i++) {
+          for (i = 0; i < length; i++) {
             if (views[i].viewDefinition.isDefault) {
               defaultView = views[i];
               break;
@@ -140,7 +141,9 @@
         // apply the default view
         // maybe do this in a separate thread
         if (defaultView) {
-          OB.Personalization.applyViewDefinition(defaultView.viewDefinition, this);
+          this.fireOnPause('setDefaultView', function() {
+            OB.Personalization.applyViewDefinition(defaultView.viewDefinition, this);
+          }, 100);
         }
         
         this.getClass().personalization.views.sort(function(v1, v2) {
@@ -161,7 +164,8 @@
     this.getClass().autoSave = data.autoSave;
     this.getClass().showAutoSaveConfirmation = data.showAutoSaveConfirmation;
     // set the views to readonly
-    for (i = 0; i < this.views.length; i++) {
+    length = this.views.length;
+    for (i = 0; i < length; i++) {
       this.views[i].setReadOnly(data.uiPattern[this.views[i].tabId] === isc.OBStandardView.UI_PATTERN_READONLY);
       this.views[i].setSingleRecord(data.uiPattern[this.views[i].tabId] === isc.OBStandardView.UI_PATTERN_SINGLERECORD);
       this.views[i].toolBar.updateButtonState(true);
@@ -189,14 +193,14 @@
   },
 
   removeAllFormPersonalizations: function() {
-    var i, updateButtons = false;
+    var i, updateButtons = false, length = this.views.length;
     if (!this.getClass().personalization) {
       return;
     }
     updateButtons = this.getClass().personalization.forms;
     if (updateButtons) {
       delete this.getClass().personalization.forms;
-      for (i = 0; i < this.views.length; i++) {
+      for (i = 0; i < length; i++) {
         this.views[i].toolBar.updateButtonState(false);
       }
     }
@@ -527,9 +531,10 @@
 
   draw: function(){
     var standardWindow = this, targetEntity,
-        ret = this.Super('draw', arguments), i;
+        ret = this.Super('draw', arguments), i,
+        length = this.views.length;
     if (this.targetTabId) {
-      for (i = 0; i < this.views.length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.views[i].tabId === this.targetTabId) {
           targetEntity = this.views[i].entity;
           this.views[i].viewGrid.targetRecordId = this.targetRecordId;
@@ -627,8 +632,8 @@
   },
 
   storeViewState: function(){
-    var result = {}, i;
-    for (i = 0; i < this.views.length; i++) {
+    var result = {}, i, length = this.views.length;
+    for (i = 0; i < length; i++) {
       if(this.views[i].viewGrid){
         result[this.views[i].tabId]=this.views[i].viewGrid.getViewState();
       }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-tab.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-tab.js	Fri Sep 09 15:34:14 2011 +0200
@@ -517,7 +517,6 @@
   },
 
   setState: function(newState){
-
     // disabled this as sometimes states have
     // to be reset to recompute heights changed automatically
     // if (this.state === newState) {
@@ -526,6 +525,7 @@
 
     var tab, i, pane;
     var tmpPreviousState = this.state;
+    var length = this.tabs.length;
 
     // is corrected below for one state
     this.setDraggable(false);
@@ -544,7 +544,7 @@
       // done otherwise the content is not drawn
       // the top member in each tab is maximized
       // the bottom member in each tab is set to the tabbar height
-      for (i = 0; i < this.tabs.length; i++) {
+      for (i = 0; i < length; i++) {
         tab = this.tabs[i];
         this.makeTabVisible(tab);
         pane = this.getTabPane(tab);
@@ -569,7 +569,7 @@
       } else if (this.parentContainer) {
         this.parentContainer.setBottomMaximum();
       }
-      for (i = 0; i < this.tabs.length; i++) {
+      for (i = 0; i < length; i++) {
         tab = this.tabs[i];
         this.makeTabVisible(tab);
         pane = this.getTabPane(tab);
@@ -579,7 +579,7 @@
       this.state = newState;
       this.setDraggable(true);
       // minimize the third level
-      for (i = 0; i < this.tabs.length; i++) {
+      for (i = 0; i < length; i++) {
         tab = this.tabs[i];
         pane = this.getTabPane(tab);
         pane.setHeight('100%');
@@ -598,7 +598,7 @@
       }
       // the content of the tabs is split in 2
       this.state = newState;
-      for (i = 0; i < this.tabs.length; i++) {
+      for (i = 0; i < length; i++) {
         tab = this.tabs[i];
         pane = this.getTabPane(tab);
         this.makeTabVisible(tab);
@@ -608,7 +608,7 @@
 
     this.previousState = tmpPreviousState;
 
-    for (i = 0; i < this.tabs.length; i++) {
+    for (i = 0; i < length; i++) {
       tab = this.tabs[i];
       tab.pane.setMaximizeRestoreButtonState();
     }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-application-menu.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-application-menu.js	Fri Sep 09 15:34:14 2011 +0200
@@ -225,8 +225,8 @@
 
   setNodeIcons: function (node) {
     if (node) {
-      var i;
-      for (i = 0; i < node.length; i++) {
+      var i, length = node.length;
+      for (i = 0; i < length; i++) {
         if (node[i].type) {
           node[i].icon = this.getNodeIcon(node[i].type);
           if (node[i].submenu) {
@@ -239,10 +239,11 @@
 
   setMenuItems: function () {
     var recent = OB.RecentUtilities.getRecentValue('UINAVBA_MenuRecentList');
-    var recentEntries = [];
+    var recentEntries = [], length;
     var completeMenuTree, recentIndex;
     if (recent && recent.length > 0) {
-      for (recentIndex = 0; recentIndex < recent.length; recentIndex++) {
+      length = recent.length;
+      for (recentIndex = 0; recentIndex < length; recentIndex++) {
         var recentEntry = recent[recentIndex];
         if (recentEntry) {
           recentEntries[recentIndex] = {title: recentEntry.tabTitle, recentObject: recentEntry, type: recentEntry.type};
@@ -259,8 +260,8 @@
   // as arguments, note that the function does not expect an array as this
   // did not seem to be supported by selenium
   getSCLocator : function() {
-    var index = 0, path = [];
-    for (; index < arguments.length; index++) {
+    var index = 0, path = [], length;
+    for (; index < length; index++) {
       path[index] = arguments[index];
     }
     index = 0;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js	Fri Sep 09 15:34:14 2011 +0200
@@ -80,8 +80,8 @@
 
     if (recent && recent.length > 0) {
       var newFields = [];
-      var index = 0, recentIndex;
-      for (recentIndex = 0; recentIndex < recent.length; recentIndex++) {
+      var index = 0, recentIndex, length = recent.length;
+      for (recentIndex = 0; recentIndex < length; recentIndex++) {
         if (recent[recentIndex]) {
           newFields[index] = isc.OBQuickLaunchRecentLinkButton.create({recentObject: recent[recentIndex], prefixLabel: this.prefixLabel, nodeIcons: this.nodeIcons});
           newFields[index].recentPropertyName = this.recentPropertyName;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quickrun-widget.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quickrun-widget.js	Fri Sep 09 15:34:14 2011 +0200
@@ -108,8 +108,8 @@
     // compute the height
     if (this.members) {
       defaultLayoutProperties.members = this.members;
-      var computedHeight = 0, i;
-      for (i = 0; i < this.members.length; i++) {
+      var computedHeight = 0, i, length = this.members.length;
+      for (i = 0; i < length; i++) {
         if (this.members[i].height) {
           computedHeight = computedHeight + this.members[i].height;
         }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-user-profile-widget.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-user-profile-widget.js	Fri Sep 09 15:34:14 2011 +0200
@@ -262,8 +262,9 @@
         }
       },
       setValueMaps: function(){
-        var i, role, roleId = roleForm.getValue('role');
-        for (i = 0; i < roleForm.localFormData.role.roles.length; i++) {
+        var i, role, roleId = roleForm.getValue('role'),
+          length = roleForm.localFormData.role.roles.length;
+        for (i = 0; i < length; i++) {
           role = roleForm.localFormData.role.roles[i];
           if (role.id === roleId) {
             roleForm.setValueMap('organization', role.organizationValueMap);
@@ -272,15 +273,18 @@
         }
       },
       setWarehouseValueMap: function() {
-        var i, j, warehouseOrg, role, roleId, orgId = roleForm.getItem('organization').getValue();
+        var i, j, warehouseOrg, role, roleId, length, 
+          orgId = roleForm.getItem('organization').getValue();
         if (!orgId) {
           return;
         }
+        length = roleForm.localFormData.role.roles.length;
         roleId = roleForm.getValue('role');
-        for (i = 0; i < roleForm.localFormData.role.roles.length; i++) {
+        for (i = 0; i < length; i++) {
           role = roleForm.localFormData.role.roles[i];
           if (role.id === roleId) {
-            for (j = 0; j < role.warehouseOrgMap.length; j++) {
+            length = role.warehouseOrgMap.length;
+            for (j = 0; j < length; j++) {
               warehouseOrg = role.warehouseOrgMap[j];
               if (warehouseOrg.orgId === orgId) {
                 roleForm.setValueMap('warehouse', warehouseOrg.warehouseMap);
@@ -438,7 +442,7 @@
       
       // the callback displays an info dialog and then hides the form
       doSaveCallback: function(rpcResponse, data, rpcRequest){
-        var i;
+        var i, length;
         if (data.result === OB.Constants.SUCCESS) {
           isc.OBQuickRun.hide();
           isc.say(OB.I18N.getLabel('UINAVBA_PasswordChanged'));
@@ -447,7 +451,8 @@
             isc.showPrompt(OB.I18N.getLabel(data.message));
           }
           if (data.fields) {
-            for (i = 0; i < data.fields.length; i++) {
+            length = data.fields.length;
+            for (i = 0; i < length; i++) {
               var field = data.fields[i];
               passwordForm.addFieldErrors(field.field, OB.I18N.getLabel(field.messageCode), true);
             }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-popups.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-popups.js	Fri Sep 09 15:34:14 2011 +0200
@@ -134,10 +134,11 @@
     var value, personalization = this.standardWindow.getClass().personalization, 
       views = personalization && personalization.views ? personalization.views : [], 
       valueMap = {}, flds = [], 
-      standardWindow = this.standardWindow;
+      standardWindow = this.standardWindow, length;
     
     if (views) {
-      for (i = 0; i < views.length; i++) {
+      length = views.length;
+      for (i = 0; i < length; i++) {
         if (views[i].canEdit) {
           valueMap[views[i].personalizationId] = views[i].viewDefinition.name;
         }
@@ -184,10 +185,11 @@
     var personalization = this.standardWindow.getClass().personalization, 
       views = personalization && personalization.views ? personalization.views : [], 
       valueMap = {}, flds = [], 
-      standardWindow = this.standardWindow;
+      standardWindow = this.standardWindow, length;
     
     if (views) {
-      for (i = 0; i < views.length; i++) {
+      length = views.length;
+      for (i = 0; i < length; i++) {
         if (views[i].canEdit) {
           valueMap[views[i].personalizationId] = views[i].viewDefinition.name;
         }
@@ -228,14 +230,15 @@
   // change or set views for different levels
   getFields: function() {
     var i, formData, valueMap = {}, levelMapSet = false, 
-      levelMap = {'': ''}, flds = [], 
+      levelMap = {'': ''}, flds = [], length, 
       standardWindow = this.standardWindow,
       personalization = standardWindow.getClass().personalization, 
       views = personalization && personalization.views ? personalization.views : [];
     
     // create the view combo
     if (views) {
-      for (i = 0; i < views.length; i++) {
+      length = views.length;
+      for (i = 0; i < length; i++) {
         if (views[i].canEdit) {
           valueMap[views[i].personalizationId] = views[i].viewDefinition.name;
         }
@@ -254,7 +257,7 @@
         // if changed, then set the level and levelvalue
         // fields to the current level of the personalization
         changed: function(form, item, value) {
-          var i, levelField = form.getField('level'), 
+          var i, levelField = form.getField('level'), length,
             levelValueField = form.getField('levelValue'), 
             personalization = this.standardWindow.getClass().personalization, views;
           
@@ -263,7 +266,8 @@
             // and the view, and set the level and level value
             // combos
             views = personalization.views;
-            for (i = 0; i < views.length; i++) {
+            length = views.length;
+            for (i = 0; i < length; i++) {
               if (views[i].personalizationId === value) {
                 if (views[i].clientId) {
                   levelField.storeValue('clients');
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-toolbar.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views-toolbar.js	Fri Sep 09 15:34:14 2011 +0200
@@ -48,13 +48,13 @@
     action: function() {
       var data = [], i, undef, view,
         standardWindow = this.view.standardWindow,
-        adminLevel = false,
+        adminLevel = false, length,
         personalization = standardWindow.getClass().personalization, 
         views = personalization && personalization.views ? personalization.views : [],
         canDelete = false;
       
       // TODO: disabled license check to facilitate testing
-      if(OB.Application.licenseType !== 'DUMMY') {
+      if(OB.Application.licenseType === 'DUMMY') {
 //      if(OB.Application.licenseType === 'C') {
         isc.warn(OB.I18N.getLabel('OBUIAPP_ActivateMessage', [OB.I18N.getLabel('OBUIAPP_ActivateMessagePersonalization')]), {
             isModal: true,
@@ -65,7 +65,8 @@
       }
       
       // create the list of current views to show
-      for (i = 0; i < views.length; i++) {
+      length = views.length;
+      for (i = 0; i < length; i++) {
         view = views[i];
         canDelete = view.canEdit || canDelete;
         data.push({title: view.viewDefinition.name, viewDefinition: view.viewDefinition});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js	Fri Sep 09 15:34:14 2011 +0200
@@ -99,7 +99,7 @@
 // ** {{{OB.Personalization.applyViewDefinition}}} **
 // Apply a selected view definition to a window
 OB.Personalization.applyViewDefinition = function(viewDefinition, standardWindow) {
-  var i, view, viewTabDefinition, 
+  var i, view, viewTabDefinition, length = standardWindow.views.length,
     windowDefinition = viewDefinition.window;
   
   // delete the current form personalization 
@@ -108,7 +108,7 @@
   
   if (windowDefinition) {
     if (windowDefinition.activeTabId) {
-      for (i = 0; i < standardWindow.views.length; i++) {
+      for (i = 0; i < length; i++) {
         if (standardWindow.views[i].tabId === windowDefinition.activeTabId) {
           view = standardWindow.views[i];
           break;
@@ -133,7 +133,7 @@
   
   // the viewdefinition contains both the global info (form, canDelete, personalizationid)  
   // set the view state for each tab
-  for (i = 0; i < standardWindow.views.length; i++) {
+  for (i = 0; i < length; i++) {
     view = standardWindow.views[i];
     viewTabDefinition = viewDefinition[view.tabId];
     if (viewTabDefinition) {
@@ -157,10 +157,10 @@
 // view state is stored in the standardWindow.getClass().personalization object.
 OB.Personalization.storeViewDefinition = function(standardWindow, levelInformation, persId, name, isDefault) {
   var params, view, persDataByTab, 
-    personalizationData = {}, i, formData;
+    personalizationData = {}, i, formData, length = standardWindow.views.length;
   
   // retrieve the viewstate from the server
-  for (i = 0; i < standardWindow.views.length; i++) {
+  for (i = 0; i < length; i++) {
     persDataByTab = {};
     view = standardWindow.views[i];
     
@@ -232,7 +232,7 @@
     'org.openbravo.client.application.personalization.PersonalizationActionHandler', 
     personalizationData, params,
     function(resp, data, req){
-      var i = 0, fnd = false;
+      var i = 0, fnd = false, length;
       var newView, 
         personalization = standardWindow.getClass().personalization, 
         views = personalization && personalization.views ? personalization.views : []; 
@@ -250,7 +250,8 @@
       // first check if there is an existing record, if so 
       // update it
       if (views) {
-        for (i = 0; i < views.length; i++) {
+        length = views.length;
+        for (i = 0; i < length; i++) {
           if (views[i].personalizationId === data.personalizationId) {
             views[i] = newView;
             fnd = true;
@@ -301,11 +302,13 @@
       },
       function(resp, data, req){
         var personalization = standardWindow.getClass().personalization, 
+          length,
           views = personalization && personalization.views ? personalization.views : [];
         
         if (views) {
+          length = views.length;
           // remove the entry from the global list
-          for (i = 0; i < views.length; i++) {
+          for (i = 0; i < length; i++) {
             if (views[i].personalizationId === personalizationId) {
               views.splice(i, 1);
               break;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization-treegrid.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization-treegrid.js	Fri Sep 09 15:34:14 2011 +0200
@@ -64,11 +64,12 @@
     this.folderIcon = OB.Styles.Personalization.Icons.fieldGroup;
 
     // register a change notifier
-    var i = 0, me = this, changedFunction = function() {
-      me.personalizeForm.changed();
-    };
+    var i = 0, length = this.fields.length,
+      me = this, changedFunction = function() {
+        me.personalizeForm.changed();
+      };
     
-    for (i = 0; i < this.fields.length; i++) {
+    for (i = 0; i < length; i++) {
       this.fields[i].changed = changedFunction;
     }
 
@@ -131,7 +132,7 @@
   // in the same location (code commented out, seems to prevent move..)
   // - set isStatusBarField flag when moved into the status bar folder
   folderDrop : function (nodes, folder, index, sourceWidget, callback) {
-    var i, oldNode, oldValue, newCallback, changed;
+    var i, oldNode, oldValue, newCallback, changed, length;
     
     if (!nodes) {
       return;
@@ -141,11 +142,13 @@
     if (folder && folder.name === '/') {
       return;
     }
+
+    length = nodes.length;
     
     // don't allow required fields without default value 
     // to be dropped on the statusbar
     if (folder.name === OB.Personalization.STATUSBAR_GROUPNAME) {
-      for (i = 0; i < nodes.length; i++) {
+      for (i = 0; i < length; i++) {
         if (!nodes[i].wasOnStatusBarField && nodes[i].required && !nodes[i].hasDefaultValue) {
           return;
         }
@@ -171,7 +174,7 @@
 //    }
     
     // folders can not be dropped outside of the main group
-    for (i = 0; i < nodes.length; i++) {
+    for (i = 0; i < length; i++) {
       if (nodes[i].isFolder && (!folder || folder.name !== OB.Personalization.MAIN_GROUPNAME)) {
         return;
       }
@@ -212,7 +215,7 @@
   // entries are shown for status bar or normal fields
   createCellContextItems: function(record){
     var menuItems = [], updatePropertyFunction, me = this,
-      personalizeForm = this.personalizeForm;
+      personalizeForm = this.personalizeForm, length;
     
     updatePropertyFunction = function(record, property, value) {
       record[property] = value;
@@ -220,7 +223,8 @@
       // make sure only one record has first focus
       if (record.firstFocus) {
         allNodes = personalizeForm.fieldsTreeGrid.data.getAllNodes();
-        for (i = 0; i < allNodes.length; i++) {
+        length = allNode.length;
+        for (i = 0; i < length; i++) {
           if (allNodes[i].firstFocus) {
             allNodes[i].firstFocus = false;
           }
@@ -290,8 +294,10 @@
   },
   
   computeNodeIcons: function(nodes) {
-    var iconSuffix, node, i, data = nodes || this.data.getAllNodes();
-    for (i = 0; i < data.length; i++) {
+    var iconSuffix, node, i, 
+      data = nodes || this.data.getAllNodes(),
+      length = data.length;
+    for (i = 0; i < length; i++) {
       node = data[i];
       if (node.isFolder) {
         continue;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalization.js	Fri Sep 09 15:34:14 2011 +0200
@@ -40,7 +40,7 @@
 // used as the basis. This can be used to make sure that the 
 // personalizationData used is up-to-date with the current form fields.
 OB.Personalization.getPersonalizationDataFromForm = function(form) {
-  var i, dataFields = [], statusBarFields, 
+  var i, dataFields = [], statusBarFields, length,
     origPersonalizationData = form && form.view ? form.view.getFormPersonalization() : null;
 
   // just use the personalization data which was used on the 
@@ -54,7 +54,8 @@
   // create the statusbar array so we don't use the one from the form
   if (dataFields && dataFields.length > 0) {
     statusBarFields = [];
-    for (i = 0; i < dataFields.length; i++) {
+    length = dataFields.length;
+    for (i = 0; i < length; i++) {
       if (dataFields[i].parentName === OB.Personalization.STATUSBAR_GROUPNAME) {
         statusBarFields.push(dataFields[i].name);
       }
@@ -101,6 +102,8 @@
   
   // required and title and removal of fields
   // length is recomputed every time as fields can be removed
+  // note: not factored out in a separate length attribute,
+  // length changes
   for (i = 0; i < dataFields.length; i++) {
     dataField = dataFields[i];
     fld = fields.find('name', dataField.name);
@@ -161,7 +164,8 @@
   }
   
   // iterate over the fields of the form and handle sections and fields
-  for (i = 0; i < fields.length; i++) {
+  length = fields.length;
+  for (i = 0; i < length; i++) {
     fld = fields[i];
     
     if (fld.personalizable === false) {
@@ -220,7 +224,8 @@
   // now resolve the parent names, i.e. in Smartclient a section item
   // has a set of item ids, in the tree we use (as we use 'parent' mode) the items
   // refer to the parent, so the other way
-  for (i = 0; i < dataFields.length; i++) {
+  length = dataFields.length;
+  for (i = 0; i < length; i++) {
     if (dataFields[i].childNames) {
       for (j = 0; j < dataFields[i].childNames.length; j++) {
         // find is a smartclient extension
@@ -233,7 +238,8 @@
   }
 
   // add to the status bar fields
-  for (i = 0; i < statusBarFields.length; i++) {
+  length = statusBarFields.length;
+  for (i = 0; i < length; i++) {
     record = dataFields.find('name', statusBarFields[i]);
     if (record && !record.parentName) {
       record.parentName = OB.Personalization.STATUSBAR_GROUPNAME;
@@ -245,7 +251,8 @@
     }
   }
 
-  for (i = 0; i < dataFields.length; i++) {
+  length = dataFields.length;
+  for (i = 0; i < length; i++) {
     record = dataFields[i];
     
     // do not consider the not-displayed ones which are not
@@ -268,7 +275,8 @@
 // Also handles the case that a personalization record is deleted so that the
 // form falls back to the default state
 OB.Personalization.personalizeWindow = function(data, window) {
-  var tabId, personalizationData, undef, form, view, i, viewsToReset = [], done;
+  var tabId, personalizationData, undef, form, view, 
+    i, viewsToReset = [], done, length;
 
   // no personalization, nothing to do
   if (!data) {
@@ -277,7 +285,8 @@
 
   // keep track of the tabs which are personalized
   // is used below to de-personalize them
-  for (i = 0; i < window.views.length; i++) {
+  length = window.views.length;
+  for (i = 0; i < length; i++) {
     if (window.getFormPersonalization(window.views[i])) {
       viewsToReset.push({tabId: window.views[i].tabId});
     }
@@ -311,8 +320,9 @@
   }
   
   // a personalization may have been removed, reset the form
-  // to its original state 
-  for (i = 0; i < viewsToReset.length; i++) {
+  // to its original state
+  length = viewsToReset.length;
+  for (i = 0; i < length; i++) {
     view = window.getView(viewsToReset[i].tabId);
     
     // the personalization button has 2 icons: one 2 show that there is
@@ -346,7 +356,9 @@
 // Applies the data structure which contains the personalization settings to a
 // form.
 OB.Personalization.personalizeForm = function(data, form) {
-  var persId, i, j, fld, undef, fldDef, childFld, newField, newFields = [], record, allChildFieldsHidden, statusBarFields = [];
+  var persId, i, j, fld, undef, fldDef, 
+    childFld, newField, newFields = [], record, length, 
+    allChildFieldsHidden, statusBarFields = [];
   
   // work further with the fields themselves
   data = data.form.fields;
@@ -367,7 +379,8 @@
 
   // iterate over the personalized data, this ensures that we follow
   // the order defined by the user
-  for (i = 0; i < data.length; i++) {
+  length = data.length;
+  for (i = 0; i < length; i++) {
     record = data[i];
 
     // original name is used when a field is visible in the status bar
@@ -451,7 +464,8 @@
   // now add the ones we did not know about, these maybe new 
   // fields or hidden fields
   if (!form.isPreviewForm) {
-    for (i = 0; i < form.getFields().length; i++) {
+    length = form.getFields().length;
+    for (i = 0; i < length; i++) {
       record = data.find('name', form.getFields()[i].name);
       // use the original.fields as we are then sure
       // that we do not get ready build form items
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form-toolbar-button.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form-toolbar-button.js	Fri Sep 09 15:34:14 2011 +0200
@@ -121,7 +121,9 @@
     buttonType: 'edit_personalization',
     prompt: OB.I18N.getLabel('OBUIAPP_Personalization_Toolbar_Edit_Button'),
     updateState: function(){
-      var view = this.view, form = view.viewForm, grid = view.viewGrid, selectedRecords = grid.getSelectedRecords(), i;
+      var view = this.view, form = view.viewForm, 
+        grid = view.viewGrid, length, 
+        selectedRecords = grid.getSelectedRecords(), i;
       
       // only show for records which can be edited
       if (selectedRecords.length !== 1) {
@@ -134,7 +136,8 @@
         return;
       }
 
-      for (i = 0; i < selectedRecords.length; i++) {
+      length = selectedRecords.length;
+      for (i = 0; i < length; i++) {
         if (!grid.isWritable(selectedRecords[i])) {
           this.setDisabled(true);
           return;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js	Fri Sep 09 15:34:14 2011 +0200
@@ -276,10 +276,11 @@
       
       // is called when a field in the tree is clicked
       setRecord: function(record) {
-        var fld;
+        var fld, i = 0, length = this.getFields().length;
+        
         this.record = record;
-        var i = 0;
-        for (i = 0; i < this.getFields().length; i++) {
+
+        for (i = 0; i < length; i++) {
           fld = this.getFields()[i];
           // the field has the opposite meaning of the form
           if (fld.name === 'displayed') {
@@ -314,7 +315,7 @@
       
       // store the values in the record
       doSave: function() {
-        var i, allNodes;
+        var i, allNodes, length;
         
         // don't save if there are errors
         // could be an idea to disable the save button
@@ -327,7 +328,8 @@
         // first get rid of all first focus if it was set now
         if (this.getValue('firstFocus')) {
           allNodes = this.personalizeForm.fieldsTreeGrid.data.getAllNodes();
-          for (i = 0; i < allNodes.length; i++) {
+          length = allNodes.length;
+          for (i = 0; i < length; i++) {
             if (allNodes[i].firstFocus) {
               allNodes[i].firstFocus = false;
             }
@@ -769,8 +771,10 @@
       // even if the status bar field does not have a value (which it
       // does not have in the form preview)
       getStatusBarFields: function() {
-        var statusBarFields = [[],[]], i, item, value, tmpValue;
-        for(i = 0; i < this.statusBarFields.length; i++) {
+        var statusBarFields = [[],[]], i, 
+          item, value, tmpValue, length = this.statusBarFields.length;
+        
+        for(i = 0; i < length; i++) {
           item = this.getItem(this.statusBarFields[i]);
           statusBarFields[0].push(item.getTitle());
           statusBarFields[1].push('&nbsp;&nbsp&nbsp;');
@@ -796,13 +800,14 @@
 //      }
     };
     
-    var persFields = this.getPersonalizationFields();
+    var persFields = this.getPersonalizationFields(), length;
     if (persFields) {
       OB.Personalization.personalizeForm({form: persFields}, this.previewForm);
     }
     
     // expand by default
-    for (i = 0; i < this.previewForm.getFields().length; i++) {
+    length = this.previewForm.getFields().length;
+    for (i = 0; i < length; i++) {
       fld = this.previewForm.getFields()[i];
       
       fld.showFocused = false;
@@ -878,7 +883,7 @@
   },
   
   buildFieldsTreeGrid: function() {
-    var i, prop, fld;
+    var i, prop, fld, length;
     
     this.fieldsLayout.destroyAndRemoveMembers(this.fieldsLayout.getMembers());
     if (this.fieldsTreeGrid) {
@@ -896,7 +901,8 @@
       'colSpan', 'rowSpan', 'required', 
       'startRow', 'name', 'hasDisplayLogic'
     ];
-    for (i = 0; i < this.personalizationData.form.fields.length; i++) {
+    length = this.personalizationData.form.fields.length;
+    for (i = 0; i < length; i++) {
       fld = this.personalizationData.form.fields[i];
       for (prop in fld) {
         if (fld.hasOwnProperty(prop) && 
@@ -1019,6 +1025,10 @@
       OB.RemoteCallManager.call('org.openbravo.client.application.personalization.PersonalizationActionHandler', {}, {action: 'getFormDefinition', tabId: this.tabId}, 
           function(resp, data, req){
         me.previewFormProperties = data;
+        
+        // copy some stuff
+        me.previewFormProperties._originalFields = isc.clone(me.previewFormProperties.fields);
+        
         me.doOpen(true);
       });
       return;
@@ -1066,14 +1076,16 @@
   // reads the data from the tree grid and returns it in the expected
   // format. Note may return null during initialization
   getPersonalizationFields: function() {
-    var i, record, result = [], node, nodes, value, j, undef;
+    var i, record, result = [], node, nodes, 
+      value, j, undef, length;
     if (!this.fieldsTreeGrid || !this.fieldsTreeGrid.data) {
       return null;
     }
     // the nodes will contain internal data from the tree
     // only get the properties we want
     nodes = this.fieldsTreeGrid.data.getAllNodes();
-    for (i = 0; i < nodes.length; i++) {
+    length = nodes.length;
+    for (i = 0; i < length; i++) {
       node = nodes[i];
       record = {};
       for (j = 0; j < this.personalizationDataProperties.length; j++) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Fri Sep 09 15:34:14 2011 +0200
@@ -147,8 +147,12 @@
     buttonType: 'eliminate',
     prompt: OB.I18N.getLabel('OBUIAPP_DeleteRow'),
     updateState: function(){
-      var view = this.view, form = view.viewForm, grid = view.viewGrid, selectedRecords = grid.getSelectedRecords(), i;
-      for (i = 0; i < selectedRecords.length; i++) {
+      var view = this.view, form = view.viewForm, 
+        grid = view.viewGrid, 
+        selectedRecords = grid.getSelectedRecords(),
+        length = selectedRecords.length, i;
+      
+      for (i = 0; i < length; i++) {
         if (!grid.isWritable(selectedRecords[i])) {
           this.setDisabled(true);
           return;
@@ -429,7 +433,10 @@
 isc.OBToolbar.addProperties({
   randomId: null,
   initWidget: function(){
+    var newMembers = [], i = 0, j = 0, length;
+    
     this.Super('initWidget', arguments);
+
     function getRandomId(){
       var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz', stringLength = 8, randomString = '', i, rnum;
       for (i = 0; i < stringLength; i++) {
@@ -438,13 +445,15 @@
       }
       return randomString;
     }
+    
     this.randomId = getRandomId();
+    
     this.members = null;
     
-    var newMembers = [], i = 0, j = 0;
     if(!this.leftMembers || this.leftMembers.length===0){
       this.leftMembers = OB.ToolbarRegistry.getButtons(this.view.tabId);
     }
+    
     newMembers[j] = isc.HLayout.create({
       width: this.leftMargin,
       height: 1
@@ -452,7 +461,10 @@
     j++;
     
     if (this.leftMembers) {
-      for (i = 0; i < this.leftMembers.length; i++) {
+      
+      length = this.leftMembers.length;
+      
+      for (i = 0; i < length; i++) {
        
         newMembers[j] = this.leftMembers[i];
         
@@ -487,7 +499,10 @@
     j++;
     
     if (this.rightMembers) {
-      for (i = 0; i < this.rightMembers.length; i++) {
+      
+      length = this.rightMembers.length;
+      
+      for (i = 0; i < length; i++) {
         newMembers[j] = this.rightMembers[i];
         OB.TestRegistry.register('org.openbravo.client.application.toolbar.button.' + this.rightMembers[i].property + '.' + this.view.tabId, this.rightMembers[i]);
         newMembers[j].toolBar = this;
@@ -522,7 +537,9 @@
   // NOTE: new buttons should implement the updateState method.
   //
   updateButtonState: function(noSetSession, changeEvent){
-    for (i = 0; i < this.leftMembers.length; i++) {
+    var length = this.leftMembers.length;
+    
+    for (i = 0; i < length; i++) {
       if (this.leftMembers[i].updateState) {
         this.leftMembers[i].updateState();
       }
@@ -546,19 +563,19 @@
   //
   // Returns:  type: Canvas - left member widget.
   getLeftMember: function(member){
-    var i = 0;
+    var i = 0, length = this.leftMembers.length;
     if (typeof member === 'number') {
       if (member >= 0 && member < this.leftMembers.length) {
         return this.leftMembers[member];
       }
     } else if (typeof member === 'string') {
-      for (i = 0; i < this.leftMembers.length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.leftMembers[i].buttonType === member) {
           return this.leftMembers[i];
         }
       }
     } else if (typeof member === 'object') {
-      for (i = 0; i < this.leftMembers.length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.leftMembers[i] === member) {
           return this.leftMembers[i];
         }
@@ -590,8 +607,8 @@
   //
   // Returns: type: Array - the Array of matching left members.
   getLeftMembersByAttribute: function(attribute, value){
-    var members = [], i = 0;
-    for (i = 0; i < this.leftMembers.length; i++) {
+    var members = [], i = 0, length = this.leftMembers.length;
+    for (i = 0; i < length; i++) {
       if (this.leftMembers[i][attribute] === value) {
         members.push(this.leftMembers[i]);
       }
@@ -610,8 +627,8 @@
   //
   // Returns: type: Number - the left member Canvas position (starting from 0).
   getLeftMemberNumber: function(member){
-    var i = 0;
-    for (i = 0; i < this.leftMembers.length; i++) {
+    var i = 0, length = this.leftMembers.length;
+    for (i = 0; i < length; i++) {
       if (this.leftMembers[i] === member) {
         return i;
       }
@@ -627,13 +644,15 @@
   // Parameters:
   // * {{{members}}} type: Array | Canvas - array of left members to be removed, or reference to single left member.
   removeLeftMembers: function(members){
-    var oldMembersSorted = [], oldArray = [], position = 0, i = 0, sortFunc = function(a, b){
-      return (a - b);
-    };
+    var oldMembersSorted = [], oldArray = [], position = 0, 
+      length, i = 0, sortFunc = function(a, b){
+        return (a - b);
+      };
     if (!(typeof members.length === 'number' && !(members.propertyIsEnumerable('length')) && typeof members.splice === 'function')) {
       members = [members];
     }
-    for (i = 0; i < members.length; i++) { /* Clean-up of the given input and sort */
+    length = members.length;
+    for (i = 0; i < length; i++) { /* Clean-up of the given input and sort */
       if (typeof members[i] !== 'number') {
         members[i] = this.getLeftMemberNumber(members[i]);
       }
@@ -642,14 +661,17 @@
       }
       oldMembersSorted = oldMembersSorted.sort(sortFunc);
     }
-    for (i = 0; i < oldMembersSorted.length; i++) { /* Generate an array to determine which elements visually will be removed */
+    length = oldMembersSorted.length;
+    for (i = 0; i < length; i++) { /* Generate an array to determine which elements visually will be removed */
       position = oldMembersSorted[i];
       position = position * 2;
       position = position + 1;
       oldArray.push(position, position + 1);
     }
     oldMembersSorted = oldMembersSorted.reverse();
-    for (i = 0; i < oldMembersSorted.length; i++) { /* Update the 'leftMembers' array */
+    
+    length = oldMembersSorted.length;
+    for (i = 0; i < length; i++) { /* Update the 'leftMembers' array */
       this.leftMembers.splice(oldMembersSorted[i], 1);
     }
     this.destroyAndRemoveMembers(oldArray); /* Remove visually the desired elements */
@@ -661,8 +683,9 @@
   // Removes all left members from the layout.
   //
   removeAllLeftMembers: function(){
-    var membersNumArray = [], i = 0;
-    for (i = 0; i < this.leftMembers.length; i++) {
+    var membersNumArray = [], i = 0, 
+      length = this.leftMembers.length;
+    for (i = 0; i < length; i++) {
       membersNumArray.push(i);
     }
     this.removeLeftMembers(membersNumArray);
@@ -677,19 +700,21 @@
   // * {{{newMembers}}} type: Array || Object - array of canvases to be added, or reference to single canvas.
   // * {{{position (optional)}}} type: Number - position to add newMembers; if omitted newMembers will be added at the last position.
   addLeftMembers: function(newMembers, position){
-    var i = 0;
+    var i = 0, length;
     if (!(typeof newMembers.length === 'number' && !(newMembers.propertyIsEnumerable('length')) && typeof newMembers.splice === 'function')) {
       newMembers = [newMembers];
     }
     if (position > this.leftMembers.length || typeof position === 'undefined') {
       position = this.leftMembers.length;
     }
-    for (i = 0; i < newMembers.length; i++) {
+    length = newMembers.length;
+    for (i = 0; i < length; i++) {
       this.leftMembers.splice(position + i, 0, newMembers[i]);
     }
     position = position * 2;
     position = position + 1;
-    for (i = 0; i < newMembers.length; i++) {
+    length = newMembers.length;
+    for (i = 0; i < length; i++) {
       this.Super('addMembers', [newMembers[i], position]);
       position = position + 1;
       this.Super('addMembers', [isc.HLayout.create({
@@ -757,19 +782,20 @@
   //
   // Returns: type: Canvas - right member widget.
   getRightMember: function(member){
-    var i = 0;
+    var i = 0, length = this.rightMembers.length;
     if (typeof member === 'number') {
       if (member >= 0 && member < this.rightMembers.length) {
         return this.rightMembers[member];
       }
     } else if (typeof member === 'string') {
-      for (i = 0; i < this.rightMembers.length; i++) {
+      
+      for (i = 0; i < length; i++) {
         if (this.rightMembers[i].ID === member) {
           return this.rightMembers[i];
         }
       }
     } else if (typeof member === 'object') {
-      for (i = 0; i < this.rightMembers.length; i++) {
+      for (i = 0; i < length; i++) {
         if (this.rightMembers[i] === member) {
           return this.rightMembers[i];
         }
@@ -801,8 +827,8 @@
   //
   // Returns: type: Array - the Array of matching right members.
   getRightMembersByAttribute: function(attribute, value){
-    var members = [], i = 0;
-    for (i = 0; i < this.rightMembers.length; i++) {
+    var members = [], i = 0, length = this.rightMembers.length;
+    for (i = 0; i < length; i++) {
       if (this.rightMembers[i][attribute] === value) {
         members.push(this.rightMembers[i]);
       }
@@ -821,8 +847,8 @@
   //
   // Returns: type: Number - the right member Canvas position (starting from 0).
   getRightMemberNumber: function(member){
-    var i = 0;
-    for (i = 0; i < this.rightMembers.length; i++) {
+    var i = 0, length = this.rightMembers.length;
+    for (i = 0; i < length; i++) {
       if (this.rightMembers[i] === member) {
         return i;
       }
@@ -838,13 +864,15 @@
   // Parameters:
   // * {{{members}}} type: Array | Canvas - array of right members to be removed, or reference to single right member.
   removeRightMembers: function(members){
-    var oldMembersSorted = [], oldArray = [], position = 0, i = 0, sortFunc = function(a, b){
+    var oldMembersSorted = [], length, oldArray = [], 
+      position = 0, i = 0, sortFunc = function(a, b){
       return (a - b);
     };
     if (!(typeof members.length === 'number' && !(members.propertyIsEnumerable('length')) && typeof members.splice === 'function')) {
       members = [members];
     }
-    for (i = 0; i < members.length; i++) { /* Clean-up of the given input and sort */
+    length = members.length;
+    for (i = 0; i < length; i++) { /* Clean-up of the given input and sort */
       if (typeof members[i] !== 'number') {
         members[i] = this.getRightMemberNumber(members[i]);
       }
@@ -853,7 +881,9 @@
       }
       oldMembersSorted = oldMembersSorted.sort(sortFunc);
     }
-    for (i = 0; i < oldMembersSorted.length; i++) { /* Generate an array to determine which elements visually will be removed */
+    
+    length = oldMembersSorted.length;
+    for (i = 0; i < length; i++) { /* Generate an array to determine which elements visually will be removed */
       position = oldMembersSorted[i];
       position = position * 2;
       position = position + 3;
@@ -861,7 +891,8 @@
       oldArray.push(position, position + 1);
     }
     oldMembersSorted = oldMembersSorted.reverse();
-    for (i = 0; i < oldMembersSorted.length; i++) { /* Update the 'rightMembers' array */
+    length = oldMembersSorted.length;
+    for (i = 0; i < length; i++) { /* Update the 'rightMembers' array */
       this.rightMembers.splice(oldMembersSorted[i], 1);
     }
     this.destroyAndRemoveMembers(oldArray); /* Remove visually the desired elements */
@@ -873,8 +904,8 @@
   // Removes all right members from the layout.
   //
   removeAllRightMembers: function(){
-    var membersNumArray = [], i = 0;
-    for (i = 0; i < this.rightMembers.length; i++) {
+    var membersNumArray = [], i = 0, length = this.rightMembers.length;
+    for (i = 0; i < length; i++) {
       membersNumArray.push(i);
     }
     this.removeRightMembers(membersNumArray);
@@ -889,20 +920,24 @@
   // * {{{newMembers}}} type: Array || Object - array of canvases to be added, or reference to single canvas.
   // * {{{position (optional)}}} type: Number - position to add newMembers; if omitted newMembers will be added at the last position.
   addRightMembers: function(newMembers, position){
-    var i = 0;
+    var i = 0, length;
     if (!(typeof newMembers.length === 'number' && !(newMembers.propertyIsEnumerable('length')) && typeof newMembers.splice === 'function')) {
       newMembers = [newMembers];
     }
     if (position > this.rightMembers.length || typeof position === 'undefined') {
       position = this.rightMembers.length;
     }
-    for (i = 0; i < newMembers.length; i++) {
+    
+    length = newMembers.length;
+    for (i = 0; i < length; i++) {
       this.rightMembers.splice(position + i, 0, newMembers[i]);
     }
     position = position * 2;
     position = position + 3;
     position = position + this.leftMembers.length * 2;
-    for (i = 0; i < newMembers.length; i++) {
+
+    length = newMembers.length;
+    for (i = 0; i < length; i++) {
       this.Super('addMembers', [newMembers[i], position]);
       position = position + 1;
       this.Super('addMembers', [isc.HLayout.create({
@@ -964,35 +999,39 @@
   refreshCustomButtons: function(noSetSession){
     var selectedRecords, multipleSelectedRowIds, allProperties, i;
     function doRefresh(buttons, currentValues, hideAllButtons, me) {
-      var i;
-      for (i = 0; i < me.rightMembers.length; i++) { // To disable any button previous defined keyboard shortcut
+      var i, length = me.rightMembers.length;
+      for (i = 0; i < length; i++) { // To disable any button previous defined keyboard shortcut
         me.rightMembers[i].disableShortcut();
       }
-      for (i = 0; i < buttons.length; i++) {
+      length = buttons.length;
+      for (i = 0; i < length; i++) {
         if (buttons[i].updateState) {
           buttons[i].updateState(currentValues, hideAllButtons);
         }
       }
-      for (i = 0; i < me.leftMembers.length; i++) {
+      length = me.leftMembers.length;
+      for (i = 0; i < length; i++) {
         if (me.leftMembers[i].updateState) {
             me.leftMembers[i].updateState();
         }
       }
       if (me.view.isActiveView()) {
         me.defineRightMembersShortcuts(); // To re-calculate the target key for keyboard shortcuts
-        for (i = 0; i < me.rightMembers.length; i++) {
+        length = me.rightMembers.length;
+        for (i = 0; i < length; i++) {
           me.rightMembers[i].enableShortcut(); // To enable each button keyboard shortcut
         }
       }
     }
 
-    var buttons = this.getRightMembers(), buttonContexts = [], currentContext, buttonsByContext = [];
+    var buttons = this.getRightMembers(), buttonContexts = [], 
+      currentContext, buttonsByContext = [], length;
 
     if (buttons.length === 0) {
       return;
     }
-    
-    for (i = 0; i < buttons.length; i++) {
+    length = buttons.length;
+    for (i = 0; i < length; i++) {
       if (!currentContext || currentContext !== buttons[i].contextView) {
         // Adding new context
         currentContext = buttons[i].contextView;
@@ -1028,7 +1067,8 @@
     };
 
     var currentTabCalled = false, me = this;
-    for (iButtonContext = 0; iButtonContext < buttonContexts.length; iButtonContext++) {
+    length = buttonContexts.length;
+    for (iButtonContext = 0; iButtonContext < length; iButtonContext++) {
       currentContext = buttonContexts[iButtonContext];
 
       selectedRecords = currentContext.viewGrid.getSelectedRecords() || [];
@@ -1105,9 +1145,11 @@
   // Used to update state of buttons dynamically on field change
   //
   refreshCustomButtonsView: function (view) {
-    var i, context = view.getContextInfo(false, true, true);
+    var i, context = view.getContextInfo(false, true, true),
+      length;
 
-    for (i=0; i<this.rightMembers.length; i++) {
+    length = this.rightMembers.length;
+    for (i=0; i < length; i++) {
       if (this.rightMembers[i].contextView === view) {
         this.rightMembers[i].updateState(view.getCurrentValues(), false, context);
       }
@@ -1131,15 +1173,16 @@
   rightMembersShortcuts: [],
 
   defineRightMembersShortcuts: function(){
-    var i, j, k, id, character, position;
+    var i, j, k, id, character, position, length, titleLength;
     function isAssignedCharacter(character, me){
-      var n;
+      var n, length;
       if (character === ' ') {
         return true;
       }
       character = character.toString();
       character = character.toUpperCase();
-      for (n = 0; n < me.rightMembersShortcuts.length; n++) {
+      length = me.rightMembersShortcuts.length;
+      for (n = 0; n < length; n++) {
         if (me.rightMembersShortcuts[n][0] === character) {
           return true;
         }
@@ -1148,12 +1191,14 @@
     }
 
     this.rightMembersShortcuts = [];
-    for (i = 0; i < this.rightMembers.length; i++) {
+    length = this.rightMembers.length;
+    for (i = 0; i < length; i++) {
       var title = this.rightMembers[i].realTitle, haveToContinue = true;
       this.rightMembersShortcuts[i] = [];
       if (haveToContinue) { // Check if free character and assign
         haveToContinue = true;
-        for (j = 0; j < title.length; j++) {
+        titleLength = title.length;
+        for (j = 0; j < titleLength; j++) {
           if (!isAssignedCharacter(title.substring(j, j + 1), this)) {
             this.rightMembersShortcuts[i][0] = title.substring(j, j + 1).toUpperCase();
             this.rightMembersShortcuts[i][1] = j + 1;
@@ -1184,8 +1229,10 @@
   },
   
   enableShortcuts: function(){
+    var length;
     if (this.leftMembers) {
-      for (i = 0; i < this.leftMembers.length; i++) {
+      length = this.leftMembers.length;
+      for (i = 0; i < length; i++) {
         if (this.leftMembers[i].enableShortcut) {
           this.leftMembers[i].enableShortcut();
         }
@@ -1193,7 +1240,8 @@
     }
     if (this.rightMembers) {
       this.defineRightMembersShortcuts();
-      for (i = 0; i < this.rightMembers.length; i++) {
+      length = this.rightMembers.length;
+      for (i = 0; i < length; i++) {
         if (this.rightMembers[i].enableShortcut) {
           this.rightMembers[i].enableShortcut();
         }
@@ -1202,15 +1250,18 @@
   },
   
   disableShortcuts: function(){
+    var length;
     if (this.leftMembers) {
-      for (i = 0; i < this.leftMembers.length; i++) {
+      length = this.leftMembers.length;
+      for (i = 0; i < length; i++) {
         if (this.leftMembers[i].disableShortcut) {
           this.leftMembers[i].disableShortcut();
         }
       }
     }
     if (this.rightMembers) {
-      for (i = 0; i < this.rightMembers.length; i++) {
+      length = this.rightMembers.length;
+      for (i = 0; i < length; i++) {
         if (this.rightMembers[i].disableShortcut) {
           this.rightMembers[i].disableShortcut();
         }
@@ -1357,9 +1408,10 @@
 OB.ToolbarUtils = {};
 
 OB.ToolbarUtils.print = function(view, url, directPrint){
-  var selectedRecords = view.viewGrid.getSelectedRecords();
+  var selectedRecords = view.viewGrid.getSelectedRecords(),
+    length = selectedRecords.length;
 
-  if (selectedRecords.length === 0) {
+  if (length === 0) {
     view.messageBar.setMessage(OBMessageBar.TYPE_WARNING, '', OB.I18N.getLabel('OBUIAPP_PrintNoRecordSelected'));
     return;
   }
@@ -1387,7 +1439,7 @@
   }
 
   selectedIds = '';
-  for (i = 0; i < selectedRecords.length; i++) {
+  for (i = 0; i < length; i++) {
     selectedIds += (i > 0 ? ',' : '') + selectedRecords[i].id;
   }
 
@@ -1441,6 +1493,8 @@
     
     // note tabIds is an array of strings, but maybe null/undefined
     registerButton: function(buttonId, clazz, properties, sortOrder, tabIds) {
+      var length;
+      
       if (tabIds && !isc.isA.Array(tabIds)) {
         tabIds = [tabIds];
       }
@@ -1455,14 +1509,15 @@
       };
  
       // already registered, bail
-      for (i = 0; i < this.buttonDefinitions.length; i++) {   
+      length = this.buttonDefinitions.length;
+      for (i = 0; i < length; i++) {   
         if (this.buttonDefinitions[i].buttonId === buttonId) {
           return;
         }
       }
       
       index = this.buttonDefinitions.length;
-      for (i = 0; i < this.buttonDefinitions.length; i++) {   
+      for (i = 0; i < length; i++) {   
         if (this.buttonDefinitions[i].sortOrder > sortOrder) {
           index = i;
           break;
@@ -1482,12 +1537,15 @@
 		  // and pick them up in the correct order
 		  // the return should be an array of button instances created by doing 
 		  //  btnDefinitionClass.create(btnDefinitionProperties);
-		  var result = [], resultIndex = 0, i, validTabId, tabIds;	
-		  for (i = 0; i < this.buttonDefinitions.length; i++) {	
+		  var result = [], resultIndex = 0, i, validTabId, 
+		    tabIds, length = this.buttonDefinitions.length,
+		    tabIdsLength;	
+		  for (i = 0; i < length; i++) {	
 		    tabIds = this.buttonDefinitions[i].tabIds;
 		    validTabId = !tabIds;
 		    if (tabIds) {
-		      for (j = 0; j < tabIds.length; j++) {
+		      tabIdsLength = tabIds.length;
+		      for (j = 0; j < tabIdsLength; j++) {
 		        if (tabIds[j] === tabId) {
 		          validTabId = true;
 		          break;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-keyboard-manager.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-keyboard-manager.js	Fri Sep 09 15:34:14 2011 +0200
@@ -39,12 +39,12 @@
     Shortcuts: {
     
       setPredefinedList: function(RefList){
-        var i;
-        var list = [];
+        var i, list = [], length;
         
         list = OB.PropertyStore.get(RefList);
         if (list) {
-          for (i = 0; i < list.length; i++) {
+          length = list.length;
+          for (i = 0; i < length; i++) {
             this.set(list[i].id, null, null, null, list[i].keyComb);
           }
         }
@@ -168,8 +168,8 @@
       },
 
       getProperty: function(property, element, searchPattern) {
-        var i, position = null;
-        for (i = 0; i < this.list.length; i++) {
+        var i, position = null, length = this.list.length;
+        for (i = 0; i < length; i++) {
           if (typeof this.list[i] === 'undefined') {
             break;
           }
@@ -215,7 +215,7 @@
       },
 
       monitor: function(execLevel){
-        var i, j,
+        var i, j, length = this.list.length,
             position = null,
             pushedKS = {};
         pushedKS.ctrl = false;
@@ -233,7 +233,7 @@
         }
         pushedKS.key = isc.Event.getKey();
 
-        for (i = 0; i < this.list.length; i++) {
+        for (i = 0; i < length; i++) {
           if (typeof this.list[i] === 'undefined' && !execLevel) {
             break;
           }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-property-store.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-property-store.js	Fri Sep 09 15:34:14 2011 +0200
@@ -76,7 +76,7 @@
     //
     set: function(/* String */propertyName, /* Object */ value, windowId, noSetInServer, setAsSystem) {
       var currentValue = OB.Properties[propertyName], data={property: propertyName, system: setAsSystem?true:false},
-          localPropertyName=propertyName, i;
+          localPropertyName=propertyName, i, length;
       if(windowId){
         data.windowId=windowId;
         localPropertyName=propertyName + '_' + windowId;
@@ -92,7 +92,8 @@
       }
 
       // call the listeners
-      for (i = 0; i < this.listeners.length; i++) {
+      length = this.listeners.length;
+      for (i = 0; i < length; i++) {
         this.listeners[i](localPropertyName, currentValue, value);
       }
 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-recent-utilities.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-recent-utilities.js	Fri Sep 09 15:34:14 2011 +0200
@@ -94,8 +94,8 @@
       }
       var currentRecentValue = this.getRecentValue(propertyName);
       // check if there is already an entry for the new recent
-      var currentIndex = -1, i;
-      for (i = 0; i < currentRecentValue.length; i++) {
+      var currentIndex = -1, i, length = currentRecentValue.length;
+      for (i = 0; i < length; i++) {
         // if the title is the same then assume they are the same, only 
         // check this if there is no recentId being used
         if (!currentRecentValue[i].recentId && currentRecentValue[i].tabTitle && 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.js	Fri Sep 09 15:34:14 2011 +0200
@@ -198,8 +198,8 @@
     
     object.customApplyMethod = method;
     
-    var argsString = [], i;
-    for (i = 0; i < parameters.length; i++) {
+    var argsString = [], i, length = parameters.length;
+    for (i = 0; i < length; i++) {
       argsString[i] = 'parameters[' + i + ']';
     }
     
@@ -399,11 +399,12 @@
 // ** {{{OB.Utilities.getPromptString}}} **
 // Translates a string or array of strings to a string with html returns.
 OB.Utilities.getPromptString = function(msg){
-  var msgString = '', i;
+  var msgString = '', i, length;
   if (!isc.isAn.Array(msg)) {
     msg = [msg];
   }
-  for (i = 0; i < msg.length; i++) {
+  length = msg.length;
+  for (i = 0; i < length; i++) {
     msgString += (i > 0 ? '<br>' : '') + msg[i].asHTML();
   }
   return msgString;
@@ -413,9 +414,12 @@
 // where no & is used for character encoding, this is fine for most cases.
 OB.Utilities.getUrlParameters = function(href){
   href = href || window.location.href;
-  var vars = {}, hash, hashes = href.slice(href.indexOf('?') + 1).split('&'), i;
-
-  for (i = 0; i < hashes.length; i++) {
+  var vars = {}, hash, length,
+    hashes = href.slice(href.indexOf('?') + 1).split('&'), i;
+  
+  length = hashes.length;
+  
+  for (i = 0; i < length; i++) {
     hash = hashes[i].split('=');
     if (hash[i] && hash[i].contains('#')) {
       hash[i] = hash[i].substring(0, hash[i].indexOf('#'));
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js	Thu Sep 08 14:14:01 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js	Fri Sep 09 15:34:14 2011 +0200
@@ -91,11 +91,12 @@
     },
 
     findLoadingTab: function(params) {
-      var i;
+      var i, length;
       if (!params.loadingTabId) {
         return null;
       }
-      for (i = 0; i < OB.MainView.TabSet.tabs.length; i++) {
+      length = OB.MainView.TabSet.tabs.length;
+      for (i = 0; i < length; i++) {
         var pane = OB.MainView.TabSet.tabs[i].pane;
         if (pane.viewTabId && pane.isLoadingTab && pane.viewTabId === params.loadingTabId) {
           return OB.MainView.TabSet.tabs[i];