├── LICENSE ├── README.md ├── index.html ├── itens ├── apple.gif ├── cobblestone.png ├── diamond-pickaxe.png ├── diamond-sword.png ├── diamond.png ├── iron.png ├── steak.png └── wood.png ├── script.js └── styles.css /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 lavininhamelo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Minecraft Inventory in Javascript 3 |

4 | 5 |

6 | 7 | Repository size 8 | 9 | 10 | Made by Lavínia Melo 11 | 12 | 13 | 14 | GitHub last commit 15 | 16 | 17 | License 18 | 19 | Stargazers 20 | 21 |

22 | 23 | ## 💻 Project 24 | 25 | An implementation of the interface and the functionalities of the minecraft inventory, developed in javascript vanilla and CSS as a personal challenge. 26 | 27 | [![Minecraft Inventory](https://i.imgur.com/QtTYvuo.gif)](https://codepen.io/lavininhamelo/full/NWxPKLJ) 28 | 29 | ## 🤔 How to contribute 30 | 31 | - Make a fork; 32 | - Create a branck with your feature: `git checkout -b my-feature`; 33 | - Commit changes: `git commit -m 'feat: My new feature'`; 34 | - Make a push to your branch: `git push origin my-feature`. 35 | 36 | After merging your receipt request to done, you can delete a branch from yours. 37 | 38 | ## :memo: License 39 | 40 | This project is under the MIT license. See the [LICENSE](https://github.com/lavininhamelo/minecraft-inventory-in-javascript/blob/master/LICENSE) for details. 41 | 42 | Made by Lavínia Melo :wave: [Get in touch!](https://www.linkedin.com/in/laviniamelo/) 43 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Minecraft Inventory 8 | 9 | 10 | 11 |
12 |
13 |

Inventory

14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 | 33 27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | 39 |
40 | 3 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 |
53 | 14 54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 68 |
1
69 |
70 |
71 |
72 |
73 | 74 |
12
75 |
76 |
77 |
78 |
79 | 80 |
81 | 33 82 |
83 |
84 |
85 |
86 |
87 | 88 |
89 | 8 90 |
91 |
92 |
93 |
94 |
95 | 96 |
97 | 12 98 |
99 |
100 |
101 |
102 |
103 | 104 |
1
105 |
106 |
107 |
108 |
109 | 110 |
111 | 32 112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | by Lavínia Melo 123 |
124 |
125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /itens/apple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/apple.gif -------------------------------------------------------------------------------- /itens/cobblestone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/cobblestone.png -------------------------------------------------------------------------------- /itens/diamond-pickaxe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/diamond-pickaxe.png -------------------------------------------------------------------------------- /itens/diamond-sword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/diamond-sword.png -------------------------------------------------------------------------------- /itens/diamond.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/diamond.png -------------------------------------------------------------------------------- /itens/iron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/iron.png -------------------------------------------------------------------------------- /itens/steak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/steak.png -------------------------------------------------------------------------------- /itens/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavininhamelo/minecraft-inventory-in-javascript/3256e2df0b4c7a850eee824e92ba02ac0a053302/itens/wood.png -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | let current_slot = null; 2 | let status_click = false; 3 | let current_itemId = null; 4 | let current_itemType = null; 5 | let current_itemValue = null; 6 | 7 | let body = document.getElementsByTagName('body'); 8 | 9 | const items = document.querySelectorAll('.item'); 10 | 11 | items.forEach((item) => { 12 | item.addEventListener('click', moveItem); 13 | item.addEventListener('contextmenu', moveItem); 14 | item.setAttribute('draggable', false); 15 | }); 16 | 17 | function moveItem() { 18 | event.preventDefault(); 19 | 20 | const item = this; 21 | 22 | let ghostItem = item.cloneNode(true); 23 | ghostItem.setAttribute('class', 'ghostItem'); 24 | item.classList.add('invisible'); 25 | 26 | let shiftX = ghostItem.getBoundingClientRect().left + 20; 27 | let shiftY = ghostItem.getBoundingClientRect().top + 20; 28 | 29 | ghostItem.style.position = 'absolute'; 30 | ghostItem.style.zIndex = 1000; 31 | document.body.append(ghostItem); 32 | 33 | ghostItem.onclick = function (event) { 34 | if (current_itemId && current_itemId != item.parentNode.id) { 35 | let area = document.getElementById(current_itemId); 36 | let free_space = !!!area.firstElementChild; 37 | 38 | if (free_space) { 39 | area.append(item); 40 | } else if (current_itemType == item.id) { 41 | let destiny = area.firstElementChild.lastElementChild.innerHTML; 42 | let origin = item.lastElementChild.innerHTML; 43 | let total = parseInt(destiny) + parseInt(origin); 44 | area.firstElementChild.lastElementChild.innerHTML = total; 45 | item.remove(); 46 | } else { 47 | item.parentNode.append(area.firstElementChild); 48 | area.append(item); 49 | } 50 | } 51 | item && item.classList.remove('invisible'); 52 | ghostItem.remove(); 53 | status_click = !status_click; 54 | }; 55 | 56 | ghostItem.oncontextmenu = function (event) { 57 | event.preventDefault(); 58 | if (current_itemId && current_itemId != item.parentNode.id) { 59 | let area = document.getElementById(current_itemId); 60 | let free_space = !!!area.firstElementChild; 61 | if (free_space) { 62 | let newItem = item.cloneNode(true); 63 | newItem.addEventListener('click', moveItem); 64 | newItem.addEventListener('contextmenu', moveItem); 65 | newItem.setAttribute('draggable', false); 66 | if (parseInt(item.lastElementChild.innerHTML) == 1) { 67 | ghostItem.remove(); 68 | status_click = !status_click; 69 | item.remove(); 70 | } else { 71 | item.lastElementChild.innerHTML = 72 | parseInt(item.lastElementChild.innerHTML) - 1; 73 | ghostItem.lastElementChild.innerHTML = 74 | parseInt(ghostItem.lastElementChild.innerHTML) - 1; 75 | } 76 | newItem.lastElementChild.innerHTML = 1; 77 | area.append(newItem); 78 | newItem.classList.remove('invisible'); 79 | } else if (current_itemType == item.id) { 80 | if (parseInt(item.lastElementChild.innerHTML) == 1) { 81 | ghostItem.remove(); 82 | status_click = !status_click; 83 | item.remove(); 84 | } 85 | let destiny = parseInt( 86 | area.firstElementChild.lastElementChild.innerHTML 87 | ); 88 | let origin = parseInt(item.lastElementChild.innerHTML); 89 | let ghost = parseInt(ghostItem.lastElementChild.innerHTML); 90 | 91 | area.firstElementChild.lastElementChild.innerHTML = destiny + 1; 92 | item.lastElementChild.innerHTML = origin - 1; 93 | ghostItem.lastElementChild.innerHTML = ghost - 1; 94 | } 95 | } 96 | }; 97 | 98 | status_click = !status_click; 99 | 100 | if (status_click) { 101 | moveAt(event.pageX, event.pageY); 102 | } 103 | 104 | function moveAt(pageX, pageY) { 105 | ghostItem.style.left = pageX - shiftX + 'px'; 106 | ghostItem.style.top = pageY - shiftY + 'px'; 107 | } 108 | 109 | function onMouseMove(event) { 110 | if (status_click) { 111 | moveAt(event.pageX, event.pageY); 112 | } 113 | ghostItem.hidden = true; 114 | let elemBelow = document.elementFromPoint(event.clientX, event.clientY); 115 | ghostItem.hidden = false; 116 | 117 | if (!elemBelow) return; 118 | let droppableBelow = elemBelow.closest('.slot'); 119 | if (current_slot != droppableBelow) { 120 | if (current_slot) { 121 | leaveDroppable(current_slot); 122 | } 123 | current_slot = droppableBelow; 124 | if (current_slot) { 125 | enterDroppable(current_slot); 126 | } 127 | } 128 | } 129 | 130 | document.addEventListener('mousemove', onMouseMove); 131 | } 132 | 133 | function enterDroppable(elem) { 134 | current_itemId = elem.id; 135 | if (elem.firstElementChild) { 136 | current_itemType = elem.firstElementChild.id; 137 | child = elem.firstElementChild; 138 | current_itemValue = child.lastElementChild.innerHTML; 139 | } 140 | } 141 | 142 | function leaveDroppable(elem) { 143 | current_itemId = null; 144 | current_itemType = null; 145 | current_itemValue = null; 146 | free_space = false; 147 | } 148 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=VT323&display=swap'); 2 | 3 | @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); 4 | 5 | body { 6 | background: #ccc; 7 | box-sizing: border-box; 8 | width: 100%; 9 | height: 80vh; 10 | } 11 | 12 | .content { 13 | width: 100%; 14 | height: 100%; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | flex-direction: column; 19 | } 20 | 21 | .inventory { 22 | width: 335px; 23 | height: 200px; 24 | background: #c6c6c6; 25 | border-radius: 3px; 26 | box-shadow: 5px 5px 0px #555555, inset 4px 4px 0px #fefefe; 27 | padding-top: 5px; 28 | padding-left: 5px; 29 | margin-bottom: 10px; 30 | } 31 | 32 | h1 { 33 | margin: 5px 10px; 34 | font-family: 'VT323', monospace; 35 | font-size: 24px; 36 | color: #404040; 37 | } 38 | 39 | .number { 40 | font-family: 'VT323', monospace; 41 | font-size: 24px; 42 | color: #fefefe; 43 | position: relative; 44 | text-shadow: #333 1px 2px 1px; 45 | top: -16px; 46 | right: -8px; 47 | cursor: default; 48 | } 49 | 50 | .slot { 51 | width: 35px; 52 | height: 35px; 53 | display: flex; 54 | justify-content: center; 55 | background: #8b8b8b; 56 | box-shadow: inset 1.5px 1.5px 0px rgba(55, 55, 55, 0.8), 57 | inset -2px -2px 0px #ffffff; 58 | } 59 | 60 | .slotSpace { 61 | margin: 10px 10px; 62 | display: flex; 63 | flex-wrap: wrap; 64 | } 65 | 66 | .invisible { 67 | visibility: hidden; 68 | } 69 | 70 | .item { 71 | margin: 2px; 72 | display: flex; 73 | flex-direction: column; 74 | align-items: center; 75 | width: 30px; 76 | height: 30px; 77 | } 78 | 79 | .item img { 80 | width: 28px; 81 | } 82 | 83 | .ghostItem img { 84 | width: 28px; 85 | } 86 | .ghostItem .number { 87 | top: -20px; 88 | right: -13px; 89 | } 90 | 91 | ::selection { 92 | background: transparent; 93 | } 94 | 95 | ::-moz-selection { 96 | background: transparent; 97 | } 98 | 99 | .copy { 100 | font-family: 'VT323', monospace; 101 | font-size: 18px; 102 | width: 350px; 103 | display: flex; 104 | justify-content: flex-end; 105 | color: #333; 106 | } 107 | 108 | a { 109 | color: inherit; 110 | text-decoration: inherit; 111 | } 112 | --------------------------------------------------------------------------------