1/* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/** 32 * @constructor 33 * @param {!Element} relativeToElement 34 * @param {!WebInspector.DialogDelegate} delegate 35 */ 36WebInspector.Dialog = function(relativeToElement, delegate) 37{ 38 this._delegate = delegate; 39 this._relativeToElement = relativeToElement; 40 41 this._glassPane = new WebInspector.GlassPane(); 42 WebInspector.GlassPane.DefaultFocusedViewStack.push(this); 43 44 // Install glass pane capturing events. 45 this._glassPane.element.tabIndex = 0; 46 this._glassPane.element.addEventListener("focus", this._onGlassPaneFocus.bind(this), false); 47 48 this._element = this._glassPane.element.createChild("div"); 49 this._element.tabIndex = 0; 50 this._element.addEventListener("focus", this._onFocus.bind(this), false); 51 this._element.addEventListener("keydown", this._onKeyDown.bind(this), false); 52 this._closeKeys = [ 53 WebInspector.KeyboardShortcut.Keys.Enter.code, 54 WebInspector.KeyboardShortcut.Keys.Esc.code, 55 ]; 56 57 delegate.show(this._element); 58 59 this._position(); 60 this._delegate.focus(); 61} 62 63/** 64 * @return {?WebInspector.Dialog} 65 */ 66WebInspector.Dialog.currentInstance = function() 67{ 68 return WebInspector.Dialog._instance; 69} 70 71/** 72 * @param {!Element} relativeToElement 73 * @param {!WebInspector.DialogDelegate} delegate 74 */ 75WebInspector.Dialog.show = function(relativeToElement, delegate) 76{ 77 if (WebInspector.Dialog._instance) 78 return; 79 WebInspector.Dialog._instance = new WebInspector.Dialog(relativeToElement, delegate); 80} 81 82WebInspector.Dialog.hide = function() 83{ 84 if (!WebInspector.Dialog._instance) 85 return; 86 WebInspector.Dialog._instance._hide(); 87} 88 89WebInspector.Dialog.prototype = { 90 focus: function() 91 { 92 this._element.focus(); 93 }, 94 95 _hide: function() 96 { 97 if (this._isHiding) 98 return; 99 this._isHiding = true; 100 101 this._delegate.willHide(); 102 103 delete WebInspector.Dialog._instance; 104 WebInspector.GlassPane.DefaultFocusedViewStack.pop(); 105 this._glassPane.dispose(); 106 }, 107 108 _onGlassPaneFocus: function(event) 109 { 110 this._hide(); 111 }, 112 113 _onFocus: function(event) 114 { 115 this._delegate.focus(); 116 }, 117 118 _position: function() 119 { 120 this._delegate.position(this._element, this._relativeToElement); 121 }, 122 123 _onKeyDown: function(event) 124 { 125 if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) { 126 event.preventDefault(); 127 return; 128 } 129 130 if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) 131 this._delegate.onEnter(event); 132 133 if (!event.handled && this._closeKeys.indexOf(event.keyCode) >= 0) { 134 this._hide(); 135 event.consume(true); 136 } 137 } 138}; 139 140/** 141 * @constructor 142 * @extends {WebInspector.Object} 143 */ 144WebInspector.DialogDelegate = function() 145{ 146 /** @type {!Element} */ 147 this.element; 148} 149 150WebInspector.DialogDelegate.prototype = { 151 /** 152 * @param {!Element} element 153 */ 154 show: function(element) 155 { 156 element.appendChild(this.element); 157 this.element.classList.add("dialog-contents"); 158 element.classList.add("dialog", "toolbar-colors"); 159 }, 160 161 /** 162 * @param {!Element} element 163 * @param {!Element} relativeToElement 164 */ 165 position: function(element, relativeToElement) 166 { 167 var container = WebInspector.Dialog._modalHostView.element; 168 var box = relativeToElement.boxInWindow(window).relativeToElement(container); 169 170 var positionX = box.x + (relativeToElement.offsetWidth - element.offsetWidth) / 2; 171 positionX = Number.constrain(positionX, 0, container.offsetWidth - element.offsetWidth); 172 173 var positionY = box.y + (relativeToElement.offsetHeight - element.offsetHeight) / 2; 174 positionY = Number.constrain(positionY, 0, container.offsetHeight - element.offsetHeight); 175 176 element.style.position = "absolute"; 177 element.positionAt(positionX, positionY, container); 178 }, 179 180 focus: function() { }, 181 182 onEnter: function(event) { }, 183 184 willHide: function() { }, 185 186 __proto__: WebInspector.Object.prototype 187} 188 189/** @type {?WebInspector.View} */ 190WebInspector.Dialog._modalHostView = null; 191 192/** 193 * @param {!WebInspector.View} view 194 */ 195WebInspector.Dialog.setModalHostView = function(view) 196{ 197 WebInspector.Dialog._modalHostView = view; 198}; 199 200/** 201 * FIXME: make utility method in Dialog, so clients use it instead of this getter. 202 * Method should be like Dialog.showModalElement(position params, reposition callback). 203 * @return {?WebInspector.View} 204 */ 205WebInspector.Dialog.modalHostView = function() 206{ 207 return WebInspector.Dialog._modalHostView; 208}; 209 210WebInspector.Dialog.modalHostRepositioned = function() 211{ 212 if (WebInspector.Dialog._instance) 213 WebInspector.Dialog._instance._position(); 214}; 215 216