jellyfin-web/dashboard-ui/bower_components/paper-input/paper-input-behavior.html
2015-09-14 21:17:19 -04:00

424 lines
11 KiB
HTML

<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-behaviors/iron-control-state.html">
<script>
/**
* Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This
* behavior is implemented by `<paper-input>`. It exposes a number of properties from
* `<paper-input-container>` and `<input is="iron-input">` and they should be bound in your
* template.
*
* The input element can be accessed by the `inputElement` property if you need to access
* properties or methods that are not exposed.
* @polymerBehavior Polymer.PaperInputBehavior
*/
Polymer.PaperInputBehaviorImpl = {
properties: {
/**
* Fired when the input changes due to user interaction.
*
* @event change
*/
/**
* The label for this input. Bind this to `<paper-input-container>`'s `label` property.
*/
label: {
type: String
},
/**
* The value for this input. Bind this to the `<input is="iron-input">`'s `bindValue`
* property, or the value property of your input that is `notify:true`.
*/
value: {
notify: true,
type: String
},
/**
* Set to true to disable this input. Bind this to both the `<paper-input-container>`'s
* and the input's `disabled` property.
*/
disabled: {
type: Boolean,
value: false
},
/**
* Returns true if the value is invalid. Bind this to both the `<paper-input-container>`'s
* and the input's `invalid` property.
*/
invalid: {
type: Boolean,
value: false,
notify: true
},
/**
* Set to true to prevent the user from entering invalid input. Bind this to the
* `<input is="iron-input">`'s `preventInvalidInput` property.
*/
preventInvalidInput: {
type: Boolean
},
/**
* Set this to specify the pattern allowed by `preventInvalidInput`. Bind this to the
* `<input is="iron-input">`'s `allowedPattern` property.
*/
allowedPattern: {
type: String
},
/**
* The type of the input. The supported types are `text`, `number` and `password`. Bind this
* to the `<input is="iron-input">`'s `type` property.
*/
type: {
type: String
},
/**
* The datalist of the input (if any). This should match the id of an existing <datalist>. Bind this
* to the `<input is="iron-input">`'s `list` property.
*/
list: {
type: String
},
/**
* A pattern to validate the `input` with. Bind this to the `<input is="iron-input">`'s
* `pattern` property.
*/
pattern: {
type: String
},
/**
* Set to true to mark the input as required. Bind this to the `<input is="iron-input">`'s
* `required` property.
*/
required: {
type: Boolean,
value: false
},
/**
* The error message to display when the input is invalid. Bind this to the
* `<paper-input-error>`'s content, if using.
*/
errorMessage: {
type: String
},
/**
* Set to true to show a character counter.
*/
charCounter: {
type: Boolean,
value: false
},
/**
* Set to true to disable the floating label. Bind this to the `<paper-input-container>`'s
* `noLabelFloat` property.
*/
noLabelFloat: {
type: Boolean,
value: false
},
/**
* Set to true to always float the label. Bind this to the `<paper-input-container>`'s
* `alwaysFloatLabel` property.
*/
alwaysFloatLabel: {
type: Boolean,
value: false
},
/**
* Set to true to auto-validate the input value. Bind this to the `<paper-input-container>`'s
* `autoValidate` property.
*/
autoValidate: {
type: Boolean,
value: false
},
/**
* Name of the validator to use. Bind this to the `<input is="iron-input">`'s `validator`
* property.
*/
validator: {
type: String
},
// HTMLInputElement attributes for binding if needed
/**
* Bind this to the `<input is="iron-input">`'s `autocomplete` property.
*/
autocomplete: {
type: String,
value: 'off'
},
/**
* Bind this to the `<input is="iron-input">`'s `autofocus` property.
*/
autofocus: {
type: Boolean
},
/**
* Bind this to the `<input is="iron-input">`'s `inputmode` property.
*/
inputmode: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `minlength` property.
*/
minlength: {
type: Number
},
/**
* The maximum length of the input value. Bind this to the `<input is="iron-input">`'s
* `maxlength` property.
*/
maxlength: {
type: Number
},
/**
* The minimum (numeric or date-time) input value.
* Bind this to the `<input is="iron-input">`'s `min` property.
*/
min: {
type: String
},
/**
* The maximum (numeric or date-time) input value.
* Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`).
* Bind this to the `<input is="iron-input">`'s `max` property.
*/
max: {
type: String
},
/**
* Limits the numeric or date-time increments.
* Bind this to the `<input is="iron-input">`'s `step` property.
*/
step: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `name` property.
*/
name: {
type: String
},
/**
* A placeholder string in addition to the label. If this is set, the label will always float.
*/
placeholder: {
type: String,
// need to set a default so _computeAlwaysFloatLabel is run
value: ''
},
/**
* Bind this to the `<input is="iron-input">`'s `readonly` property.
*/
readonly: {
type: Boolean,
value: false
},
/**
* Bind this to the `<input is="iron-input">`'s `size` property.
*/
size: {
type: Number
},
// Nonstandard attributes for binding if needed
/**
* Bind this to the `<input is="iron-input">`'s `autocapitalize` property.
*/
autocapitalize: {
type: String,
value: 'none'
},
/**
* Bind this to the `<input is="iron-input">`'s `autocorrect` property.
*/
autocorrect: {
type: String,
value: 'off'
},
_ariaDescribedBy: {
type: String,
value: ''
}
},
listeners: {
'addon-attached': '_onAddonAttached'
},
observers: [
'_focusedControlStateChanged(focused)'
],
/**
* Returns a reference to the input element.
*/
get inputElement() {
return this.$.input;
},
attached: function() {
this._updateAriaLabelledBy();
},
_appendStringWithSpace: function(str, more) {
if (str) {
str = str + ' ' + more;
} else {
str = more;
}
return str;
},
_onAddonAttached: function(event) {
var target = event.path ? event.path[0] : event.target;
if (target.id) {
this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, target.id);
} else {
var id = 'paper-input-add-on-' + Math.floor((Math.random() * 100000));
target.id = id;
this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, id);
}
},
/**
* Validates the input element and sets an error style if needed.
*
* @return {boolean}
*/
validate: function() {
return this.inputElement.validate();
},
/**
* If `autoValidate` is true, then validates the element.
*/
_handleAutoValidate: function() {
if (this.autoValidate)
this.validate();
},
/**
* Restores the cursor to its original position after updating the value.
* @param {string} newValue The value that should be saved.
*/
updateValueAndPreserveCaret: function(newValue) {
// Not all elements might have selection, and even if they have the
// right properties, accessing them might throw an exception (like for
// <input type=number>)
try {
var start = this.inputElement.selectionStart;
this.value = newValue;
// The cursor automatically jumps to the end after re-setting the value,
// so restore it to its original position.
this.inputElement.selectionStart = start;
this.inputElement.selectionEnd = start;
} catch (e) {
// Just set the value and give up on the caret.
this.value = newValue;
}
},
_computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) {
return placeholder || alwaysFloatLabel;
},
_focusedControlStateChanged: function(focused) {
// IronControlState stops the focus and blur events in order to redispatch them on the host
// element, but paper-input-container listens to those events. Since there are more
// pending work on focus/blur in IronControlState, I'm putting in this hack to get the
// input focus state working for now.
if (!this.$.container) {
this.$.container = Polymer.dom(this.root).querySelector('paper-input-container');
if (!this.$.container) {
return;
}
}
if (focused) {
this.$.container._onFocus();
} else {
this.$.container._onBlur();
}
},
_updateAriaLabelledBy: function() {
var label = Polymer.dom(this.root).querySelector('label');
if (!label) {
this._ariaLabelledBy = '';
return;
}
var labelledBy;
if (label.id) {
labelledBy = label.id;
} else {
labelledBy = 'paper-input-label-' + new Date().getUTCMilliseconds();
label.id = labelledBy;
}
this._ariaLabelledBy = labelledBy;
},
_onChange:function(event) {
// In the Shadow DOM, the `change` event is not leaked into the
// ancestor tree, so we must do this manually.
// See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-not-leaked-into-ancestor-trees.
if (this.shadowRoot) {
this.fire(event.type, {sourceEvent: event}, {
node: this,
bubbles: event.bubbles,
cancelable: event.cancelable
});
}
}
};
/** @polymerBehavior */
Polymer.PaperInputBehavior = [Polymer.IronControlState, Polymer.PaperInputBehaviorImpl];
</script>