]> src.bluestatic.org Git - armadillo.git/blob - frontend/path_control.js
Include the path in "outside of jail" errors.
[armadillo.git] / frontend / path_control.js
1 //
2 // Armadillo File Manager
3 // Copyright (c) 2010-2012, Robert Sesek <http://www.bluestatic.org>
4 //
5 // This program is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free Software
7 // Foundation, either version 3 of the License, or any later version.
8 //
9
10 $.namespace('armadillo.PathControl');
11
12 /**
13 * Creates a new path editing control for a given path.
14 * @param {string} path The path to create an editor for
15 * @param {bool} editLastComponent Whether the last component should be shown as an edit box
16 * @constructor
17 */
18 armadillo.PathControl = function(path, editLastComponent) {
19 /**
20 * Full path of the control.
21 * @type {string}
22 */
23 this.path_ = null;
24
25 /**
26 * The name of the file at the |path_|.
27 * @type {string}
28 */
29 this.name_ = null;
30 this.setPath(path);
31
32 /**
33 * Whether or not the last component is editable.
34 * @type {bool}
35 */
36 this.editableLastComponent_ = editLastComponent;
37
38 /**
39 * Control UI for the name component of the path.
40 * @type {Element}
41 */
42 this.nameControl_ = null;
43 };
44
45 /**
46 * Sets the path.
47 * @param {string} path
48 */
49 armadillo.PathControl.prototype.setPath = function(path) {
50 this.path_ = app.stripLastPathComponent(path);
51 this.name_ = path.substr(this.path_.length);
52 };
53
54 /**
55 * Gets the new path.
56 * @returns {string}
57 */
58 armadillo.PathControl.prototype.getPath = function() {
59 return app.joinPath(this.path_, this.name_);
60 };
61
62 /**
63 * Gets the name control.
64 * @returns {Element}
65 */
66 armadillo.PathControl.prototype.getNameControl = function() {
67 return this.nameControl_;
68 };
69
70 /**
71 * Creates a new path control object.
72 * @returns {Element}
73 */
74 armadillo.PathControl.prototype.createDom = function() {
75 this.element_ = $.createDom('div');
76 this.createDom_(this.element_);
77 return this.element_;
78 };
79
80 /**
81 * Decorates the given element into a path control.
82 * @param {Element} element
83 */
84 armadillo.PathControl.prototype.createDom_ = function(element) {
85 var components = this.path_.split('/');
86
87 // If this is an item that lives at the root, generate a special node for
88 // moving between items at the top level.
89 components[0] = '/';
90
91 // If the last component is emtpy, do not use it because it means a directory
92 // is being moved.
93 if (components[components.length - 1] == '') {
94 components.splice(-1);
95 }
96
97 var path = '';
98 $.each(components, function (i, part) {
99 element.append(this.createComponentNode_(path, part));
100 path = app.joinPath(path, part);
101 }.bind(this));
102
103 if (this.editableLastComponent_) {
104 this.nameControl_ = $.createDom('input');
105 this.nameControl_.attr({
106 'type' : 'text',
107 'name' : 'pathName',
108 'value' : this.name_
109 });
110
111 this.nameControl_.bind('change keydown', this.nameChanged_.bind(this));
112 } else {
113 this.nameControl_ = $.createDom('span').text(this.name_);
114 }
115
116 element.append(this.nameControl_);
117 };
118
119 /**
120 * @inheritDoc
121 */
122 armadillo.PathControl.prototype.enterDocument = function() {
123 armadillo.PathControl.superClass_.enterDocument.call(this);
124 this.nameControl_.getElement().focus();
125 };
126
127 /**
128 * Creates a node for a single path component.
129 * @param {string} path The path up to this point.
130 * @param {string} name The current component after |path|.
131 */
132 armadillo.PathControl.prototype.createComponentNode_ = function(path, name) {
133 var menu = $.createDom('select');
134 this.fetchMenuContents_(path, name, menu);
135
136 var option = $.createDom('option');
137 option.text('Loading...').attr('selected', 'selected');
138
139 menu.append(option);
140 menu.change(this.componentChanged_.bind(this));
141
142 return menu;
143 };
144
145 /**
146 * Queries the back-end for all the items at a given path and attaches them to
147 * the given menu.
148 * @param {string} path The path to get a list of items in
149 * @param {string} name The name to select
150 * @param {Element} The menu to attach items to
151 */
152 armadillo.PathControl.prototype.fetchMenuContents_ = function(path, name, menu) {
153 var fullPath = this.path_;
154 var callback = function(data, status, xhr) {
155 // Create an empty node for the current directory.
156 data.unshift('/');
157
158 menu.empty();
159 $.each(data, function (i, caption) {
160 // It only makes sense to be able to move into directories.
161 if (!app.isDirectory(caption)) {
162 return;
163 }
164 var item = $.createDom('option');
165 var componentPath = app.joinPath(path, name, caption);
166 item.val(componentPath).text(caption);
167 menu.append(item);
168 if (fullPath.substr(0, componentPath.length) == componentPath) {
169 item.attr('selected', 'selected');
170 }
171 });
172 };
173 app.sendRequest('list', {'path' : app.joinPath(path, name)}, callback);
174 };
175
176 /**
177 * Handler for changing a component of the control.
178 * @param {Event} e
179 */
180 armadillo.PathControl.prototype.componentChanged_ = function(e) {
181 this.path_ = $(e.target).val();
182 this.element_.empty();
183 this.createDom_(this.element_);
184 };
185
186 /**
187 * Handler for changing the editable name component.
188 * @param {Event} e
189 */
190 armadillo.PathControl.prototype.nameChanged_ = function(e) {
191 console.log(e);
192 // TODO: assert(this.editableLastComponent_)
193 this.name_ = e.target.value;
194 e.stopPropagation();
195 return true;
196 };