~didrocks/+junk/face-detection-15.04

« back to all changes in this revision

Viewing changes to facedetection/www/bower_components/paper-input/paper-input-container.html

  • Committer: Didier Roche
  • Date: 2016-05-10 23:09:11 UTC
  • Revision ID: didier.roche@canonical.com-20160510230911-c7xr490zrj3yrzxd
New version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!--
 
2
@license
 
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.github.io/LICENSE.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/CONTRIBUTORS.txt
 
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/PATENTS.txt
 
9
-->
 
10
 
 
11
<link rel="import" href="../polymer/polymer.html">
 
12
<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
 
13
<link rel="import" href="../paper-styles/default-theme.html">
 
14
<link rel="import" href="../paper-styles/typography.html">
 
15
 
 
16
<!--
 
17
`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or
 
18
`<iron-autogrow-textarea>` and optional add-on elements such as an error message or character
 
19
counter, used to implement Material Design text fields.
 
20
 
 
21
For example:
 
22
 
 
23
    <paper-input-container>
 
24
      <label>Your name</label>
 
25
      <input is="iron-input">
 
26
    </paper-input-container>
 
27
 
 
28
Do not wrap `<paper-input-container>` around elements that already include it, such as `<paper-input>`.
 
29
Doing so may cause events to bounce infintely between the container and its contained element.
 
30
 
 
31
### Listening for input changes
 
32
 
 
33
By default, it listens for changes on the `bind-value` attribute on its children nodes and perform
 
34
tasks such as auto-validating and label styling when the `bind-value` changes. You can configure
 
35
the attribute it listens to with the `attr-for-value` attribute.
 
36
 
 
37
### Using a custom input element
 
38
 
 
39
You can use a custom input element in a `<paper-input-container>`, for example to implement a
 
40
compound input field like a social security number input. The custom input element should have the
 
41
`paper-input-input` class, have a `notify:true` value property and optionally implements
 
42
`Polymer.IronValidatableBehavior` if it is validatable.
 
43
 
 
44
    <paper-input-container attr-for-value="ssn-value">
 
45
      <label>Social security number</label>
 
46
      <ssn-input class="paper-input-input"></ssn-input>
 
47
    </paper-input-container>
 
48
 
 
49
 
 
50
If you're using a `<paper-input-container>` imperatively, it's important to make sure
 
51
that you attach its children (the `iron-input` and the optional `label`) before you
 
52
attach the `<paper-input-container>` itself, so that it can be set up correctly.
 
53
 
 
54
### Validation
 
55
 
 
56
If the `auto-validate` attribute is set, the input container will validate the input and update
 
57
the container styling when the input value changes.
 
58
 
 
59
### Add-ons
 
60
 
 
61
Add-ons are child elements of a `<paper-input-container>` with the `add-on` attribute and
 
62
implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified when the input value
 
63
or validity changes, and may implement functionality such as error messages or character counters.
 
64
They appear at the bottom of the input.
 
65
 
 
66
### Prefixes and suffixes
 
67
These are child elements of a `<paper-input-container>` with the `prefix`
 
68
or `suffix` attribute, and are displayed inline with the input, before or after.
 
69
 
 
70
    <paper-input-container>
 
71
      <div prefix>$</div>
 
72
      <label>Total</label>
 
73
      <input is="iron-input">
 
74
      <paper-icon-button suffix icon="clear"></paper-icon-button>
 
75
    </paper-input-container>
 
76
 
 
77
### Styling
 
78
 
 
79
The following custom properties and mixins are available for styling:
 
80
 
 
81
Custom property | Description | Default
 
82
----------------|-------------|----------
 
83
`--paper-input-container-color` | Label and underline color when the input is not focused | `--secondary-text-color`
 
84
`--paper-input-container-focus-color` | Label and underline color when the input is focused | `--primary-color`
 
85
`--paper-input-container-invalid-color` | Label and underline color when the input is is invalid | `--error-color`
 
86
`--paper-input-container-input-color` | Input foreground color | `--primary-text-color`
 
87
`--paper-input-container` | Mixin applied to the container | `{}`
 
88
`--paper-input-container-disabled` | Mixin applied to the container when it's disabled | `{}`
 
89
`--paper-input-container-label` | Mixin applied to the label | `{}`
 
90
`--paper-input-container-label-focus` | Mixin applied to the label when the input is focused | `{}`
 
91
`--paper-input-container-label-floating` | Mixin applied to the label when floating | `{}`
 
92
`--paper-input-container-input` | Mixin applied to the input | `{}`
 
93
`--paper-input-container-underline` | Mixin applied to the underline | `{}`
 
94
`--paper-input-container-underline-focus` | Mixin applied to the underline when the input is focused | `{}`
 
95
`--paper-input-container-underline-disabled` | Mixin applied to the underline when the input is disabled | `{}`
 
96
`--paper-input-prefix` | Mixin applied to the input prefix | `{}`
 
97
`--paper-input-suffix` | Mixin applied to the input suffix | `{}`
 
98
 
 
99
This element is `display:block` by default, but you can set the `inline` attribute to make it
 
100
`display:inline-block`.
 
101
-->
 
102
 
 
103
<dom-module id="paper-input-container">
 
104
  <template>
 
105
    <style>
 
106
      :host {
 
107
        display: block;
 
108
        padding: 8px 0;
 
109
 
 
110
        @apply(--paper-input-container);
 
111
      }
 
112
 
 
113
      :host[inline] {
 
114
        display: inline-block;
 
115
      }
 
116
 
 
117
      :host([disabled]) {
 
118
        pointer-events: none;
 
119
        opacity: 0.33;
 
120
 
 
121
        @apply(--paper-input-container-disabled);
 
122
      }
 
123
 
 
124
      .floated-label-placeholder {
 
125
        @apply(--paper-font-caption);
 
126
      }
 
127
 
 
128
      .underline {
 
129
        position: relative;
 
130
      }
 
131
 
 
132
      .focused-line {
 
133
        @apply(--layout-fit);
 
134
 
 
135
        background: var(--paper-input-container-focus-color, --primary-color);
 
136
        height: 2px;
 
137
 
 
138
        -webkit-transform-origin: center center;
 
139
        transform-origin: center center;
 
140
        -webkit-transform: scale3d(0,1,1);
 
141
        transform: scale3d(0,1,1);
 
142
 
 
143
        @apply(--paper-input-container-underline-focus);
 
144
      }
 
145
 
 
146
      .underline.is-highlighted .focused-line {
 
147
        -webkit-transform: none;
 
148
        transform: none;
 
149
        -webkit-transition: -webkit-transform 0.25s;
 
150
        transition: transform 0.25s;
 
151
 
 
152
        @apply(--paper-transition-easing);
 
153
      }
 
154
 
 
155
      .underline.is-invalid .focused-line {
 
156
        background: var(--paper-input-container-invalid-color, --error-color);
 
157
        -webkit-transform: none;
 
158
        transform: none;
 
159
        -webkit-transition: -webkit-transform 0.25s;
 
160
        transition: transform 0.25s;
 
161
 
 
162
        @apply(--paper-transition-easing);
 
163
      }
 
164
 
 
165
      .unfocused-line {
 
166
        @apply(--layout-fit);
 
167
 
 
168
        background: var(--paper-input-container-color, --secondary-text-color);
 
169
        height: 1px;
 
170
 
 
171
        @apply(--paper-input-container-underline);
 
172
      }
 
173
 
 
174
      :host([disabled]) .unfocused-line {
 
175
        border-bottom: 1px dashed;
 
176
        border-color: var(--paper-input-container-color, --secondary-text-color);
 
177
        background: transparent;
 
178
 
 
179
        @apply(--paper-input-container-underline-disabled);
 
180
      }
 
181
 
 
182
      .label-and-input-container {
 
183
        @apply(--layout-flex-auto);
 
184
        @apply(--layout-relative);
 
185
 
 
186
        width: 100%;
 
187
        max-width: 100%;
 
188
      }
 
189
 
 
190
      .input-content {
 
191
        @apply(--layout-horizontal);
 
192
        @apply(--layout-center);
 
193
 
 
194
        position: relative;
 
195
      }
 
196
 
 
197
      .input-content ::content label,
 
198
      .input-content ::content .paper-input-label {
 
199
        position: absolute;
 
200
        top: 0;
 
201
        right: 0;
 
202
        left: 0;
 
203
        width: 100%;
 
204
        font: inherit;
 
205
        color: var(--paper-input-container-color, --secondary-text-color);
 
206
        -webkit-transition: -webkit-transform 0.25s, width 0.25s;
 
207
        transition: transform 0.25s, width 0.25s;
 
208
        -webkit-transform-origin: left top;
 
209
        transform-origin: left top;
 
210
 
 
211
        @apply(--paper-font-common-nowrap);
 
212
        @apply(--paper-font-subhead);
 
213
        @apply(--paper-input-container-label);
 
214
        @apply(--paper-transition-easing);
 
215
      }
 
216
 
 
217
      .input-content.label-is-floating ::content label,
 
218
      .input-content.label-is-floating ::content .paper-input-label {
 
219
        -webkit-transform: translateY(-75%) scale(0.75);
 
220
        transform: translateY(-75%) scale(0.75);
 
221
 
 
222
        /* Since we scale to 75/100 of the size, we actually have 100/75 of the
 
223
        original space now available */
 
224
        width: 133%;
 
225
 
 
226
        @apply(--paper-input-container-label-floating);
 
227
      }
 
228
 
 
229
      :host-context([dir="rtl"]) .input-content.label-is-floating ::content label,
 
230
      :host-context([dir="rtl"]) .input-content.label-is-floating ::content .paper-input-label {
 
231
        /* TODO(noms): Figure out why leaving the width at 133% before the animation
 
232
         * actually makes
 
233
         * it wider on the right side, not left side, as you would expect in RTL */
 
234
        width: 100%;
 
235
        -webkit-transform-origin: right top;
 
236
        transform-origin: right top;
 
237
      }
 
238
 
 
239
      .input-content.label-is-highlighted ::content label,
 
240
      .input-content.label-is-highlighted ::content .paper-input-label {
 
241
        color: var(--paper-input-container-focus-color, --primary-color);
 
242
 
 
243
        @apply(--paper-input-container-label-focus);
 
244
      }
 
245
 
 
246
      .input-content.is-invalid ::content label,
 
247
      .input-content.is-invalid ::content .paper-input-label {
 
248
        color: var(--paper-input-container-invalid-color, --error-color);
 
249
      }
 
250
 
 
251
      .input-content.label-is-hidden ::content label,
 
252
      .input-content.label-is-hidden ::content .paper-input-label {
 
253
        visibility: hidden;
 
254
      }
 
255
 
 
256
      .input-content ::content input,
 
257
      .input-content ::content textarea,
 
258
      .input-content ::content iron-autogrow-textarea,
 
259
      .input-content ::content .paper-input-input {
 
260
        position: relative; /* to make a stacking context */
 
261
        outline: none;
 
262
        box-shadow: none;
 
263
        padding: 0;
 
264
        width: 100%;
 
265
        max-width: 100%;
 
266
        background: transparent;
 
267
        border: none;
 
268
        color: var(--paper-input-container-input-color, --primary-text-color);
 
269
        -webkit-appearance: none;
 
270
        text-align: inherit;
 
271
 
 
272
        @apply(--paper-font-subhead);
 
273
        @apply(--paper-input-container-input);
 
274
      }
 
275
 
 
276
      ::content [prefix] {
 
277
        @apply(--paper-font-subhead);
 
278
 
 
279
        @apply(--paper-input-prefix);
 
280
        @apply(--layout-flex-none);
 
281
      }
 
282
 
 
283
      ::content [suffix] {
 
284
        @apply(--paper-font-subhead);
 
285
 
 
286
        @apply(--paper-input-suffix);
 
287
        @apply(--layout-flex-none);
 
288
      }
 
289
 
 
290
      /* Firefox sets a min-width on the input, which can cause layout issues */
 
291
      .input-content ::content input {
 
292
        min-width: 0;
 
293
      }
 
294
 
 
295
      .input-content ::content textarea {
 
296
        resize: none;
 
297
      }
 
298
 
 
299
      .add-on-content {
 
300
        position: relative;
 
301
      }
 
302
 
 
303
      .add-on-content.is-invalid ::content * {
 
304
        color: var(--paper-input-container-invalid-color, --error-color);
 
305
      }
 
306
 
 
307
      .add-on-content.is-highlighted ::content * {
 
308
        color: var(--paper-input-container-focus-color, --primary-color);
 
309
      }
 
310
    </style>
 
311
 
 
312
    <template is="dom-if" if="[[!noLabelFloat]]">
 
313
      <div class="floated-label-placeholder">&nbsp;</div>
 
314
    </template>
 
315
 
 
316
    <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]">
 
317
      <content select="[prefix]" id="prefix"></content>
 
318
 
 
319
      <div class="label-and-input-container" id="labelAndInputContainer">
 
320
        <content select=":not([add-on]):not([prefix]):not([suffix])"></content>
 
321
      </div>
 
322
 
 
323
      <content select="[suffix]"></content>
 
324
    </div>
 
325
 
 
326
    <div class$="[[_computeUnderlineClass(focused,invalid)]]">
 
327
      <div class="unfocused-line"></div>
 
328
      <div class="focused-line"></div>
 
329
    </div>
 
330
 
 
331
    <div class$="[[_computeAddOnContentClass(focused,invalid)]]">
 
332
      <content id="addOnContent" select="[add-on]"></content>
 
333
    </div>
 
334
  </template>
 
335
</dom-module>
 
336
 
 
337
<script>
 
338
  Polymer({
 
339
    is: 'paper-input-container',
 
340
 
 
341
    properties: {
 
342
      /**
 
343
       * Set to true to disable the floating label. The label disappears when the input value is
 
344
       * not null.
 
345
       */
 
346
      noLabelFloat: {
 
347
        type: Boolean,
 
348
        value: false
 
349
      },
 
350
 
 
351
      /**
 
352
       * Set to true to always float the floating label.
 
353
       */
 
354
      alwaysFloatLabel: {
 
355
        type: Boolean,
 
356
        value: false
 
357
      },
 
358
 
 
359
      /**
 
360
       * The attribute to listen for value changes on.
 
361
       */
 
362
      attrForValue: {
 
363
        type: String,
 
364
        value: 'bind-value'
 
365
      },
 
366
 
 
367
      /**
 
368
       * Set to true to auto-validate the input value when it changes.
 
369
       */
 
370
      autoValidate: {
 
371
        type: Boolean,
 
372
        value: false
 
373
      },
 
374
 
 
375
      /**
 
376
       * True if the input is invalid. This property is set automatically when the input value
 
377
       * changes if auto-validating, or when the `iron-input-validate` event is heard from a child.
 
378
       */
 
379
      invalid: {
 
380
        observer: '_invalidChanged',
 
381
        type: Boolean,
 
382
        value: false
 
383
      },
 
384
 
 
385
      /**
 
386
       * True if the input has focus.
 
387
       */
 
388
      focused: {
 
389
        readOnly: true,
 
390
        type: Boolean,
 
391
        value: false,
 
392
        notify: true
 
393
      },
 
394
 
 
395
      _addons: {
 
396
        type: Array
 
397
        // do not set a default value here intentionally - it will be initialized lazily when a
 
398
        // distributed child is attached, which may occur before configuration for this element
 
399
        // in polyfill.
 
400
      },
 
401
 
 
402
      _inputHasContent: {
 
403
        type: Boolean,
 
404
        value: false
 
405
      },
 
406
 
 
407
      _inputSelector: {
 
408
        type: String,
 
409
        value: 'input,textarea,.paper-input-input'
 
410
      },
 
411
 
 
412
      _boundOnFocus: {
 
413
        type: Function,
 
414
        value: function() {
 
415
          return this._onFocus.bind(this);
 
416
        }
 
417
      },
 
418
 
 
419
      _boundOnBlur: {
 
420
        type: Function,
 
421
        value: function() {
 
422
          return this._onBlur.bind(this);
 
423
        }
 
424
      },
 
425
 
 
426
      _boundOnInput: {
 
427
        type: Function,
 
428
        value: function() {
 
429
          return this._onInput.bind(this);
 
430
        }
 
431
      },
 
432
 
 
433
      _boundValueChanged: {
 
434
        type: Function,
 
435
        value: function() {
 
436
          return this._onValueChanged.bind(this);
 
437
        }
 
438
      }
 
439
    },
 
440
 
 
441
    listeners: {
 
442
      'addon-attached': '_onAddonAttached',
 
443
      'iron-input-validate': '_onIronInputValidate'
 
444
    },
 
445
 
 
446
    get _valueChangedEvent() {
 
447
      return this.attrForValue + '-changed';
 
448
    },
 
449
 
 
450
    get _propertyForValue() {
 
451
      return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
 
452
    },
 
453
 
 
454
    get _inputElement() {
 
455
      return Polymer.dom(this).querySelector(this._inputSelector);
 
456
    },
 
457
 
 
458
    get _inputElementValue() {
 
459
      return this._inputElement[this._propertyForValue] || this._inputElement.value;
 
460
    },
 
461
 
 
462
    ready: function() {
 
463
      if (!this._addons) {
 
464
        this._addons = [];
 
465
      }
 
466
      this.addEventListener('focus', this._boundOnFocus, true);
 
467
      this.addEventListener('blur', this._boundOnBlur, true);
 
468
    },
 
469
 
 
470
    attached: function() {
 
471
      if (this.attrForValue) {
 
472
        this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged);
 
473
      } else {
 
474
        this.addEventListener('input', this._onInput);
 
475
      }
 
476
 
 
477
      // Only validate when attached if the input already has a value.
 
478
      if (this._inputElementValue != '') {
 
479
        this._handleValueAndAutoValidate(this._inputElement);
 
480
      } else {
 
481
        this._handleValue(this._inputElement);
 
482
      }
 
483
    },
 
484
 
 
485
    _onAddonAttached: function(event) {
 
486
      if (!this._addons) {
 
487
        this._addons = [];
 
488
      }
 
489
      var target = event.target;
 
490
      if (this._addons.indexOf(target) === -1) {
 
491
        this._addons.push(target);
 
492
        if (this.isAttached) {
 
493
          this._handleValue(this._inputElement);
 
494
        }
 
495
      }
 
496
    },
 
497
 
 
498
    _onFocus: function() {
 
499
      this._setFocused(true);
 
500
    },
 
501
 
 
502
    _onBlur: function() {
 
503
      this._setFocused(false);
 
504
      this._handleValueAndAutoValidate(this._inputElement);
 
505
    },
 
506
 
 
507
    _onInput: function(event) {
 
508
      this._handleValueAndAutoValidate(event.target);
 
509
    },
 
510
 
 
511
    _onValueChanged: function(event) {
 
512
      this._handleValueAndAutoValidate(event.target);
 
513
    },
 
514
 
 
515
    _handleValue: function(inputElement) {
 
516
      var value = this._inputElementValue;
 
517
 
 
518
      // type="number" hack needed because this.value is empty until it's valid
 
519
      if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) {
 
520
        this._inputHasContent = true;
 
521
      } else {
 
522
        this._inputHasContent = false;
 
523
      }
 
524
 
 
525
      this.updateAddons({
 
526
        inputElement: inputElement,
 
527
        value: value,
 
528
        invalid: this.invalid
 
529
      });
 
530
    },
 
531
 
 
532
    _handleValueAndAutoValidate: function(inputElement) {
 
533
      if (this.autoValidate) {
 
534
        var valid;
 
535
        if (inputElement.validate) {
 
536
          valid = inputElement.validate(this._inputElementValue);
 
537
        } else {
 
538
          valid = inputElement.checkValidity();
 
539
        }
 
540
        this.invalid = !valid;
 
541
      }
 
542
 
 
543
      // Call this last to notify the add-ons.
 
544
      this._handleValue(inputElement);
 
545
    },
 
546
 
 
547
    _onIronInputValidate: function(event) {
 
548
      this.invalid = this._inputElement.invalid;
 
549
    },
 
550
 
 
551
    _invalidChanged: function() {
 
552
      if (this._addons) {
 
553
        this.updateAddons({invalid: this.invalid});
 
554
      }
 
555
    },
 
556
 
 
557
    /**
 
558
     * Call this to update the state of add-ons.
 
559
     * @param {Object} state Add-on state.
 
560
     */
 
561
    updateAddons: function(state) {
 
562
      for (var addon, index = 0; addon = this._addons[index]; index++) {
 
563
        addon.update(state);
 
564
      }
 
565
    },
 
566
 
 
567
    _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) {
 
568
      var cls = 'input-content';
 
569
      if (!noLabelFloat) {
 
570
        var label = this.querySelector('label');
 
571
 
 
572
        if (alwaysFloatLabel || _inputHasContent) {
 
573
          cls += ' label-is-floating';
 
574
          // If the label is floating, ignore any offsets that may have been
 
575
          // applied from a prefix element.
 
576
          this.$.labelAndInputContainer.style.position = 'static';
 
577
 
 
578
          if (invalid) {
 
579
            cls += ' is-invalid';
 
580
          } else if (focused) {
 
581
            cls += " label-is-highlighted";
 
582
          }
 
583
        } else {
 
584
          // When the label is not floating, it should overlap the input element.
 
585
          if (label) {
 
586
            this.$.labelAndInputContainer.style.position = 'relative';
 
587
          }
 
588
        }
 
589
      } else {
 
590
        if (_inputHasContent) {
 
591
          cls += ' label-is-hidden';
 
592
        }
 
593
      }
 
594
      return cls;
 
595
    },
 
596
 
 
597
    _computeUnderlineClass: function(focused, invalid) {
 
598
      var cls = 'underline';
 
599
      if (invalid) {
 
600
        cls += ' is-invalid';
 
601
      } else if (focused) {
 
602
        cls += ' is-highlighted'
 
603
      }
 
604
      return cls;
 
605
    },
 
606
 
 
607
    _computeAddOnContentClass: function(focused, invalid) {
 
608
      var cls = 'add-on-content';
 
609
      if (invalid) {
 
610
        cls += ' is-invalid';
 
611
      } else if (focused) {
 
612
        cls += ' is-highlighted'
 
613
      }
 
614
      return cls;
 
615
    }
 
616
  });
 
617
</script>