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

highlight current words #25

Closed
pietrop opened this issue Nov 26, 2018 · 4 comments
Closed

highlight current words #25

pietrop opened this issue Nov 26, 2018 · 4 comments
Assignees
Labels
Feature New feature that is going to be implemented

Comments

@pietrop
Copy link
Contributor

pietrop commented Nov 26, 2018

Some notes on possible implementation here

@pietrop pietrop added the Feature New feature that is going to be implemented label Nov 26, 2018
@pietrop
Copy link
Contributor Author

pietrop commented Nov 27, 2018

Alternative implementation - simplified

from docs notes for implementaton see branch - words-highlight-css-selector

Simplified version only showing current words approximated to the seconds

At a high level, by this point we have already have the current time available to TimeTextEditor from MediaPlayer as this.props.currentTime.

selecting words using attribute based on timecode

span.Word selects a word element

span.Word[data-start="18.14"] {
    background-color: red;
}

If you load the demo loacalhost:3006 and type this in the inspector tools, the word robot in the demo text will become red.

However currentTime property on HTML5 video and audio element does not progress at regular reliable interval. (cit needed) so it's unlikely that the this.props.currentTime will hit exactly 18.14 value and even if it did it would only stay on it for 0.01 sec.

we can approximate time

However we can approximate time to seconds and ignore the milliseconds.

We can chose two selectors to help with this

[attr^=value] selector
Selects an element with a certain attribute that starts > with a certain value`

or

[attr*=value] selector
Selects an element with a certain attribute that contains a certain value; not necessarily space-separated

so we can change our selector be

span.Word[data-start^="18."] {
    background-color: red;
}

Now two words are selected robot and upside. Because the first one as we know has timecode of 18.14 while the other one has 18.72. So both are selected.

we add a . after the number so that ignore milliseconds in the matching eg 0.18. and we use ^ so that it ignores other partial matches such as 118. (which would have been a problem if we had used *)

we can connect it to currentTime

To connect it with currentTime In TimedTextEditor we can do a CSS injection adding a style tag in the return of the render function fo the component.

This allows to make the data attribute value we are looking for dynamics. And round the currentTime time to int. to enable the comparison explained above.

render() {
    return (
      <section >
        <section
          className={ styles.editor }
          onDoubleClick={ event => this.handleDoubleClick(event) }
          // onClick={ event => this.handleOnClick(event) }
        >
          <style scoped>
            {`span.Word[data-start^="${ parseInt(this.props.currentTime) }."] {
                background-color: lightblue;
              }` } 
          </style>
          {/* <p> {JSON.stringify(this.state.transcriptData)}</p> */}
          <Editor
            editorState={ this.state.editorState }
            onChange={ this.onChange }
            stripPastedStyles
          />
        </section>
      </section>
    );
  }

This will highlight a couple of words that match to the current time code.

However we notice that when multiple words are selected, only the words are selected and the space in between is blank, doesn't look great.

Making it as continuos line

To select spaces we used the +

+ selector
Selects an element that is a next sibling of another element

span.Word[data-start^="36."]+span {
    background-color: lightblue;
}

So we can change previous code to be

render() {
    return (
      <section >
        <section
          className={ styles.editor }
          onDoubleClick={ event => this.handleDoubleClick(event) }
          // onClick={ event => this.handleOnClick(event) }
        >
          <style scoped>
            {`span.Word[data-start^="${ parseInt(this.props.currentTime) }."] {
                background-color: lightblue;
              }` } 
            {/* To select the spaces in between words */}
            {`span.Word[data-start^="${ parseInt(this.props.currentTime) }."]+span {
                  background-color: lightblue;
              }`}
          </style>
          {/* <p> {JSON.stringify(this.state.transcriptData)}</p> */}
          <Editor
            editorState={ this.state.editorState }
            onChange={ this.onChange }
            stripPastedStyles
          />
        </section>
      </section>
    );
}

making previous words selectable

see this article to make previous words to currentTime highlightable, adding all numbers from zero to start time of that word rounded up, to seconds to make it highlightable.

in Word.js

class Word extends PureComponent {
  render() {
    const data = this.props.entityKey
      ? this.props.contentState.getEntity(this.props.entityKey).getData()
      : {};

     
      let res = '';
      for(let i =0; i< parseInt(data.start); i++){
        res += ` ${ i }`; 
      }

    return (
      <span data-start={ data.start } data-prev-times={ res } data-entity-key={ data.key } className="Word">
        {this.props.children}
      </span>
    );
  }
}

Then change TimedTextEditor to be

 render() {
    return (
      <section >
        <section
          className={ styles.editor }
          onDoubleClick={ event => this.handleDoubleClick(event) }
          // onClick={ event => this.handleOnClick(event) }
        >
          <style scoped>
            {`span.Word[data-start^="${ parseInt(this.props.currentTime) }."] {
                background-color: lightblue;
              }` } 
            {/* To select the spaces in between words */}
            {`span.Word[data-start^="${ parseInt(this.props.currentTime) }."]+span {
                  background-color: lightblue;
              }`}

            {/* To select previous words */}
            {`span.Word[data-prev-times~="${ parseInt(this.props.currentTime) }"] {
                  color: grey;
              }`}
          </style>
          {/* <p> {JSON.stringify(this.state.transcriptData)}</p> */}
          <Editor
            editorState={ this.state.editorState }
            onChange={ this.onChange }
            stripPastedStyles
          />
        </section>
      </section>
    );
  }

Performance

However not sure about performance of this last part.

Screenshot

timecode-highlight

Background readings

@pietrop
Copy link
Contributor Author

pietrop commented Nov 28, 2018

PR #33

@pietrop pietrop closed this as completed Nov 28, 2018
@vipulLB
Copy link

vipulLB commented Sep 6, 2022

can you Please provide me the code for this ??

@tejasri12345
Copy link

tejasri12345 commented Mar 6, 2023

Hai..... Can I see the code for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature New feature that is going to be implemented
Projects
None yet
Development

No branches or pull requests

4 participants