Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / emulation / DevicesSettingsTab.js
blob5ccba223dbd45b1feea649d8351d6b4d484df773
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.
5 /**
6  * @constructor
7  * @extends {WebInspector.VBox}
8  */
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 = {
37     wasShown: function()
38     {
39         WebInspector.VBox.prototype.wasShown.call(this);
40         this._devicesUpdated();
41         this._stopEditing();
42     },
44     _devicesUpdated: function()
45     {
46         if (this._muteUpdate)
47             return;
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));
63     },
65     _updateSeparatorVisibility: function()
66     {
67         this._customListSearator.classList.toggle("hidden", this._devicesList.firstChild === this._customListSearator);
68     },
70     /**
71      * @param {boolean} custom
72      */
73     _muteAndSaveDeviceList: function(custom)
74     {
75         this._muteUpdate = true;
76         if (custom)
77             WebInspector.emulatedDevicesList.saveCustomDevices();
78         else
79             WebInspector.emulatedDevicesList.saveStandardDevices();
80         this._muteUpdate = false;
81     },
83     /**
84      * @param {!WebInspector.EmulatedDevice} device
85      * @param {boolean} custom
86      * @return {!Element}
87      */
88     _createDeviceListItem: function(device, custom)
89     {
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());
97         if (custom) {
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);
105         }
107         /**
108          * @param {!Event} event
109          * @this {WebInspector.DevicesSettingsTab}
110          */
111         function onItemClicked(event)
112         {
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);
118             event.consume();
119         }
121         /**
122          * @param {!Event} event
123          * @this {WebInspector.DevicesSettingsTab}
124          */
125         function onEditClicked(event)
126         {
127             event.consume();
128             this._startEditing(device, item);
129         }
131         /**
132          * @param {!Event} event
133          */
134         function onRemoveClicked(event)
135         {
136             WebInspector.emulatedDevicesList.removeCustomDevice(device);
137             event.consume();
138         }
140         return item;
141     },
143     _addCustomDevice: function()
144     {
145         this._startEditing(new WebInspector.EmulatedDevice(), null);
146     },
148     _createEditDeviceElement: function()
149     {
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);
178         /**
179          * @param {function(!Event):boolean} predicate
180          * @param {function()} callback
181          * @param {!Event} event
182          */
183         function onKeyDown(predicate, callback, event)
184         {
185             if (predicate(event)) {
186                 event.consume(true);
187                 callback();
188             }
189         }
190     },
192     /**
193      * @param {string} title
194      * @param {string=} width
195      * @return {!Element}
196      */
197     _createInput: function(title, width)
198     {
199         var input = createElement("input");
200         input.type = "text";
201         if (width)
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);
206         return input;
207     },
209     /**
210      * @param {boolean} forceValid
211      */
212     _validateInputs: function(forceValid)
213     {
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;
229     },
231     /**
232      * @param {number} value
233      * @return {string}
234      */
235     _toNumericInputValue: function(value)
236     {
237         return value ? String(value) : "";
238     },
240     /**
241      * @param {!WebInspector.EmulatedDevice} device
242      * @param {?Element} listItem
243      */
244     _startEditing: function(device, listItem)
245     {
246         this._stopEditing();
248         this._addCustomButton.disabled = true;
249         this._devicesList.classList.add("devices-list-editing");
250         this._editDevice = device;
251         this._editDeviceListItem = listItem;
252         if (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);
266         else
267             this._devicesList.insertBefore(this._editDeviceElement, this._customListSearator);
268         this._editDeviceCommitButton.scrollIntoView();
269         this._editDeviceTitle.focus();
270     },
272     _editDeviceCommitClicked: function()
273     {
274         if (this._editDeviceCommitButton.disabled)
275             return;
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});
288         this._stopEditing();
289         if (this._editDeviceListItem)
290             WebInspector.emulatedDevicesList.saveCustomDevices();
291         else
292             WebInspector.emulatedDevicesList.addCustomDevice(this._editDevice);
293         this._editDevice = null;
294         this._editDeviceListItem = null;
295     },
297     _stopEditing: function()
298     {
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();
306     },
308     __proto__: WebInspector.VBox.prototype