react-touch-screen-keyboard icon indicating copy to clipboard operation
react-touch-screen-keyboard copied to clipboard

Pass events in callbacks

Open buesing opened this issue 7 years ago • 8 comments

I want to animate the keyboard on focus/blur. It would be helpful if the events would be passed to e.g. onBlur so I can prevent it, do my animation, and the fire it again. Unless I'm missing another easy way to do this.

buesing avatar Sep 28 '18 11:09 buesing

@buesing

The <KeyboardedInput /> component has callbacks for for onFocus and onBlur. Do you have an animation workflow that doesn't fit those callbacks?

reganlawton avatar Oct 01 '18 21:10 reganlawton

Yes, I want to

  onBlur = (e) => {
    e.preventDefault();
    TweenMax.fromTo(".keyboard-wrapper", 0.5, {
      y: 0,
      autoAlpha: 1,
    }, {
      autoAlpha: 0,
      y: 100,
    });
  }

But I can't, because the event is not passed and the element disappears instantly. Is there any way to get it to have an out-animation?

buesing avatar Oct 02 '18 08:10 buesing

@buesing Could you possible do the using the KeyboardInput ref?

  <KeyboardedInput
    ref={ref => { this.myInput = ref; }}
    ...

Or is it possible to use CSS transitions to achieve your goal?

reganlawton avatar Oct 03 '18 00:10 reganlawton

@buesing Due to the way the project works by triggering the the focus event on the input I'm not sure your animation is going to be supported with out breaking support for other cases.

reganlawton avatar Oct 08 '18 03:10 reganlawton

If you passed me the event I think I could just prevent it, no? That wouldn't break anything.

buesing avatar Oct 08 '18 07:10 buesing

@buesing

The event is handled inside a setTimeout() function. I believe this is done to keep the input focused when hitting the virtual keys. See below.

handleFocus() {
    const that = this;
    // Prevent blinking of the keyboard if opaque
    setTimeout(() => {
      if (that.input && typeof (that.props.value) !== 'undefined') {
        that.input.focus();
        that.input.select();
        that.input.setSelectionRange(that.props.value.length, that.props.value.length);

        // Only trigger on first focus
        if (this.state.showKeyboard === false && that.props.onFocus) {
          that.props.onFocus(that.props.value);
        }

        that.setState({ ...this.state, showKeyboard: true });
      }
    }, 0);
  }

  handleFocusLost() {
    const that = this;
    setTimeout(() => {
      if (!document.activeElement.classList.contains('keyboard-button')
        && !document.activeElement.classList.contains('keyboard')
        && !document.activeElement.classList.contains('keyboard-row')
        && !document.activeElement.classList.contains('react-draggable-transparent-selection')) {

        if (that.props.onBlur) {
          that.props.onBlur(that.props.value);
        }

        that.setState({ ...that.state, showKeyboard: false });
      }
    }, 0);
  }```

I had a quick play and refactored to pass the event through as a second param for the callback but quickly noticed that the event is fired continuously to keep focus on the input. Which would fire the animation multiple times and my guess would look quite funny.

My idea would be to create a `onStart` and `onEnd` callback prop. Which could pass the event one time then skip over after.

reganlawton avatar Oct 08 '18 22:10 reganlawton

Yes, sounds like it could work. I just need some way to fade out the keyboard after focus is lost.

buesing avatar Oct 09 '18 07:10 buesing

@buesing Sorry for the late reply this change is gonna take abit of testing to make sure the change doesn't impact the current workflow of the library. I'll buzz you once I have a branch for you to test.

reganlawton avatar Oct 17 '18 21:10 reganlawton