1 // Copyright 2015 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.
7 * @extends {WebInspector.VBox}
9 WebInspector.DevicesSettingsTab = function()
11 WebInspector.VBox.call(this);
12 this.element.classList.add("settings-tab-container");
13 this.element.classList.add("devices-settings-tab");
14 this.registerRequiredCSS("emulation/devicesSettingsTab.css");
16 var header = this.element.createChild("header");
17 header.createChild("h3").createTextChild(WebInspector.UIString("Emulated Devices"));
18 this.containerElement = this.element.createChild("div", "help-container-wrapper").createChild("div", "settings-tab help-content help-container");
20 var buttonsRow = this.containerElement.createChild("div", "devices-button-row");
21 this._addCustomButton = createTextButton(WebInspector.UIString("Add custom device..."), this._addCustomDevice.bind(this));
22 buttonsRow.appendChild(this._addCustomButton);
24 this._devicesList = this.containerElement.createChild("div", "devices-list");
25 this._customListSearator = createElementWithClass("div", "devices-custom-separator");
27 this._editDevice = null;
28 this._editDeviceListItem = null;
29 this._createEditDeviceElement();
31 this._muteUpdate = false;
32 WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._devicesUpdated, this);
33 WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._devicesUpdated, this);
36 WebInspector.DevicesSettingsTab.prototype = {
39 WebInspector.VBox.prototype.wasShown.call(this);
40 this._devicesUpdated();
44 _devicesUpdated: function()
49 this._devicesList.removeChildren();
51 var devices = WebInspector.emulatedDevicesList.custom().slice();
52 devices.sort(WebInspector.EmulatedDevice.compareByTitle);
53 for (var i = 0; i < devices.length; ++i)
54 this._devicesList.appendChild(this._createDeviceListItem(devices[i], true));
56 this._devicesList.appendChild(this._customListSearator);
57 this._updateSeparatorVisibility();
59 devices = WebInspector.emulatedDevicesList.standard().slice();
60 devices.sort(WebInspector.EmulatedDevice.compareByTitle);
61 for (var i = 0; i < devices.length; ++i)
62 this._devicesList.appendChild(this._createDeviceListItem(devices[i], false));
65 _updateSeparatorVisibility: function()
67 this._customListSearator.classList.toggle("hidden", this._devicesList.firstChild === this._customListSearator);
71 * @param {boolean} custom
73 _muteAndSaveDeviceList: function(custom)
75 this._muteUpdate = true;
77 WebInspector.emulatedDevicesList.saveCustomDevices();
79 WebInspector.emulatedDevicesList.saveStandardDevices();
80 this._muteUpdate = false;
84 * @param {!WebInspector.EmulatedDevice} device
85 * @param {boolean} custom
88 _createDeviceListItem: function(device, custom)
90 var item = createElementWithClass("div", "devices-list-item");
91 var checkbox = item.createChild("input", "devices-list-checkbox");
92 checkbox.type = "checkbox";
93 checkbox.checked = device.show();
94 item.createChild("div", "devices-list-title").textContent = device.title;
95 item.addEventListener("click", onItemClicked.bind(this), false);
96 item.classList.toggle("device-list-item-show", device.show());
98 var editButton = item.createChild("div", "devices-list-edit");
99 editButton.title = WebInspector.UIString("Edit");
100 editButton.addEventListener("click", onEditClicked.bind(this), false);
102 var removeButton = item.createChild("div", "devices-list-remove");
103 removeButton.title = WebInspector.UIString("Remove");
104 removeButton.addEventListener("click", onRemoveClicked, false);
108 * @param {!Event} event
109 * @this {WebInspector.DevicesSettingsTab}
111 function onItemClicked(event)
113 var show = !checkbox.checked;
114 device.setShow(show);
115 this._muteAndSaveDeviceList(custom);
116 checkbox.checked = show;
117 item.classList.toggle("device-list-item-show", show);
122 * @param {!Event} event
123 * @this {WebInspector.DevicesSettingsTab}
125 function onEditClicked(event)
128 this._startEditing(device, item);
132 * @param {!Event} event
134 function onRemoveClicked(event)
136 WebInspector.emulatedDevicesList.removeCustomDevice(device);
143 _addCustomDevice: function()
145 this._startEditing(new WebInspector.EmulatedDevice(), null);
148 _createEditDeviceElement: function()
150 this._editDeviceElement = createElementWithClass("div", "devices-edit-container");
151 this._editDeviceElement.addEventListener("keydown", onKeyDown.bind(null, isEscKey, this._stopEditing.bind(this)), false);
152 this._editDeviceElement.addEventListener("keydown", onKeyDown.bind(null, isEnterKey, this._editDeviceCommitClicked.bind(this)), false);
153 this._editDeviceCheckbox = this._editDeviceElement.createChild("input", "devices-edit-checkbox");
154 this._editDeviceCheckbox.type = "checkbox";
155 var fields = this._editDeviceElement.createChild("div", "devices-edit-fields");
157 this._editDeviceTitle = this._createInput(WebInspector.UIString("Device name"));
158 fields.appendChild(this._editDeviceTitle);
160 var screen = fields.createChild("div", "hbox");
161 this._editDeviceWidth = this._createInput(WebInspector.UIString("Width"), "80px");
162 screen.appendChild(this._editDeviceWidth);
163 this._editDeviceHeight = this._createInput(WebInspector.UIString("Height"), "80px");
164 screen.appendChild(this._editDeviceHeight);
165 this._editDeviceScale = this._createInput(WebInspector.UIString("Device pixel ratio"));
166 screen.appendChild(this._editDeviceScale);
168 this._editDeviceUserAgent = this._createInput(WebInspector.UIString("User agent string"));
169 fields.appendChild(this._editDeviceUserAgent);
171 var buttonsRow = fields.createChild("div", "devices-edit-buttons");
172 this._editDeviceCommitButton = createTextButton("", this._editDeviceCommitClicked.bind(this));
173 buttonsRow.appendChild(this._editDeviceCommitButton);
174 this._editDeviceCancelButton = createTextButton(WebInspector.UIString("Cancel"), this._stopEditing.bind(this));
175 this._editDeviceCancelButton.addEventListener("keydown", onKeyDown.bind(null, isEnterKey, this._stopEditing.bind(this)), false);
176 buttonsRow.appendChild(this._editDeviceCancelButton);
179 * @param {function(!Event):boolean} predicate
180 * @param {function()} callback
181 * @param {!Event} event
183 function onKeyDown(predicate, callback, event)
185 if (predicate(event)) {
193 * @param {string} title
194 * @param {string=} width
197 _createInput: function(title, width)
199 var input = createElement("input");
202 input.style.width = width;
203 input.placeholder = title;
204 input.addEventListener("input", this._validateInputs.bind(this, false), false);
205 input.addEventListener("blur", this._validateInputs.bind(this, false), false);
210 * @param {boolean} forceValid
212 _validateInputs: function(forceValid)
214 var trimmedTitle = this._editDeviceTitle.value.trim();
215 var titleValid = trimmedTitle.length > 0 && trimmedTitle.length < 50;
216 this._editDeviceTitle.classList.toggle("error-input", !titleValid && !forceValid);
218 var widthValid = !WebInspector.OverridesSupport.deviceSizeValidator(this._editDeviceWidth.value);
219 this._editDeviceWidth.classList.toggle("error-input", !widthValid && !forceValid);
221 var heightValid = !WebInspector.OverridesSupport.deviceSizeValidator(this._editDeviceHeight.value);
222 this._editDeviceHeight.classList.toggle("error-input", !heightValid && !forceValid);
224 var scaleValid = !WebInspector.OverridesSupport.deviceScaleFactorValidator(this._editDeviceScale.value);
225 this._editDeviceScale.classList.toggle("error-input", !scaleValid && !forceValid);
227 var allValid = titleValid && widthValid && heightValid && scaleValid;
228 this._editDeviceCommitButton.disabled = !allValid;
232 * @param {number} value
235 _toNumericInputValue: function(value)
237 return value ? String(value) : "";
241 * @param {!WebInspector.EmulatedDevice} device
242 * @param {?Element} listItem
244 _startEditing: function(device, listItem)
248 this._addCustomButton.disabled = true;
249 this._devicesList.classList.add("devices-list-editing");
250 this._editDevice = device;
251 this._editDeviceListItem = listItem;
253 listItem.classList.add("hidden");
255 this._editDeviceCommitButton.textContent = listItem ? WebInspector.UIString("Save") : WebInspector.UIString("Add device");
256 this._editDeviceCheckbox.checked = device.show();
257 this._editDeviceTitle.value = device.title;
258 this._editDeviceWidth.value = listItem ? this._toNumericInputValue(device.vertical.width) : "";
259 this._editDeviceHeight.value = listItem ? this._toNumericInputValue(device.vertical.height) : "";
260 this._editDeviceScale.value = listItem ? this._toNumericInputValue(device.deviceScaleFactor) : "";
261 this._editDeviceUserAgent.value = device.userAgent;
262 this._validateInputs(true);
264 if (listItem && listItem.nextElementSibling)
265 this._devicesList.insertBefore(this._editDeviceElement, listItem.nextElementSibling);
267 this._devicesList.insertBefore(this._editDeviceElement, this._customListSearator);
268 this._editDeviceCommitButton.scrollIntoView();
269 this._editDeviceTitle.focus();
272 _editDeviceCommitClicked: function()
274 if (this._editDeviceCommitButton.disabled)
277 this._editDevice.setShow(this._editDeviceCheckbox.checked);
278 this._editDevice.title = this._editDeviceTitle.value;
279 this._editDevice.vertical.width = this._editDeviceWidth.value ? parseInt(this._editDeviceWidth.value, 10) : 0;
280 this._editDevice.vertical.height = this._editDeviceHeight.value ? parseInt(this._editDeviceHeight.value, 10) : 0;
281 this._editDevice.horizontal.width = this._editDevice.vertical.height;
282 this._editDevice.horizontal.height = this._editDevice.vertical.width;
283 this._editDevice.deviceScaleFactor = this._editDeviceScale.value ? parseFloat(this._editDeviceScale.value) : 0;
284 this._editDevice.userAgent = this._editDeviceUserAgent.value;
285 this._editDevice.modes.push({title: "", orientation: WebInspector.EmulatedDevice.Horizontal, insets: new Insets(0, 0, 0, 0), images: null});
286 this._editDevice.modes.push({title: "", orientation: WebInspector.EmulatedDevice.Vertical, insets: new Insets(0, 0, 0, 0), images: null});
289 if (this._editDeviceListItem)
290 WebInspector.emulatedDevicesList.saveCustomDevices();
292 WebInspector.emulatedDevicesList.addCustomDevice(this._editDevice);
293 this._editDevice = null;
294 this._editDeviceListItem = null;
297 _stopEditing: function()
299 this._devicesList.classList.remove("devices-list-editing");
300 if (this._editDeviceListItem)
301 this._editDeviceListItem.classList.remove("hidden");
302 if (this._editDeviceElement.parentElement)
303 this._devicesList.removeChild(this._editDeviceElement);
304 this._addCustomButton.disabled = false;
305 this._addCustomButton.focus();
308 __proto__: WebInspector.VBox.prototype