| /* |
| * Copyright (C) 2014 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 |
| * @extends {WebInspector.VBox} |
| */ |
| WebInspector.OverridesView = function() |
| { |
| WebInspector.VBox.call(this); |
| this.registerRequiredCSS("overrides.css"); |
| this.element.classList.add("overrides-view"); |
| |
| this._tabbedPane = new WebInspector.TabbedPane(); |
| this._tabbedPane.shrinkableTabs = false; |
| this._tabbedPane.verticalTabLayout = true; |
| |
| new WebInspector.OverridesView.DeviceTab().appendAsTab(this._tabbedPane); |
| new WebInspector.OverridesView.MediaTab().appendAsTab(this._tabbedPane); |
| new WebInspector.OverridesView.NetworkTab().appendAsTab(this._tabbedPane); |
| new WebInspector.OverridesView.SensorsTab().appendAsTab(this._tabbedPane); |
| |
| this._lastSelectedTabSetting = WebInspector.settings.createSetting("lastSelectedEmulateTab", "device"); |
| this._tabbedPane.selectTab(this._lastSelectedTabSetting.get()); |
| this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); |
| this._tabbedPane.show(this.element); |
| |
| var resetButtonElement = this._tabbedPane.headerElement().createChild("button", "text-button"); |
| resetButtonElement.id = "overrides-reset-button"; |
| resetButtonElement.textContent = WebInspector.UIString("Reset"); |
| resetButtonElement.addEventListener("click", WebInspector.overridesSupport.reset.bind(WebInspector.overridesSupport), false); |
| |
| if (!WebInspector.overridesSupport.responsiveDesignAvailable()) { |
| var disableButtonElement = this._tabbedPane.headerElement().createChild("button", "text-button overrides-disable-button"); |
| disableButtonElement.id = "overrides-disable-button"; |
| disableButtonElement.textContent = WebInspector.UIString("Disable"); |
| disableButtonElement.addEventListener("click", this._toggleEmulationEnabled.bind(this), false); |
| } |
| |
| this._splashScreenElement = this.element.createChild("div", "overrides-splash-screen"); |
| this._unavailableSplashScreenElement = this.element.createChild("div", "overrides-splash-screen"); |
| this._unavailableSplashScreenElement.createTextChild(WebInspector.UIString("Emulation is not available.")); |
| |
| if (WebInspector.overridesSupport.responsiveDesignAvailable()) { |
| this._splashScreenElement.createTextChild(WebInspector.UIString("Emulation is currently disabled. Toggle ")); |
| var toggleEmulationButton = new WebInspector.StatusBarButton("", "emulation-status-bar-item"); |
| toggleEmulationButton.addEventListener("click", this._toggleEmulationEnabled, this); |
| this._splashScreenElement.appendChild(toggleEmulationButton.element); |
| this._splashScreenElement.createTextChild(WebInspector.UIString("in the main toolbar to enable it.")); |
| } else { |
| var toggleEmulationButton = this._splashScreenElement.createChild("button", "text-button overrides-enable-button"); |
| toggleEmulationButton.textContent = WebInspector.UIString("Enable emulation"); |
| toggleEmulationButton.addEventListener("click", this._toggleEmulationEnabled.bind(this), false); |
| } |
| |
| this._warningFooter = this.element.createChild("div", "overrides-footer"); |
| this._overridesWarningUpdated(); |
| |
| WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport.Events.OverridesWarningUpdated, this._overridesWarningUpdated, this); |
| WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport.Events.EmulationStateChanged, this._emulationStateChanged, this); |
| this._emulationStateChanged(); |
| } |
| |
| WebInspector.OverridesView.prototype = { |
| /** |
| * @param {!WebInspector.Event} event |
| */ |
| _tabSelected: function(event) |
| { |
| this._lastSelectedTabSetting.set(this._tabbedPane.selectedTabId); |
| }, |
| |
| _overridesWarningUpdated: function() |
| { |
| var message = WebInspector.overridesSupport.warningMessage(); |
| this._warningFooter.classList.toggle("hidden", !message); |
| this._warningFooter.textContent = message; |
| }, |
| |
| _toggleEmulationEnabled: function() |
| { |
| WebInspector.overridesSupport.setEmulationEnabled(!WebInspector.overridesSupport.emulationEnabled()); |
| }, |
| |
| _emulationStateChanged: function() |
| { |
| this._unavailableSplashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.canEmulate()); |
| this._tabbedPane.element.classList.toggle("hidden", !WebInspector.overridesSupport.emulationEnabled()); |
| this._splashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.emulationEnabled() || !WebInspector.overridesSupport.canEmulate()); |
| }, |
| |
| __proto__: WebInspector.VBox.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.VBox} |
| * @param {string} id |
| * @param {string} name |
| * @param {!Array.<!WebInspector.Setting>} settings |
| * @param {!Array.<function():boolean>=} predicates |
| */ |
| WebInspector.OverridesView.Tab = function(id, name, settings, predicates) |
| { |
| WebInspector.VBox.call(this); |
| this._id = id; |
| this._name = name; |
| this._settings = settings; |
| this._predicates = predicates || []; |
| for (var i = 0; i < settings.length; ++i) |
| settings[i].addChangeListener(this.updateActiveState, this); |
| } |
| |
| WebInspector.OverridesView.Tab.prototype = { |
| /** |
| * @param {!WebInspector.TabbedPane} tabbedPane |
| */ |
| appendAsTab: function(tabbedPane) |
| { |
| this._tabbedPane = tabbedPane; |
| tabbedPane.appendTab(this._id, this._name, this); |
| this.updateActiveState(); |
| }, |
| |
| updateActiveState: function() |
| { |
| if (!this._tabbedPane) |
| return; |
| var active = false; |
| for (var i = 0; !active && i < this._settings.length; ++i) |
| active = this._settings[i].get(); |
| for (var i = 0; !active && i < this._predicates.length; ++i) |
| active = this._predicates[i](); |
| this._tabbedPane.element.classList.toggle("overrides-activate-" + this._id, active); |
| }, |
| |
| /** |
| * @param {string} name |
| * @param {!WebInspector.Setting} setting |
| * @param {function(boolean)=} callback |
| */ |
| _createSettingCheckbox: function(name, setting, callback) |
| { |
| var checkbox = WebInspector.SettingsUI.createSettingCheckbox(name, setting, true); |
| |
| function changeListener(value) |
| { |
| callback(setting.get()); |
| } |
| |
| if (callback) |
| setting.addChangeListener(changeListener); |
| |
| return checkbox; |
| }, |
| |
| __proto__: WebInspector.VBox.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.OverridesView.Tab} |
| */ |
| WebInspector.OverridesView.DeviceTab = function() |
| { |
| WebInspector.OverridesView.Tab.call(this, "device", WebInspector.UIString("Device"), [ |
| WebInspector.overridesSupport.settings.emulateResolution, |
| WebInspector.overridesSupport.settings.deviceScaleFactor, |
| WebInspector.overridesSupport.settings.emulateMobile |
| ]); |
| this.element.classList.add("overrides-device"); |
| |
| this.element.appendChild(this._createDeviceElement()); |
| |
| var footnote = this.element.createChild("p", "help-footnote"); |
| var footnoteLink = footnote.createChild("a"); |
| footnoteLink.href = "https://developers.google.com/chrome-developer-tools/docs/mobile-emulation"; |
| footnoteLink.target = "_blank"; |
| footnoteLink.createTextChild(WebInspector.UIString("More information about screen emulation")); |
| } |
| |
| WebInspector.OverridesView.DeviceTab.prototype = { |
| _createDeviceElement: function() |
| { |
| var fieldsetElement = document.createElement("fieldset"); |
| fieldsetElement.id = "metrics-override-section"; |
| |
| var deviceModelElement = fieldsetElement.createChild("p", "overrides-device-model-section"); |
| deviceModelElement.createChild("span").textContent = WebInspector.UIString("Model:"); |
| |
| var deviceSelectElement = WebInspector.OverridesUI.createDeviceSelect(document, this._showTitleDialog.bind(this)); |
| var buttons = deviceSelectElement.querySelectorAll("button"); |
| for (var i = 0; i < buttons.length; ++i) |
| buttons[i].classList.add("text-button"); |
| deviceModelElement.appendChild(deviceSelectElement); |
| |
| var emulateResolutionCheckbox = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Emulate screen resolution"), WebInspector.overridesSupport.settings.emulateResolution, true); |
| fieldsetElement.appendChild(emulateResolutionCheckbox); |
| var resolutionFieldset = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.emulateResolution); |
| fieldsetElement.appendChild(resolutionFieldset); |
| |
| var tableElement = resolutionFieldset.createChild("table", "nowrap"); |
| var rowElement = tableElement.createChild("tr"); |
| var cellElement = rowElement.createChild("td"); |
| cellElement.appendChild(document.createTextNode(WebInspector.UIString("Resolution:"))); |
| cellElement = rowElement.createChild("td"); |
| |
| var widthOverrideInput = WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceWidth, true, 4, "80px", WebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UIString("\u2013")); |
| cellElement.appendChild(widthOverrideInput); |
| this._swapDimensionsElement = cellElement.createChild("button", "overrides-swap"); |
| this._swapDimensionsElement.appendChild(document.createTextNode(" \u21C4 ")); // RIGHTWARDS ARROW OVER LEFTWARDS ARROW. |
| this._swapDimensionsElement.title = WebInspector.UIString("Swap dimensions"); |
| this._swapDimensionsElement.addEventListener("click", WebInspector.overridesSupport.swapDimensions.bind(WebInspector.overridesSupport), false); |
| this._swapDimensionsElement.tabIndex = -1; |
| var heightOverrideInput = WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceHeight, true, 4, "80px", WebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UIString("\u2013")); |
| cellElement.appendChild(heightOverrideInput); |
| |
| rowElement = tableElement.createChild("tr"); |
| cellElement = rowElement.createChild("td"); |
| cellElement.colSpan = 4; |
| |
| rowElement = tableElement.createChild("tr"); |
| rowElement.title = WebInspector.UIString("Ratio between a device's physical pixels and device-independent pixels."); |
| rowElement.createChild("td").appendChild(document.createTextNode(WebInspector.UIString("Device pixel ratio:"))); |
| rowElement.createChild("td").appendChild(WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceScaleFactor, true, 4, "80px", WebInspector.OverridesSupport.deviceScaleFactorValidator, true, true, WebInspector.UIString("\u2013"))); |
| |
| var mobileCheckbox = this._createSettingCheckbox(WebInspector.UIString("Emulate mobile"), WebInspector.overridesSupport.settings.emulateMobile); |
| mobileCheckbox.title = WebInspector.UIString("Enable meta viewport, overlay scrollbars, text autosizing and default 980px body width"); |
| fieldsetElement.appendChild(mobileCheckbox); |
| |
| fieldsetElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Shrink to fit"), WebInspector.overridesSupport.settings.deviceFitWindow)); |
| |
| return fieldsetElement; |
| }, |
| |
| /** |
| * @param {!function(string)} callback |
| */ |
| _showTitleDialog: function(callback) |
| { |
| WebInspector.Dialog.show(this.element, new WebInspector.OverridesView.DeviceTab.CustomDeviceTitleDialog(callback)); |
| }, |
| |
| __proto__: WebInspector.OverridesView.Tab.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.DialogDelegate} |
| * @param {!function(string)} callback |
| */ |
| WebInspector.OverridesView.DeviceTab.CustomDeviceTitleDialog = function(callback) |
| { |
| WebInspector.DialogDelegate.call(this); |
| |
| this.element = document.createElementWithClass("div", "custom-device-title-dialog"); |
| this.element.createChild("label").textContent = WebInspector.UIString("Save as: "); |
| |
| this._input = this.element.createChild("input"); |
| this._input.setAttribute("type", "text"); |
| this._input.placeholder = WebInspector.UIString("device model name"); |
| this._input.addEventListener("input", this._onInput.bind(this), false); |
| |
| this._saveButton = this.element.createChild("button"); |
| this._saveButton.textContent = WebInspector.UIString("Save"); |
| this._saveButton.addEventListener("click", this._onSaveClick.bind(this), false); |
| |
| this._callback = callback; |
| this._result = ""; |
| this._onInput(); |
| } |
| |
| WebInspector.OverridesView.DeviceTab.CustomDeviceTitleDialog.prototype = { |
| focus: function() |
| { |
| WebInspector.setCurrentFocusElement(this._input); |
| this._input.select(); |
| }, |
| |
| _onSaveClick: function() |
| { |
| this._result = this._input.value.trim(); |
| WebInspector.Dialog.hide(); |
| }, |
| |
| _onInput: function() |
| { |
| this._saveButton.disabled = !this._input.value.trim(); |
| }, |
| |
| /** |
| * @param {!Event} event |
| */ |
| onEnter: function(event) |
| { |
| if (this._input.value.trim()) { |
| this._result = this._input.value.trim(); |
| } else { |
| event.consume(); |
| } |
| }, |
| |
| willHide: function() |
| { |
| this._callback(this._result); |
| }, |
| |
| __proto__: WebInspector.DialogDelegate.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.OverridesView.Tab} |
| */ |
| WebInspector.OverridesView.MediaTab = function() |
| { |
| var settings = [WebInspector.overridesSupport.settings.overrideCSSMedia]; |
| WebInspector.OverridesView.Tab.call(this, "media", WebInspector.UIString("Media"), settings); |
| this.element.classList.add("overrides-media"); |
| |
| this._createMediaEmulationFragment(); |
| } |
| |
| WebInspector.OverridesView.MediaTab.prototype = { |
| _createMediaEmulationFragment: function() |
| { |
| var checkbox = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("CSS media"), WebInspector.overridesSupport.settings.overrideCSSMedia, true); |
| var fieldsetElement = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.overrideCSSMedia); |
| var mediaSelectElement = fieldsetElement.createChild("select"); |
| var mediaTypes = WebInspector.CSSStyleModel.MediaTypes; |
| var defaultMedia = WebInspector.overridesSupport.settings.emulatedCSSMedia.get(); |
| for (var i = 0; i < mediaTypes.length; ++i) { |
| var mediaType = mediaTypes[i]; |
| if (mediaType === "all") { |
| // "all" is not a device-specific media type. |
| continue; |
| } |
| var option = document.createElement("option"); |
| option.text = mediaType; |
| option.value = mediaType; |
| mediaSelectElement.add(option); |
| if (mediaType === defaultMedia) |
| mediaSelectElement.selectedIndex = mediaSelectElement.options.length - 1; |
| } |
| |
| mediaSelectElement.addEventListener("change", this._emulateMediaChanged.bind(this, mediaSelectElement), false); |
| var fragment = document.createDocumentFragment(); |
| fragment.appendChild(checkbox); |
| fragment.appendChild(fieldsetElement); |
| this.element.appendChild(fragment); |
| }, |
| |
| _emulateMediaChanged: function(select) |
| { |
| var media = select.options[select.selectedIndex].value; |
| WebInspector.overridesSupport.settings.emulatedCSSMedia.set(media); |
| }, |
| |
| __proto__: WebInspector.OverridesView.Tab.prototype |
| } |
| |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.OverridesView.Tab} |
| */ |
| WebInspector.OverridesView.NetworkTab = function() |
| { |
| WebInspector.OverridesView.Tab.call(this, "network", WebInspector.UIString("Network"), [], [this._userAgentOverrideEnabled.bind(this), this._networkThroughputIsLimited.bind(this)]); |
| this.element.classList.add("overrides-network"); |
| this._createNetworkConditionsElement(); |
| this._createUserAgentSection(); |
| } |
| |
| WebInspector.OverridesView.NetworkTab.prototype = { |
| /** |
| * @return {boolean} |
| */ |
| _networkThroughputIsLimited: function() |
| { |
| return WebInspector.overridesSupport.networkThroughputIsLimited(); |
| }, |
| |
| _createNetworkConditionsElement: function() |
| { |
| var fieldsetElement = this.element.createChild("fieldset"); |
| fieldsetElement.createChild("span").textContent = WebInspector.UIString("Limit network throughput:"); |
| fieldsetElement.createChild("br"); |
| fieldsetElement.appendChild(WebInspector.OverridesUI.createNetworkConditionsSelect(document)); |
| |
| WebInspector.overridesSupport.settings.networkConditions.addChangeListener(this.updateActiveState, this); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _userAgentOverrideEnabled: function() |
| { |
| return !!WebInspector.overridesSupport.settings.userAgent.get(); |
| }, |
| |
| _createUserAgentSection: function() |
| { |
| var fieldsetElement = this.element.createChild("fieldset"); |
| fieldsetElement.createChild("label").textContent = WebInspector.UIString("Spoof user agent:"); |
| var selectAndInput = WebInspector.OverridesUI.createUserAgentSelectAndInput(document); |
| fieldsetElement.appendChild(selectAndInput.select); |
| fieldsetElement.appendChild(selectAndInput.input); |
| |
| WebInspector.overridesSupport.settings.userAgent.addChangeListener(this.updateActiveState, this); |
| }, |
| |
| __proto__: WebInspector.OverridesView.Tab.prototype |
| } |
| |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.OverridesView.Tab} |
| */ |
| WebInspector.OverridesView.SensorsTab = function() |
| { |
| WebInspector.OverridesView.Tab.call(this, "sensors", WebInspector.UIString("Sensors"), [ |
| WebInspector.overridesSupport.settings.overrideGeolocation, |
| WebInspector.overridesSupport.settings.overrideDeviceOrientation, |
| WebInspector.overridesSupport.settings.emulateTouch |
| ]); |
| |
| this.element.classList.add("overrides-sensors"); |
| this.registerRequiredCSS("accelerometer.css"); |
| this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Emulate touch screen"), WebInspector.overridesSupport.settings.emulateTouch, undefined)); |
| this._appendGeolocationOverrideControl(); |
| this._apendDeviceOrientationOverrideControl(); |
| } |
| |
| WebInspector.OverridesView.SensorsTab.prototype = { |
| _appendGeolocationOverrideControl: function() |
| { |
| const geolocationSetting = WebInspector.overridesSupport.settings.geolocationOverride.get(); |
| var geolocation = WebInspector.OverridesSupport.GeolocationPosition.parseSetting(geolocationSetting); |
| this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Emulate geolocation coordinates"), WebInspector.overridesSupport.settings.overrideGeolocation, this._geolocationOverrideCheckboxClicked.bind(this))); |
| this.element.appendChild(this._createGeolocationOverrideElement(geolocation)); |
| this._geolocationOverrideCheckboxClicked(WebInspector.overridesSupport.settings.overrideGeolocation.get()); |
| }, |
| |
| /** |
| * @param {boolean} enabled |
| */ |
| _geolocationOverrideCheckboxClicked: function(enabled) |
| { |
| if (enabled && !this._latitudeElement.value) |
| this._latitudeElement.focus(); |
| }, |
| |
| _applyGeolocationUserInput: function() |
| { |
| this._setGeolocationPosition(WebInspector.OverridesSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value.trim(), this._longitudeElement.value.trim(), this._geolocationErrorElement.checked), true); |
| }, |
| |
| /** |
| * @param {?WebInspector.OverridesSupport.GeolocationPosition} geolocation |
| * @param {boolean} userInputModified |
| */ |
| _setGeolocationPosition: function(geolocation, userInputModified) |
| { |
| if (!geolocation) |
| return; |
| |
| if (!userInputModified) { |
| this._latitudeElement.value = geolocation.latitude; |
| this._longitudeElement.value = geolocation.longitude; |
| } |
| |
| var value = geolocation.toSetting(); |
| WebInspector.overridesSupport.settings.geolocationOverride.set(value); |
| }, |
| |
| /** |
| * @param {!WebInspector.OverridesSupport.GeolocationPosition} geolocation |
| * @return {!Element} |
| */ |
| _createGeolocationOverrideElement: function(geolocation) |
| { |
| var fieldsetElement = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.overrideGeolocation); |
| fieldsetElement.id = "geolocation-override-section"; |
| |
| var tableElement = fieldsetElement.createChild("table"); |
| var rowElement = tableElement.createChild("tr"); |
| var cellElement = rowElement.createChild("td"); |
| cellElement = rowElement.createChild("td"); |
| cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lat = "))); |
| this._latitudeElement = WebInspector.SettingsUI.createInput(cellElement, "geolocation-override-latitude", String(geolocation.latitude), this._applyGeolocationUserInput.bind(this), true); |
| cellElement.appendChild(document.createTextNode(" , ")); |
| cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lon = "))); |
| this._longitudeElement = WebInspector.SettingsUI.createInput(cellElement, "geolocation-override-longitude", String(geolocation.longitude), this._applyGeolocationUserInput.bind(this), true); |
| rowElement = tableElement.createChild("tr"); |
| cellElement = rowElement.createChild("td"); |
| cellElement.colSpan = 2; |
| var geolocationErrorLabelElement = document.createElement("label"); |
| var geolocationErrorCheckboxElement = geolocationErrorLabelElement.createChild("input"); |
| geolocationErrorCheckboxElement.id = "geolocation-error"; |
| geolocationErrorCheckboxElement.type = "checkbox"; |
| geolocationErrorCheckboxElement.checked = !geolocation || geolocation.error; |
| geolocationErrorCheckboxElement.addEventListener("click", this._applyGeolocationUserInput.bind(this), false); |
| geolocationErrorLabelElement.appendChild(document.createTextNode(WebInspector.UIString("Emulate position unavailable"))); |
| this._geolocationErrorElement = geolocationErrorCheckboxElement; |
| cellElement.appendChild(geolocationErrorLabelElement); |
| |
| return fieldsetElement; |
| }, |
| |
| _apendDeviceOrientationOverrideControl: function() |
| { |
| const deviceOrientationSetting = WebInspector.overridesSupport.settings.deviceOrientationOverride.get(); |
| var deviceOrientation = WebInspector.OverridesSupport.DeviceOrientation.parseSetting(deviceOrientationSetting); |
| this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Accelerometer"), WebInspector.overridesSupport.settings.overrideDeviceOrientation, this._deviceOrientationOverrideCheckboxClicked.bind(this))); |
| this.element.appendChild(this._createDeviceOrientationOverrideElement(deviceOrientation)); |
| this._deviceOrientationOverrideCheckboxClicked(WebInspector.overridesSupport.settings.overrideDeviceOrientation.get()); |
| }, |
| |
| /** |
| * @param {boolean} enabled |
| */ |
| _deviceOrientationOverrideCheckboxClicked: function(enabled) |
| { |
| if (enabled && !this._alphaElement.value) |
| this._alphaElement.focus(); |
| }, |
| |
| _applyDeviceOrientationUserInput: function() |
| { |
| this._setDeviceOrientation(WebInspector.OverridesSupport.DeviceOrientation.parseUserInput(this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()), WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserInput); |
| }, |
| |
| _resetDeviceOrientation: function() |
| { |
| this._setDeviceOrientation(new WebInspector.OverridesSupport.DeviceOrientation(0, 0, 0), WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.ResetButton); |
| }, |
| |
| /** |
| * @param {?WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation |
| * @param {!WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource} modificationSource |
| */ |
| _setDeviceOrientation: function(deviceOrientation, modificationSource) |
| { |
| if (!deviceOrientation) |
| return; |
| |
| if (modificationSource != WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserInput) { |
| this._alphaElement.value = deviceOrientation.alpha; |
| this._betaElement.value = deviceOrientation.beta; |
| this._gammaElement.value = deviceOrientation.gamma; |
| } |
| |
| if (modificationSource != WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserDrag) |
| this._setBoxOrientation(deviceOrientation); |
| |
| var value = deviceOrientation.toSetting(); |
| WebInspector.overridesSupport.settings.deviceOrientationOverride.set(value); |
| }, |
| |
| /** |
| * @param {!Element} parentElement |
| * @param {string} id |
| * @param {string} label |
| * @param {string} defaultText |
| * @return {!Element} |
| */ |
| _createAxisInput: function(parentElement, id, label, defaultText) |
| { |
| var div = parentElement.createChild("div", "accelerometer-axis-input-container"); |
| div.appendChild(document.createTextNode(label)); |
| return WebInspector.SettingsUI.createInput(div, id, defaultText, this._applyDeviceOrientationUserInput.bind(this), true); |
| }, |
| |
| /** |
| * @param {!WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation |
| */ |
| _createDeviceOrientationOverrideElement: function(deviceOrientation) |
| { |
| var fieldsetElement = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.overrideDeviceOrientation); |
| fieldsetElement.id = "device-orientation-override-section"; |
| var tableElement = fieldsetElement.createChild("table"); |
| var rowElement = tableElement.createChild("tr"); |
| var cellElement = rowElement.createChild("td", "accelerometer-inputs-cell"); |
| |
| this._alphaElement = this._createAxisInput(cellElement, "device-orientation-override-alpha", "\u03B1: ", String(deviceOrientation.alpha)); |
| this._betaElement = this._createAxisInput(cellElement, "device-orientation-override-beta", "\u03B2: ", String(deviceOrientation.beta)); |
| this._gammaElement = this._createAxisInput(cellElement, "device-orientation-override-gamma", "\u03B3: ", String(deviceOrientation.gamma)); |
| |
| var resetButton = cellElement.createChild("button", "text-button accelerometer-reset-button"); |
| resetButton.textContent = WebInspector.UIString("Reset"); |
| resetButton.addEventListener("click", this._resetDeviceOrientation.bind(this), false); |
| |
| this._stageElement = rowElement.createChild("td","accelerometer-stage"); |
| this._boxElement = this._stageElement.createChild("section", "accelerometer-box"); |
| |
| this._boxElement.createChild("section", "front"); |
| this._boxElement.createChild("section", "top"); |
| this._boxElement.createChild("section", "back"); |
| this._boxElement.createChild("section", "left"); |
| this._boxElement.createChild("section", "right"); |
| this._boxElement.createChild("section", "bottom"); |
| |
| WebInspector.installDragHandle(this._stageElement, this._onBoxDragStart.bind(this), this._onBoxDrag.bind(this), this._onBoxDragEnd.bind(this), "move"); |
| this._setBoxOrientation(deviceOrientation); |
| return fieldsetElement; |
| }, |
| |
| /** |
| * @param {!WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation |
| */ |
| _setBoxOrientation: function(deviceOrientation) |
| { |
| var matrix = new WebKitCSSMatrix(); |
| this._boxMatrix = matrix.rotate(-deviceOrientation.beta, deviceOrientation.gamma, -deviceOrientation.alpha); |
| this._boxElement.style.webkitTransform = this._boxMatrix.toString(); |
| }, |
| |
| /** |
| * @param {!MouseEvent} event |
| * @return {boolean} |
| */ |
| _onBoxDrag: function(event) |
| { |
| var mouseMoveVector = this._calculateRadiusVector(event.x, event.y); |
| if (!mouseMoveVector) |
| return true; |
| |
| event.consume(true); |
| var axis = WebInspector.Geometry.crossProduct(this._mouseDownVector, mouseMoveVector); |
| axis.normalize(); |
| var angle = WebInspector.Geometry.calculateAngle(this._mouseDownVector, mouseMoveVector); |
| var matrix = new WebKitCSSMatrix(); |
| var rotationMatrix = matrix.rotateAxisAngle(axis.x, axis.y, axis.z, angle); |
| this._currentMatrix = rotationMatrix.multiply(this._boxMatrix) |
| this._boxElement.style.webkitTransform = this._currentMatrix; |
| var eulerAngles = WebInspector.Geometry.EulerAngles.fromRotationMatrix(this._currentMatrix); |
| var newOrientation = new WebInspector.OverridesSupport.DeviceOrientation(-eulerAngles.alpha, -eulerAngles.beta, eulerAngles.gamma); |
| this._setDeviceOrientation(newOrientation, WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserDrag); |
| return false; |
| }, |
| |
| /** |
| * @param {!MouseEvent} event |
| * @return {boolean} |
| */ |
| _onBoxDragStart: function(event) |
| { |
| if (!WebInspector.overridesSupport.settings.overrideDeviceOrientation.get()) |
| return false; |
| |
| this._mouseDownVector = this._calculateRadiusVector(event.x, event.y); |
| |
| if (!this._mouseDownVector) |
| return false; |
| |
| event.consume(true); |
| return true; |
| }, |
| |
| _onBoxDragEnd: function() |
| { |
| this._boxMatrix = this._currentMatrix; |
| }, |
| |
| /** |
| * @param {number} x |
| * @param {number} y |
| * @return {?WebInspector.Geometry.Vector} |
| */ |
| _calculateRadiusVector: function(x, y) |
| { |
| var rect = this._stageElement.getBoundingClientRect(); |
| var radius = Math.max(rect.width, rect.height) / 2; |
| var sphereX = (x - rect.left - rect.width / 2) / radius; |
| var sphereY = (y - rect.top - rect.height / 2) / radius; |
| var sqrSum = sphereX * sphereX + sphereY * sphereY; |
| if (sqrSum > 0.5) |
| return new WebInspector.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum)); |
| |
| return new WebInspector.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum)); |
| }, |
| |
| __proto__ : WebInspector.OverridesView.Tab.prototype |
| } |
| |
| /** @enum {string} */ |
| WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource = { |
| UserInput: "userInput", |
| UserDrag: "userDrag", |
| ResetButton: "resetButton" |
| } |
| |
| /** |
| * @constructor |
| * @implements {WebInspector.Revealer} |
| */ |
| WebInspector.OverridesView.Revealer = function() |
| { |
| } |
| |
| WebInspector.OverridesView.Revealer.prototype = { |
| /** |
| * @param {!Object} overridesSupport |
| */ |
| reveal: function(overridesSupport) |
| { |
| WebInspector.inspectorView.showViewInDrawer("emulation"); |
| } |
| } |