JaredReisinger / react-crossword

A flexible, responsive, and easy-to-use crossword component for React apps.
https://react-crossword.jaredreisinger.com
MIT License
171 stars 84 forks source link

Allow to show what characters have been entered correctly/incorrectly #54

Closed otacke closed 2 years ago

otacke commented 4 years ago

If used in a learning context, it'd be desirable to show users what characters were entered correctly (or incorrectly). This could be achieved by following the input field changes and finding the appropriate cell in the DOM, but this is pretty inconvenient :-) So:

As a developer, I want to have a way to show the user what characters were entered correctly/incorrectly in order to provide feedback.

Suggestions to choose from :-) (and a query to pre-qualify these for a possible pull-request - accepting isCorrect() and highlight() would be highly appreciated):

JaredReisinger commented 4 years ago

A follow-up question for clarity: Are you interested in being able to show correct/incorrect answers:

  1. while the answers are being typed
  2. after all of the cells in an answer are filled
  3. only after the crossword is complete
  4. in response to a user-initiated "am I right?" action

(You might be looking for several of these.)

Right now, there is an onCorrect() callback that gets called any time a correct answer is provided, and the clue (but not the cells!) receives a correct class, which can be used to, for example, cross-out the clue and mark it as "done". If you're looking for something like #1 above, my instinct would be to add a similar correct (and/or incorrect) class on the individual cells, and also to provide a theming property (like highlightCorrect as you describe).

otacke commented 4 years ago

@JaredReisinger It could be any of these depending on what the developer wants to do.

I may have a particular use case (which would be 4): a) user enters characters until he/she thinks he/she is done b) user requests to check c) crossword provides feedback but from what I learned over the past years, it's best not to assume a particular use case and just to provide general functions as useful building blocks - so isCorrect and highlight would make me very happy.

JaredReisinger commented 3 years ago

I think an imperative isCorrect(row, col) might be useful; I'm less sure about highlight(row, col, color) because it seems too overly generalized. I mean, I guess if an app wants to run through the entire crossword and change every cell's color to something different that's up to the app... but I don't particularly want to be an "enabler" for that. 😄 If every cell has some classes that represent the row and column, however (class="row_2 col_4"), then an app could wreak whatever color havoc they wished, without Crossword necessarily "endorsing" that kind of behavior.

For the "user requests to check the puzzle" scenario, what about using classes for that as well? As the letters are typed, individual cells can be marked with class="correct" or class="incorrect". If an app wants to show (in)correct values immediately, it can use styles like:

.cell.correct { /* styling for correct cells */ }
.cell.incorrect { /* styling for incorrect cells */ }

If it wants a delayed "only when requested" behavior, it can provide a button/state to trigger the "show correct/incorrect" behavior, and update a class on a parent component (class="show-correct", say). Then the app can style:

.show-correct .cell.correct { /* styling for correct cells */ }
.show-correct .cell.incorrect { /* styling for incorrect cells */ }

This way, there's no knowledge of the "has the user asked to be shown correct/incorrect?" in the Crossword itself at all. That's entirely an app decision.

(This discussion is making me think it might be useful to have something like a "Crossword Cookbook" set of examples for the kinds of things folks might want to do with the Crossword component...)

otacke commented 3 years ago

@JaredReisinger I'd even prefer classes (also over your theming options), but I was not sure you had any plans to add any given your statement "No class names are currently applied within the grid, as the SVG layout is very layout-sensitive." in the readme.

One catch maybe: Some mechanism would have to set the classes for correct/wrong answers on the cells - so the Crossword would either still need to know when to put the class there or to do it on its own whenever a letter is typed - thus giving away the correct solution in the DOM (that's actually a real world problem in educational settings).

JaredReisinger commented 3 years ago

@otacke, nice catch on my previous statement about class names and the grid! I think the utility of these classes outweighs the risk. If someone complains that things don't line up after they've styled correct answers with extra padding and a weird size, well, the response will be "don't do that, then!" 🤷

As for setting the classes, there is already code that examines input as it happens in order to provide the onCorrect callbacks to the parent component. It should be a straightforward manner to also poke the "correct" or "incorrect" class on the cell during that process.

The issue about leaking correctness through the DOM via the "correct" class is theoretically a concern, but since the answers themselves are in the DOM, it's not really a new or additional risk. This Crossword component was meant more for fun than as a rigorous testing/puzzle tool. The only way to reliably prevent cheating would be to round-trip guesses through a server. (Even using encrypted local content suffers from needing the decrypting key locally.) Something like this would be different enough that I'd recommend starting from scratch, or perhaps by forking from this project (if one wanted to use some of the layout/parsing logic, etc.). If you, or anyone else, want to do that it wouldn't bother me at all!

otacke commented 3 years ago

@JaredReisinger I see. Full anti-cheating measures would need server-side evaluation, of course, but the answers can at least be kept in memory only, not in the DOM or its HTML representation :-)

ungurnicoleta commented 3 years ago

@JaredReisinger follow up - is there a method isCorrect(direction, number) or isCorrect(row, col) or something that will help me getting the clue for one word (not for all)?

JaredReisinger commented 2 years ago

I'm not sure why merging #121 didn't close this... it should have!