No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Aplicación de fromEvent en PlatziWordle

9/36
Recursos

Aportes 18

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

MI SOLUCIÓN
Consiste en añadir un nuevo observador para el caso específico de borrar una letra, lo llamé deleteLetter y suscribirse al observable onKeyDown$.
No es una buena implementación añadir un elseIf al observador insertLetter porque como su nombre lo dice, únicamente es para insertar letras.

Acá mi código:

/**
 * Aplicación de fromEvent en PlatziWordle:
 * fromEvent nos ayuda a atrapar eventos generados por elementos en el DOM.
 */

import { fromEvent } from "rxjs";

const letterRows = document.getElementsByClassName("letter-row");
const onKeyDown$ = fromEvent(document, "keydown");
let letterIndex = 0;
let letterRowIndex = 0;

const insertLetter = {
    next: (event) => {
        const pressedKey = event.key.toUpperCase();
        if (pressedKey.length === 1 && pressedKey.match(/[a-z]/i)) {
            let letterBox =
                Array.from(letterRows)[letterRowIndex].children[letterIndex];
            letterBox.textContent = pressedKey;
            letterBox.classList.add("filled-letter");
            letterIndex++;
        }
    },
};

const deleteLetter = {
    next: (event) => {
        const pressedKey = event.key.toUpperCase();
        if (pressedKey === 'BACKSPACE') {
            let letterBox =
                Array.from(letterRows)[letterRowIndex].children[letterIndex-1];
            letterBox.textContent = null;
            letterBox.classList.remove("filled-letter");
            letterIndex--;
        }
    },
};

onKeyDown$.subscribe(insertLetter);
onKeyDown$.subscribe(deleteLetter);

Me adelanté un poco e implementé que se pueda agregar las letras en la siguiente row. Además, usé Typescript.

import "../src/styles/main.css"
import { fromEvent } from "rxjs";

const onKey$ = fromEvent<KeyboardEvent>(document, "keydown"); //Se crea el observable que lanza un
//evento cuando se presione una tecla.

const wordleRows: Element[] = Array.from(document.querySelectorAll(".wordle__row"));


const regex: RegExp = /[a-z]/i;

class Wordle {

	constructor(
		private maxIndex: number,
		private maxRow: number,
		private index: number = 0,
		private rowIndex: number = 0,
	){
		this.maxIndex--;
		this.maxRow--;
	}

	private alterWordle = (addingLetter: boolean): void => {
		if (addingLetter) {
			if (this.maxIndex > this.index) {
				this.alterIndex(true);
			} else {
				this.alterIndex(true, true);
				this.alterRowIndex(true);
			}
		} else {
			if (this.index === 0 && this.rowIndex !== 0) {
				this.alterIndex(false, false);
				this.alterRowIndex(false);
			} else if(this.index !== 0){
				this.alterIndex(false);
			}
		}
	}

	public writeLetter = (letter: string): void => {

		wordleRows[this.rowIndex].children[this.index].textContent = letter.toUpperCase();
		this.alterWordle(true);
	};

	public deleteLetter = () => {
		this.alterWordle(false);
		wordleRows[this.rowIndex].children[this.index].textContent = " ";
	};

	private alterIndex = (isIncreasing: boolean, atBeginning?: boolean): void => {
		if (atBeginning === undefined) {
			if(isIncreasing) {
				this.index++;
			} else {
				this.index--;
			}
		} else {
			if (isIncreasing && atBeginning){
				this.index = 0;
			} else if (!isIncreasing && !atBeginning){
				this.index = this.maxIndex;
			}
		}

	}

	private alterRowIndex = (isIncreasing: boolean): void => {
		if(isIncreasing && this.rowIndex < this.maxRow) {
			this.rowIndex++;
		} else if (isIncreasing && this.rowIndex !== 0){
			this.rowIndex--;
		}
	}

}

const wordle = new Wordle(5, 6);

const observatorLetter = { //Se crea el observador que indica como usará la data obtenida.
	next: (event: KeyboardEvent) => {
		const keyPressed = event.key;

		if (keyPressed.match(regex) && keyPressed.length === 1) {
			wordle.writeLetter(keyPressed);
		}
	},
	complete: () => {
		console.log("There is no more events");
	},
	error: (error: Error) => {
		console.log("Something went wrong: ", error.message);
	}
}

const observatorBackSpace = { //Se crea el observador que indica como usará la data obtenida.
	next: (event: KeyboardEvent) => {
		const keyPressed = event.key;

		if (keyPressed === "Backspace") {
			wordle.deleteLetter();
		}
	},
	complete: () => {
		console.log("There is no more events");
	},
	error: (error: Error) => {
		console.log("Something went wrong: ", error.message);
	}
}

onKey$.subscribe(observatorLetter); //Se subscribe el observador al observable.
onKey$.subscribe(observatorBackSpace);

Hola a todos !
Esta es una posible solucion al exercicio =)
Espero tengan un buen dia!

else if(pressedKey === "BACKSPACE"){
        letterIndex--;
        let letterBox =
        Array.from(letterRows)[letterRowIndex].children[letterIndex];
        
        letterBox.textContent = ""
        letterBox.classList.remove("filled-letter")
    }

😊 Ahora que conocemos cómo funciona fromEvent vamos a implementarlo en PlatziWordle.

Este profe pensó en todo, que orden, que buenas explicaciones, que mimo que le da al curso, seguro era estudiante de platzi

Una alternativa para validar que solo se ingresen letras, es a través del atributo “keyCode” del evento “keyDown” Ej:

import { fromEvent } from "rxjs";

const onKeyDown$ = fromEvent(document, "keydown");

const insertLetter = {
  next: (event) => {
    const pressedKeyCode = event.keyCode;
    const pressedKey = event.key;

    //Only allow alpha characters
    if (pressedKeyCode >= 65 && pressedKeyCode <= 90) {
      console.log(pressedKey);
    }
  },
};

onKeyDown$.subscribe(insertLetter);

Aporte platzi wordle

Hola a tod@s.
Aquí mi aportación. He llevado la implementación a una clase que crea una instancia de cada row y encapsula todo su comportamiento. De esta forma, en cada nuevo intento crearemos una nueva instancia pasándole el elemento .letter_row correspondiente. En el futuro, si añadimos un teclado virtual o más posibles comportamientos, quizás sería interesante valorar añadir un patrón command para gestionar los diferentes comandos (escribir, borrar, confirmar, pegar, clickar una tecla en el teclado virtual, etc). Aquí va el código:

import {fromEvent, Observable} from "rxjs";

class LetterRow {
  private index: number = 0;
  private onKeyDown$: Observable<Event> = fromEvent(document, 'keydown');

  private constructor(public readonly element: Element) {
    this.onKeyDown$.subscribe({
      next: (event: any) => {
        switch(event.key) {
          case 'Backspace':
            this.delete();
            break;
          default:
            this.type(event.key);
        }
      }
    });
  }

  static create(element: Element) {
    LetterRow.validate(element);
    return new LetterRow(element);
  }

  static validate(element: Element): void {
    if (!element) {
      throw new Error('No valid element');
    }
  }

  private type(key: string): void {
    if (this.isEndOfRow()) return;
    const pressedKey: string = key.toUpperCase();
    if (pressedKey.length === 1 && pressedKey.match(/[A-Z]/)) {
      let letterBox: Element = this.element.children[this.index];
      letterBox.textContent = pressedKey;
      letterBox.classList.add('filled-letter');
      this.moveForward();
    }
  }

  private delete(): void {
    let letterBox: Element = this.element.children[this.index - 1];
    letterBox.textContent = '';
    letterBox.classList.remove('filled-letter');
    this.moveBackward();
  }

  private moveForward(): void {
    if (this.isEndOfRow()) return;
    this.index++;
  }

  private moveBackward(): void {
    if (this.index <= 0) return;
    this.index--;
  }

  private isEndOfRow(): boolean {
    return this.index >= this.element.children.length;
  }
}

const letterRows: HTMLCollection = document.getElementsByClassName('letter-row');
let letterRowIndex = 0;
const row: LetterRow = LetterRow.create(Array.from(letterRows)[letterRowIndex]);

Regex:

pressedKey.match(/[a-z]/i)

Mi solución

import { fromEvent } from "rxjs";
const letterRows = Array.from(document.getElementsByClassName('letter-row') || [])
const onKeyDown$ = fromEvent(document, 'keydown');
let letterIndex = 0;
let letterRowIndex = 0;

const insertLetter$ = {
  next: (value) => {
    const pressedKey = value.key;
    if (letterRowIndex > 5) {
      return
    }
    if (pressedKey.length == 1 && pressedKey.match(/[a-z]/i) && letterIndex <= 4) {
      let letterBox = letterRows[letterRowIndex].children[letterIndex];
      letterBox.textContent = pressedKey.toUpperCase();
      letterBox.classList.add('filled-letter');
      letterIndex++;
    }

    if (pressedKey == 'Backspace' && letterRows[letterRowIndex].children[letterIndex - 1]) {
      let letterBox = letterRows[letterRowIndex].children[letterIndex - 1];
      letterBox.textContent = null;
      letterBox.classList.remove('filled-letter');
      letterIndex--;
    }

  },
  complete: () => {
    console.info('Finished');
  },
  error: (error) => {
    console.error(error)
  }
}
onKeyDown$.subscribe(insertLetter$);
import { fromEvent } from "rxjs";

const letterRows = document.getElementsByClassName("letter-row");
const onKeyDown$ = fromEvent(document, "keydown");

const onKeyDownErase$ = fromEvent(document, "keydown");

let letterRowIndex = 0;
let letterIndex = 0;
let arrLetters = [];

const insertLetter = {
  next: (event) => {
    const pressedKey = event.key.toUpperCase();
    if (
      pressedKey.length === 1 &&
      pressedKey.match(/[a-z]/i) &&
      arrLetters.length < 5
    ) {
      arrLetters.push(pressedKey);
      let letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex];
      letterBox.textContent = pressedKey;
      letterBox.classList.add("filled-letter");
      letterIndex++;
    }
  },
};

const eraseLetter = {
  next: (event) => {
    const pressedKey = event.key;
    if (pressedKey === "Backspace" && arrLetters.length !== 0) {
      arrLetters.splice(letterIndex - 1, 1);
      let letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex - 1];
      letterBox.textContent = "";
      letterBox.classList.remove("filled-letter");
      letterIndex--;
    }
  },
};

onKeyDown$.subscribe(insertLetter);
onKeyDownErase$.subscribe(eraseLetter);
 if ( pressedKey == 'Backspace'.toUpperCase()) {debugger
            letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex - 1];
            letterBox.textContent = '';
            letterBox.classList.remove("filled-letter");
            letterIndex--;
        }

Muy buen reto, me hizo pensar al principio, pero ya resuelto, las pistas ayudan mucho.

MI SOLUCIÓN

const { fromEvent, map, filter } = require("rxjs");

const letterRows = document.getElementsByClassName("letter-row");
const onKeyDown$ = fromEvent(document, "keydown");
const getLetterPressed$ = map((x) => x.key);
const upperCase$ = map((x) => x.toUpperCase());

let letterIndex = 0;
let letterRowIndex = 0;

const insertLetter = {
  next: (pressedKey) => {
    if (pressedKey.length === 1 && pressedKey.match(/[a-z]/i)) {
      let letterBox =
        Array.from(letterRows)[letterRowIndex].children[letterIndex];
      letterBox.textContent = pressedKey;
      letterBox.classList.add("filled-letter");
      if (letterIndex < 4) {
        letterIndex++;
      }
    }
  },
};

const removeLetter = {
  next: (pressed) => {
    console.log(pressed);
    let letterBox =
      Array.from(letterRows)[letterRowIndex].children[letterIndex];
    letterBox.textContent = "";
    letterBox.classList.remove("filled-letter");

    if (letterIndex > 0) letterIndex--;
  },
};
onKeyDown$
  .pipe(
    getLetterPressed$,
    upperCase$,
    filter(
      (pressedKey) => pressedKey.length === 1 && pressedKey.match(/[a-z]/i)
    )
  )
  .subscribe(insertLetter);

onKeyDown$
  .pipe(
    getLetterPressed$,
    upperCase$,
    filter((key) => key === "BACKSPACE")
  )
  .subscribe(removeLetter);

````js //importanto operador fromEvent import {fromEvent} from 'rxjs'; const letterRow= document.querySelectorAll('.letter-row'); const onKeyDown$=fromEvent(document,'keydown'); let letterIndex=0; let letterRowIndex=0; const insertLetter={ next:(event)=>{ const pressedKey=event.key; if(pressedKey.length===1 && pressedKey.match(/[a-z]+/gi)){ let letterBox=Array.from(letterRow)[0].children[letterIndex]; letterBox.textContent=pressedKey; letterBox.classList.add('filled-letter'); letterIndex++; } //console.log(event); }, } const deleteLetter={ next:(event)=>{ if(event.keyCode === 8){ let deleteLetterBox=Array.from(letterRow)[0].children[letterIndex-1]; deleteLetterBox.textContent=''; deleteLetterBox.classList.remove('filled-letter'); letterIndex--; } } } onKeyDown$.subscribe(insertLetter); onKeyDown$.subscribe(deleteLetter); ```//importanto operador fromEvent import {fromEvent} from 'rxjs';const letterRow= document.querySelectorAll('.letter-row'); const onKeyDown$=fromEvent(document,'keydown'); let letterIndex=0;let letterRowIndex=0; const insertLetter={    next:(event)=>{        const pressedKey=event.key;        if(pressedKey.length===1 && pressedKey.match(/\[a-z]+/gi)){            let letterBox=Array.from(letterRow)\[0].children\[letterIndex];            letterBox.textContent=pressedKey;            letterBox.classList.add('filled-letter');            letterIndex++;        }        //console.log(event);    },} const deleteLetter={    next:(event)=>{        if(event.keyCode === 8){            let deleteLetterBox=Array.from(letterRow)\[0].children\[letterIndex-1];            deleteLetterBox.textContent='';            deleteLetterBox.classList.remove('filled-letter');            letterIndex--;        }    }} onKeyDown$.subscribe(insertLetter);onKeyDown$.subscribe(deleteLetter); ````

Me encanta la didáctica de este maestro,
Mi solución al reto es un nuevo observador:

const eraseLetter = {
  next: (event) => {
    if ( event.keyCode === 8) {
      let letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex - 1];
      letterBox.textContent = '';
      letterIndex--;
    }
  }
}

onBackDelete$.subscribe(eraseLetter);

Mi solución es la siguiente.

Utilice el mismo observable para detectar cuando se precione el boton para borrar y valide que si el index es 0 no pase nada.

import { fromEvent } from 'rxjs';

const letterRows = document.getElementsByClassName('letter-row');
const onkeyDown$ = fromEvent(document, 'keydown');
let letterIndex = 0;
let letterRowIndex = 0;

const insertLetter = {
    next: (event) => {
        
        const pressedKey = event.key;
        if(pressedKey === 'Backspace') {
            if( letterIndex <= 0) return;

            letterIndex --;
            let letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex];
            letterBox.textContent = '';
            letterBox.classList.remove('filled-letter');
        }

        if(letterIndex === 5) return console.log('salto de linea.');

        if(pressedKey.length === 1 && pressedKey.match(/[a-z]/i)) {

            let letterBox = Array.from(letterRows)[letterRowIndex].children[letterIndex];
            letterBox.textContent = pressedKey
            letterBox.classList.add('filled-letter');
            letterIndex ++;
        } 

    }
};

onkeyDown$.subscribe(insertLetter);

No es necesario crear otro observador para este reto, sin embargo para el curso está bien. Mi solución en un poco minimalista jejeje.
Solo pregunto por código ASCII de la tecla retroceso (8) y luego lo envió a una función que haga el trabajo. Así evito un doble subscribe.

let letterIndex = 0;
let letterRowIndex = 0;
const insertLetter = {
  next: (event) => {
    const pressedKey = event.key.toUpperCase();
    const BACK = event.keyCode === 8 ?? event.key;
    if (BACK) {
      letterIndex--;
      return backLetter(letterRows);
    }
    if (pressedKey.length === 1 && pressedKey.match(/[a-z]/i)) {
      let letterBox = letterRows[letterRowIndex].children[letterIndex];
      letterBox.textContent = pressedKey;
      letterBox.classList.add("filled-letter");
      letterIndex++;
    }
  },
};

function backLetter(letterRows) {
  let letterBox = letterRows[letterRowIndex].children[letterIndex];
  letterBox.textContent = "";
  letterBox.classList.remove("filled-letter");
}
onKeyDown$.subscribe(insertLetter);

Comparto mi solucion al ejercicio

<code> 
onKeyDownObservable$.subscribe( {
    next: (value) => {
        console.log(value);
        if (value.code === 'Delete' || value.code == 'Backspace') {
            deleteLetter();
        } else if  ( value.key?.length == 1 && value.key?.match(/[a-z]/i) ){
            //solo debe aceptar letras
            setLetter( value.key );
        } else {
            console.log("solo letras");
        }
    }
});

function deleteLetter(){
    letterCol = letterCol == 0 ? 0 : letterCol-1;    
    const acualLetter = Array.from(letterRows)[letterRow].children[letterCol];
    acualLetter.textContent = null;
    acualLetter.classList.remove('filled-letter')
}