Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: third_party/polymer/v0_8/components/paper-input/paper-input-container.html

Issue 1162563004: Upgrade to 1.0 and switch clients to dom-repeat where needed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a layout import and remove the gzipped webanimation in reproduce.sh Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!-- 1 <!--
2 @license 2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt 4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also 7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 --> 9 -->
10 10
11 <link rel="import" href="../polymer/polymer.html"> 11 <link rel="import" href="../polymer/polymer.html">
12 <link rel="import" href="../paper-styles/paper-styles.html"> 12 <link rel="import" href="../paper-styles/paper-styles.html">
13 13
14 <style is="x-style">
15
16 * {
17
18 --paper-input-container-font: var(--paper-font-subhead);
19 --paper-input-container-floating-label-font: var(--paper-font-caption);
20 --paper-input-container-add-on-font: var(--paper-font-caption);
21
22 --paper-input-container-focus-color: var(--default-primary-color);
23 --paper-input-container-color: var(--secondary-text-color);
24 --paper-input-container-invalid-color: var(--google-red-500);
25 --paper-input-container-input-color: var(--primary-text-color);
26
27 }
28
29 </style>
30
31 <!-- 14 <!--
32 `<paper-input-container>` wraps an `<input>` and `<label>` element, decorating 15 `<paper-input-container>` is a container for a `<label>`, an `<input is="iron-in put">` or
33 them following the [Material Design spec](http://www.google.com/design/spec/comp onents/text-fields.html#text-fields-single-line-text-field) 16 `<iron-autogrow-textarea>` and optional add-on elements such as an error message or character
17 counter, used to implement Material Design text fields.
34 18
35 For example: 19 For example:
36 20
37 <paper-input-container> 21 <paper-input-container>
38 <label>email address</label> 22 <label>Your name</label>
39 <input type="email"> 23 <input is="iron-input">
40 </paper-input-container> 24 </paper-input-container>
41 25
26 ### Listening for input changes
27
28 By default, it listens for changes on the `bind-value` attribute on its children nodes and perform
29 tasks such as auto-validating and label styling when the `bind-value` changes. Y ou can configure
30 the attribute it listens to with the `attr-for-value` attribute.
31
32 ### Using a custom input element
33
34 You can use a custom input element in a `<paper-input-container>`, for example t o implement a
35 compound input field like a social security number input. The custom input eleme nt should have the
36 `paper-input-input` class, have a `notify:true` value property and optionally im plements
37 `Polymer.IronValidatableBehavior` if it is validatble.
38
39 <paper-input-container attr-for-value="ssn-value">
40 <label>Social security number</label>
41 <ssn-input class="paper-input-input"></ssn-input>
42 </paper-input-container>
43
44 ### Validation
45
46 If the `auto-validate` attribute is set, the input container will validate the i nput and update
47 the container styling when the input value changes.
48
49 ### Add-ons
50
51 Add-ons are child elements of a `<paper-input-container>` with the `add-on` attr ibute and
52 implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified whe n the input value
53 or validity changes, and may implement functionality such as error messages or c haracter counters.
54 They appear at the bottom of the input.
55
56 ### Styling
57
58 The following custom properties and mixins are available for styling:
59
60 Custom property | Description | Default
61 ----------------|-------------|----------
62 `--paper-input-container-color` | Label and underline color when the input is no t focused | `--secondary-text-color`
63 `--paper-input-container-focus-color` | Label and underline color when the input is focused | `--default-primary-color`
64 `--paper-input-container-invalid-color` | Label and underline color when the inp ut is focused | `--google-red-500`
65 `--paper-input-container-input-color` | Input foreground color | `--primary-text -color`
66 `--paper-input-container` | Mixin applied to the container | `{}`
67 `--paper-input-container-label` | Mixin applied to the label | `{}`
68 `--paper-input-container-input` | Mixin applied to the input | `{}`
69
70 This element is `display:block` by default, but you can set the `inline` attribu te to make it
71 `display:inline-block`.
42 --> 72 -->
43 <dom-module id="paper-input-container"> 73 <dom-module id="paper-input-container">
44 74
45 <style> 75 <style>
46 76
47 :host { 77 :host {
48 display: block; 78 display: block;
49 padding: 8px 0; 79 padding: 8px 0;
50 80
51 --mixin(--paper-input-container); 81 @apply(--paper-input-container);
82 }
83
84 :host[inline] {
85 display: inline-block;
52 } 86 }
53 87
54 :host([disabled]) { 88 :host([disabled]) {
55 pointer-events: none; 89 pointer-events: none;
56 opacity: 0.33; 90 opacity: 0.33;
57 } 91 }
58 92
59 .floated-label-placeholder { 93 .floated-label-placeholder {
60 mixin(--paper-input-container-label-font); 94 @apply(--paper-font-caption);
95 }
96
97 .underline {
98 position: relative;
61 } 99 }
62 100
63 .focused-line { 101 .focused-line {
64 height: 2px; 102 height: 2px;
65 103
66 -webkit-transform-origin: center center; 104 -webkit-transform-origin: center center;
67 transform-origin: center center; 105 transform-origin: center center;
68 -webkit-transform: scale3d(0,1,1); 106 -webkit-transform: scale3d(0,1,1);
69 transform: scale3d(0,1,1); 107 transform: scale3d(0,1,1);
70 108
71 background: var(--paper-input-container-focus-color); 109 background: var(--paper-input-container-focus-color, --default-primary-col or);
72 } 110 }
73 111
74 .is-highlighted .focused-line { 112 .is-highlighted .focused-line {
75 -webkit-transform: none; 113 -webkit-transform: none;
76 transform: none; 114 transform: none;
77 -webkit-transition: -webkit-transform 0.25s; 115 -webkit-transition: -webkit-transform 0.25s;
78 transition: transform 0.25s; 116 transition: transform 0.25s;
79 117
80 mixin(--paper-transition-easing); 118 @apply(--paper-transition-easing);
81 } 119 }
82 120
83 .is-invalid .focused-line { 121 .is-invalid .focused-line {
84 background: var(--paper-input-container-invalid-color); 122 background: var(--paper-input-container-invalid-color, --google-red-500);
85 123
86 -webkit-transform: none; 124 -webkit-transform: none;
87 transform: none; 125 transform: none;
88 -webkit-transition: -webkit-transform 0.25s; 126 -webkit-transition: -webkit-transform 0.25s;
89 transition: transform 0.25s; 127 transition: transform 0.25s;
90 128
91 mixin(--paper-transition-easing); 129 @apply(--paper-transition-easing);
92 } 130 }
93 131
94 .unfocused-line { 132 .unfocused-line {
95 height: 1px; 133 height: 1px;
96 background: var(--paper-input-container-color); 134 background: var(--paper-input-container-color, --secondary-text-color);
97 } 135 }
98 136
99 :host([disabled]) .unfocused-line { 137 :host([disabled]) .unfocused-line {
100 border-bottom: 1px dashed; 138 border-bottom: 1px dashed;
101 border-color: var(--paper-input-container-color); 139 border-color: var(--paper-input-container-color, --secondary-text-color);
102 background: transparent; 140 background: transparent;
103 } 141 }
104 142
143 .input-content {
144 position: relative;
145 }
146
105 .input-content ::content label, 147 .input-content ::content label,
106 .input-content ::content .paper-input-label { 148 .input-content ::content .paper-input-label {
107 position: absolute; 149 position: absolute;
108 top: 0; 150 top: 0;
109 right: 0; 151 right: 0;
110 left: 0; 152 left: 0;
111 font: inherit; 153 font: inherit;
112 color: var(--paper-input-container-color); 154 color: var(--paper-input-container-color, --secondary-text-color);
113 155
114 mixin(--paper-input-container-font); 156 @apply(--paper-font-subhead);
115 157 @apply(--paper-input-container-label);
116 mixin(--paper-input-container-label);
117 } 158 }
118 159
119 .input-content.label-is-floating ::content label, 160 .input-content.label-is-floating ::content label,
120 .input-content.label-is-floating ::content .paper-input-label { 161 .input-content.label-is-floating ::content .paper-input-label {
121 -webkit-transform: translate3d(0, -75%, 0) scale(0.75); 162 -webkit-transform: translate3d(0, -75%, 0) scale(0.75);
122 transform: translate3d(0, -75%, 0) scale(0.75); 163 transform: translate3d(0, -75%, 0) scale(0.75);
123 -webkit-transform-origin: left top; 164 -webkit-transform-origin: left top;
124 transform-origin: left top; 165 transform-origin: left top;
125 -webkit-transition: -webkit-transform 0.25s; 166 -webkit-transition: -webkit-transform 0.25s;
126 transition: transform 0.25s; 167 transition: transform 0.25s;
127 168
128 mixin(--paper-transition-easing); 169 @apply(--paper-transition-easing);
129 } 170 }
130 171
131 .input-content.label-is-highlighted ::content label, 172 .input-content.label-is-highlighted ::content label,
132 .input-content.label-is-highlighted ::content .paper-input-label { 173 .input-content.label-is-highlighted ::content .paper-input-label {
133 color: var(--paper-input-container-focus-color); 174 color: var(--paper-input-container-focus-color, --default-primary-color);
134 } 175 }
135 176
136 .input-content.is-invalid ::content label, 177 .input-content.is-invalid ::content label,
137 .input-content.is-invalid ::content .paper-input-label { 178 .input-content.is-invalid ::content .paper-input-label {
138 color: var(--paper-input-container-invalid-color); 179 color: var(--paper-input-container-invalid-color, --google-red-500);
139 } 180 }
140 181
141 .input-content.label-is-hidden ::content label, 182 .input-content.label-is-hidden ::content label,
142 .input-content.label-is-hidden ::content .paper-input-label { 183 .input-content.label-is-hidden ::content .paper-input-label {
143 visibility: hidden; 184 visibility: hidden;
144 } 185 }
145 186
146 .input-content ::content input, 187 .input-content ::content input,
147 .input-content ::content textarea, 188 .input-content ::content textarea,
189 .input-content ::content iron-autogrow-textarea,
148 .input-content ::content .paper-input-input { 190 .input-content ::content .paper-input-input {
149 position: relative; /* to make a stacking context */ 191 position: relative; /* to make a stacking context */
150 outline: none; 192 outline: none;
151 color: var(--paper-input-container-input-color); 193 box-shadow: none;
152
153 mixin(--paper-input-container-floating-label-font);
154 }
155
156 .input-content ::content input,
157 .input-content ::content textarea {
158 padding: 0; 194 padding: 0;
159 width: 100%; 195 width: 100%;
160 background: transparent; 196 background: transparent;
161 border: none; 197 border: none;
198 color: var(--paper-input-container-input-color, --primary-text-color);
162 199
163 mixin(--paper-input-container-font); 200 @apply(--paper-font-subhead);
201 @apply(--paper-input-container-input);
202 }
164 203
165 mixin(--paper-input-container-input); 204 /* Firefox sets a min-width on the input, which can cause layout issues */
205 .input-content ::content input {
206 min-width: 0;
166 } 207 }
167 208
168 .input-content ::content textarea { 209 .input-content ::content textarea {
169 resize: none; 210 resize: none;
170 } 211 }
171 212
172 .add-on-content.is-invalid ::content * { 213 .add-on-content.is-invalid ::content * {
173 color: var(--paper-input-container-invalid-color); 214 color: var(--paper-input-container-invalid-color, --google-red-500);
174 } 215 }
175 216
176 .add-on-content.is-highlighted ::content * { 217 .add-on-content.is-highlighted ::content * {
177 color: var(--paper-input-container-focus-color); 218 color: var(--paper-input-container-focus-color, --default-primary-color);
178 }
179
180 .input-content,
181 .underline {
182 position: relative;
183 } 219 }
184 220
185 </style> 221 </style>
186 222
187 <template> 223 <template>
188 224
189 <template is="x-if" if="[[!noLabelFloat]]"> 225 <template is="dom-if" if="[[!noLabelFloat]]">
190 <div class="floated-label-placeholder">&nbsp;</div> 226 <div class="floated-label-placeholder">&nbsp;</div>
191 </template> 227 </template>
192 228
193 <div class$="[[_computeInputContentClass(noLabelFloat,focused,_inputHasConte nt,_inputIsInvalid)]]"> 229 <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focus ed,invalid,_inputHasContent)]]">
194 <content select=":not([add-on])"></content> 230 <content select=":not([add-on])"></content>
195 </div> 231 </div>
196 232
197 <div class$="[[_computeUnderlineClass(focused,_inputIsInvalid)]]"> 233 <div class$="[[_computeUnderlineClass(focused,invalid)]]">
198 <div class="unfocused-line fit"></div> 234 <div class="unfocused-line fit"></div>
199 <div class="focused-line fit"></div> 235 <div class="focused-line fit"></div>
200 </div> 236 </div>
201 237
202 <div class$="[[_computeAddOnContentClass(focused,_inputIsInvalid)]]"> 238 <div class$="[[_computeAddOnContentClass(focused,invalid)]]">
203 <content id="addOnContent" select="[add-on]"></content> 239 <content id="addOnContent" select="[add-on]"></content>
204 </div> 240 </div>
205 241
206 </template> 242 </template>
207 243
208 </dom-module> 244 </dom-module>
209 245
210 <script> 246 <script>
211 (function() { 247 (function() {
212 248
213 Polymer({ 249 Polymer({
214 250
215 is: 'paper-input-container', 251 is: 'paper-input-container',
216 252
217 enableCustomStyleProperties: true,
218
219 properties: { 253 properties: {
220 254
221 /** 255 /**
222 * Set to true to disable the floating label. 256 * Set to true to disable the floating label. The label disappears when th e input value is
257 * not null.
223 */ 258 */
224 noLabelFloat: { 259 noLabelFloat: {
225 type: Boolean, 260 type: Boolean,
226 value: false 261 value: false
227 }, 262 },
228 263
229 /** 264 /**
265 * Set to true to always float the floating label.
266 */
267 alwaysFloatLabel: {
268 type: Boolean,
269 value: false
270 },
271
272 /**
230 * The attribute to listen for value changes on. 273 * The attribute to listen for value changes on.
231 */ 274 */
232 attrForValue: { 275 attrForValue: {
233 type: String, 276 type: String,
234 value: 'bind-value' 277 value: 'bind-value'
235 }, 278 },
236 279
237 /** 280 /**
238 * Set to true to auto-validate the input value. 281 * Set to true to auto-validate the input value when it changes.
239 */ 282 */
240 autoValidate: { 283 autoValidate: {
241 type: Boolean, 284 type: Boolean,
242 value: false 285 value: false
243 }, 286 },
244 287
245 /** 288 /**
289 * True if the input is invalid. This property is set automatically when t he input value
290 * changes if auto-validating, or when the `iron-input-valid` event is hea rd from a child.
291 */
292 invalid: {
293 observer: '_invalidChanged',
294 type: Boolean,
295 value: false
296 },
297
298 /**
246 * True if the input has focus. 299 * True if the input has focus.
247 */ 300 */
248 focused: { 301 focused: {
249 readOnly: true, 302 readOnly: true,
250 type: Boolean, 303 type: Boolean,
251 value: false 304 value: false
252 }, 305 },
253 306
254 _addons: { 307 _addons: {
255 type: Array, 308 type: Array,
256 value: function() { 309 value: function() {
257 return []; 310 return [];
258 } 311 }
259 }, 312 },
260 313
261 _inputHasContent: { 314 _inputHasContent: {
262 type: Boolean, 315 type: Boolean,
263 value: false 316 value: false
264 }, 317 },
265 318
266 _inputIsInvalid: {
267 type: Boolean,
268 value: false
269 },
270
271 _inputSelector: { 319 _inputSelector: {
272 type: String, 320 type: String,
273 value: 'input,textarea,.paper-input-input' 321 value: 'input,textarea,.paper-input-input'
274 }, 322 },
275 323
276 _boundOnFocus: { 324 _boundOnFocus: {
277 type: Function, 325 type: Function,
278 value: function() { 326 value: function() {
279 return this._onFocus.bind(this); 327 return this._onFocus.bind(this);
280 } 328 }
281 }, 329 },
282 330
283 _boundOnBlur: { 331 _boundOnBlur: {
284 type: Function, 332 type: Function,
285 value: function() { 333 value: function() {
286 return this._onBlur.bind(this); 334 return this._onBlur.bind(this);
287 } 335 }
288 }, 336 },
289 337
338 _boundOnInput: {
339 type: Function,
340 value: function() {
341 this._onInput.bind(this)
342 }
343 },
344
290 _boundValueChanged: { 345 _boundValueChanged: {
291 type: Function, 346 type: Function,
292 value: function() { 347 value: function() {
293 return this._onValueChanged.bind(this); 348 return this._onValueChanged.bind(this);
294 } 349 }
295 } 350 }
296 351
297 }, 352 },
298 353
299 listeners: { 354 listeners: {
300 'addon-attached': '_onAddonAttached', 355 'addon-attached': '_onAddonAttached',
301 'input': '_onInput' 356 'iron-input-validate': '_onIronInputValidate'
302 }, 357 },
303 358
304 get _valueChangedEvent() { 359 get _valueChangedEvent() {
305 return this.attrForValue + '-changed'; 360 return this.attrForValue + '-changed';
306 }, 361 },
307 362
308 get _propertyForValue() { 363 get _propertyForValue() {
309 return Polymer.CaseMap.dashToCamelCase(this.attrForValue); 364 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
310 }, 365 },
311 366
312 get _inputElement() { 367 get _inputElement() {
313 return Polymer.dom(this).querySelector(this._inputSelector); 368 return Polymer.dom(this).querySelector(this._inputSelector);
314 }, 369 },
315 370
316 ready: function() { 371 ready: function() {
317 this.addEventListener('focus', this._boundOnFocus, true); 372 this.addEventListener('focus', this._boundOnFocus, true);
318 this.addEventListener('blur', this._boundOnBlur, true); 373 this.addEventListener('blur', this._boundOnBlur, true);
319 this.addEventListener(this._valueChangedEvent, this._boundValueChanged, tr ue); 374 if (this.attrForValue) {
375 this._inputElement.addEventListener(this._valueChangedEvent, this._bound ValueChanged);
376 } else {
377 this.addEventListener('input', this._onInput);
378 }
320 }, 379 },
321 380
322 attached: function() { 381 attached: function() {
323 this._handleInput(this._inputElement); 382 this._handleValue(this._inputElement);
324 }, 383 },
325 384
326 _onAddonAttached: function(event) { 385 _onAddonAttached: function(event) {
327 this._addons.push(event.target); 386 this._addons.push(event.target);
328 this._handleInput(this._inputElement); 387 this._handleValue(this._inputElement);
329 }, 388 },
330 389
331 _onFocus: function() { 390 _onFocus: function() {
332 this._setFocused(true); 391 this._setFocused(true);
333 }, 392 },
334 393
335 _onBlur: function() { 394 _onBlur: function() {
336 this._setFocused(false); 395 this._setFocused(false);
337 }, 396 },
338 397
339 _onInput: function(event) { 398 _onInput: function(event) {
340 this._handleInput(event.target); 399 this._handleValue(event.target);
341 }, 400 },
342 401
343 _onValueChanged: function(event) { 402 _onValueChanged: function(event) {
344 this._handleInput(event.target); 403 this._handleValue(event.target);
345 }, 404 },
346 405
347 _handleInput: function(inputElement) { 406 _handleValue: function(inputElement) {
348 var value = inputElement[this._propertyForValue] || inputElement.value; 407 var value = inputElement[this._propertyForValue] || inputElement.value;
349 var valid = inputElement.checkValidity(); 408
409 if (this.autoValidate) {
410 var valid;
411 if (inputElement.validate) {
412 valid = inputElement.validate(value);
413 } else {
414 valid = inputElement.checkValidity();
415 }
416 this.invalid = !valid;
417 }
350 418
351 // type="number" hack needed because this.value is empty until it's valid 419 // type="number" hack needed because this.value is empty until it's valid
352 if (value || inputElement.type === 'number' && !valid) { 420 if (value || (inputElement.type === 'number' && !inputElement.checkValidit y())) {
353 this._inputHasContent = true; 421 this._inputHasContent = true;
354 } else { 422 } else {
355 this._inputHasContent = false; 423 this._inputHasContent = false;
356 } 424 }
357 425
358 if (this.autoValidate) { 426 this.updateAddons({
359 this._inputIsInvalid = !valid; 427 inputElement: inputElement,
360 } 428 value: value,
429 invalid: this.invalid
430 });
431 },
361 432
362 // notify add-ons 433 _onIronInputValidate: function(event) {
363 for (var addon, i = 0; addon = this._addons[i]; i++) { 434 this.invalid = this._inputElement.invalid;
364 // need to set all of these, or call method... thanks input type="number "! 435 },
365 addon.inputElement = inputElement; 436
366 addon.value = value; 437 _invalidChanged: function() {
367 addon.invalid = !valid; 438 if (this._addons) {
439 this.updateAddons({invalid: this.invalid});
368 } 440 }
369 }, 441 },
370 442
371 _computeInputContentClass: function(noLabelFloat, focused, _inputHasContent, _inputIsInvalid) { 443 /**
444 * Call this to update the state of add-ons.
445 * @param {Object} state Add-on state.
446 */
447 updateAddons: function(state) {
448 for (var addon, index = 0; addon = this._addons[index]; index++) {
449 addon.update(state);
450 }
451 },
452
453 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) {
372 var cls = 'input-content'; 454 var cls = 'input-content';
373 if (!noLabelFloat) { 455 if (!noLabelFloat) {
374 if (_inputHasContent) { 456 if (alwaysFloatLabel || _inputHasContent) {
375 cls += ' label-is-floating'; 457 cls += ' label-is-floating';
376 if (_inputIsInvalid) { 458 if (invalid) {
377 cls += ' is-invalid'; 459 cls += ' is-invalid';
378 } else if (focused) { 460 } else if (focused) {
379 cls += " label-is-highlighted"; 461 cls += " label-is-highlighted";
380 } 462 }
381 } 463 }
382 } else { 464 } else {
383 if (_inputHasContent) { 465 if (_inputHasContent) {
384 cls += ' label-is-hidden'; 466 cls += ' label-is-hidden';
385 } 467 }
386 } 468 }
387 return cls; 469 return cls;
388 }, 470 },
389 471
390 _computeUnderlineClass: function(focused, _inputIsInvalid) { 472 _computeUnderlineClass: function(focused, invalid) {
391 var cls = 'underline'; 473 var cls = 'underline';
392 if (_inputIsInvalid) { 474 if (invalid) {
393 cls += ' is-invalid'; 475 cls += ' is-invalid';
394 } else if (focused) { 476 } else if (focused) {
395 cls += ' is-highlighted' 477 cls += ' is-highlighted'
396 } 478 }
397 return cls; 479 return cls;
398 }, 480 },
399 481
400 _computeAddOnContentClass: function(focused, _inputIsInvalid) { 482 _computeAddOnContentClass: function(focused, invalid) {
401 var cls = 'add-on-content'; 483 var cls = 'add-on-content';
402 if (_inputIsInvalid) { 484 if (invalid) {
403 cls += ' is-invalid'; 485 cls += ' is-invalid';
404 } else if (focused) { 486 } else if (focused) {
405 cls += ' is-highlighted' 487 cls += ' is-highlighted'
406 } 488 }
407 return cls; 489 return cls;
408 } 490 }
409 491
410 }); 492 });
411 493
412 })(); 494 })();
413 </script> 495 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698