Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

on Animation Start event is not triggering #14453

Closed
supreetssethi opened this issue Feb 7, 2019 · 6 comments
Closed

on Animation Start event is not triggering #14453

supreetssethi opened this issue Feb 7, 2019 · 6 comments
Labels
status: waiting for author Issue with insufficient information

Comments

@supreetssethi
Copy link

supreetssethi commented Feb 7, 2019

Wanted to catch animation event for textbox's input element.

onAnimationStart function is not getting called in below code.

import React from 'react';
import PropTypes from "prop-types";
import TextField from '@material-ui/core/TextField';
import _isEqual from 'lodash.isequal';
import { validateInput, validateValue } from './../../Services/FormValidationService.js';
import { withStyles } from '@material-ui/core/styles';
import { isMobile } from 'react-device-detect';
import { debounce } from "debounce";
import _ from 'lodash';
import InputAdornment from '@material-ui/core/InputAdornment';
import IconButton from '@material-ui/core/IconButton';
import Visibility from '@material-ui/icons/Visibility';
import VisibilityOff from '@material-ui/icons/VisibilityOff';


class TextBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: '',
            isInvalid: false,
            showPassword: false
        };
        this.onKeyDown = this.onKeyDown.bind(this);
        this.onChange = this.onChange.bind(this);
        this.onBlur = this.onBlur.bind(this);
        this.onPaste = this.onPaste.bind(this);
        this.onFocus = this.onFocus.bind(this);
        this.onChangedebounce = debounce(event => {
            this.onChangeSentProps(event);
        }, 400);

        this.isKeyAllowed = true;
        this.newValue = "";
        this.oldValue = "";
        this.status = "";
        this.allowedKey = ["Backspace", "Tab", "Delete", "Alt"];
        this.onKeyDownMobile = this.onKeyDownMobile.bind(this);
        this.onChangeMobile = this.onChangeMobile.bind(this);
        this.onInputMobile = this.onInputMobile.bind(this);
        // this.handleAnimation=this.handleAnimation.bind(this);
        this.handleClickShowPassword = this.handleClickShowPassword.bind(this);
        this.inputRef = React.createRef();
    }
    componentDidMount() {
        this.setStateOnLoadOrUpdate(this.props);        
    }
   
    componentDidUpdate(prevProps) {
        //If value changes due to change in props from parent, Update the state
        if (!_isEqual(this.props, prevProps)) {
            this.setStateOnLoadOrUpdate(this.props);
        }
    }
    setStateOnLoadOrUpdate(props) {
        let invalid;
        let newRules = _.omit(this.props.validations, ['maxLength', 'minLength', 'format', 'isMultiSpace']);
        this.props.value && (invalid = !(validateValue(this.props.name, this.props.value, newRules).isValid) || this.props.isInvalid);
        !this.props.value && (invalid = this.props.isInvalid);
        !(this.props.canEdit && this.props.isEditable) && (invalid = false);
        this.setState({
            value: props.value,
            isInvalid: invalid
        });
    }
    getNewKey(value1, value2) {
        let values = [];
        for (let i = 0; i < value2.length; i++) {
            if (value1[i] !== value2[i]) {
                values.push(value2[i]);
            }
        }
        return values[0];
    }
    createNewInputValidationObject(validations) {
        let validation = {};
        Object.keys(validations).map(key => {
            if (key === "format" || key === "maxLength")
                validation[key] = this.props.validations[key];
        });
        return validation;
    }

    handleAutoFill = e => {
       console.log(e); //this event is not triggered
    
      };

 
        if (this.props.validations) {
            this.setState({ isInvalid: false });
            (typeof (this.props.onValidity) !== "undefined") && (this.props.onValidity(this.props.name, true));
        }
    }

    onBlur(event) {
        if (this.props.validations) {
            this.status = validateValue(event.target.name, event.target.value.trim(), this.props.validations);
            this.setState({ isInvalid: !this.status.isValid });
            (typeof (this.props.onValidity) !== "undefined") && (this.props.onValidity(this.props.name, this.status.isValid));
        }
    }

    onChange(event) {
        event.persist();
        this.setState({ value: event.target.value });
        this.onChangedebounce(event);
    }

    onChangeSentProps(event) {
        this.props.onChange({ 'key': this.props.name, 'value': event.target.value });
        if (event.target !== document.activeElement) {
            this.status = validateValue(event.target.name, event.target.value.trim(), this.props.validations);
            this.setState({ isInvalid: !this.status.isValid });
            (typeof (this.props.onValidity) !== "undefined") && (this.props.onValidity(this.props.name, this.status.isValid));
        }
    }
    onChangeMobile(event) {
        if (this.props.validations) {
            let validation = this.createNewInputValidationObject(this.props.validations);
            this.status = validateValue(event.target.name, event.target.value, validation);
            this.setState({ isInvalid: !this.status.isValid });
            this.props.onValidity(this.props.name, this.status.isValid);
        }
        this.setState({
            value: event.target.value
        });
        this.onChangedebounce(event);
        this.isKeyAllowed = true;
    }

    onKeyDown(event) {
        if (event.key === "Enter" && (!this.props.isMultiline)) {
            this.onChangedebounce.flush();
            this.status = validateValue(event.target.name, event.target.value.trim(), this.props.validations);
            this.setState({ isInvalid: !this.status.isValid });
            if (this.status.isValid) {
                (typeof (this.props.onValidity) !== "undefined") && (this.props.onValidity(this.props.name, this.status.isValid));
                (typeof (this.props.onSubmit) !== "undefined") && (this.props.onSubmit());
            }
        }

        let selectedTextCount = event.target.selectionEnd - event.target.selectionStart;
        if (event.ctrlKey || selectedTextCount > 0)
            return true;
        if (this.props.validations) {
            let validation = this.createNewInputValidationObject(this.props.validations);
            if (!validateInput(event.key, event.target.value, validation))
                event.preventDefault();
        }
    }
    onKeyDownMobile(event) {
        this.oldValue = event.target.value;
        if (event.target.value.length && _.indexOf(this.allowedKey, event.key) != -1)
            this.isKeyAllowed = false;
    }
    onInputMobile(event) {
        if (this.isKeyAllowed) {
            this.newValue = event.target.value;
            let key = this.getNewKey(this.oldValue, this.newValue);
            if (this.props.validations) {
                let validation = this.createNewInputValidationObject(this.props.validations);
                ((!_.isEmpty(validation)) && validation.maxLength) && (validation.maxLength = validation.maxLength + 1);
                if ((!_.isEmpty(validation)) && !validateInput(key, this.newValue, validation))
                    event.target.value = this.oldValue;
            }
        }
        this.isKeyAllowed = true;
    }
    onPaste(event) {
        (isMobile) && (this.isKeyAllowed = false);
        let value = event.target.value + event.clipboardData.getData('Text');
        this.status = validateValue(event.target.name, value, this.props.validations);
        this.setState({ isInvalid: !this.status.isValid });
        (typeof (this.props.onValidity) !== "undefined") && (this.props.onValidity(this.props.name, this.status.isValid));
    }
    handleClickShowPassword = () => {
        this.setState(state => ({ showPassword: !state.showPassword }));
    };
    render() {
        let componentType = this.props.componentType;
        (componentType === "password" && this.props.addEyeIcon) && (componentType = (this.state.showPassword) ? 'text' : 'password');
        let inputAdornment = null;
        (this.props.componentType === "password" && this.props.addEyeIcon) && (inputAdornment = (
            <InputAdornment position="end">
                <IconButton
                    aria-label="Toggle password visibility"
                    onClick={this.handleClickShowPassword}
                >
                    {this.state.showPassword ? <Visibility className="font-size-20" /> : <VisibilityOff className="font-size-20" />}
                </IconButton>
            </InputAdornment>
        ));
        const { classes } = this.props;
        return (
            <div className={"col-md-4 " + (this.props.className ? this.props.className : "")}>
                <TextField
                    name={this.props.name}
                    multiline={this.props.isMultiLine}
                    rows={this.props.noOfRows}
                    rowsMax={this.props.rowsMax}
                    label={this.props.label}
                    value={this.state.value}
                    onBlur={this.onBlur}
                    onChange={this.onChange}
                    onFocus={this.onFocus}
                    onInput={(isMobile) ? (this.onInputMobile) : () => { }}
                    onKeyDown={isMobile ? this.onKeyDownMobile : this.onKeyDown}
                    onPaste={this.onPaste}
                    margin="normal"
                    className={classes.textField}
                    disabled={!(this.props.canEdit && this.props.isEditable)}
                    error={this.state.isInvalid}
                    fullWidth
                    required={this.props.isRequired && this.props.isEditable}
                    
                    InputProps={{
                        disableUnderline: !(this.props.canEdit && this.props.isEditable),
                        inputProps: {
                            className: classes.input,
                            onAnimationStart :this.handleAutoFill,
                            onAnimationEnd  :this.handleAutoFill,
                            onAnimationIteration :this.handleAutoFill
                        },
                        endAdornment: inputAdornment,
                        
                    }}
                    inputRef={this.inputRef}
                    autoComplete="off"
                    placeholder={this.props.placeholder}
                    type={componentType}
                />
            </div>);
    }
}

`


css file that triggers animation on autofill
`
input:-webkit-autofill {
    animation-name: onAutoFillStart;
    transition: background-color 50000s ease-in-out 0s;
  }
  
  input:not(:-webkit-autofill) {
    animation-name: onAutoFillCancel;
  }

Context 🔦

I am trying to record autofill event using css animation and catching that event in react code.

Your Environment 🌎

Tech Version
Material-UI v3.6.0
React ^16.6.3
Browser chrome
@oliviertassinari
Copy link
Member

@supys12 What animation are you interested in?

@supreetssethi
Copy link
Author

@oliviertassinari I wanted to catch the animation which will be triggered from css for webkit-autofill.
So that when webkit-autofill is triggered i will check my input value and save to state.
As on autofill onChange event is not triggered.

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 7, 2019

@supys12 Does it work with a native <input type="text" /> element?

@supreetssethi
Copy link
Author

I didnt actullay try it directly but i had refer to below link.
https://codedaily.io/tutorials/69/Animated-Input-Label-with-Chrome-Autofill-Detection-in-React

If it is not how this should work.
Can you help me with the below requirement.
on autofill of username and password inside the textbox from browser it should trigger on change or any other function which should allow me to record the autofilled values in my state.

@oliviertassinari
Copy link
Member

@supys12 Do you have an example of reproduction? How can I reproduce the problem?

@oliviertassinari oliviertassinari added the status: waiting for author Issue with insufficient information label Feb 8, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 8, 2019

Ok, I'm moving the discussion to #14427.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting for author Issue with insufficient information
Projects
None yet
Development

No branches or pull requests

2 participants