Every year, my wife's book club has a book exchange during the holidays. Due to the need to maintain physical distance in 2020, I created an online gift exchange for them to use during a book club videoconference. Apparently, the virtual book exchange worked out (at least, I received kind compliments from the book club members), so I decided to share this simple little hack.
### How the book exchange usually works
In past years, the exchange has gone something like this:
2. Everyone arrives at the host's home and puts the wrapped books in a pile.
3. Each person draws a number out of a hat, which establishes their turn.
4. The person who drew No. 1 selects a book from the pile and unwraps it. In turn, each subsequent person chooses to either take a wrapped book from the pile or to steal an unwrapped book from someone who has gone before.
5. When someone's book is stolen, they can either replace it with a wrapped book from the pile or steal another book (but not the one that was stolen from them) from someone else.
6. And so on… eventually, someone has to take the last unwrapped book to end the exchange.
My first decision was which implementation platform to use for the book exchange. Because there would already be a browser open to host the videoconference, I decided to use HTML, CSS, and JavaScript.
Then it was design time. After some thinking, I decided to use rectangles to represent the book club members and the books. The books would be draggable, and when one was dropped on a member's rectangle,the bookwould unwrap (and stay unwrapped). I needed some "wrapping paper," so I used this source of [free-to-use images][4].
I needed a way to handle draggable and droppable interactions; given that I've been using jQuery and jQuery UI for several years now, I decided to continue along that path.
For a while, I struggled with what a droppable element should do when something was dropped on it. Finally, I realized that all I needed to do was unwrap the dropped item (if it was still wrapped). I also spent some time fretting over how to lay stuff out until I realized that the easiest thing to do was just leave the elements floating.
Jumping to the results, here's a screenshot of the user interface at the beginning of the exchange:
* Lines 1–6: Upfront, I have the usual `HTML` boilerplate, HTML, `HEAD`, `META`, `TITLE` elements, followed by a link to the CSS for jQuery UI.
* Lines 7–25: I added two new style classes: `draggable` and `droppable`. These define the layout for the books (draggable) and the people (droppable). Note that, aside from defining the size, background color, padding, and margin, I established that these need to float left. This way, the layout adjusts to the browser window width in a reasonably acceptable form.
* Line 26–27: With the CSS out of the way, it's time for the JavaScript libraries, first jQuery, then jQuery UI.
* Lines 29–83: Now that the `HEAD``element` is done, next is the `BODY`:
* Lines 30–31:Thesecouple of titles, `H1` and `H2`, let people know what they're doing here.
Lines 33–43: A `DIV` to contain the people:
Lines 34–42: The people are defined as `droppable``DIV` elements and given `ID` fields corresponding to their names.
Lines 44–54: A `DIV` to contain the books:
Lines 45–53: The books are defined as `draggable``DIV` elements. Each element is declared with a background image corresponding to the `wrapping` paperwith no text between the `<div>` and `</div>`. The `ID`fields correspond to the wrapping paper.
Lines 56–81: These contain JavaScript to make it all work.
* Lines 57–67: This JavaScript object contains the book definitions. The keys ('bows', `'boxes'`, etc.) correspond to the `ID` fields of the book `DIV` elements. The values ('Untamed by Glennon Doyle', `"The Heart's Invisible Furies by John Boyne"`, etc.) are the book titles and authors.
Lines 68–79: This JavaScript jQuery UI function defines the `droppable` functionality to be attached to HTML elements whose class is `drop`pable.
Lines 69–75: When a `draggable` element is dropped onto a droppable element, thefunction drop is called.
Line 70: The element variable is assigned the draggable object that was dropped (this will be a `<div id="..." class="draggable"...></div>` element.
Line 71: The wrapping variable is assigned the value of the `ID` field in the draggable object.
Line 72: This line is commented `out`, but while I was learning and testing, calls to `alert()` were useful.
* Line 73: This reassigns the draggable object's background image to a bland image on which text can be read; part 1 of unwrapping is getting rid of the wrapping paper.
* Line 74: This sets the text of the draggable object to the title of the book, looked up in the book's object using the draggable object's ID; part 2 of the unwrapping is showing the book title and author.
Lines 76–78: For a while, I thought I wanted something to happen when a draggable object was removed from a droppable object (e.g., when a club member stole a book), which would require using the out function in a droppable object. Eventually, I decided not to do anything. But, this could note that the book was stolen and make it "unstealable" for one turn; or it could show a status line that says something like: "Wanda's book Blah Blah by Joe Blogs was stolen, and she needs to choose another."
Line 80: This JavaScript jQuery UI function defines the draggable functionality to be attached to HTML elements whose class is draggable. In my case, the default behavior was all I needed.
Libraries like jQuery and jQuery UI are incredibly helpful when trying to do something complicated in JavaScript. Look at the `$().draggable()` and `$().droppable()` functions, for example:
The `".draggable"` allows associating the `draggable()` function with any HTML element whose class is "draggable."The `draggable()` function comes with all sorts of useful behavior about picking, dragging, and releasing a draggable HTML element.
If you haven't spent much time with jQuery, I really like the book [jQuery in Action][9] by Bear Bibeault, Yehuda Katz, and Aurelio De Rosa. Similarly, [jQuery UI in Action][10] by TJ VanToll is a great help with the jQuery UI (where draggable and droppable come from).
Of course, there are many other JavaScript libraries, frameworks, and what-nots around to do good stuff in the user interface. I haven't really started to explore all that jQuery and jQuery UI offer, and I want to play around with the rest to see what can be done.