172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved.
272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// found in the LICENSE file.
472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsencr.define('options', function() {
672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const DeletableItem = options.DeletableItem;
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const DeletableItemList = options.DeletableItemList;
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  /**
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * Creates a new list item with support for inline editing.
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * @constructor
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * @extends {options.DeletableListItem}
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   */
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  function InlineEditableItem() {
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    var el = cr.doc.createElement('div');
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InlineEditableItem.decorate(el);
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return el;
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  /**
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * Decorates an element as a inline-editable list item. Note that this is
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * a subclass of DeletableItem.
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   * @param {!HTMLElement} el The element to decorate.
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen   */
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  InlineEditableItem.decorate = function(el) {
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    el.__proto__ = InlineEditableItem.prototype;
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    el.decorate();
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  };
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  InlineEditableItem.prototype = {
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    __proto__: DeletableItem.prototype,
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Whether or not this item can be edited.
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    editable_: true,
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * Whether or not this is a placeholder for adding a new item.
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @type {boolean}
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @private
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     */
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    isPlaceholder_: false,
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    /**
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * Fields associated with edit mode.
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @type {array}
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @private
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     */
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    editFields_: null,
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    /**
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Whether or not the current edit should be considered cancelled, rather
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * than committed, when editing ends.
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    editCancelled_: true,
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    /**
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * The editable item corresponding to the last click, if any. Used to decide
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * initial focus when entering edit mode.
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * @type {HTMLElement}
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * @private
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     */
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    editClickTarget_: null,
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /** @inheritDoc */
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    decorate: function() {
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      DeletableItem.prototype.decorate.call(this);
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.editFields_ = [];
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      this.addEventListener('mousedown', this.handleMouseDown_.bind(this));
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.addEventListener('keydown', this.handleKeyDown_.bind(this));
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.addEventListener('leadChange', this.handleLeadChange_);
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /** @inheritDoc */
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    selectionChanged: function() {
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.updateEditState();
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Called when this element gains or loses 'lead' status. Updates editing
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * mode accordingly.
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    handleLeadChange_: function() {
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.updateEditState();
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Updates the edit state based on the current selected and lead states.
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    updateEditState: function() {
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (this.editable)
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.editing = this.selected && this.lead;
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Whether the user is currently editing the list item.
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    get editing() {
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return this.hasAttribute('editing');
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    set editing(editing) {
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (this.editing == editing)
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        return;
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (editing)
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.setAttribute('editing', '');
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      else
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.removeAttribute('editing');
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (editing) {
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.editCancelled_ = false;
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        cr.dispatchSimpleEvent(this, 'edit', true);
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        var focusElement = this.editClickTarget_ || this.initialFocusElement;
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        this.editClickTarget_ = null;
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // When this is called in response to the selectedChange event,
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // the list grabs focus immediately afterwards. Thus we must delay
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // our focus grab.
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        var self = this;
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (focusElement) {
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          window.setTimeout(function() {
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            // Make sure we are still in edit mode by the time we execute.
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            if (self.editing) {
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              focusElement.focus();
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              focusElement.select();
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            }
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          }, 50);
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        }
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      } else {
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (!this.editCancelled_ && this.hasBeenEdited &&
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            this.currentInputIsValid) {
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          this.updateStaticValues_();
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          cr.dispatchSimpleEvent(this, 'commitedit', true);
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        } else {
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          this.resetEditableValues_();
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          cr.dispatchSimpleEvent(this, 'canceledit', true);
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        }
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Whether the item is editable.
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    get editable() {
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return this.editable_;
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    set editable(editable) {
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.editable_ = editable;
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!editable)
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.editing = false;
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * Whether the item is a new item placeholder.
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @type {boolean}
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     */
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    get isPlaceholder() {
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return this.isPlaceholder_;
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    set isPlaceholder(isPlaceholder) {
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.isPlaceholder_ = isPlaceholder;
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (isPlaceholder)
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.deletable = false;
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    /**
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * The HTML element that should have focus initially when editing starts,
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * if a specific element wasn't clicked.
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Defaults to the first <input> element; can be overriden by subclasses if
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * a different element should be focused.
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {HTMLElement}
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    get initialFocusElement() {
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return this.contentElement.querySelector('input');
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Whether the input in currently valid to submit. If this returns false
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * when editing would be submitted, either editing will not be ended,
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * or it will be cancelled, depending on the context.
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Can be overrided by subclasses to perform input validation.
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    get currentInputIsValid() {
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Returns true if the item has been changed by an edit.
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Can be overrided by subclasses to return false when nothing has changed
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * to avoid unnecessary commits.
20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @type {boolean}
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    get hasBeenEdited() {
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Returns a div containing an <input>, as well as static text if
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * isPlaceholder is not true.
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @param {string} text The text of the cell.
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @return {HTMLElement} The HTML element for the cell.
21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    createEditableTextCell: function(text) {
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      var container = this.ownerDocument.createElement('div');
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!this.isPlaceholder) {
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        var textEl = this.ownerDocument.createElement('div');
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        textEl.className = 'static-text';
22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        textEl.textContent = text;
22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        textEl.setAttribute('displaymode', 'static');
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        container.appendChild(textEl);
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      var inputEl = this.ownerDocument.createElement('input');
22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      inputEl.type = 'text';
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      inputEl.value = text;
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!this.isPlaceholder) {
23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        inputEl.setAttribute('displaymode', 'edit');
23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        inputEl.staticVersion = textEl;
23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      container.appendChild(inputEl);
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.editFields_.push(inputEl);
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return container;
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Resets the editable version of any controls created by createEditable*
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * to match the static text.
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    resetEditableValues_: function() {
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var editFields = this.editFields_;
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      for (var i = 0; i < editFields.length; i++) {
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        var staticLabel = editFields[i].staticVersion;
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (!staticLabel && !this.isPlaceholder)
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          continue;
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (editFields[i].tagName == 'INPUT') {
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          editFields[i].value =
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            this.isPlaceholder ? '' : staticLabel.textContent;
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Add more tag types here as new createEditable* methods are added.
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        editFields[i].setCustomValidity('');
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Sets the static version of any controls created by createEditable*
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * to match the current value of the editable version. Called on commit so
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * that there's no flicker of the old value before the model updates.
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    updateStaticValues_: function() {
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var editFields = this.editFields_;
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      for (var i = 0; i < editFields.length; i++) {
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        var staticLabel = editFields[i].staticVersion;
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (!staticLabel)
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          continue;
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (editFields[i].tagName == 'INPUT')
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          staticLabel.textContent = editFields[i].value;
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Add more tag types here as new createEditable* methods are added.
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Called a key is pressed. Handles committing and cancelling edits.
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @param {Event} e The key down event.
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    handleKeyDown_: function(e) {
28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!this.editing)
28672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        return;
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      var endEdit = false;
28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      switch (e.keyIdentifier) {
29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        case 'U+001B':  // Esc
29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          this.editCancelled_ = true;
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          endEdit = true;
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          break;
29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        case 'Enter':
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          if (this.currentInputIsValid)
29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            endEdit = true;
29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          break;
29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (endEdit) {
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Blurring will trigger the edit to end; see InlineEditableItemList.
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        this.ownerDocument.activeElement.blur();
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Make sure that handled keys aren't passed on and double-handled.
30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // (e.g., esc shouldn't both cancel an edit and close a subpage)
30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        e.stopPropagation();
30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    /**
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * Called when the list item is clicked. If the click target corresponds to
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * an editable item, stores that item to focus when edit mode is started.
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * @param {Event} e The mouse down event.
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     * @private
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen     */
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    handleMouseDown_: function(e) {
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!this.editable || this.editing)
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return;
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      var clickTarget = e.target;
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var editFields = this.editFields_;
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      for (var i = 0; i < editFields.length; i++) {
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (editFields[i] == clickTarget ||
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            editFields[i].staticVersion == clickTarget) {
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          this.editClickTarget_ = editFields[i];
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          return;
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    },
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  };
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  var InlineEditableItemList = cr.ui.define('list');
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  InlineEditableItemList.prototype = {
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    __proto__: DeletableItemList.prototype,
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /** @inheritDoc */
33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    decorate: function() {
33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      DeletableItemList.prototype.decorate.call(this);
33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.setAttribute('inlineeditable', '');
34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      this.addEventListener('hasElementFocusChange',
34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                            this.handleListFocusChange_);
34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    /**
34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * Called when the list hierarchy as a whole loses or gains focus; starts
34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * or ends editing for the lead item if necessary.
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @param {Event} e The change event.
34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     * @private
34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     */
35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    handleListFocusChange_: function(e) {
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex);
35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (leadItem) {
35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (e.newValue)
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          leadItem.updateEditState();
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        else
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          leadItem.editing = false;
35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    },
35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  };
36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Export
36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return {
36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InlineEditableItem: InlineEditableItem,
36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InlineEditableItemList: InlineEditableItemList,
36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  };
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen});
367