diff options
-rw-r--r-- | about.html | 6 | ||||
-rw-r--r-- | play.css | 113 | ||||
-rw-r--r-- | play.html | 115 | ||||
-rw-r--r-- | play.js | 92 |
4 files changed, 183 insertions, 143 deletions
@@ -9,16 +9,16 @@ frontier, build fortification networks through the harsh wilderness, recruit Indian allies, besiege forts and fortresses, and deal with events occurring in Europe that are above and beyond your control. -<br clear="left"> <p> Designer: Volko Ruhnke. - -<p> +<br> Copyright © 2010 <a href="https://www.gmtgames.com/p-1045-wilderness-war-4th-printing.aspx">GMT Games, LLC</a>. <br> Cover art by Rodger B. MacGowan © 2001, 2013. +<br> +Programming © 2021 Tor Andersson. <ul> <li><a href="/wilderness-war/info/rulebook.html">Rulebook</a> @@ -5,7 +5,7 @@ body.France header.your_turn { background-color: lightskyblue; } body.Britain header.your_turn { background-color: salmon; } #role_France, #log .h2.france { background-color: #bdf; } #role_Britain, #log .h2.britain { background-color: #fcb; } -aside { width: 220px; } +aside { min-width: 220px; } :root { --highlight-color: yellow; @@ -17,6 +17,11 @@ aside { width: 220px; } .checked::before { content: "\2714 " } .unchecked::before { content: "\2714 "; color:transparent; } +@media (max-width: 600px) { + #stack_menu { display: none } + #piece_button { display: none } +} + /* LOG */ #log { background-color: floralwhite; } @@ -53,11 +58,21 @@ aside { width: 220px; } /* CARDS */ .hand { - margin: 15px; + margin: 10px auto; + padding: 15px; display: flex; + gap: 20px; flex-wrap: wrap; justify-content: center; - min-height: 370px; + min-width: calc(242px * 3 + 30px + 20px * 2); + max-width: calc(2550px - 30px); + min-height: 340px; +} + +@media (max-width: 800px) { + .hand { + min-width: calc(2550px - 30px); + } } .card { @@ -85,7 +100,6 @@ aside { width: 220px; } transform: translateY(-10px); } -.hand .card { margin: 10px; } .hand .card { display: none; } .hand .card.show { display: block; } @@ -101,11 +115,17 @@ aside { width: 220px; } margin: 0 auto; } +@media (max-height: 800px) { + .card_info { + display: none; + } +} + #tooltip { display: none; pointer-events: none; position: fixed; - z-index: 300; + z-index: 600; right: 240px; top: 60px; } @@ -114,10 +134,21 @@ aside { width: 220px; } display: block; } +@media (max-width: 800px) { + #tooltip { + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + } +} + /* CARD LIST DIALOGS */ .card_list_dialog { position: fixed; + background-color: floralwhite; width: 300px; border: 1px solid black; box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.5); @@ -141,8 +172,7 @@ aside { width: 220px; } } .card_list_body { padding: 5px 10px; - background-color: floralwhite; - overflow-y: scroll; + overflow-y: auto; max-height: 500px; } .card_list_body div { @@ -150,29 +180,37 @@ aside { width: 220px; } margin-left: 30px; } -#removed { top: 100px; left: 100px; z-index: 98; } -#discard { top: 100px; left: 425px; z-index: 99; } +#removed { top: 120px; left: 50px; z-index: 498; } +#discard { top: 145px; left: 75px; z-index: 499; } + +@media (max-width: 400px) { + .card_list_dialog { + position: static; + grid-column: 1; + grid-row: 2; + width: auto; + box-shadow: none; + border: none; + } + .card_list_body { + max-height: none; + } +} /* CARD MENU */ #popup { - position: fixed; - user-select: none; - background-color: white; - left: 10px; - top: 100px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.3); - z-index: 300; - min-width: 20ex; - white-space: nowrap; - display: none; - border: 1px solid black; + box-shadow: 2px 2px 4px #0004; + min-width: 160px; + max-width: 250px; } -#popup div { padding: 3pt 8pt; color: gray; display: none; } -#popup div.enabled { color: black; display: block; } -#popup div.enabled:hover { background-color: black; color: white; } -#popup div.always { display: block; } -body:not(.shift) #popup #menu_discard { display: none; } + +#popup li.title { + text-align: center; + white-space: normal; +} + +body:not(.shift) #popup li[data-action="discard"] { display: none; } /* MAP */ @@ -615,28 +653,3 @@ body.bevel .unit.french.highlight{box-shadow:0 0 0 1px #29607a,0 0 0 4px var(--h body.bevel .leader.selected{box-shadow:0 0 0 3px var(--selected-color)} body.bevel .unit.british.selected{box-shadow:0 0 0 3px var(--selected-color)} body.bevel .unit.french.selected{box-shadow:0 0 0 3px var(--selected-color)} - -/* MOBILE PHONE LAYOUT */ - -@media (max-width: 640px) { - .hand .card { - width: 120px; - height: 168px; - border-radius: 8px; - } - .hand { - min-height: 168px; - } - #tooltip { - top: 10px; - right: 10px; - } - #removed, #discard { - position: static; - box-shadow: none; - border-top: none; - width: auto; - } - #removed { grid-row: 3; } - #discard { grid-row: 4; } -} @@ -1,15 +1,16 @@ <!DOCTYPE html> <html lang="en"> <head> -<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"> +<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, interactive-widget=resizes-content, viewport-fit=content, viewport-fit=cover"> +<meta name="theme-color" content="#444"> <meta charset="utf-8"> <title>WILDERNESS WAR</title> <link rel="icon" href="logo.png"> <link rel="stylesheet" href="/fonts/fonts.css"> -<link rel="stylesheet" href="/common/play.css"> +<link rel="stylesheet" href="/common/client.css"> <link rel="stylesheet" href="play.css"> <link rel="stylesheet" href="images.css"> -<script defer src="/common/play.js"></script> +<script defer src="/common/client.js"></script> <script defer src="data.js"></script> <script defer src="play.js"></script> </head> @@ -17,14 +18,16 @@ <div id="tooltip"></div> -<div id="popup" onmouseleave="hide_popup_menu()"> -<div id="menu_play_event" class="always" onclick="on_play_event()">Play Event</div> -<div id="menu_activate_force" class="always" onclick="on_activate_force()">Activate force</div> -<div id="menu_activate_individually" class="always" onclick="on_activate_individually()">Activate individually</div> -<div id="menu_construct_stockades" class="always" onclick="on_construct_stockades()">Construct stockades</div> -<div id="menu_construct_forts" class="always" onclick="on_construct_forts()">Construct forts</div> -<div id="menu_discard" onclick="on_discard()">Discard</div> -</div> +<menu id="popup"> + <li class="title">CARD + <li class="separator"> + <li data-action="play_event"> 🎴 Play Event + <li data-action="activate_force"> 👤 Activate force + <li data-action="activate_individually"> 👥 Activate individually + <li data-action="construct_stockades"> 🔨 Construct stockades + <li data-action="construct_forts"> 🔨 Construct forts + <li data-action="discard"> 🚫 Discard +</menu> <div id="removed" class="card_list_dialog hide"> <div id="removed_x" class="card_list_x" onclick="hide_card_list('removed')">❌</div> @@ -40,53 +43,49 @@ <header> <div id="toolbar"> - <div class="menu"> - <div class="menu_title"><img src="/images/cog.svg"></div> - <div class="menu_popup"> - <a class="menu_item" href="info/rulebook.html" target="_blank">Rulebook</a> - <a class="menu_item" href="info/playbook.html" target="_blank">Playbook</a> - <a class="menu_item" href="info/charts.html" target="_blank">Charts & Tables</a> - <a class="menu_item" href="info/cards.html" target="_blank">Cards</a> - <a class="menu_item" href="info/pieces.html" target="_blank">Leaders & Units</a> - <div class="resign menu_separator"></div> - <div class="resign menu_item" onclick="confirm_resign()">Resign</div> - </div> - </div> - <div class="menu"> - <div class="menu_title"><img src="/images/stack.svg"></div> - <div class="menu_popup"> - <div id="stack_v" class="menu_item unchecked" onclick="set_layout(0)">Vertical</div> - <div id="stack_h" class="menu_item unchecked" onclick="set_layout(1)">Horizontal</div> - <div id="stack_d" class="menu_item unchecked" onclick="set_layout(2)">Diagonal</div> - <div class="menu_separator"></div> - <div id="mouse_focus" class="menu_item unchecked" onclick="set_mouse_focus()">Mouse-focus</div> - <div class="menu_separator"></div> - <div id="style_bevel" class="menu_item unchecked" onclick="set_style('bevel')">Beveled</div> - <div id="style_flat" class="menu_item unchecked" onclick="set_style('flat')">Flat</div> - </div> - </div> - <div class="menu"> - <div class="menu_title"><img src="/images/wooden-sign.svg"></div> - <div class="menu_popup"> - <div class="menu_item" onclick="send_query('supply')">Supply lines</div> - <div class="menu_item" onclick="send_query('removed')">Removed</div> - <div class="menu_item" onclick="send_query('discard')">Discard</div> - </div> - </div> - <div class="icon_button" onclick="toggle_counters()"><img src="/images/earth-america.svg"></div> - <div class="icon_button" onclick="toggle_zoom()"><img src="/images/magnifying-glass.svg"></div> - <div class="icon_button" onclick="toggle_log()"><img src="/images/scroll-quill.svg"></div> - <div id="demolish_menu" class="menu hide"> - <div class="menu_title"><img src="/images/dig-dug.svg"></div> - <div class="menu_popup"> - <div id="demolish_fort" class="menu_item" onclick="send_action('demolish_fort')">Demolish fort</div> - <div id="demolish_stockade" class="menu_item" onclick="send_action('demolish_stockade')">Demolish stockade</div> - <div id="demolish_fieldworks" class="menu_item" onclick="send_action('demolish_fieldworks')">Demolish fieldworks</div> - </div> - </div> + <details> + <summary><img src="/images/cog.svg"></summary> + <menu> + <li><a href="info/rulebook.html" target="_blank">Rulebook</a> + <li><a href="info/playbook.html" target="_blank">Playbook</a> + <li><a href="info/charts.html" target="_blank">Charts & Tables</a> + <li><a href="info/cards.html" target="_blank">Cards</a> + <li><a href="info/pieces.html" target="_blank">Leaders & Units</a> + <li class="resign separator"> + <li class="resign" onclick="confirm_resign()">Resign + </menu> + </details> + <details id="stack_menu"> + <summary><img src="/images/stack.svg"></summary> + <menu> + <li class="unchecked" id="stack_v" onclick="set_layout(0)"> Vertical + <li class="unchecked" id="stack_h" onclick="set_layout(1)"> Horizontal + <li class="unchecked" id="stack_d" onclick="set_layout(2)"> Diagonal + <li class="separator"> + <li class="unchecked" id="mouse_focus" onclick="set_mouse_focus()"> Mouse-focus + <li class="separator"> + <li class="unchecked" id="style_bevel" onclick="set_style('bevel')"> Beveled + <li class="unchecked" id="style_flat" onclick="set_style('flat')"> Flat + </menu> + </details> + <details id="info_menu"> + <summary><img src="/images/wooden-sign.svg"></summary> + <menu> + <li onclick="send_query('supply')"> Supply lines + <li onclick="send_query('removed')"> Removed + <li onclick="send_query('discard')"> Discard + </menu> + </details> + <button id="piece_button" onclick="toggle_counters()"><img src="/images/earth-america.svg"></button> + <details id="demolish_menu" class="hide"> + <summary><img src="/images/dig-dug.svg"></summary> + <menu> + <li id="demolish_fort" onclick="send_action('demolish_fort')"> Demolish fort + <li id="demolish_stockade" onclick="send_action('demolish_stockade')"> Demolish stockade + <li id="demolish_fieldworks" onclick="send_action('demolish_fieldworks')"> Demolish fieldworks + </menu> + </details> </div> - <div id="prompt"></div> - <div id="actions"></div> </header> <aside> @@ -110,7 +109,7 @@ <div id="log"></div> </aside> -<main> +<main data-max-zoom="2" onclick="hide_popup_menu()"> <div id="mapwrap"> <div id="map"> <div id="events"> @@ -701,37 +701,68 @@ function on_blur_card(evt) { // CARD MENU -const card_action_menu = [ - 'play_event', - 'activate_force', - 'activate_individually', - 'construct_stockades', - 'construct_forts', - 'discard', -] +var card_action_menu = Array.from(document.getElementById("popup").querySelectorAll("li[data-action]")).map(e => e.dataset.action) + +function is_popup_menu_action(menu_id, target_id) { + let menu = document.getElementById(menu_id) + for (let item of menu.querySelectorAll("li")) { + let action = item.dataset.action + if (action) + return true + } + return false +} + +function show_popup_menu(evt, menu_id, target_id, title) { + let menu = document.getElementById(menu_id) + + let show = false + for (let item of menu.querySelectorAll("li")) { + let action = item.dataset.action + if (action) { + if (is_action(action, target_id)) { + show = true + item.classList.add("action") + item.classList.remove("disabled") + item.onclick = function () { + send_action(action, target_id) + hide_popup_menu() + evt.stopPropagation() + } + } else { + item.classList.remove("action") + item.classList.add("disabled") + item.onclick = null + } + } + } + + if (show) { + menu.onmouseleave = hide_popup_menu + menu.style.display = "block" + if (title) { + let item = menu.querySelector("li.title") + if (item) { + item.onclick = hide_popup_menu + item.textContent = title + } + } -let current_popup_card = 0 + let w = menu.clientWidth + let h = menu.clientHeight + let x = Math.max(5, Math.min(evt.clientX - w / 2, window.innerWidth - w - 5)) + let y = Math.max(5, Math.min(evt.clientY - 12, window.innerHeight - h - 40)) + menu.style.left = x + "px" + menu.style.top = y + "px" -function show_popup_menu(evt, list) { - document.querySelectorAll("#popup div").forEach(e => e.classList.remove('enabled')) - for (let item of list) { - let e = document.getElementById("menu_" + item) - e.classList.add('enabled') + return true } - let popup = document.getElementById("popup") - popup.style.display = 'block' - popup.style.left = (evt.clientX-50) + "px" - popup.style.top = (evt.clientY-12) + "px" - cards[current_popup_card].element.classList.add("selected") + + return false } function hide_popup_menu() { - let popup = document.getElementById("popup") - popup.style.display = 'none' - if (current_popup_card) { - cards[current_popup_card].element.classList.remove("selected") - current_popup_card = 0 - } + document.getElementById("popup").style.display = "none" } function is_card_enabled(card) { @@ -744,20 +775,17 @@ function is_card_enabled(card) { return false } -function is_card_action(action, card) { +function is_action(action, card) { return view.actions && view.actions[action] && view.actions[action].includes(card) } function on_click_card(evt) { let card = evt.target.card - if (is_card_action('card', card)) { + if (is_action('card', card)) { send_action('card', card) } else { - let menu = card_action_menu.filter(a => is_card_action(a, card)) - if (menu.length > 0) { - current_popup_card = card - show_popup_menu(evt, menu) - } + show_popup_menu(evt, "popup", card, cards[card].name) + evt.stopPropagation() } } |