📜 ⬆️ ⬇️

Developing the bottom menu in HTML5

image

Let's talk about the lower navigation sites. I am sure that you have seen it many times (on various sites). As a rule, it is three-four columns of the menu with various links. Today I would like to show you a design that you can use to create a lower menu. The main goal of this development is to prepare static HTML code (as a cache file) for embedding in the lower part of the site. If you are interested in such a topic, then I will tell you about creating a good, convenient menu. This manual is divided into 2 parts, today I will tell you about the first part: a user interface with the ability to drag and drop blocks.

For starters, I advise you to download the source files and run the demo in a new tab for better understanding.
')
DEMO
Source files


So let's start developing

Step 1. HTML


intex.html
<div class="actions"> Actions: <button id="preview" disabled>Preview</button> <button id="add_col">Add Column</button> </div> <div class="actions">Columns (with active elements)</div> <div class="columns"> <div class="column" id="drop_1" droppable="true"><img src="" onclick="removeColumn(this)" /></div> <div class="column" id="drop_2" droppable="true"><img src="" onclick="removeColumn(this)" /></div> <div class="column" id="drop_3" droppable="true"><img src="" onclick="removeColumn(this)" /></div> </div> <div style="clear:both"></div> <div class="actions">All (inactive) elements. You can drag these elements into columns.</div> <div class="inactive" droppable="true"> <a id="1" draggable="true">Link 1</a> <a id="2" draggable="true">Link 2</a> <a id="3" draggable="true">Link 3</a> <a id="4" draggable="true">Link 4</a> <a id="5" draggable="true">Link 5</a> <a id="6" draggable="true">Link 6</a> <a id="7" draggable="true">Link 7</a> <a id="8" draggable="true">Link 8</a> <a id="9" draggable="true">Link 9</a> <a id="10" draggable="true">Link 10</a> <a id="11" draggable="true">Link 11</a> <a id="12" draggable="true">Link 12</a> </div> <script src="js/main.js"></script> 


There are three main parts: a block with actions, a block with active columns and a block with inactive elements. All elements can be dragged between the columns. We can also add and remove our columns.

Step 2. CSS


Now it's time to add style to our menu.

 /* menu builder styles */ .actions { border: 1px solid #CCCCCC; font-size: 24px; margin: 20px auto 5px; overflow: hidden; padding: 10px; width: 900px; /* CSS3 Box sizing property */ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; } .actions button { cursor: pointer; font-size: 20px; padding: 5px; } .actions #add_col { float: right; } .inactive { border: 1px dashed #ccc; margin: 0 auto; width: 900px; } .inactive a { border-color: #FFFFFF; border-style: solid; border-width: 8px 8px 20px; cursor: pointer; display: inline-block; font-size: 20px; height: 20px; margin: 10px; opacity: 1; position: relative; text-align: center; width: 180px; -khtml-user-drag: element; /* CSS3 Prevent selections */ -moz-user-select: none; -webkit-user-select: none; -khtml-user-select: none; user-select: none; /* CSS3 Box Shadow */ -webkit-box-shadow: 2px 2px 4px #444; -o-box-shadow: 2px 2px 4px #444; box-shadow: 2px 2px 4px #444; } .inactive a.hidden { height: 0; margin: 0; opacity: 0; width: 0; } .columns { margin: 0 auto; overflow: hidden; width: 900px; } .column { border: 2px dashed #ccc; float: left; min-height: 100px; padding: 10px; position: relative; width: 33.3%; /* CSS3 Box sizing property */ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; } .column a { border-color: #FFFFFF; border-style: solid; border-width: 4px 4px 10px; cursor: pointer; display: block; font-size: 16px; height: 30px; margin-bottom: 15px; opacity: 1; position: relative; text-align: center; -khtml-user-drag: element; -webkit-user-drag: element; /* CSS3 Prevent selections */ -moz-user-select: none; -webkit-user-select: none; -khtml-user-select: none; user-select: none; /* CSS3 Box Shadow */ -webkit-box-shadow: 2px 2px 4px #444; -o-box-shadow: 2px 2px 4px #444; box-shadow: 2px 2px 4px #444; /* CSS3 Box sizing property */ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; } .column img { cursor: pointer; position: absolute; right: 2px; top: 2px; z-index: 5; } 


Step 3. JS


js / main.js

 // add event handler realization var addEvent = (function () { if (document.addEventListener) { return function (el, type, fn) { if (el && el.nodeName || el === window) { el.addEventListener(type, fn, false); } else if (el && el.length) { for (var i = 0; i < el.length; i++) { addEvent(el[i], type, fn); } } }; } else { return function (el, type, fn) { if (el && el.nodeName || el === window) { el.attachEvent('on' + type, function () { return fn.call(el, window.event); }); } else if (el && el.length) { for (var i = 0; i < el.length; i++) { addEvent(el[i], type, fn); } } }; } })(); // update handlers for draggable objects function updateHandlerDrag() { var dragItems = document.querySelectorAll('[draggable=true]'); for (var i = 0; i < dragItems.length; i++) { // dragstart event handler addEvent(dragItems[i], 'dragstart', function (event) { event.dataTransfer.setData('obj_id', this.id); return false; }); } } // update handlers for droppable objects function updateHandlerDrop() { var dropAreas = document.querySelectorAll('[droppable=true]'); // dragover event handler addEvent(dropAreas, 'dragover', function (event) { if (event.preventDefault) event.preventDefault(); this.style.borderColor = "#000"; return false; }); // dragleave event handler addEvent(dropAreas, 'dragleave', function (event) { if (event.preventDefault) event.preventDefault(); this.style.borderColor = "#ccc"; return false; }); // dragenter event handler addEvent(dropAreas, 'dragenter', function (event) { if (event.preventDefault) event.preventDefault(); return false; }); // drop event handler addEvent(dropAreas, 'drop', function (event) { if (event.preventDefault) event.preventDefault(); // get dropped object var iObj = event.dataTransfer.getData('obj_id'); var oldObj = document.getElementById(iObj); // get inner text var linkText = oldObj.innerHTML; oldObj.className += 'hidden'; // remove object from DOM oldObj.parentNode.removeChild(oldObj); // add similar object in another place this.innerHTML += '<a id="'+iObj+'" draggable="true">'+linkText+'</a>'; // and update event handlers updateHandlerDrag(); this.style.borderColor = "#ccc"; return false; }); } // add column button var addColBtn = document.querySelectorAll('#add_col'); addEvent(addColBtn, 'click', function (event) { if (event.preventDefault) event.preventDefault(); // recalculate widths for columns var oCols = document.querySelector('div.columns'); var iChilds = oCols.childElementCount + 1; var dWidth = 100 / iChilds; // add single column oCols.innerHTML += '<div class="column" id="drop_'+(iChilds+1)+'" droppable="true"><img src="" onclick="removeColumn(this)" /></div>'; // set new widths for (var i = 0; i < iChilds; i++) { oCols.children[i].style.width = dWidth + '%'; } // update handlers updateHandlerDrop(); return false; }); // remove columns function removeColumn(obj) { var oParent = obj.parentNode; // move object to inactive area var oInactive = document.querySelector('div.inactive'); for (var i = 0; i < oParent.childNodes.length; i++) { if (oParent.childNodes[i].nodeType == document.ELEMENT_NODE && oParent.childNodes[i].tagName == 'A') { oInactive.innerHTML += '<a id="'+oParent.childNodes[i].id+'" draggable="true">'+oParent.childNodes[i].innerHTML+'</a>'; } } // remove column oParent.parentElement.removeChild(oParent); // recalculate widths for columns var oCols = document.querySelector('div.columns'); var iChilds = oCols.childElementCount; var dWidth = 100 / iChilds; // set new widths for (var i = 0; i < iChilds; i++) { oCols.children[i].id = 'drop_' + (i + 1); oCols.children[i].style.width = dWidth + '%'; } // update handlers updateHandlerDrop(); updateHandlerDrag(); } // update handlers updateHandlerDrag(); updateHandlerDrop(); 


Here we used a lot of event handlers. At the beginning, the script updates various handlers for all drag and drop objects. When moving between blocks (from the bottom area), we have to recreate the objects in the top area and update the event handlers. In the case when we need to delete a column, we need to move the object back to the lower inactive area, which contains a list of all possible elements.

Conclusion


That's all, today we have implemented the first half of our menu building with drag and drop functions. Hope our guide helped you. Feel free to share your knowledge with friends. Good luck!

DEMO
Source files

UPD: Since this article has received a lot of negative opinions, the continuation will not be published on Habré, but if anyone is interested, you can read it here.

Source: https://habr.com/ru/post/143944/


All Articles