UNPKG

monaca-lib

Version:

Monaca cloud API bindings for JavaScript

1,381 lines (1,207 loc) 52.8 kB
/* * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @constructor * @param {function()} onHide * @extends {WebInspector.HelpScreen} */ WebInspector.SettingsScreen = function(onHide) { WebInspector.HelpScreen.call(this); this.element.id = "settings-screen"; /** @type {function()} */ this._onHide = onHide; this._contentElement = this.element.createChild("div", "help-window-main"); var settingsLabelElement = createElementWithClass("div", "help-window-label"); settingsLabelElement.createTextChild(WebInspector.UIString("Settings")); this._contentElement.appendChild(this.createCloseButton()); this._tabbedPane = new WebInspector.TabbedPane(); this._tabbedPane.insertBeforeTabStrip(settingsLabelElement); this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.General, WebInspector.UIString("General"), new WebInspector.GenericSettingsTab()); this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Workspace, WebInspector.UIString("Workspace"), new WebInspector.WorkspaceSettingsTab()); this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Devices, WebInspector.UIString("Devices"), new WebInspector.DevicesSettingsTab()); if (Runtime.experiments.supportEnabled()) this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Experiments, WebInspector.UIString("Experiments"), new WebInspector.ExperimentsSettingsTab()); this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Shortcuts, WebInspector.UIString("Shortcuts"), WebInspector.shortcutsScreen.createShortcutsTabView()); this._tabbedPane.setShrinkableTabs(false); this._tabbedPane.setVerticalTabLayout(true); this._lastSelectedTabSetting = WebInspector.settings.createSetting("lastSelectedSettingsTab", WebInspector.SettingsScreen.Tabs.General); this.selectTab(this._lastSelectedTabSetting.get()); this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); this.element.addEventListener("keydown", this._keyDown.bind(this), false); this._developerModeCounter = 0; } /** * @param {number} min * @param {number} max * @param {string} text * @return {?string} */ WebInspector.SettingsScreen.integerValidator = function(min, max, text) { var value = Number(text); if (isNaN(value)) return WebInspector.UIString("Invalid number format"); if (value < min || value > max) return WebInspector.UIString("Value is out of range [%d, %d]", min, max); return null; } WebInspector.SettingsScreen.Tabs = { General: "general", Overrides: "overrides", Workspace: "workspace", Devices: "devices", Experiments: "experiments", Shortcuts: "shortcuts" } WebInspector.SettingsScreen.prototype = { /** * @param {string} tabId */ selectTab: function(tabId) { this._tabbedPane.selectTab(tabId); }, /** * @param {!WebInspector.Event} event */ _tabSelected: function(event) { this._lastSelectedTabSetting.set(this._tabbedPane.selectedTabId); }, /** * @override */ wasShown: function() { this._tabbedPane.show(this._contentElement); WebInspector.HelpScreen.prototype.wasShown.call(this); }, /** * @override * @return {boolean} */ isClosingKey: function(keyCode) { return [ WebInspector.KeyboardShortcut.Keys.Enter.code, WebInspector.KeyboardShortcut.Keys.Esc.code, ].indexOf(keyCode) >= 0; }, /** * @override */ willHide: function() { this._onHide(); WebInspector.HelpScreen.prototype.willHide.call(this); }, /** * @param {!Event} event */ _keyDown: function(event) { var shiftKeyCode = 16; if (event.keyCode === shiftKeyCode && ++this._developerModeCounter > 5) this.element.classList.add("settings-developer-mode"); }, __proto__: WebInspector.HelpScreen.prototype } /** * @constructor * @extends {WebInspector.VBox} * @param {string} name * @param {string=} id */ WebInspector.SettingsTab = function(name, id) { WebInspector.VBox.call(this); this.element.classList.add("settings-tab-container"); if (id) this.element.id = id; var header = this.element.createChild("header"); header.createChild("h3").createTextChild(name); this.containerElement = this.element.createChild("div", "help-container-wrapper").createChild("div", "settings-tab help-content help-container"); } WebInspector.SettingsTab.prototype = { /** * @param {string=} name * @return {!Element} */ _appendSection: function(name) { var block = this.containerElement.createChild("div", "help-block"); if (name) block.createChild("div", "help-section-title").textContent = name; return block; }, _createSelectSetting: function(name, options, setting) { var p = createElement("p"); p.createChild("label").textContent = name; var select = p.createChild("select", "chrome-select"); var settingValue = setting.get(); for (var i = 0; i < options.length; ++i) { var option = options[i]; select.add(new Option(option[0], option[1])); if (settingValue === option[1]) select.selectedIndex = i; } function changeListener(e) { // Don't use e.target.value to avoid conversion of the value to string. setting.set(options[select.selectedIndex][1]); } select.addEventListener("change", changeListener, false); return p; }, __proto__: WebInspector.VBox.prototype } /** * @constructor * @extends {WebInspector.SettingsTab} */ WebInspector.GenericSettingsTab = function() { WebInspector.SettingsTab.call(this, WebInspector.UIString("General"), "general-tab-content"); this._populateSectionsFromExtensions(); this._appendSection().appendChild(createTextButton(WebInspector.UIString("Restore defaults and reload"), restoreAndReload)); function restoreAndReload() { if (window.localStorage) window.localStorage.clear(); WebInspector.reload(); } } WebInspector.GenericSettingsTab.prototype = { _populateSectionsFromExtensions: function() { /** @const */ var explicitSectionOrder = ["", "Appearance", "Elements", "Sources", "Network", "Profiler", "Console", "Extensions"]; var allExtensions = self.runtime.extensions("ui-setting"); /** @type {!StringMultimap.<!Runtime.Extension>} */ var extensionsBySectionId = new StringMultimap(); /** @type {!StringMultimap.<!Runtime.Extension>} */ var childSettingExtensionsByParentName = new StringMultimap(); allExtensions.forEach(function(extension) { var descriptor = extension.descriptor(); var sectionName = descriptor["section"] || ""; if (!sectionName && descriptor["parentSettingName"]) { childSettingExtensionsByParentName.set(descriptor["parentSettingName"], extension); return; } extensionsBySectionId.set(sectionName, extension); }); var sectionIds = extensionsBySectionId.keysArray(); var explicitlyOrderedSections = explicitSectionOrder.keySet(); for (var i = 0; i < explicitSectionOrder.length; ++i) { var extensions = extensionsBySectionId.get(explicitSectionOrder[i]); if (!extensions.size) continue; this._addSectionWithExtensionProvidedSettings(explicitSectionOrder[i], extensions.valuesArray(), childSettingExtensionsByParentName); } for (var i = 0; i < sectionIds.length; ++i) { if (explicitlyOrderedSections[sectionIds[i]]) continue; this._addSectionWithExtensionProvidedSettings(sectionIds[i], extensionsBySectionId.get(sectionIds[i]).valuesArray(), childSettingExtensionsByParentName); } }, /** * @param {string} sectionName * @param {!Array.<!Runtime.Extension>} extensions * @param {!StringMultimap.<!Runtime.Extension>} childSettingExtensionsByParentName */ _addSectionWithExtensionProvidedSettings: function(sectionName, extensions, childSettingExtensionsByParentName) { var uiSectionName = sectionName && WebInspector.UIString(sectionName); var sectionElement = this._appendSection(uiSectionName); extensions.forEach(processSetting.bind(this, null)); /** * @param {?Element} parentFieldset * @param {!Runtime.Extension} extension * @this {WebInspector.GenericSettingsTab} */ function processSetting(parentFieldset, extension) { var descriptor = extension.descriptor(); var experimentName = descriptor["experiment"]; if (experimentName && !Runtime.experiments.isEnabled(experimentName)) return; if (descriptor["settingType"] === "custom") { extension.instancePromise().then(appendCustomSetting); return; } var uiTitle = WebInspector.UIString(descriptor["title"]); var settingName = descriptor["settingName"]; var setting = WebInspector.settings[settingName]; var settingControl = createSettingControl.call(this, uiTitle, setting, descriptor); if (settingName) { var childSettings = childSettingExtensionsByParentName.get(settingName); if (childSettings.size) { var fieldSet = WebInspector.SettingsUI.createSettingFieldset(setting); settingControl.appendChild(fieldSet); childSettings.valuesArray().forEach(function(item) { processSetting.call(this, fieldSet, item); }, this); } } appendAsChild(settingControl); /** * @param {!Object} object */ function appendCustomSetting(object) { var uiSettingDelegate = /** @type {!WebInspector.UISettingDelegate} */ (object); var element = uiSettingDelegate.settingElement(); if (element) appendAsChild(element); } /** * @param {!Object} settingControl */ function appendAsChild(settingControl) { (parentFieldset || sectionElement).appendChild(/** @type {!Element} */ (settingControl)); } } /** * @param {string} uiTitle * @param {!WebInspector.Setting} setting * @param {!Object} descriptor * @return {!Element} * @this {WebInspector.GenericSettingsTab} */ function createSettingControl(uiTitle, setting, descriptor) { switch (descriptor["settingType"]) { case "checkbox": return WebInspector.SettingsUI.createSettingCheckbox(uiTitle, setting); case "select": var descriptorOptions = descriptor["options"]; var options = new Array(descriptorOptions.length); for (var i = 0; i < options.length; ++i) { // The third array item flags that the option name is "raw" (non-i18n-izable). var optionName = descriptorOptions[i][2] ? descriptorOptions[i][0] : WebInspector.UIString(descriptorOptions[i][0]); options[i] = [optionName, descriptorOptions[i][1]]; } return this._createSelectSetting(uiTitle, options, setting); default: throw "Invalid setting type: " + descriptor["settingType"]; } } }, __proto__: WebInspector.SettingsTab.prototype } /** * @constructor * @extends {WebInspector.UISettingDelegate} */ WebInspector.SettingsScreen.SkipStackFramePatternSettingDelegate = function() { WebInspector.UISettingDelegate.call(this); } WebInspector.SettingsScreen.SkipStackFramePatternSettingDelegate.prototype = { /** * @override * @return {!Element} */ settingElement: function() { return createTextButton(WebInspector.manageBlackboxingButtonLabel(), this._onManageButtonClick.bind(this), "", WebInspector.UIString("Skip stepping through sources with particular names")); }, _onManageButtonClick: function() { WebInspector.FrameworkBlackboxDialog.show(WebInspector.inspectorView.element); }, __proto__: WebInspector.UISettingDelegate.prototype } /** * @constructor * @extends {WebInspector.SettingsTab} */ WebInspector.WorkspaceSettingsTab = function() { WebInspector.SettingsTab.call(this, WebInspector.UIString("Workspace"), "workspace-tab-content"); WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, this._fileSystemAdded, this); WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this); this._commonSection = this._appendSection(WebInspector.UIString("Common")); var folderExcludePatternInput = WebInspector.SettingsUI.createSettingInputField(WebInspector.UIString("Folder exclude pattern"), WebInspector.settings.workspaceFolderExcludePattern, false, 0, "270px", WebInspector.SettingsUI.regexValidator); this._commonSection.appendChild(folderExcludePatternInput); this._fileSystemsSection = this._appendSection(WebInspector.UIString("Folders")); this._fileSystemsListContainer = this._fileSystemsSection.createChild("p", "settings-list-container"); this._addFileSystemRowElement = this._fileSystemsSection.createChild("div"); this._addFileSystemRowElement.appendChild(createTextButton(WebInspector.UIString("Add folder\u2026"), this._addFileSystemClicked.bind(this))); this._editFileSystemButton = createTextButton(WebInspector.UIString("Folder options\u2026"), this._editFileSystemClicked.bind(this)); this._addFileSystemRowElement.appendChild(this._editFileSystemButton); this._updateEditFileSystemButtonState(); this._reset(); } WebInspector.WorkspaceSettingsTab.prototype = { wasShown: function() { WebInspector.SettingsTab.prototype.wasShown.call(this); this._reset(); }, _reset: function() { this._resetFileSystems(); }, _resetFileSystems: function() { this._fileSystemsListContainer.removeChildren(); var fileSystemPaths = WebInspector.isolatedFileSystemManager.mapping().fileSystemPaths(); delete this._fileSystemsList; if (!fileSystemPaths.length) { var noFileSystemsMessageElement = this._fileSystemsListContainer.createChild("div", "no-file-systems-message"); noFileSystemsMessageElement.textContent = WebInspector.UIString("You have no file systems added."); return; } this._fileSystemsList = new WebInspector.SettingsList([{ id: "path" }], this._renderFileSystem.bind(this)); this._fileSystemsList.element.classList.add("file-systems-list"); this._fileSystemsList.addEventListener(WebInspector.SettingsList.Events.Selected, this._fileSystemSelected.bind(this)); this._fileSystemsList.addEventListener(WebInspector.SettingsList.Events.Removed, this._fileSystemRemovedfromList.bind(this)); this._fileSystemsList.addEventListener(WebInspector.SettingsList.Events.DoubleClicked, this._fileSystemDoubleClicked.bind(this)); this._fileSystemsListContainer.appendChild(this._fileSystemsList.element); for (var i = 0; i < fileSystemPaths.length; ++i) this._fileSystemsList.addItem(fileSystemPaths[i]); this._updateEditFileSystemButtonState(); }, _updateEditFileSystemButtonState: function() { this._editFileSystemButton.disabled = !this._selectedFileSystemPath(); }, /** * @param {!WebInspector.Event} event */ _fileSystemSelected: function(event) { this._updateEditFileSystemButtonState(); }, /** * @param {!WebInspector.Event} event */ _fileSystemDoubleClicked: function(event) { var id = /** @type{?string} */ (event.data); this._editFileSystem(id); }, _editFileSystemClicked: function() { this._editFileSystem(this._selectedFileSystemPath()); }, /** * @param {?string} id */ _editFileSystem: function(id) { WebInspector.EditFileSystemDialog.show(WebInspector.inspectorView.element, id); }, /** * @param {!Element} columnElement * @param {{id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}} column * @param {?string} id */ _renderFileSystem: function(columnElement, column, id) { if (!id) return ""; var fileSystemPath = id; var textElement = columnElement.createChild("span", "list-column-text"); var pathElement = textElement.createChild("span", "file-system-path"); pathElement.title = fileSystemPath; const maxTotalPathLength = 55; const maxFolderNameLength = 30; var lastIndexOfSlash = fileSystemPath.lastIndexOf(WebInspector.isWin() ? "\\" : "/"); var folderName = fileSystemPath.substr(lastIndexOfSlash + 1); var folderPath = fileSystemPath.substr(0, lastIndexOfSlash + 1); folderPath = folderPath.trimMiddle(maxTotalPathLength - Math.min(maxFolderNameLength, folderName.length)); folderName = folderName.trimMiddle(maxFolderNameLength); var folderPathElement = pathElement.createChild("span"); folderPathElement.textContent = folderPath; var nameElement = pathElement.createChild("span", "file-system-path-name"); nameElement.textContent = folderName; }, /** * @param {!WebInspector.Event} event */ _fileSystemRemovedfromList: function(event) { var id = /** @type{?string} */ (event.data); if (!id) return; WebInspector.isolatedFileSystemManager.removeFileSystem(id); }, _addFileSystemClicked: function() { WebInspector.isolatedFileSystemManager.addFileSystem(); }, _fileSystemAdded: function(event) { var fileSystem = /** @type {!WebInspector.IsolatedFileSystem} */ (event.data); if (!this._fileSystemsList) this._reset(); else this._fileSystemsList.addItem(fileSystem.path()); }, _fileSystemRemoved: function(event) { var fileSystem = /** @type {!WebInspector.IsolatedFileSystem} */ (event.data); if (this._fileSystemsList.itemForId(fileSystem.path())) this._fileSystemsList.removeItem(fileSystem.path()); if (!this._fileSystemsList.itemIds().length) this._reset(); this._updateEditFileSystemButtonState(); }, _selectedFileSystemPath: function() { return this._fileSystemsList ? this._fileSystemsList.selectedId() : null; }, __proto__: WebInspector.SettingsTab.prototype } /** * @constructor * @extends {WebInspector.SettingsTab} */ WebInspector.DevicesSettingsTab = function() { WebInspector.SettingsTab.call(this, WebInspector.UIString("Devices"), "devices-tab-content"); this.containerElement.createChild("div", "devices-title").textContent = WebInspector.UIString("Emulated devices"); this._devicesList = this.containerElement.createChild("div", "devices-list"); this._customListSearator = createElementWithClass("div", "devices-custom-separator"); var buttonsRow = this.containerElement.createChild("div", "devices-button-row"); this._addCustomButton = createTextButton(WebInspector.UIString("Add custom device..."), this._addCustomDevice.bind(this)); buttonsRow.appendChild(this._addCustomButton); this._updateStandardButton = createTextButton("", this._updateStandardDevices.bind(this)); if (Runtime.experiments.isEnabled("externalDeviceList")) buttonsRow.appendChild(this._updateStandardButton); this._editDevice = null; this._editDeviceListItem = null; this._createEditDeviceElement(); this._muteUpdate = false; WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._devicesUpdated, this); WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._devicesUpdated, this); WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.IsUpdatingChanged, this._isUpdatingChanged, this); } WebInspector.DevicesSettingsTab.prototype = { wasShown: function() { WebInspector.SettingsTab.prototype.wasShown.call(this); this._devicesUpdated(); this._isUpdatingChanged(); this._stopEditing(); }, _devicesUpdated: function() { if (this._muteUpdate) return; this._devicesList.removeChildren(); var devices = WebInspector.emulatedDevicesList.custom().slice(); devices.sort(WebInspector.EmulatedDevice.compareByTitle); for (var i = 0; i < devices.length; ++i) this._devicesList.appendChild(this._createDeviceListItem(devices[i], true)); this._devicesList.appendChild(this._customListSearator); this._updateSeparatorVisibility(); devices = WebInspector.emulatedDevicesList.standard().slice(); devices.sort(WebInspector.EmulatedDevice.compareByTitle); for (var i = 0; i < devices.length; ++i) this._devicesList.appendChild(this._createDeviceListItem(devices[i], false)); }, _isUpdatingChanged: function() { if (WebInspector.emulatedDevicesList.isUpdating()) { this._updateStandardButton.textContent = WebInspector.UIString("Updating..."); this._updateStandardButton.disabled = true; } else { this._updateStandardButton.textContent = WebInspector.UIString("Update devices"); this._updateStandardButton.disabled = false; } }, _updateSeparatorVisibility: function() { this._customListSearator.classList.toggle("hidden", this._devicesList.firstChild === this._customListSearator); }, /** * @param {boolean} custom */ _muteAndSaveDeviceList: function(custom) { this._muteUpdate = true; if (custom) WebInspector.emulatedDevicesList.saveCustomDevices(); else WebInspector.emulatedDevicesList.saveStandardDevices(); this._muteUpdate = false; }, /** * @param {!WebInspector.EmulatedDevice} device * @param {boolean} custom * @return {!Element} */ _createDeviceListItem: function(device, custom) { var item = createElementWithClass("div", "devices-list-item"); var checkbox = item.createChild("input", "devices-list-checkbox"); checkbox.type = "checkbox"; checkbox.checked = device.show(); item.createChild("div", "devices-list-title").textContent = device.title; item.addEventListener("click", onItemClicked.bind(this), false); item.classList.toggle("device-list-item-show", device.show()); if (custom) { var editButton = item.createChild("div", "devices-list-edit"); editButton.title = WebInspector.UIString("Edit"); editButton.addEventListener("click", onEditClicked.bind(this), false); var removeButton = item.createChild("div", "devices-list-remove"); removeButton.title = WebInspector.UIString("Remove"); removeButton.addEventListener("click", onRemoveClicked, false); } /** * @param {!Event} event * @this {WebInspector.DevicesSettingsTab} */ function onItemClicked(event) { var show = !checkbox.checked; device.setShow(show); this._muteAndSaveDeviceList(custom); checkbox.checked = show; item.classList.toggle("device-list-item-show", show); event.consume(); } /** * @param {!Event} event * @this {WebInspector.DevicesSettingsTab} */ function onEditClicked(event) { event.consume(); this._startEditing(device, item); } /** * @param {!Event} event */ function onRemoveClicked(event) { WebInspector.emulatedDevicesList.removeCustomDevice(device); event.consume(); } return item; }, _addCustomDevice: function() { this._startEditing(new WebInspector.EmulatedDevice(), null); }, _createEditDeviceElement: function() { this._editDeviceElement = createElementWithClass("div", "devices-edit-container"); this._editDeviceCheckbox = this._editDeviceElement.createChild("input", "devices-edit-checkbox"); this._editDeviceCheckbox.type = "checkbox"; var fields = this._editDeviceElement.createChild("div", "devices-edit-fields"); this._editDeviceTitle = this._createInput(WebInspector.UIString("Device name")); fields.appendChild(this._editDeviceTitle); var screen = fields.createChild("div", "hbox"); this._editDeviceWidth = this._createInput(WebInspector.UIString("Width"), "120px"); screen.appendChild(this._editDeviceWidth); this._editDeviceHeight = this._createInput(WebInspector.UIString("Height"), "120px"); screen.appendChild(this._editDeviceHeight); this._editDeviceScale = this._createInput(WebInspector.UIString("Device pixel ratio")); screen.appendChild(this._editDeviceScale); this._editDeviceUserAgent = this._createInput(WebInspector.UIString("User agent string")); fields.appendChild(this._editDeviceUserAgent); var buttonsRow = fields.createChild("div", "devices-edit-buttons"); this._editDeviceCommitButton = createTextButton("", this._editDeviceCommitClicked.bind(this)); buttonsRow.appendChild(this._editDeviceCommitButton); this._editDeviceCancelButton = createTextButton(WebInspector.UIString("Cancel"), this._stopEditing.bind(this)); buttonsRow.appendChild(this._editDeviceCancelButton); }, /** * @param {string} title * @param {string=} width * @return {!Element} */ _createInput: function(title, width) { var input = createElement("input"); input.type = "text"; if (width) input.style.width = width; input.placeholder = title; input.addEventListener("input", this._validateInputs.bind(this), false); input.addEventListener("keydown", onKeyDown.bind(this), false); /** * @param {!Event} event * @this {WebInspector.DevicesSettingsTab} */ function onKeyDown(event) { if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) { event.consume(true); this._stopEditing(); } if (isEnterKey(event)) { event.consume(true); if (!this._editDeviceCommitButton.disabled) this._editDeviceCommitClicked(); } } return input; }, _validateInputs: function() { var trimmedTitle = this._editDeviceTitle.value.trim(); var titleValid = trimmedTitle.length > 0 && trimmedTitle.length < 50; this._editDeviceTitle.classList.toggle("error-input", !titleValid); var widthValid = !WebInspector.OverridesSupport.deviceSizeValidator(this._editDeviceWidth.value); this._editDeviceWidth.classList.toggle("error-input", !widthValid); var heightValid = !WebInspector.OverridesSupport.deviceSizeValidator(this._editDeviceHeight.value); this._editDeviceHeight.classList.toggle("error-input", !heightValid); var scaleValid = !WebInspector.OverridesSupport.deviceScaleFactorValidator(this._editDeviceScale.value); this._editDeviceScale.classList.toggle("error-input", !scaleValid); var allValid = titleValid && widthValid && heightValid && scaleValid; this._editDeviceCommitButton.disabled = !allValid; }, /** * @param {number} value * @return {string} */ _toNumericInputValue: function(value) { return value ? String(value) : ""; }, /** * @param {!WebInspector.EmulatedDevice} device * @param {?Element} listItem */ _startEditing: function(device, listItem) { this._stopEditing(); this._addCustomButton.disabled = true; this._devicesList.classList.add("devices-list-editing"); this._editDevice = device; this._editDeviceListItem = listItem; if (listItem) listItem.classList.add("hidden"); this._editDeviceCommitButton.textContent = listItem ? WebInspector.UIString("Save") : WebInspector.UIString("Add device"); this._editDeviceCheckbox.checked = device.show(); this._editDeviceTitle.value = device.title; this._editDeviceWidth.value = listItem ? this._toNumericInputValue(device.vertical.width) : ""; this._editDeviceHeight.value = listItem ? this._toNumericInputValue(device.vertical.height) : ""; this._editDeviceScale.value = listItem ? this._toNumericInputValue(device.deviceScaleFactor) : ""; this._editDeviceUserAgent.value = device.userAgent; this._validateInputs(); if (listItem && listItem.nextElementSibling) this._devicesList.insertBefore(this._editDeviceElement, listItem.nextElementSibling); else this._devicesList.insertBefore(this._editDeviceElement, this._customListSearator); this._editDeviceCommitButton.scrollIntoView(); this._editDeviceTitle.focus(); }, _editDeviceCommitClicked: function() { this._editDevice.setShow(this._editDeviceCheckbox.checked); this._editDevice.title = this._editDeviceTitle.value; this._editDevice.vertical.width = this._editDeviceWidth.value ? parseInt(this._editDeviceWidth.value, 10) : 0; this._editDevice.vertical.height = this._editDeviceHeight.value ? parseInt(this._editDeviceHeight.value, 10) : 0; this._editDevice.horizontal.width = this._editDevice.vertical.height; this._editDevice.horizontal.height = this._editDevice.vertical.width; this._editDevice.deviceScaleFactor = this._editDeviceScale.value ? parseFloat(this._editDeviceScale.value) : 0; this._editDevice.userAgent = this._editDeviceUserAgent.value; this._stopEditing(); if (this._editDeviceListItem) WebInspector.emulatedDevicesList.saveCustomDevices(); else WebInspector.emulatedDevicesList.addCustomDevice(this._editDevice); this._editDevice = null; this._editDeviceListItem = null; }, _stopEditing: function() { this._devicesList.classList.remove("devices-list-editing"); if (this._editDeviceListItem) this._editDeviceListItem.classList.remove("hidden"); if (this._editDeviceElement.parentElement) this._devicesList.removeChild(this._editDeviceElement); this._addCustomButton.disabled = false; this._addCustomButton.focus(); }, _updateStandardDevices: function() { WebInspector.emulatedDevicesList.update(); }, __proto__: WebInspector.SettingsTab.prototype } /** * @constructor * @extends {WebInspector.SettingsTab} */ WebInspector.ExperimentsSettingsTab = function() { WebInspector.SettingsTab.call(this, WebInspector.UIString("Experiments"), "experiments-tab-content"); var experiments = Runtime.experiments.allConfigurableExperiments(); if (experiments.length) { var experimentsSection = this._appendSection(); experimentsSection.appendChild(this._createExperimentsWarningSubsection()); for (var i = 0; i < experiments.length; ++i) experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i])); } } WebInspector.ExperimentsSettingsTab.prototype = { /** * @return {!Element} element */ _createExperimentsWarningSubsection: function() { var subsection = createElement("div"); var warning = subsection.createChild("span", "settings-experiments-warning-subsection-warning"); warning.textContent = WebInspector.UIString("WARNING:"); subsection.createTextChild(" "); var message = subsection.createChild("span", "settings-experiments-warning-subsection-message"); message.textContent = WebInspector.UIString("These experiments could be dangerous and may require restart."); return subsection; }, _createExperimentCheckbox: function(experiment) { var label = createCheckboxLabel(WebInspector.UIString(experiment.title), experiment.isEnabled()); var input = label.checkboxElement; input.name = experiment.name; function listener() { experiment.setEnabled(input.checked); } input.addEventListener("click", listener, false); var p = createElement("p"); p.className = experiment.hidden && !experiment.isEnabled() ? "settings-experiment-hidden" : ""; p.appendChild(label); return p; }, __proto__: WebInspector.SettingsTab.prototype } /** * @constructor */ WebInspector.SettingsController = function() { /** @type {?WebInspector.SettingsScreen} */ this._settingsScreen; this._resizeBound = this._resize.bind(this); } WebInspector.SettingsController.prototype = { _onHideSettingsScreen: function() { var window = this._settingsScreen.element.ownerDocument.defaultView; window.removeEventListener("resize", this._resizeBound, false); delete this._settingsScreenVisible; }, /** * @param {string=} tabId */ showSettingsScreen: function(tabId) { if (!this._settingsScreen) this._settingsScreen = new WebInspector.SettingsScreen(this._onHideSettingsScreen.bind(this)); if (tabId) this._settingsScreen.selectTab(tabId); this._settingsScreen.showModal(); this._settingsScreenVisible = true; var window = this._settingsScreen.element.ownerDocument.defaultView; window.addEventListener("resize", this._resizeBound, false); }, _resize: function() { if (this._settingsScreen && this._settingsScreen.isShowing()) this._settingsScreen.doResize(); } } /** * @constructor * @implements {WebInspector.ActionDelegate} */ WebInspector.SettingsController.SettingsScreenActionDelegate = function() { } WebInspector.SettingsController.SettingsScreenActionDelegate.prototype = { /** * @override * @return {boolean} */ handleAction: function() { WebInspector._settingsController.showSettingsScreen(WebInspector.SettingsScreen.Tabs.General); return true; } } /** * @constructor * @extends {WebInspector.Object} * @param {!Array.<{id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}>} columns * @param {function(!Element, {id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}, ?string)} itemRenderer */ WebInspector.SettingsList = function(columns, itemRenderer) { this.element = createElementWithClass("div", "settings-list"); this.element.tabIndex = -1; this._itemRenderer = itemRenderer; /** @type {!Map.<string, !Element>} */ this._listItems = new Map(); /** @type {!Array.<?string>} */ this._ids = []; this._columns = columns; } WebInspector.SettingsList.Events = { Selected: "Selected", Removed: "Removed", DoubleClicked: "DoubleClicked", } WebInspector.SettingsList.prototype = { /** * @param {?string} itemId * @param {?string=} beforeId * @return {!Element} */ addItem: function(itemId, beforeId) { var listItem = createElementWithClass("div", "settings-list-item"); listItem._id = itemId; if (typeof beforeId !== "undefined") this.element.insertBefore(listItem, this.itemForId(beforeId)); else this.element.appendChild(listItem); var listItemContents = listItem.createChild("div", "settings-list-item-contents"); var listItemColumnsElement = listItemContents.createChild("div", "settings-list-item-columns"); listItem.columnElements = {}; for (var i = 0; i < this._columns.length; ++i) { var column = this._columns[i]; var columnElement = listItemColumnsElement.createChild("div", "list-column settings-list-column-" + column.id); listItem.columnElements[column.id] = columnElement; this._itemRenderer(columnElement, column, itemId); } var removeItemButton = this._createRemoveButton(removeItemClicked.bind(this)); listItemContents.addEventListener("click", this.selectItem.bind(this, itemId), false); listItemContents.addEventListener("dblclick", this._onDoubleClick.bind(this, itemId), false); listItemContents.appendChild(removeItemButton); this._listItems.set(itemId || "", listItem); if (typeof beforeId !== "undefined") this._ids.splice(this._ids.indexOf(beforeId), 0, itemId); else this._ids.push(itemId); /** * @param {!Event} event * @this {WebInspector.SettingsList} */ function removeItemClicked(event) { removeItemButton.disabled = true; this.removeItem(itemId); this.dispatchEventToListeners(WebInspector.SettingsList.Events.Removed, itemId); event.consume(); } return listItem; }, /** * @param {?string} id */ removeItem: function(id) { var listItem = this._listItems.remove(id || ""); if (listItem) listItem.remove(); this._ids.remove(id); if (id === this._selectedId) { delete this._selectedId; if (this._ids.length) this.selectItem(this._ids[0]); } }, /** * @return {!Array.<?string>} */ itemIds: function() { return this._ids.slice(); }, /** * @return {!Array.<string>} */ columns: function() { return this._columns.select("id"); }, /** * @return {?string} */ selectedId: function() { return this._selectedId; }, /** * @return {?Element} */ selectedItem: function() { return this._selectedId ? this.itemForId(this._selectedId) : null; }, /** * @param {?string} itemId * @return {?Element} */ itemForId: function(itemId) { return this._listItems.get(itemId || "") || null; }, /** * @param {?string} id * @param {!Event=} event */ _onDoubleClick: function(id, event) { this.dispatchEventToListeners(WebInspector.SettingsList.Events.DoubleClicked, id); }, /** * @param {?string} id * @param {!Event=} event */ selectItem: function(id, event) { if (typeof this._selectedId !== "undefined") this.itemForId(this._selectedId).classList.remove("selected"); this._selectedId = id; if (typeof this._selectedId !== "undefined") this.itemForId(this._selectedId).classList.add("selected"); this.dispatchEventToListeners(WebInspector.SettingsList.Events.Selected, id); if (event) event.consume(); }, /** * @param {function(!Event)} handler * @return {!Element} */ _createRemoveButton: function(handler) { var removeButton = createElementWithClass("div", "remove-item-button"); removeButton.addEventListener("click", handler, false); return removeButton; }, __proto__: WebInspector.Object.prototype } /** * @constructor * @extends {WebInspector.SettingsList} * @param {!Array.<{id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}>} columns * @param {function(string, string):string} valuesProvider * @param {function(?string, !Object):!Array.<string>} validateHandler * @param {function(?string, !Object)} editHandler */ WebInspector.EditableSettingsList = function(columns, valuesProvider, validateHandler, editHandler) { WebInspector.SettingsList.call(this, columns, this._renderColumn.bind(this)); this._valuesProvider = valuesProvider; this._validateHandler = validateHandler; this._editHandler = editHandler; /** @type {!Map.<string, (!HTMLInputElement|!HTMLSelectElement)>} */ this._addInputElements = new Map(); /** @type {!Map.<string, !Map.<string, (!HTMLInputElement|!HTMLSelectElement)>>} */ this._editInputElements = new Map(); /** @type {!Map.<string, !Map.<string, !HTMLSpanElement>>} */ this._textElements = new Map(); this._addMappingItem = this.addItem(null); this._addMappingItem.classList.add("item-editing", "add-list-item"); } WebInspector.EditableSettingsList.prototype = { /** * @override * @param {?string} itemId * @param {?string=} beforeId * @return {!Element} */ addItem: function(itemId, beforeId) { var listItem = WebInspector.SettingsList.prototype.addItem.call(this, itemId, beforeId); listItem.classList.add("editable"); return listItem; }, /** * @param {?string} itemId */ refreshItem: function(itemId) { if (!itemId) return; var listItem = this.itemForId(itemId); if (!listItem) return; for (var i = 0; i < this._columns.length; ++i) { var column = this._columns[i]; var columnId = column.id; var value = this._valuesProvider(itemId, columnId); this._setTextElementContent(itemId, columnId, value); var editElement = this._editInputElements.get(itemId).get(columnId); this._setEditElementValue(editElement, value || ""); } }, /** * @param {?string} itemId * @param {string} columnId */ _textElementContent: function(itemId, columnId) { if (!itemId) return ""; return this._textElements.get(itemId).get(columnId).textContent.replace(/\u200B/g, ""); }, /** * @param {string} itemId * @param {string} columnId * @param {string} text */ _setTextElementContent: function(itemId, columnId, text) { var textElement = this._textElements.get(itemId).get(columnId); textElement.textContent = text.replace(/.{4}/g, "$&\u200B"); textElement.title = text; }, /** * @param {!Element} columnElement * @param {{id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}} column * @param {?string} itemId */ _renderColumn: function(columnElement, column, itemId) { var columnId = column.id; if (itemId === null) { this._createEditElement(columnElement, column, itemId); return; } var validItemId = itemId; if (!this._editInputElements.has(itemId)) this._editInputElements.set(itemId, new Map()); if (!this._textElements.has(itemId)) this._textElements.set(itemId, new Map()); var value = this._valuesProvider(itemId, columnId); var textElement = /** @type {!HTMLSpanElement} */ (columnElement.createChild("span", "list-column-text")); columnElement.addEventListener("click", rowClicked.bind(this), false); this._textElements.get(itemId).set(columnId, textElement); this._setTextElementContent(itemId, columnId, value); this._createEditElement(columnElement, column, itemId, value); /** * @param {!Event} event * @this {WebInspector.EditableSettingsList} */ function rowClicked(event) { if (itemId === this._editingId) return; console.assert(!this._editingId); this._editingId = validItemId; var listItem = this.itemForId(validItemId); listItem.classList.add("item-editing"); var editElement = event.target.editElement || this._editInputElements.get(validItemId).get(this.columns()[0]); editElement.focus(); if (editElement.select) editElement.select(); } }, /** * @param {!Element} columnElement * @param {{id: string, placeholder: (string|undefined), options: (!Array.<string>|undefined)}} column * @param {?string} itemId * @param {string=} value * @return {!Element} */ _createEditElement: function(columnElement, column, itemId, value) { var options = column.options; if (options) { var editElement = /** @type {!HTMLSelectElement} */ (columnElement.createChild("select", "chrome-select list-column-editor")); for (var i = 0; i < options.length; ++i) { var option = editElement.createChild("option"); option.value = options[i]; option.textContent = options[i]; } editElement.addEventListener("blur", this._editMappingBlur.bind(this, itemId), false); editElement.addEventListener("change", this._editMappingBlur.bind(this, itemId), false); } else { var editElement = /** @type {!HTMLInputElement} */ (columnElement.createChild("input", "list-column-editor")); editElement.addEventListener("blur", this._editMappingBlur.bind(this, itemId), false); editElement.addEventListener("input", this._validateEdit.bind(this, itemId), false); if (itemId === null) editElement.placeholder = column.placeholder || ""; } if (itemId === null) this._addInputElements.set(column.id, editElement); else this._editInputElements.get(itemId).set(column.id, editElement); this._setEditElementValue(editElement, value || ""); columnElement.editElement = editElement; return editElement; }, /** * @param {!HTMLInputElement|!HTMLSelectElement|undefined} editElement * @param {string} value */ _setEditElementValue: function(editElement, value) { if (!editElement) return; if (editElement instanceof HTMLSelectElement) { var options = editElement.options; for (var i = 0; i < options.length; ++i) options[i].selected = (options[i].value === value); } else { editElement.value = value; } }, /** * @param {?string} itemId * @return {!Object} */ _data: function(itemId) { var inputElements = this._inputElements(itemId); var data = { __proto__: null }; var columns = this.columns(); for (var i = 0; i < columns.length; ++i) data[columns[i]] = inputElements.get(columns[i]).value; return data; }, /** * @param {?string} itemId * @return {?Map.<string, (!HTMLInputElement|!HTMLSelectElement)>} */ _inputElements: function(itemId) { if (!itemId) return this._addInputElements; return this._editInputElements.get(itemId) || null; }, /** * @param {?string} itemId * @return {boolean} */ _validateEdit: function(itemId) { var errorColumns = this._validateHandler(itemId, this._data(itemId)); var hasChanges = this._hasChanges(itemId); var columns = this.columns(); for (var i = 0; i < columns.length; ++i) {