1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7
8/**
9 * DefaultActionDialog contains a message, a list box, an ok button, and a
10 * cancel button.
11 * This dialog should be used as action picker for file operations.
12 */
13cr.define('cr.filebrowser', function() {
14
15  /**
16   * Creates dialog in DOM tree.
17   *
18   * @param {HTMLElement} parentNode Node to be parent for this dialog.
19   * @constructor
20   * @extends {FileManagerDialogBase}
21   */
22  function DefaultActionDialog(parentNode) {
23    FileManagerDialogBase.call(this, parentNode);
24
25    this.frame_.id = 'default-action-dialog';
26
27    this.list_ = new cr.ui.List();
28    this.list_.id = 'default-actions-list';
29    this.frame_.insertBefore(this.list_, this.text_.nextSibling);
30
31    this.selectionModel_ = this.list_.selectionModel =
32        new cr.ui.ListSingleSelectionModel();
33    this.dataModel_ = this.list_.dataModel = new cr.ui.ArrayDataModel([]);
34
35    // List has max-height defined at css, so that list grows automatically,
36    // but doesn't exceed predefined size.
37    this.list_.autoExpands = true;
38    this.list_.activateItemAtIndex = this.activateItemAtIndex_.bind(this);
39    // Use 'click' instead of 'change' for keyboard users.
40    this.list_.addEventListener('click', this.onSelected_.bind(this));
41
42    this.initialFocusElement_ = this.list_;
43
44    var self = this;
45
46    // Binding stuff doesn't work with constructors, so we have to create
47    // closure here.
48    this.list_.itemConstructor = function(item) {
49      return self.renderItem(item);
50    };
51  }
52
53  DefaultActionDialog.prototype = {
54    __proto__: FileManagerDialogBase.prototype
55  };
56
57  /**
58   * @override
59   */
60  DefaultActionDialog.prototype.onInputFocus = function() {
61    this.list_.select();
62  };
63
64  /**
65   * Renders item for list.
66   * @param {Object} item Item to render.
67   */
68  DefaultActionDialog.prototype.renderItem = function(item) {
69    var result = this.document_.createElement('li');
70
71    var div = this.document_.createElement('div');
72    div.textContent = item.label;
73
74    if (item.iconType) {
75      div.setAttribute('file-type-icon', item.iconType);
76    } else if (item.iconUrl) {
77      div.style.backgroundImage = 'url(' + item.iconUrl + ')';
78    }
79
80    if (item.class)
81      div.classList.add(item.class);
82
83    result.appendChild(div);
84
85    cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR);
86    cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR);
87
88    return result;
89  };
90
91  /**
92   * Shows dialog.
93   *
94   * @param {string} title Title in dialog caption.
95   * @param {string} message Message in dialog caption.
96   * @param {Array.<Object>} items Items to render in the list.
97   * @param {number} defaultIndex Item to select by default.
98   * @param {function(Object)} onSelectedItem Callback which is called when an
99   *     item is selected.
100   */
101  DefaultActionDialog.prototype.show = function(title, message, items,
102      defaultIndex, onSelectedItem) {
103
104    this.onSelectedItemCallback_ = onSelectedItem;
105
106    var show = FileManagerDialogBase.prototype.showTitleAndTextDialog.call(
107        this, title, message);
108
109    if (!show) {
110      console.error('DefaultActionDialog can\'t be shown.');
111      return;
112    }
113
114    if (!message) {
115      this.text_.setAttribute('hidden', 'hidden');
116    } else {
117      this.text_.removeAttribute('hidden');
118    }
119
120    this.list_.startBatchUpdates();
121    this.dataModel_.splice(0, this.dataModel_.length);
122    for (var i = 0; i < items.length; i++) {
123      this.dataModel_.push(items[i]);
124    }
125    this.selectionModel_.selectedIndex = defaultIndex;
126    this.list_.endBatchUpdates();
127  };
128
129  /**
130   * List activation handler. Closes dialog and calls 'ok' callback.
131   * @param {number} index Activated index.
132   */
133  DefaultActionDialog.prototype.activateItemAtIndex_ = function(index) {
134    this.hide();
135    this.onSelectedItemCallback_(this.dataModel_.item(index));
136  };
137
138  /**
139   * Closes dialog and invokes callback with currently-selected item.
140   */
141  DefaultActionDialog.prototype.onSelected_ = function() {
142    if (this.selectionModel_.selectedIndex !== -1)
143      this.activateItemAtIndex_(this.selectionModel_.selectedIndex);
144  };
145
146  /**
147   * @override
148   */
149  DefaultActionDialog.prototype.onContainerKeyDown_ = function(event) {
150    // Handle Escape.
151    if (event.keyCode == 27) {
152      this.hide();
153      event.preventDefault();
154    } else if (event.keyCode == 32 || event.keyCode == 13) {
155      this.onSelected_();
156      event.preventDefault();
157    }
158  };
159
160  return {DefaultActionDialog: DefaultActionDialog};
161});
162