You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/07/28 20:01:18 UTC

incubator-ignite git commit: IGNITE-843 Added support for set focus to specified control.

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-843 b90a6d73b -> 2e4daaa83


IGNITE-843 Added support for set focus to specified control.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/2e4daaa8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/2e4daaa8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/2e4daaa8

Branch: refs/heads/ignite-843
Commit: 2e4daaa83271659e01698ae094e6367cd93624ab
Parents: b90a6d7
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 29 01:01:11 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 29 01:01:11 2015 +0700

----------------------------------------------------------------------
 .../src/main/js/controllers/common-module.js    | 29 +++++++
 .../src/main/js/controllers/models/caches.json  |  7 +-
 .../main/js/controllers/models/clusters.json    | 20 ++---
 .../main/js/controllers/models/metadata.json    | 14 +++-
 .../src/main/js/views/configuration/caches.jade |  4 +-
 .../main/js/views/configuration/clusters.jade   |  4 +-
 .../main/js/views/configuration/metadata.jade   |  4 +-
 .../src/main/js/views/includes/controls.jade    | 84 ++++++++++----------
 8 files changed, 102 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/common-module.js b/modules/web-control-center/src/main/js/controllers/common-module.js
index 8f31397..df2ff19 100644
--- a/modules/web-control-center/src/main/js/controllers/common-module.js
+++ b/modules/web-control-center/src/main/js/controllers/common-module.js
@@ -406,6 +406,35 @@ controlCenterModule.directive('ngEscape', function() {
     };
 });
 
+// Factory function to focus element.
+controlCenterModule.factory('focus', function ($timeout, $window) {
+    return function (id) {
+        // Timeout makes sure that is invoked after any other event has been triggered.
+        // E.g. click events that need to run before the focus or inputs elements that are
+        // in a disabled state but are enabled when those events are triggered.
+        $timeout(function () {
+            var element = $window.document.getElementById(id);
+
+            if (element)
+                element.focus();
+        });
+    };
+});
+
+// Directive to mark elements to focus.
+controlCenterModule.directive('eventFocus', function (focus) {
+    return function (scope, elem, attr) {
+        elem.on(attr.eventFocus, function () {
+            focus(attr.eventFocusId);
+        });
+
+        // Removes bound events in the element itself when the scope is destroyed
+        scope.$on('$destroy', function () {
+            element.off(attr.eventFocus);
+        });
+    };
+});
+
 // Navigation bar controller.
 controlCenterModule.controller('activeLink', [
     '$scope', function ($scope) {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/controllers/models/caches.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/caches.json b/modules/web-control-center/src/main/js/controllers/models/caches.json
index 6f334d2..932eecc 100644
--- a/modules/web-control-center/src/main/js/controllers/models/caches.json
+++ b/modules/web-control-center/src/main/js/controllers/models/caches.json
@@ -22,7 +22,8 @@
       "type": "text",
       "model": "name",
       "required": true,
-      "placeholder": "Input name"
+      "placeholder": "Input name",
+      "id": "defaultFocusId"
     },
     {
       "label": "Mode",
@@ -386,6 +387,8 @@
           "model": "indexedTypes",
           "keyName": "keyClass",
           "valueName": "valueClass",
+          "focusNewItemId": "newIndexedType",
+          "focusCurItemId": "curIndexedType",
           "addTip": "Add new key and value classes to indexed types.",
           "removeTip": "Remove item from indexed types.",
           "tip": [
@@ -398,6 +401,8 @@
           "model": "sqlFunctionClasses",
           "editIdx": -1,
           "placeholder": "SQL function full class name",
+          "focusNewItemId": "newSqlFxField",
+          "focusCurItemId": "curSqlFxField",
           "addTip": "Add new user-defined functions for SQL queries.",
           "removeTip": "Remove user-defined function.",
           "tableTip": [

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/clusters.json b/modules/web-control-center/src/main/js/controllers/models/clusters.json
index 0ffb1b3..36d0dd8 100644
--- a/modules/web-control-center/src/main/js/controllers/models/clusters.json
+++ b/modules/web-control-center/src/main/js/controllers/models/clusters.json
@@ -29,7 +29,8 @@
       "type": "text",
       "model": "name",
       "required": true,
-      "placeholder": "Input name"
+      "placeholder": "Input name",
+      "id": "defaultFocusId"
     },
     {
       "label": "Caches",
@@ -68,6 +69,8 @@
               "reordering": true,
               "ipaddress": true,
               "placeholder": "IP address:port",
+              "focusNewItemId": "newIpAddress",
+              "focusCurItemId": "curIpAddress",
               "addTip": "Add new address.",
               "removeTip": "Remove address.",
               "tip": [
@@ -157,7 +160,6 @@
               "required": true,
               "path": "discovery.S3",
               "model": "bucketName",
-              "placeholder": "",
               "tip": [
                 "Bucket name for IP finder."
               ]
@@ -176,7 +178,6 @@
               "type": "text",
               "path": "discovery.Cloud",
               "model": "credential",
-              "placeholder": "",
               "tip": [
                 "Credential that is used during authentication on the cloud.",
                 "Depending on a cloud platform it can be a password or access key."
@@ -187,7 +188,6 @@
               "type": "text",
               "path": "discovery.Cloud",
               "model": "credentialPath",
-              "placeholder": "",
               "tip": [
                 "Path to a credential that is used during authentication on the cloud.",
                 "Access key or private key should be stored in a plain or PEM file without a passphrase."
@@ -199,7 +199,6 @@
               "required": true,
               "path": "discovery.Cloud",
               "model": "identity",
-              "placeholder": "",
               "tip": [
                 "Identity that is used as a user name during a connection to the cloud.",
                 "Depending on a cloud platform it can be an email address, user name, etc."
@@ -211,7 +210,6 @@
               "required": true,
               "path": "discovery.Cloud",
               "model": "provider",
-              "placeholder": "",
               "tip": [
                 "Cloud provider to use."
               ]
@@ -222,7 +220,8 @@
               "path": "discovery.Cloud",
               "model": "regions",
               "editIdx": -1,
-              "placeholder": "",
+              "focusNewItemId": "newRegion",
+              "focusCurItemId": "curRegion",
               "addTip": "Add new region.",
               "removeTip": "Remove region.",
               "tableTip": [
@@ -240,7 +239,8 @@
               "path": "discovery.Cloud",
               "model": "zones",
               "editIdx": -1,
-              "placeholder": "",
+              "focusNewItemId": "newZone",
+              "focusCurItemId": "curZone",
               "addTip": "Add new zone.",
               "removeTip": "Remove zone.",
               "tableTip": [
@@ -263,7 +263,6 @@
               "required": true,
               "path": "discovery.GoogleStorage",
               "model": "projectName",
-              "placeholder": "",
               "tip": [
                 "Google Cloud Platforms project name.",
                 "Usually this is an auto generated project number (ex. 208709979073) that can be found in 'Overview' section of Google Developer Console."
@@ -275,7 +274,6 @@
               "required": true,
               "path": "discovery.GoogleStorage",
               "model": "bucketName",
-              "placeholder": "",
               "tip": [
                 "Google Cloud Storage bucket name.",
                 "If the bucket doesn't exist Ignite will automatically create it.",
@@ -288,7 +286,6 @@
               "required": true,
               "path": "discovery.GoogleStorage",
               "model": "serviceAccountP12FilePath",
-              "placeholder": "",
               "tip": [
                 "Full path to the private key in PKCS12 format of the Service Account."
               ]
@@ -299,7 +296,6 @@
               "required": true,
               "path": "discovery.GoogleStorage",
               "model": "accountId",
-              "placeholder": "",
               "tip": [
                 "Service account ID (typically an e-mail address)."
               ]

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/metadata.json b/modules/web-control-center/src/main/js/controllers/models/metadata.json
index 85ac5aa..a9b60de 100644
--- a/modules/web-control-center/src/main/js/controllers/models/metadata.json
+++ b/modules/web-control-center/src/main/js/controllers/models/metadata.json
@@ -30,7 +30,8 @@
       "type": "text",
       "model": "name",
       "required": true,
-      "placeholder": "Input name"
+      "placeholder": "Input name",
+      "id": "defaultFocusId"
     },
     {
       "label": "Metadata for",
@@ -119,6 +120,8 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'both' && backupItem.kind != 'query'",
+      "focusNewItemId": "newQryField",
+      "focusCurItemId": "curQryField",
       "addTip": "Add field to query.",
       "removeTip": "Remove field.",
       "tip": [
@@ -132,6 +135,8 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'both' && backupItem.kind != 'query'",
+      "focusNewItemId": "newAscField",
+      "focusCurItemId": "curAscField",
       "addTip": "Add field to index in ascending order.",
       "removeTip": "Remove field.",
       "tip": [
@@ -145,6 +150,8 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'both' && backupItem.kind != 'query'",
+      "focusNewItemId": "newDescField",
+      "focusCurItemId": "curDescField",
       "addTip": "Add field to index in descending order.",
       "removeTip": "Remove field.",
       "tip": [
@@ -157,6 +164,8 @@
       "model": "textFields",
       "hide": "backupItem.kind != 'both' && backupItem.kind != 'query'",
       "placeholder": "Field name",
+      "focusNewItemId": "newTextField",
+      "focusCurItemId": "curTextField",
       "addTip": "Add field to index as text.",
       "removeTip": "Remove field.",
       "tableTip": [
@@ -218,7 +227,6 @@
       "type": "number",
       "model": "port",
       "max": 65535,
-      "placeholder": "",
       "tip": [
         "Port number for connecting to database."
       ]
@@ -227,7 +235,6 @@
       "label": "User",
       "type": "text",
       "model": "user",
-      "placeholder": "",
       "tip": [
         "User name for connecting to database."
       ]
@@ -236,7 +243,6 @@
       "label": "Password",
       "type": "password",
       "model": "password",
-      "placeholder": "",
       "tip": [
         "Password for connecting to database.",
         "Note, password would not be saved."

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/caches.jade b/modules/web-control-center/src/main/js/views/configuration/caches.jade
index 579b5aa..15d8f40 100644
--- a/modules/web-control-center/src/main/js/views/configuration/caches.jade
+++ b/modules/web-control-center/src/main/js/views/configuration/caches.jade
@@ -34,9 +34,9 @@ block content
                     tbody
                         tr(ng-repeat='row in caches track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
+                                a(event-focus='click' event-focus-id='defaultFocusId' ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
         .padding-top-dflt
-            button.btn.btn-primary(ng-click='createItem()') Add cache
+            button.btn.btn-primary(event-focus='click' event-focus-id='defaultFocusId' ng-click='createItem()') Add cache
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
             div(bs-collapse data-start-collapsed='false')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/clusters.jade b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
index 882a2b9..239a31f 100644
--- a/modules/web-control-center/src/main/js/views/configuration/clusters.jade
+++ b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
@@ -34,9 +34,9 @@ block content
                     tbody
                         tr(ng-repeat='row in clusters track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
+                                a(event-focus='click' event-focus-id='defaultFocusId' ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
         .padding-top-dflt
-            button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
+            button.btn.btn-primary(event-focus='click' event-focus-id='defaultFocusId' ng-click='createItem()') &nbspAdd cluster
             label(style='margin-left: 10px; margin-right: 10px') Use template:
             button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/metadata.jade b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
index e01eaa8..e0cc76f 100644
--- a/modules/web-control-center/src/main/js/views/configuration/metadata.jade
+++ b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
@@ -34,9 +34,9 @@ block content
                     tbody
                         tr(ng-repeat='row in metadatas track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+                                a(event-focus='click' event-focus-id='defaultFocusId' ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
         .padding-top-dflt
-            button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
+            button.btn.btn-primary(event-focus='click' event-focus-id='defaultFocusId' ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
             label(style='margin-left: 6px; margin-right: 10px') For:
             button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e4daaa8/modules/web-control-center/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/controls.jade b/modules/web-control-center/src/main/js/views/includes/controls.jade
index 94cdda4..e9fe71b 100644
--- a/modules/web-control-center/src/main/js/views/includes/controls.jade
+++ b/modules/web-control-center/src/main/js/views/includes/controls.jade
@@ -40,8 +40,8 @@ mixin ico-exclamation(mdl, err, msg)
 mixin btn-save(show, click)
     i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click bs-tooltip data-title='Save item')
 
-mixin btn-add(click, tip)
-    i.tipField.fa.fa-plus(ng-click=click bs-tooltip=tip)
+mixin btn-add(click, tip, focusId)
+    i.tipField.fa.fa-plus(ng-click=click bs-tooltip=tip event-focus='click' event-focus-id=focusId)
 
 mixin btn-remove(click, tip)
     i.tipField.fa.fa-remove(ng-click=click bs-tooltip=tip data-trigger='hover')
@@ -52,7 +52,7 @@ mixin btn-up(show, click)
 mixin btn-down(show, click)
     i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click bs-tooltip data-title='Move item down')
 
-mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes)
+mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes, focusId)
     .col-sm-6(style='float: right')
         if valueJavaBuildInTypes
             input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder bs-typeahead data-min-length='1' bs-options='javaType for javaType in javaBuildInTypes' ng-escape='tableReset()')
@@ -61,32 +61,32 @@ mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder, keyJav
     label.fieldSep /
     .input-tip
         if keyJavaBuildInTypes
-            input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead data-min-length='1' bs-options='javaType for javaType in javaBuildInTypes' ng-escape='tableReset()')
+            input.form-control(id=focusId type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead data-min-length='1' bs-options='javaType for javaType in javaBuildInTypes' ng-escape='tableReset()')
         else
-            input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder ng-escape='tableReset()')
+            input.form-control(id=focusId type='text' ng-model=keyModel placeholder=keyPlaceholder ng-escape='tableReset()')
 
 mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes)
     .col-sm-6
         label.table-header #{header}:
         +tipLabel('field.tip')
-        +btn-add('tableNewItem(field)', 'field.addTip')
+        +btn-add('tableNewItem(field)', 'field.addTip', '{{::field.focusNewItemId}}')
         .table-details(ng-show='(#{tblMdl} && #{tblMdl}.length > 0) || tableNewItemActive(field)')
             table.links-edit.col-sm-12(st-table=tblMdl)
                 tbody
                     tr(ng-repeat='item in #{tblMdl}')
                         td.col-sm-12
                             div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
+                                a.labelFormField(event-focus='click' event-focus-id='{{::field.focusCurItemId}}' ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
                                 +btn-remove('tableRemove(backupItem, field, $index)', 'field.removeTip')
-                            div(ng-show='tableEditing(field, $index)')
+                            div(ng-if='tableEditing(field, $index)')
                                 label.labelField {{$index + 1}})
                                 +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
-                                +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes)
+                                +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes, '{{::field.focusCurItemId}}')
                 tfoot(ng-show='tableNewItemActive(field)')
                     tr
                         td.col-sm-12
                             +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
-                            +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes)
+                            +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder, keyJavaBuildInTypes, valueJavaBuildInTypes, '{{::field.focusNewItemId}}')
 
 mixin details-row
     - var lblDetailClasses = ['col-sm-4', 'details-label']
@@ -139,15 +139,15 @@ mixin details-row
                     tr(ng-repeat='item in #{detailMdl} track by $index')
                         td
                             div(ng-show='!tableEditing(detail, $index)')
-                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
+                                a.labelFormField(event-focus='click' event-focus-id='{{::detail.focusCurItemId}}' ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
                                 +btn-remove('tableRemove(backupItem, detail, $index)', 'detail.removeTip')
                                 +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
                                 +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
-                            div(ng-show='tableEditing(detail, $index)')
+                            div(ng-if='tableEditing(detail, $index)')
                                 label.labelField {{$index + 1}})
                                 +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
                                 .input-tip.form-group.has-feedback
-                                    input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{::detail.placeholder}}' ng-escape='tableReset()')&attributes(customValidators)
+                                    input.form-control(id='{{::detail.focusCurItemId}}' name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{::detail.placeholder}}' ng-escape='tableReset()')&attributes(customValidators)
                                     +ico-exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
             button.btn.btn-primary.fieldButton(ng-disabled='!newValue' ng-click='tableSimpleSave(tableSimpleValid, backupItem, detail, newValue, -1)') Add
             +tipField('detail.tip')
@@ -168,7 +168,7 @@ mixin table-db-field-edit(databaseName, databaseType, javaName, javaType)
     .input-tip
         input.form-control(type='text' ng-model=databaseName placeholder='DB name' ng-escape='tableReset()')
 
-mixin table-group-item-edit(fieldName, className, direction)
+mixin table-group-item-edit(fieldName, className, direction, focusId)
     div(style='width: 15%; float: right')
         button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
     label.fieldSep /
@@ -176,7 +176,7 @@ mixin table-group-item-edit(fieldName, className, direction)
         input.form-control(type='text' ng-model=className placeholder='Class name' bs-typeahead data-min-length='1' bs-options='javaType for javaType in javaBuildInTypes' ng-escape='tableReset()')
     label.fieldSep /
     .input-tip
-        input.form-control(type='text' ng-model=fieldName placeholder='Field name' ng-escape='tableReset()')
+        input.form-control(id=focusId type='text' ng-model=fieldName placeholder='Field name' ng-escape='tableReset()')
 
 mixin form-row
     +form-row-custom(['col-sm-2'], ['col-sm-4'])
@@ -200,7 +200,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
             div(class=fieldClasses)
                 +tipField('field.tip')
                 .input-tip
-                    input.form-control(type='text' placeholder='{{::field.placeholder}}')&attributes(fieldCommon)
+                    input.form-control(id='{{::field.id}}' type='text' placeholder='{{::field.placeholder}}')&attributes(fieldCommon)
         div(ng-switch-when='withJavaBuildInTypes' ng-hide=fieldHide)
             label(class=lblClasses ng-class=fieldRequiredClass) {{::field.label}}:
             div(class=fieldClasses)
@@ -251,7 +251,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-6
                 label.table-header {{::field.label}}:
                 +tipLabel('field.tableTip')
-                +btn-add('tableNewItem(field)', 'field.addTip')
+                +btn-add('tableNewItem(field)', 'field.addTip', '{{::field.focusNewItemId}}')
             .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
                 .col-sm-6
                     .table-details
@@ -260,21 +260,21 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                 tr(ng-repeat='item in #{fieldMdl} track by $index')
                                     td.col-sm-12
                                         div(ng-show='!tableEditing(field, $index)')
-                                            a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
+                                            a.labelFormField(event-focus='click' event-focus-id='{{::field.focusCurItemId}}' ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
                                             +btn-remove('tableRemove(backupItem, field, $index)', 'field.removeTip')
                                             +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
                                             +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
-                                        div(ng-show='tableEditing(field, $index)')
+                                        div(ng-if='tableEditing(field, $index)')
                                             label.labelField {{$index + 1}})
                                             +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
                                             .input-tip
-                                                input.form-control(type='text' ng-model='curValue' placeholder='{{::field.placeholder}}' ng-enter='tableSimpleSaveVisible(curValue) && tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)' ng-escape='tableReset()')
+                                                input.form-control(id='{{::field.focusCurItemId}}' type='text' ng-model='curValue' placeholder='{{::field.placeholder}}' ng-enter='tableSimpleSaveVisible(curValue) && tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)' ng-escape='tableReset()')
                             tfoot(ng-show='tableNewItemActive(field)')
                                 tr
                                     td.col-sm-12
                                         +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
                                         .input-tip
-                                            input.form-control(type='text' ng-model='newValue' placeholder='{{::field.placeholder}}' ng-enter='tableSimpleSaveVisible(newValue) && tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)' ng-escape='tableReset()')
+                                            input.form-control(id='{{::field.focusNewItemId}}' type='text' ng-model='newValue' placeholder='{{::field.placeholder}}' ng-enter='tableSimpleSaveVisible(newValue) && tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)' ng-escape='tableReset()')
         div(ng-switch-when='indexedTypes')
             +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name', true, false)
         div(ng-switch-when='queryFields' ng-hide=fieldHide)
@@ -283,7 +283,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-6
                 label.table-header {{::field.label}}:
                 +tipLabel('field.tip')
-                +btn-add('tableNewItem(field)', 'field.addTip')
+                +btn-add('tableNewItem(field)', 'field.addTip', 'field.focusNewItemId')
             .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
                 .col-sm-6
                     .table-details
@@ -307,7 +307,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-6
                 label.table-header {{::field.label}}:
                 +tipLabel('field.tip')
-                +btn-add('tableNewItem(field)', 'field.addTip')
+                +btn-add('tableNewItem(field)', 'field.addTip', 'newGroupId')
             .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
                 .col-sm-6
                     .table-details
@@ -317,32 +317,34 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                     td.col-sm-12
                                         div
                                             .col-sm-12(ng-show='!tableEditing(field, $index)')
-                                                a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+                                                a.labelFormField(event-focus='click' event-focus-id='curGroupId' ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
                                                 +btn-remove('tableRemove(backupItem, field, $index)', 'field.removeTip')
-                                                +btn-add('tableGroupNewItem($index)', 'field.addItemTip')
-                                            div(ng-show='tableEditing(field, $index)')
+                                                +btn-add('tableGroupNewItem($index)', 'field.addItemTip', 'newGroupItemId')
+                                            div(ng-if='tableEditing(field, $index)')
                                                 label.labelField {{$index + 1}})
                                                 +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
                                                 .input-tip
-                                                    input.form-control(type='text' ng-model='curGroupName' placeholder='Index name' ng-enter='tableGroupSaveVisible(curGroupName) && tableGroupSave(curGroupName, $index)' ng-escape='tableReset()')
+                                                    input#curGroupId.form-control(type='text' ng-model='curGroupName' placeholder='Index name' ng-enter='tableGroupSaveVisible(curGroupName) && tableGroupSave(curGroupName, $index)' ng-escape='tableReset()')
                                             div
                                                 table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
-                                                    tr(ng-repeat='groupItem in group.fields')
-                                                        td
-                                                            div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
-                                                                a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction ? "DESC" : "ASC"}}
-                                                                +btn-remove('tableRemoveGroupItem(group, $index)', 'field.removeItemTip')
-                                                            div(ng-show='tableGroupItemEditing(groupIndex, $index)')
-                                                                label.labelField {{$index + 1}})
-                                                                +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
-                                                                +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
-                                                    tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
-                                                        td
-                                                            +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
-                                                            +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+                                                    tbody
+                                                        tr(ng-repeat='groupItem in group.fields')
+                                                            td
+                                                                div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
+                                                                    a.labelFormField(event-focus='click' event-focus-id='curGroupItemId' ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction ? "DESC" : "ASC"}}
+                                                                    +btn-remove('tableRemoveGroupItem(group, $index)', 'field.removeItemTip')
+                                                                div(ng-if='tableGroupItemEditing(groupIndex, $index)')
+                                                                    label.labelField {{$index + 1}})
+                                                                    +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
+                                                                    +table-group-item-edit('curFieldName', 'curClassName', 'curDirection', 'curGroupItemId')
+                                                    tfoot(ng-if='tableGroupNewItemActive(groupIndex)')
+                                                        tr.col-sm-12(style='padding-left: 18px')
+                                                            td
+                                                                +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+                                                                +table-group-item-edit('newFieldName', 'newClassName', 'newDirection', 'newGroupItemId')
                             tfoot(ng-show='tableNewItemActive(field)')
                                 tr
                                     td.col-sm-12
                                         +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
                                         .input-tip
-                                            input.form-control(type='text' ng-model='newGroupName' placeholder='Group name' ng-enter='tableGroupSaveVisible(newGroupName) && tableGroupSave(newGroupName, -1)' ng-escape='tableReset()')
\ No newline at end of file
+                                            input#newGroupId.form-control(type='text' ng-model='newGroupName' placeholder='Group name' ng-enter='tableGroupSaveVisible(newGroupName) && tableGroupSave(newGroupName, -1)' ng-escape='tableReset()')
\ No newline at end of file