diff --git a/sources/tech/20210123 How I programmed a virtual gift exchange.md b/sources/tech/20210123 How I programmed a virtual gift exchange.md new file mode 100644 index 0000000000..446c1b50c2 --- /dev/null +++ b/sources/tech/20210123 How I programmed a virtual gift exchange.md @@ -0,0 +1,237 @@ +[#]: collector: (lujun9972) +[#]: translator: ( ) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) +[#]: subject: (How I programmed a virtual gift exchange) +[#]: via: (https://opensource.com/article/21/1/open-source-gift-exchange) +[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen) + +How I programmed a virtual gift exchange +====== +A book club takes its annual gift exchange online with the help of HTML, +CSS, and JavaScript. +![Package wrapped with brown paper and red bow][1] + +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: + + 1. Each person buys a book and wraps it up. + 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. + + + +### Designing the virtual book 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 book would unwrap (and stay unwrapped). I needed some "wrapping paper," so I used this source of [free-to-use images][2]. + +I took screenshots of the patterns I liked and used [GIMP][3] to scale the images to the right width and height. + +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: + +![Virtual book exchange][4] + +(Chris Hermansen, [CC BY-SA 4.0][5]) + +There are nine book club members: Wanda, Carlos, Bill, and so on. There are also nine fairly ugly wrapped parcels. + +Let's say Wanda goes first and chooses the flower wrapping paper. The host clicks and drags that parcel to Wanda's name, and the parcel unwraps: + +![Virtual book exchange][6] + +(Chris Hermansen, [CC BY-SA 4.0][5]) + +Whoops! That title and author are a bit too long to fit on the book's "cover." Oh well, I'll fix that in the next version. + +Carlos is next. He decides he really wants to read that book, so he steals it. Wanda then chooses the paisley pattern, and the screen looks like this: + +![Virtual book exchange][7] + +(Chris Hermansen, [CC BY-SA 4.0][5]) + +And so on until the exchange ends. + +### The code + +So what about the code? Here it is: + + +``` + 1 <!doctype html> + 2 <[html][8] lang="en"> + 3 <[head][9]> + 4 <[meta][10] charset="utf-8"> + 5 <[title][11]>Book Exchange</[title][11]> + 6 <[link][12] rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css"> + 7 <[style][13]> + 8 .draggable { + 9 float: left; + 10 width: 90px; + 11 height: 90px; + 12 background: #ccc; + 13 padding: 5px; + 14 margin: 5px 5px 5px 0; + 15 } + 16 .droppable { + 17 float: left; + 18 width: 100px; + 19 height: 125px; + 20 background: #999; + 21 color: #fff; + 22 padding: 10px; + 23 margin: 10px 10px 10px 0; + 24 } + 25 </[style][13]> + 26 <[script][14] src="[https://code.jquery.com/jquery-1.12.4.js"\>\][15]</[script][14]> + 27 <[script][14] src="[https://code.jquery.com/ui/1.12.1/jquery-ui.js"\>\][16]</[script][14]> + 28 </[head][9]> + 29 <[body][17]> + 30 <[h1][18] style="color:#1a1aff;">Raffles Book Club Remote Gift Exchange</[h1][18]> + 31 <[h2][19] style="color:#aa0a0a;">The players, in random order, and the luxurious gifts, wrapped:</[h2][19]> + 32 + 33 <[div][20]> + 34 <[div][20] id="wanda" class="droppable">Wanda</[div][20]> + 35 <[div][20] id="carlos" class="droppable">Carlos</[div][20]> + 36 <[div][20] id="bill" class="droppable">Bill</[div][20]> + 37 <[div][20] id="arlette" class="droppable">Arlette</[div][20]> + 38 <[div][20] id="joanne" class="droppable">Joanne</[div][20]> + 39 <[div][20] id="aleks" class="droppable">Alekx</[div][20]> + 40 <[div][20] id="ermintrude" class="droppable">Ermintrude</[div][20]> + 41 <[div][20] id="walter" class="droppable">Walter</[div][20]> + 42 <[div][20] id="hilary" class="droppable">Hilary</[div][20]> + 43 </[div][20]> + 44 <[div][20]> + 45 <[div][20] id="bows" class="draggable" style="background-image: url('bows.png');"></[div][20]> + 46 <[div][20] id="boxes" class="draggable" style="background-image: url('boxes.png');"></[div][20]> + 47 <[div][20] id="circles" class="draggable" style="background-image: url('circles.png');"></[div][20]> + 48 <[div][20] id="gerbers" class="draggable" style="background-image: url('gerbers.png');"></[div][20]> + 49 <[div][20] id="hippie" class="draggable" style="background-image: url('hippie.png');"></[div][20]> + 50 <[div][20] id="lattice" class="draggable" style="background-image: url('lattice.png');"></[div][20]> + 51 <[div][20] id="nautical" class="draggable" style="background-image: url('nautical.png');"></[div][20]> + 52 <[div][20] id="splodges" class="draggable" style="background-image: url('splodges.png');"></[div][20]> + 53 <[div][20] id="ugly" class="draggable" style="background-image: url('ugly.png');"></[div][20]> + 54 </[div][20]> + 55 + 56 <[script][14]> + 57 var books = { + 58 'bows': 'Untamed by Glennon Doyle', + 59 'boxes': "The Heart's Invisible Furies by John Boyne", + 60 'circles': 'The Great Halifax Explosion by John Bacon', + 61 'gerbers': 'Homes: A Refugee Story by Abu Bakr al Rabeeah, Winnie Yeung', + 62 'hippie': 'Before We Were Yours by Lisa Wingate', + 63 'lattice': "Hamnet and Judith by Maggie O'Farrell", + 64 'nautical': 'Shuggy Bain by Douglas Stewart', + 65 'splodges': 'Magdalena by Wade Davis', + 66 'ugly': 'Funny Boy by Shyam Selvadurai' + 67 }; + 68 $( ".droppable" ).droppable({ + 69 drop: function(event, ui) { + 70 var element = $(ui.draggable[0]); + 71 var wrapping = element.attr('id'); + 72 /* alert( $(this).text() + " got " + wrapping); */ + 73 $(ui.draggable[0]).css("background-image","url(book_cover.png)"); + 74 $(ui.draggable[0]).text(books[wrapping]); + 75 }, + 76 out: function() { + 77 /* alert( $(this).text() + " lost it" ); */ + 78 } + 79 }); + 80 $( ".draggable" ).draggable(); + 81 </[script][14]> + 82 + 83 </[body][17]> + 84 </[html][8]> +``` + +### Breaking it down + +Let's go over this code bit by bit. + + * **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:** These couple 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 paper with no text between the `