1 /* 2 * Copyright (C) 2014 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 WebInspector.SettingsUI = {} 32 33 /** 34 * @param {string} name 35 * @param {!WebInspector.Setting} setting 36 * @param {boolean=} omitParagraphElement 37 * @param {!Element=} inputElement 38 * @param {string=} tooltip 39 * @return {!Element} 40 */ 41 WebInspector.SettingsUI.createSettingCheckbox = function(name, setting, omitParagraphElement, inputElement, tooltip) 42 { 43 var input = inputElement || document.createElement("input"); 44 input.type = "checkbox"; 45 input.name = name; 46 WebInspector.SettingsUI.bindCheckbox(input, setting); 47 48 var label = document.createElement("label"); 49 label.appendChild(input); 50 label.createTextChild(name); 51 if (tooltip) 52 label.title = tooltip; 53 54 if (omitParagraphElement) 55 return label; 56 57 var p = document.createElement("p"); 58 p.appendChild(label); 59 return p; 60 } 61 62 /** 63 * @param {!Element} input 64 * @param {!WebInspector.Setting} setting 65 */ 66 WebInspector.SettingsUI.bindCheckbox = function(input, setting) 67 { 68 function settingChanged() 69 { 70 if (input.checked !== setting.get()) 71 input.checked = setting.get(); 72 } 73 setting.addChangeListener(settingChanged); 74 settingChanged(); 75 76 function inputChanged() 77 { 78 if (setting.get() !== input.checked) 79 setting.set(input.checked); 80 } 81 input.addEventListener("change", inputChanged, false); 82 } 83 84 /** 85 * @param {string} label 86 * @param {!WebInspector.Setting} setting 87 * @param {boolean} numeric 88 * @param {number=} maxLength 89 * @param {string=} width 90 * @param {function(string):?string=} validatorCallback 91 * @param {boolean=} instant 92 * @param {boolean=} clearForZero 93 * @param {string=} placeholder 94 * @return {!Element} 95 */ 96 WebInspector.SettingsUI.createSettingInputField = function(label, setting, numeric, maxLength, width, validatorCallback, instant, clearForZero, placeholder) 97 { 98 var p = document.createElement("p"); 99 var labelElement = p.createChild("label"); 100 labelElement.textContent = label; 101 var inputElement = p.createChild("input"); 102 inputElement.type = "text"; 103 if (numeric) 104 inputElement.className = "numeric"; 105 if (maxLength) 106 inputElement.maxLength = maxLength; 107 if (width) 108 inputElement.style.width = width; 109 inputElement.placeholder = placeholder || ""; 110 111 if (validatorCallback || instant) { 112 inputElement.addEventListener("change", onInput, false); 113 inputElement.addEventListener("input", onInput, false); 114 } 115 inputElement.addEventListener("keydown", onKeyDown, false); 116 117 var errorMessageLabel; 118 if (validatorCallback) 119 errorMessageLabel = p.createChild("div", "field-error-message"); 120 121 function onInput() 122 { 123 if (validatorCallback) 124 validate(); 125 if (instant) 126 apply(); 127 } 128 129 function onKeyDown(event) 130 { 131 if (isEnterKey(event)) 132 apply(); 133 incrementForArrows(event); 134 } 135 136 function incrementForArrows(event) 137 { 138 if (!numeric) 139 return; 140 141 var increment = event.keyIdentifier === "Up" ? 1 : event.keyIdentifier === "Down" ? -1 : 0; 142 if (!increment) 143 return; 144 if (event.shiftKey) 145 increment *= 10; 146 147 var value = inputElement.value; 148 if (validatorCallback && validatorCallback(value)) 149 return; 150 value = Number(value); 151 if (clearForZero && !value) 152 return; 153 value += increment; 154 if (clearForZero && !value) 155 return; 156 value = String(value); 157 if (validatorCallback && validatorCallback(value)) 158 return; 159 160 inputElement.value = value; 161 apply(); 162 event.preventDefault(); 163 } 164 165 function validate() 166 { 167 var error = validatorCallback(inputElement.value); 168 if (!error) 169 error = ""; 170 inputElement.classList.toggle("error-input", !!error); 171 errorMessageLabel.textContent = error; 172 } 173 174 if (!instant) 175 inputElement.addEventListener("blur", apply, false); 176 177 function apply() 178 { 179 if (validatorCallback && validatorCallback(inputElement.value)) 180 return; 181 setting.removeChangeListener(onSettingChange); 182 setting.set(numeric ? Number(inputElement.value) : inputElement.value); 183 setting.addChangeListener(onSettingChange); 184 } 185 186 setting.addChangeListener(onSettingChange); 187 188 function onSettingChange() 189 { 190 var value = setting.get(); 191 if (clearForZero && !value) 192 value = ""; 193 inputElement.value = value; 194 } 195 onSettingChange(); 196 197 if (validatorCallback) 198 validate(); 199 200 return p; 201 } 202 203 /** 204 * @param {string} name 205 * @param {!Element} element 206 * @return {!Element} 207 */ 208 WebInspector.SettingsUI.createCustomSetting = function(name, element) 209 { 210 var p = document.createElement("p"); 211 var fieldsetElement = p.createChild("fieldset"); 212 fieldsetElement.createChild("label").textContent = name; 213 fieldsetElement.appendChild(element); 214 return p; 215 } 216 217 /** 218 * @param {!WebInspector.Setting} setting 219 * @return {!Element} 220 */ 221 WebInspector.SettingsUI.createSettingFieldset = function(setting) 222 { 223 var fieldset = document.createElement("fieldset"); 224 fieldset.disabled = !setting.get(); 225 setting.addChangeListener(settingChanged); 226 return fieldset; 227 228 function settingChanged() 229 { 230 fieldset.disabled = !setting.get(); 231 } 232 } 233 234 /** 235 * @param {string} text 236 * @return {?string} 237 */ 238 WebInspector.SettingsUI.regexValidator = function(text) 239 { 240 var regex; 241 try { 242 regex = new RegExp(text); 243 } catch (e) { 244 } 245 return regex ? null : WebInspector.UIString("Invalid pattern"); 246 } 247 248 /** 249 * Creates an input element under the parentElement with the given id and defaultText. 250 * @param {!Element} parentElement 251 * @param {string} id 252 * @param {string} defaultText 253 * @param {function(*)} eventListener 254 * @param {boolean=} numeric 255 * @param {string=} size 256 * @return {!Element} element 257 */ 258 WebInspector.SettingsUI.createInput = function(parentElement, id, defaultText, eventListener, numeric, size) 259 { 260 var element = parentElement.createChild("input"); 261 element.id = id; 262 element.type = "text"; 263 element.maxLength = 12; 264 element.style.width = size || "80px"; 265 element.value = defaultText; 266 element.align = "right"; 267 if (numeric) 268 element.className = "numeric"; 269 element.addEventListener("input", eventListener, false); 270 element.addEventListener("keydown", keyDownListener, false); 271 function keyDownListener(event) 272 { 273 if (isEnterKey(event)) 274 eventListener(event); 275 } 276 return element; 277 } 278 279 /** 280 * @constructor 281 */ 282 WebInspector.UISettingDelegate = function() 283 { 284 } 285 286 WebInspector.UISettingDelegate.prototype = { 287 /** 288 * @return {?Element} 289 */ 290 settingElement: function() 291 { 292 return null; 293 } 294 } 295