Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / options / inline_editable_list.js
index ec65e43..1461fca 100644 (file)
@@ -9,7 +9,7 @@ cr.define('options', function() {
   /**
    * Creates a new list item with support for inline editing.
    * @constructor
-   * @extends {options.DeletableListItem}
+   * @extends {options.DeletableItem}
    */
   function InlineEditableItem() {
     var el = cr.doc.createElement('div');
@@ -46,7 +46,7 @@ cr.define('options', function() {
 
     /**
      * Fields associated with edit mode.
-     * @type {array}
+     * @type {Array}
      * @private
      */
     editFields_: null,
@@ -95,10 +95,8 @@ cr.define('options', function() {
      * Updates the edit state based on the current selected and lead states.
      */
     updateEditState: function() {
-      if (this.editable) {
-        this.editing = this.selected && this.lead &&
-          !this.isExtraFocusableControl(document.activeElement);
-      }
+      if (this.editable)
+        this.editing = this.selected && this.lead;
     },
 
     /**
@@ -126,12 +124,24 @@ cr.define('options', function() {
         this.editClickTarget_ = null;
 
         if (focusElement) {
-          focusElement.focus();
-          // select() doesn't work well in mousedown event handler.
-          setTimeout(function() {
-              if (focusElement.ownerDocument.activeElement == focusElement)
-                focusElement.select();
-          }, 0);
+          var self = this;
+          // We should delay to give focus on |focusElement| if this is called
+          // in mousedown event handler. If we did give focus immediately, Blink
+          // would try to focus on an ancestor of the mousedown target element,
+          // and remove focus from |focusElement|.
+          if (focusElement.staticVersion &&
+              focusElement.staticVersion.hasAttribute('tabindex')) {
+            setTimeout(function() {
+              if (self.editing) {
+                if (focusElement.disabled)
+                  self.parentNode.focus();
+                self.focusAndMaybeSelect_(focusElement);
+              }
+              focusElement.staticVersion.removeAttribute('tabindex');
+            }, 0);
+          } else {
+            this.focusAndMaybeSelect_(focusElement);
+          }
         }
       } else {
         if (!this.editCancelled_ && this.hasBeenEdited &&
@@ -149,6 +159,18 @@ cr.define('options', function() {
     },
 
     /**
+     * Focus on the specified element, and select the editable text in it
+     * if possible.
+     * @param {!Element} control An element to be focused.
+     * @private
+     */
+    focusAndMaybeSelect_: function(control) {
+      control.focus();
+      if (control.tagName == 'INPUT')
+        control.select();
+    },
+
+    /**
      * Whether the item is editable.
      * @type {boolean}
      */
@@ -214,10 +236,11 @@ cr.define('options', function() {
      * @private
      */
     createEditableTextCell: function(text) {
-      var container = this.ownerDocument.createElement('div');
-
+      var container = /** @type {HTMLElement} */(
+          this.ownerDocument.createElement('div'));
+      var textEl = null;
       if (!this.isPlaceholder) {
-        var textEl = this.ownerDocument.createElement('div');
+        textEl = this.ownerDocument.createElement('div');
         textEl.className = 'static-text';
         textEl.textContent = text;
         textEl.setAttribute('displaymode', 'static');
@@ -229,7 +252,6 @@ cr.define('options', function() {
       inputEl.value = text;
       if (!this.isPlaceholder) {
         inputEl.setAttribute('displaymode', 'edit');
-        inputEl.staticVersion = textEl;
       } else {
         // At this point |this| is not attached to the parent list yet, so give
         // a short timeout in order for the attachment to occur.
@@ -244,14 +266,34 @@ cr.define('options', function() {
         }, 50);
       }
 
-      inputEl.addEventListener('focus', this.handleFocus_.bind(this));
+      // In some cases 'focus' event may arrive before 'input'.
+      // To make sure revalidation is triggered we postpone 'focus' handling.
+      var handler = this.handleFocus_.bind(this);
+      inputEl.addEventListener('focus', function() {
+        window.setTimeout(function() {
+          if (inputEl.ownerDocument.activeElement == inputEl)
+            handler();
+        }, 0);
+      });
       container.appendChild(inputEl);
-      this.editFields_.push(inputEl);
+      this.addEditField(inputEl, textEl);
 
       return container;
     },
 
     /**
+     * Register an edit field.
+     * @param {!Element} control An editable element. It's a form control
+     *     element typically.
+     * @param {Element} staticElement An element representing non-editable
+     *     state.
+     */
+    addEditField: function(control, staticElement) {
+      control.staticVersion = staticElement;
+      this.editFields_.push(control);
+    },
+
+    /**
      * Resets the editable version of any controls created by createEditable*
      * to match the static text.
      * @private
@@ -337,13 +379,10 @@ cr.define('options', function() {
         return;
 
       var clickTarget = e.target;
-      if (this.isExtraFocusableControl(clickTarget)) {
-        clickTarget.focus();
-        return;
-      }
-
       var editFields = this.editFields_;
       for (var i = 0; i < editFields.length; i++) {
+        if (editFields[i].staticVersion == clickTarget)
+          clickTarget.tabIndex = 0;
         if (editFields[i] == clickTarget ||
             editFields[i].staticVersion == clickTarget) {
           this.editClickTarget_ = editFields[i];
@@ -351,17 +390,6 @@ cr.define('options', function() {
         }
       }
     },
-
-    /**
-     * Check if the specified element is a focusable form control which is in
-     * the list item and not in |editFields_|.
-     * @param {!Element} element An element.
-     * @return {boolean} Returns true if the element is one of focusable
-     *     controls in this list item.
-     */
-    isExtraFocusableControl: function(element) {
-      return false;
-    },
   };
 
   /**
@@ -379,6 +407,10 @@ cr.define('options', function() {
   }
   handleWindowBlurs();
 
+  /**
+   * @constructor
+   * @extends {options.DeletableItemList}
+   */
   var InlineEditableItemList = cr.ui.define('list');
 
   InlineEditableItemList.prototype = {
@@ -396,6 +428,9 @@ cr.define('options', function() {
       this.setAttribute('inlineeditable', '');
       this.addEventListener('hasElementFocusChange',
                             this.handleListFocusChange_);
+      // <list> isn't focusable by default, but cr.ui.List defaults tabindex to
+      // 0 if it's not set.
+      this.tabIndex = -1;
     },
 
     /**