425 lines
11 KiB
HTML
425 lines
11 KiB
HTML
<link rel="import" href="../../components/iron-validatable-behavior/iron-validatable-behavior.html">
|
|
<link rel="import" href="../../components/paper-item/paper-item-behavior.html">
|
|
<link rel="import" href="../../components/paper-behaviors/paper-ripple-behavior.html">
|
|
<link rel="import" href="../../components/neon-animation/neon-animatable-behavior.html">
|
|
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
|
<link rel="import" href="step-horizontal-label.html">
|
|
<link rel="import" href="step-vertical.html">
|
|
<link rel="import" href="../../components/polymer/polymer.html">
|
|
|
|
<!--
|
|
Missing Doc
|
|
@element paper-step
|
|
@demo demo/index.html
|
|
@hero hero.svg
|
|
-->
|
|
<dom-module id="paper-step">
|
|
<template>
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
box-sizing: border-box;
|
|
outline: 0;
|
|
}
|
|
:host(:not([vertical])) {
|
|
overflow: hidden;
|
|
@apply(--layout);
|
|
@apply(--layout-flex);
|
|
}
|
|
:host(:not([vertical])[opened]){
|
|
overflow: visible;
|
|
}
|
|
:host(:not([opened]):not(.neon-animating)) #slideshowViewport{
|
|
display: none;
|
|
}
|
|
#slideshowViewport {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
overflow: hidden;
|
|
}
|
|
#contentWrapper {
|
|
padding: 16px 0 16px 16px;
|
|
@apply(--layout-scroll);
|
|
@apply(--layout-fit);
|
|
pointer-events: auto;
|
|
}
|
|
:host(:focus:not([opened]):not([saved])) step-horizontal-label ::content #badge {
|
|
background: var(--paper-step-selectable-hovered-badge-background, --paper-grey-500);
|
|
}
|
|
</style>
|
|
|
|
<!-- horizontal step layout -->
|
|
|
|
<template is="dom-if" if="[[!vertical]]">
|
|
<step-horizontal-label id="horizontalStepLabel" editable="[[editable]]" label="[[label]]"
|
|
alternative-label="[[_alternativeLabel]]" optional="[[optional]]"
|
|
opened="[[opened]]" selectable="[[selectable]]" index="[[index]]"
|
|
saved="[[saved]]" stepper-data="[[_stepperData]]">
|
|
</step-horizontal-label>
|
|
<div id="slideshowViewport">
|
|
<div id="contentWrapper">
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- vertical step layout -->
|
|
|
|
<template is="dom-if" if="[[vertical]]">
|
|
<step-vertical id="verticalStepLabel" editable="[[editable]]" label="[[label]]"
|
|
optional="[[optional]]" opened="[[opened]]"
|
|
selectable="[[selectable]]" stepper-data="[[_stepperData]]" index="[[index]]"
|
|
saved="[[saved]]" _attr-for-primary-button-text="[[_attrForPrimaryButtonText]]"
|
|
can-skip="[[_canSkip]]" has-back-step="[[_hasBackStep]]">
|
|
</step-vertical>
|
|
</template>
|
|
</template>
|
|
|
|
<script>
|
|
Polymer({
|
|
|
|
is: 'paper-step',
|
|
|
|
behaviors: [
|
|
Polymer.IronValidatableBehavior,
|
|
Polymer.NeonAnimatableBehavior,
|
|
Polymer.PaperItemBehavior,
|
|
Polymer.PaperRippleBehavior
|
|
],
|
|
|
|
/**
|
|
* Fired when the step has been saved.
|
|
*
|
|
* @event paper-step-saved
|
|
*/
|
|
/**
|
|
* Fired when the step has been updated
|
|
*
|
|
* @event paper-step-updated
|
|
*/
|
|
properties: {
|
|
/**
|
|
* MISSING Doc
|
|
*/
|
|
saved: {
|
|
type: Boolean,
|
|
value: false,
|
|
notify: true,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
editable: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
index: {
|
|
type: Number,
|
|
notify: true,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
_previousSaved: {
|
|
type: Boolean,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
optional: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
selectable: {
|
|
type: Boolean,
|
|
computed: '_computeSelectable(_stepperData.linear, saved, editable, _previousSaved)',
|
|
reflectToAttribute: true,
|
|
notify: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
disabled: {
|
|
computed: '_computeDisabled(selectable)'
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
label: {
|
|
type: String,
|
|
value: ''
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
opened: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
animationConfig: {
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
entryAnimation: {
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
exitAnimation: {
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
vertical: {
|
|
type: Boolean,
|
|
readOnly: true,
|
|
reflectToAttribute: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
horizontalHigherEntryAnimation: {
|
|
type: String
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
horizontalHigherExitAnimation: {
|
|
type: String
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
horizontalLowerEntryAnimation: {
|
|
type: String
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
horizontalLowerExitAnimation: {
|
|
type: String
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
_alternativeLabel: {
|
|
type: Boolean,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
_optionalText: {
|
|
type: Boolean,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
_attrForPrimaryButtonText: {
|
|
type: String,
|
|
readOnly: true
|
|
},
|
|
/**
|
|
* A reference to the parent stepper
|
|
*/
|
|
_stepper: {
|
|
type: Object,
|
|
readOnly: true
|
|
},
|
|
_stepperData: {
|
|
type: Object,
|
|
readOnly: true
|
|
},
|
|
_canSkip: {
|
|
type: Boolean,
|
|
readOnly: true
|
|
},
|
|
_hasBackStep: {
|
|
type: Boolean,
|
|
readOnly: true
|
|
}
|
|
},
|
|
|
|
listeners: {
|
|
'paper-step-vertical-skip-tapped': 'skip',
|
|
'paper-step-vertical-back-tapped': 'back',
|
|
'paper-step-vertical-continue-tapped': 'continue',
|
|
'tap': '_tapHandler'
|
|
},
|
|
|
|
observers: [
|
|
'_toggleClassPosition(index, _stepperData.stepNumber, vertical)',
|
|
'_updateSlideshowViewportTop(optional, _alternativeLabel, vertical)',
|
|
'_verticalChange(vertical)',
|
|
'_focusedChanged(receivedFocusFromKeyboard)',
|
|
'_labelElementChanged(_labelElement)'
|
|
],
|
|
|
|
_focusedChanged: function(receivedFocusFromKeyboard) {
|
|
if (receivedFocusFromKeyboard) {
|
|
this.ensureRipple();
|
|
// generate a ripple effect from the center of the badge
|
|
var badge = Polymer.dom(this._rippleContainer).querySelector('#badge');
|
|
var badgePos = badge.getBoundingClientRect();
|
|
var rippleX = badgePos.left + 12;
|
|
var rippleY = badgePos.top + 12;
|
|
this._ripple.downAction({detail: {x: rippleX, y: rippleY}});
|
|
}
|
|
if (this.hasRipple()) {
|
|
this._ripple.holdDown = receivedFocusFromKeyboard;
|
|
}
|
|
},
|
|
|
|
_tapHandler: function(e) {
|
|
var rootTarget = Polymer.dom(e).rootTarget;
|
|
if (rootTarget !== this && rootTarget !== this._rippleContainer) {
|
|
e.stopImmediatePropagation();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
skip: function() {
|
|
// would it be better to send an event?
|
|
this._stepper.progress();
|
|
},
|
|
|
|
/**
|
|
* Missing Doc
|
|
*/
|
|
back: function() {
|
|
// would it be better to send an event?
|
|
this._stepper.back();
|
|
},
|
|
|
|
/**
|
|
* Mark the step as saved and fire `paper-step-saved` if it is valid.
|
|
* @return {Boolean} True if the step has been saved.
|
|
*/
|
|
save: function() {
|
|
if ((!this.saved || this.editable) && this.validate()) {
|
|
if (this.saved) {
|
|
this.fire('paper-step-updated');
|
|
} else {
|
|
this._setSaved(true);
|
|
this.fire('paper-step-saved');
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Atempte to save the step and select and to progress into the stepper.
|
|
* @return {Boolean} True if the step is valid for saving.
|
|
*/
|
|
continue: function() {
|
|
if (this.save()) {
|
|
// would it be better to send an event?
|
|
this._stepper.progress();
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
_removeAnimatingClass: function() {
|
|
if (this._animationCanceled) {
|
|
this._set_animationCanceled(false);
|
|
} else {
|
|
this.toggleClass('neon-animating', false);
|
|
}
|
|
},
|
|
|
|
_cancelAnimation: function() {
|
|
this._set_animationCanceled(true);
|
|
this.toggleClass('neon-animating', false);
|
|
},
|
|
|
|
_updateSlideshowViewportTop: function(optional, _alternativeLabel, vertical) {
|
|
if (!vertical) {
|
|
this.async(function() {
|
|
this.$$('#slideshowViewport').style.top = this.clientHeight+'px';
|
|
this.fire('step-horizontal-label-resize');
|
|
})
|
|
}
|
|
},
|
|
|
|
_toggleClassPosition: function(index, stepNumber, vertical) {
|
|
this.async(function() {
|
|
var stepLabel = this.$$(vertical ? '#verticalStepLabel' : '#horizontalStepLabel');
|
|
this.toggleClass('first-step', (index == 1), stepLabel);
|
|
this.toggleClass('last-step', (index == stepNumber), stepLabel);
|
|
});
|
|
},
|
|
|
|
_updateAnimationConfig: function() {
|
|
/* TODO: call this method when horizontalHigher/LowerEntry/ExitAnimation change */
|
|
var animatedNode = this.$$('#contentWrapper');
|
|
this._setAnimationConfig({
|
|
'higher-step-entry': {
|
|
node: animatedNode,
|
|
name: this.horizontalHigherEntryAnimation
|
|
},
|
|
'higher-step-exit': {
|
|
node: animatedNode,
|
|
name: this.horizontalHigherExitAnimation
|
|
},
|
|
'lower-step-entry': {
|
|
node: animatedNode,
|
|
name: this.horizontalLowerEntryAnimation
|
|
},
|
|
'lower-step-exit': {
|
|
node: animatedNode,
|
|
name: this.horizontalLowerExitAnimation
|
|
}
|
|
});
|
|
},
|
|
|
|
_verticalChange: function(vertical) {
|
|
this.async(function() {
|
|
// move or create the content tag
|
|
Polymer.dom(this.$$(vertical ? '#verticalStepLabel' : '#contentWrapper')).appendChild(this.$$('content') || this.create('content'));
|
|
// reset the ripple
|
|
this._ripple = false;
|
|
this._rippleContainer = vertical ? this.$$('#verticalStepLabel').$.label : this.$$('#horizontalStepLabel').$.label;
|
|
if (!vertical) {
|
|
this._updateAnimationConfig();
|
|
}
|
|
}.bind(this));
|
|
},
|
|
|
|
_computeSelectable: function(linear, saved, editable, previousSaved) {
|
|
// TODO: factorize the expression
|
|
return (!linear || previousSaved) && (!saved || editable) || (editable && saved);
|
|
},
|
|
|
|
_computeDisabled: function(selectable) {
|
|
// disabled is used by IronMenuBehavior in paper-stepper
|
|
// TODO: remove selectable attribute and use disabled instead
|
|
return !selectable;
|
|
}
|
|
|
|
});
|
|
|
|
</script>
|
|
</dom-module>
|