strong text
I have a box in a few boxes and placed inside each box for an hour.
I want to sort by using the box clock named item.
This sorting has three modes, the first ascending, the second descending, the third without sorting.
strong text
<body>
<style>
body{margin: 0 auto;padding: 0 auto;background: skyblue;}
.full-item{width: 800px;height: 600px;margin: 50px auto;background: grey;}
.full-item .button-item{width: 100%;height: 80px;background: #B33771;}
.full-item .button-item button{margin: 30px 45%;}
.full-item .item-sort{width: 100%;height: 500px;background: white;margin-top: 10px;}
.full-item .item-sort:first-child{margin-top: 10px;}
.full-item .item-sort .item{width: 90%;height: 140px;background: red;margin: 10px auto;}
.item-sort .item .pic{width: 30%;height: 100%;background: #3B3B98;float: left;}
.item-sort .item .time{width: 70%;height: 100%;background: #1B9CFC;float: right;}
.item-sort .item .time span{color: white;text-align: center;display: block;line-height: 100px;}
</style>
<div class="full-item">
<div class="button-item">
<button id="Sort-item">Sort by</button>
</div>
<div class="item-sort">
<div class="item">
<div class="pic"></div>
<div class="time"><span>15:20</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>13:10</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>18:40</span></div>
</div>
</div>
</div>
</body>
If the data is coming from JSON or other source, as with akbansa's recommendation, you should perform the sorting on the data first; otherwise, see below for an example of how you could reorder your elements:
const button = document.querySelector('#Sort-item')
// add handler
button.addEventListener('click', clickHandler)
// handler definition
function clickHandler(){
let container = document.querySelector('.item-sort')
let items = Array.from(container.querySelectorAll('.item-sort .item'))
// sort based on time
items = items.sort((a,b)=>{
let a_time = a.querySelector('.time span').textContent
let b_time = b.querySelector('.time span').textContent
return a_time > b_time ? 1 : -1
})
// apply the order
for(let item of items)
container.appendChild(item)
}
body {
margin: 0 auto;
padding: 0 auto;
background: skyblue;
}
.full-item {
width: 800px;
height: 600px;
margin: 50px auto;
background: grey;
}
.full-item .button-item {
width: 100%;
height: 80px;
background: #B33771;
}
.full-item .button-item button {
margin: 30px 45%;
}
.full-item .item-sort {
width: 100%;
height: 500px;
background: white;
margin-top: 10px;
}
.full-item .item-sort:first-child {
margin-top: 10px;
}
.full-item .item-sort .item {
width: 90%;
height: 140px;
background: red;
margin: 10px auto;
}
.item-sort .item .pic {
width: 30%;
height: 100%;
background: #3B3B98;
float: left;
}
.item-sort .item .time {
width: 70%;
height: 100%;
background: #1B9CFC;
float: right;
}
.item-sort .item .time span {
color: white;
text-align: center;
display: block;
line-height: 100px;
}
<div class="full-item">
<div class="button-item">
<button id="Sort-item">Sort by</button>
</div>
<div class="item-sort">
<div class="item">
<div class="pic"></div>
<div class="time"><span>15:20</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>13:10</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>18:40</span></div>
</div>
</div>
</div>
Update your html inside "button-item" class
<div class="button-item">
<p>Sort By </p>
<button id="sort-asc" onclick="app.sortAsc()">Asc</button>
<button id="sort-desc" onclick="app.sortDesc()">Desc</button>
<button id="reset" onclick="app.reset()">Reset</button>
</div>
Add to your scripts
var app = (function (){
var originalArr = []
var timeArr = []
var sortedArr = []
var objArr = []
var timeElements = document.querySelectorAll('.time')
var itemSortElement = document.querySelector('.item-sort')
for ( let timeEl of timeElements) {
// retrieving text from individual span element
let timeText = timeEl.children[0].innerText;
// retrieving parent node of div with class "time"
let timeParent = timeEl.parentNode
let obj = { text: timeText, parent: timeParent }
objArr.push(obj)
timeArr.push(timeText)
}
// copying all elements/ texts from "timeArr" array to "originalArr" array
// to keep track of original order of texts
originalArr = timeArr.slice()
function sortAsc () {
// sorting the retrieved texts in ascending order
sortedArr = timeArr.sort();
while (itemSortElement.hasChildNodes()) {
// removing all child elements of class "item-sort"
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < sortedArr.length; i++) {
let filteredObj = objArr.filter((obj) => sortedArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
function sortDesc () {
sortedArr = timeArr.sort().reverse();
while (itemSortElement.hasChildNodes()) {
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < sortedArr.length; i++) {
var filteredObj = objArr.filter((obj) => sortedArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
function reset () {
while (itemSortElement.hasChildNodes()) {
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < originalArr.length; i++) {
var filteredObj = objArr.filter((obj) => originalArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
return {
sortDesc,
sortAsc,
reset
}
})()
you can check it Demo
Related
I am trying to build a page:
Like This
When a div gets into the view on the screen, then a class gets added to the right side of the "table of contents", then when it's scrolled off the screen and another div shows up the class gets moved to the next "title" of the content.
So far I have a list of divs stacked on the top of each other and some basic JS but it does not work. I am not even sure if this is a good approach to get this done?
$(window).scroll(function(){
if ( $('#field-wrap1').offset().top <= 100 ) {
$('#slide-li1').addClass("active");
}else{
$('#slide-li1').removeClass("active");
}
});
JSFiddle
<!---
With this code it doesn't require editing the JavaScript
at all, only the HTML/CSS, it will apply the class .qqq_menu_active
to the active menu item and .qqq_section_active to the active section.
--->
<style>
* {
font-family: Arial;
margin: 0;
padding: 0;
}
body {
font-size: 10pt;
}
.qqq_container {
padding: 50px;
}
.qqq_menu {
position: fixed;
width: 200px;
left: 750px;
top: 50px;
}
.qqq_menu_item {
color: #333;
}
.qqq_menu_active {
font-size: 14pt;
font-weight: bold;
color: #000;
}
.qqq_section {
width: 600px;
padding: 25px;
color: #676767;
background-color: #fff;
}
.qqq_section_active {
color: #281c96;
background-color: #bdb6ff;
}
h1 {
padding-bottom: 20px;
}
</style>
<div class="qqq_menu">
<div class='qqq_menu_item'>section_1</div>
<div class='qqq_menu_item'>section_2</div>
<div class='qqq_menu_item'>section_3</div>
<div class='qqq_menu_item'>section_4</div>
<div class='qqq_menu_item'>section_5</div>
</div>
<div class='qqq_container'>
<div class='qqq_section'>
<h1>section_1</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_2</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_3</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_4</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_5</h1>
<p class='text_fill'></p>
</div>
</div>
<script>
// note: have tried editing .repeat to 3000 to make it a lot of text and 150 to make it a little text and still works right. also added a bunch of space with <br /> above and below the .qqq_container element and still works right.
asdf_text = "asdf ".repeat(750);
document.querySelectorAll(".text_fill").forEach(function (element) {
element.innerHTML = asdf_text;
});
container = document.querySelectorAll(".qqq_container")[0];
sections = document.querySelectorAll(".qqq_section");
menu = document.querySelectorAll(".qqq_menu_item");
percentage = 0;
function qqq_menu_highlight() {
active = 0;
ttt = window.innerHeight / 100;
lll = ttt * percentage;
zzz = window.scrollY + lll;
sections.forEach(function (v, k, l) {
if (zzz > v.offsetTop) {
active = k;
}
});
menu.forEach(function (v, k, l) {
if (active === k) {
v.classList.add('qqq_menu_active');
} else {
v.classList.remove('qqq_menu_active');
}
});
sections.forEach(function (v, k, l) {
if (active === k) {
v.classList.add('qqq_section_active');
} else {
v.classList.remove('qqq_section_active');
}
});
}
function element_scroll_percentage(element) {
//inc = (document.body.scrollHeight - window.innerHeight) / 100;
//console.log(active);
rect = element.getBoundingClientRect();
if (Math.sign(rect.top) == -1) {
value = Math.abs(rect.top);
inc = (rect.height - window.innerHeight) / 100;
percentage = value / inc;
if (percentage > 100) {
percentage = 100;
}
} else {
percentage = 0;
}
return percentage;
}
document.onscroll = function() {
percentage = element_scroll_percentage(container);
qqq_menu_highlight();
//console.log(percentage);
}
document.onscroll();
</script>
In the solution below, I divided the value of this.scrollY by 200, since the height of the containers is 200px. I added the result of this action to the end of the slide-li statement to use as the id of the targeted item.
function removeClass() {
for(let i = 0 ; i < 6 ; i++)
$(`#slide-li${i + 1}`).removeClass("active");
}
$(window).scroll(function(){
console.clear();
console.log(`Scroll: ${this.scrollY}`);
removeClass();
let visibleElement = Math.floor(this.scrollY / 200);
$(`#slide-li${visibleElement + 1}`).addClass("active");
});
#container {
width: 800px;
margin: auto;
text-align: left;
display: inline-flex;
margin: 0;
margin: 100px 0;
}
#field {
width: 500px;
float: left;
font-weight: 500;
color: #001737;
}
.field-wrap {
padding: 0;
border-bottom: 1px solid #8392A5;
height: 200px;
background-color: #FF000030;
}
#slidecart {
position: fixed;
top: 10px;
right: 0px;
width: 300px;
display: inline-block;
padding: 20px;
border-left: 1px solid #8392A5;
}
#slide-ul {
list-style-type: none;
margin: 0;
padding: 5px 0 0 5px;
}
.slide-li {
margin: 0;
padding: 0 0 0 10px;
cursor: pointer;
}
.active {
padding: 0 0 0 5px;
border-left: 5px solid #0168FA;
color: #0168FA;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="field">
<div id="field-wrap1" class="field-wrap">
1.) - Hello World!
</div>
<div id="field-wrap2" class="field-wrap">
2.) - Hello World!
</div>
<div id="field-wrap3" class="field-wrap">
3.) - Hello World!
</div>
<div id="field-wrap4" class="field-wrap">
4.) - Hello World!
</div>
<div id="field-wrap5" class="field-wrap">
5.) - Hello World!
</div>
<div id="field-wrap6" class="field-wrap">
6.) - Hello World!
</div>
</div>
<div id="slidecart">
TABLE OF CONTENTS
<ul id="slide-ul">LIST
<li id="slide-li1" class="slide-li">1.) - Hello World!</li>
<li id="slide-li2" class="slide-li">2.) - Hello World!</li>
<li id="slide-li3" class="slide-li">3.) - Hello World!</li>
<li id="slide-li4" class="slide-li">4.) - Hello World!</li>
<li id="slide-li5" class="slide-li">5.) - Hello World!</li>
<li id="slide-li6" class="slide-li">6.) - Hello World!</li>
</ul>
</div>
</div>
I want to create a to do list that will add elements typed in <input type="text"> and delete when clicked on button with class .delete. When ever I push elements in an array. And innerHTML it in html page, the delete button stops working. The delete button works for elements that are written into Html code. If someone can help me I will be very thankful.
`
const itemsLIst = document.querySelector('.item-list'); // where we want to add our list
const addText = document.querySelector('.submit'); // add button
let deleteText = document.querySelectorAll('.delete'); // delete button
// const list = JSON.parse(localStorage.getItem('items')) || [];
let list = [];
function addItem(e) {
let text = document.querySelector('.input_bar').value; //text typed in input bar
if (text.length != 0) {
list.push(`<div>
<p>${text}</p>
<button class="delete" onclick='deleteItem'>π΄</button>
<button class="edit">Edit</button>
</div><hr>`);
itemsLIst.innerHTML = list.join('');
text = '0';
document.getElementById("myText").value = "";
} else {
return;
}
}
function deleteItem(e) {
this.parentElement.style.display = 'none';
}
for (var i = 0 ; i < deleteText.length; i++) {
deleteText[i].addEventListener('click', deleteItem);
}
addText.addEventListener('click', addItem);
<style>
body {
width: 100%;
height: 100vh;
background-color: rgb(115, 115, 197);
margin: 0;
padding: 0;
position: relative;
}
.container {
width:50%;
height:70%;
position: absolute;
background-color: rgb(241, 241, 241);
font-family: Arial, Helvetica, sans-serif;
border-bottom-left-radius: 25px;
border-bottom-right-radius: 25px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow-y: scroll;
}
.heading {
width: 100%;
height: 122px;
background-color: #5B45B9;
display: flex;
align-items: center;
justify-content: center;
}
.heading h1 {
color: white;
font-size: 40px;
}
.item-list {
width: 100%;
padding: 0 0 30px 0;
}
.item-list div {
width: auto;
height: 60px;
}
p {
width: 60%;
float: left;
font-size: 25px;
padding-left: 30px;
margin-top: 12px ;
}
.item-list button {
width: 60px;
height: 60px;
font-size: 18px;
float: right;
}
.delete {
font-size: 30px;
color: red;
}
.input_form {
width: 100%;
padding: 30px 0 30px 0;
position: absolute;
bottom: 0;
text-align: center;
}
.input_form .input_bar {
width: 80%;
height: 50px;
font-size: 18px;
border: none;
}
.input_form button {
width: 10%;
height: 50px;
float: right;
margin-right: 30px;
}
</style>
<html>
<head>
</head>
<body>
<div class="container">
<div class="heading">
<h1>TO-DO LIST</h1>
</div>
<div class="item-list">
<div>
<p>TEEXT2</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT1</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT3</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT4</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
</div>
<div class="input_form">
<input type="text" class="input_bar" id="myText" placeholder="Add ITEM">
<button class="submit">+ADD ITEM</button>
</div>
</div>
</body>
</html>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT1</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT3</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT4</p>
<button class="delete">π΄</button>
<button class="edit">Edit</button>
</div>
</div>
<div class="input_form">
<input type="text" class="input_bar" id="myText" placeholder="Add ITEM">
<button class="submit">+ADD ITEM</button>
</div>
<script src="script.js"></script>
</div>
</body>
</html>`
You actually only trigger DOM "original" delete button (button loaded with your HTML code) with the line :
let deleteText = document.querySelectorAll('.delete'); // delete button
Your others .delete are loaded after the first DOM loading and are not even listed in "deleteText" array !
You have to refresh deleteText every time you add a new item. Something like :
const itemsLIst = document.querySelector('.item-list'); // where we want to add our list
const addText = document.querySelector('.submit'); // add button
let deleteText = document.querySelectorAll('.delete'); // delete button
// const list = JSON.parse(localStorage.getItem('items')) || [];
let list = [];
function addItem(e) {
let text = document.querySelector('.input_bar').value; //text typed in input bar
if (text.length != 0) {
list.push(`<div>
<p>${text}</p>
<button class="delete" onclick='deleteItem'>π΄</button>
<button class="edit">Edit</button>
</div><hr>`);
itemsLIst.innerHTML = list.join('');
text = '0';
document.getElementById("myText").value = "";
} else {
return;
}
}
function deleteItem(e) {
this.parentElement.style.display = 'none';
}
function triggerDeleteButton(){
deleteText = document.querySelectorAll('.delete'); // delete button
for (var i = 0 ; i < deleteText.length; i++) {
deleteText[i].addEventListener('click', deleteItem);
}
}
addText.addEventListener('click', function(){
addItem() ;
triggerDeleteButton() ;
}
);
Without refreshing, you can add and edit data by using local storage
For example, like below, you can try once!
<script>
let customerData = [];
// Inserting new customer record into local storage
function insert() {
let company = document.getElementById("company").value;
let obj = {company};
customerData.push(obj);
synData(customerData);
let customerDetails = JSON.parse(localStorage.getItem("customerString"));
clearFileds();
displayelements(customerDetails);
}
function displayelements(customerDetails) {
let html = "<table id='customer_data' border='1'><tr><th>Sl No</th><th>Company</th><th>Delete</th></tr>";
if(customerDetails == '') {
html+="<tr>No record found!</tr>";
} else {
customerDetails.map((values, index) => {
html+="<tr id='row_data'>";
html+="<td>"+index+"</td>";
html+="<td>"+values.company+"</td>";
html+="<td onclick='deleteRow(" + index + ")'>Delete</td>";
html+="</tr>";
} )
}
html+="</table>";
document.getElementById("display").innerHTML = html;
clearFileds();
}
// Delete the specific customer record from local storage
function deleteRow(deleteKey) {
let customerDetails = JSON.parse(localStorage.getItem("customerString"));
customerDetails.map((values, index) => {
if (index == deleteKey) {
customerDetails.splice(index, 1);
}
})
customerData = customerDetails;
synData(customerDetails);
displayelements(customerDetails);
}
// Clearing the form input field data
function clearFileds() {
document.getElementById("company").value = '';
}
// Updating local storage data
function synData(customerDetails) {
localStorage.setItem('customerString', JSON.stringify(customerDetails));
}
</script>
<html>
<head>
<title>Save</title>
</head>
<script ></script>
<body id="format_background">
<div id="customerAction" >
<h1>Customer data</h1>
<label>Company Name </label>
<input id="company" type="text" />
<button type="button" value="Save&Show" onclick="insert()" id="insert">Save</button>
</div>
<div id="display"></div>
</body>
</html>
i'm trying to develop a game using html, css and js. At the moment I'm focusing on manipulating DOM elements without using the canvas tag. My idea is to create a pseudo graphical programming language, similar to the Blockly environment. So far I have inserted 3 clickable elements inside #toolbox that create their copies in #workspace.
Now, I am trying to assign functions to the elements present in #workspace, which once pressed the Run button are executed in order of appearance, so as to create a queue of commands that is able to move the pink square inside #output_section.
Therefore I cannot understand how to write the function that is able to verify the presence of the elements and then be able to perform the different functions assigned to these elements.
Any ideas? :D
I'm using Jquery 3.3.1
function addRed() {
var redWorkspace = document.createElement("DIV");
redWorkspace.className = "remove-block block red";
document.getElementById("workspace").appendChild(redWorkspace);
};
function addBlue() {
var blueWorkspace = document.createElement("DIV");
blueWorkspace.className = "remove-block block blue";
document.getElementById("workspace").appendChild(blueWorkspace);
};
function addGreen() {
var greenWorkspace = document.createElement("DIV");
greenWorkspace.className = "remove-block block green";
document.getElementById("workspace").appendChild(greenWorkspace);
};
$("#clear_workspace").click(function () {
$("#workspace").empty();
});
$(document).on("click", ".remove-block", function () {
$(this).closest("div").remove();
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
bottom: 0;
right: 0;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div onclick="addRed()" class="block red">Left</div>
<div onclick="addBlue()" class="block blue">Up</div>
<div onclick="addGreen()" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>
</body>
</html>
Completely untested but run button does something along the lines of:
$("#run_workspace").click(function() {
$("#workspace .block").each(function(elem) {
if (elem.hasClass("red")) {
moveObjectLeft();
} else if (elem.hasClass("green")) {
moveObjectRight();
} else if (elem.hasClass("blue")) {
moveObjectUp();
}
});
});
Commonly, it's a good idea to store all required information in arrays and objects, and use HTML only to display your data.
Also, if you are already using jQuery - use it for all 100%)
Made some improvements:
let mobs = {
pinky: {
node: $('#moving_square'),
coors: { top: 400, left: 400 },
step: 30,
moveQueue: [],
// moveTimeout ???
},
}; // storing here all created objects, that must move.
/* Each [moveQueue] array will store the chain of moves, like ["up", "up", "left"]
You can take each "key-word" of move, and get required function buy that key,
from the 'move' object */
let move = { // Think about how to simlify this object and functions. It's possible!)
left: function (obj) {
let left = obj.coors.left = (obj.coors.left - obj.step);
obj.node.css('left', left + 'px');
},
up: function (obj) {
let top = obj.coors.top = (obj.coors.top - obj.step);
obj.node.css('top', top + 'px');
},
right: function (obj) {
let left = obj.coors.left = (obj.coors.left + obj.step);
obj.node.css('left', left + 'px');
}
};
let stepTimeout = 1000;
let running = false;
let timeouts = {}; // store all running timeouts here,
// and clear everything with for( key in obj ) loop, if required
$('#toolbox .block').on('click', function () {
let color = $(this).attr('data-color');
let workBlock = '<div class="remove-block block ' + color + '"></div>';
$('#workspace').append(workBlock);
mobs.pinky.moveQueue.push( $(this).text().toLowerCase() ); // .attr('data-direction');
// instead of pinky - any other currently selected object
// $(this).text().toLowerCase() β must be "left", "up", "right"
});
$('#run_workspace').on('click', function () {
running = true;
runCode();
function runCode() {
for (let obj in mobs) { // mobile objects may be multiple
// Inside the loop, obj == mobs each key name. Here it's == "pinky"
let i = 0;
let pinky = mobs[obj];
localRun();
function localRun() {
let direction = pinky.moveQueue[i]; // getting direction key by array index.
move[direction](pinky); // calling the required function from storage.
if (pinky.moveQueue[++i] && running ) {
// self-calling again, if moveQueue has next element.
// At the same time increasing i by +1 ( ++i )
timeouts[obj] = setTimeout(localRun, stepTimeout);
}
}
}
}
});
$("#clear_workspace").click(function () {
$("#workspace").empty();
});
$('#workspace').on("click", ".remove-block", function () {
$(this).closest("div").remove();
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
top: 400px;
left: 400px;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div data-color="red" class="block red">Left</div>
<div data-color="blue" class="block blue">Up</div>
<div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>
But... jQuery was used only for clicks... Translation to JS:
let mobs = {
pinky: {
node: document.getElementById('moving_square'),
coors: { top: 400, left: 400 },
step: 30,
moveQueue: [],
},
};
let move = {
left: function (obj) {
let left = obj.coors.left = (obj.coors.left - obj.step);
obj.node.style.left = left + 'px';
},
up: function (obj) {
let top = obj.coors.top = (obj.coors.top - obj.step);
obj.node.style.top = top + 'px';
},
right: function (obj) {
let left = obj.coors.left = (obj.coors.left + obj.step);
obj.node.style.left = left + 'px';
}
};
let stepTimeout = 1000;
let running = false;
let timeouts = {};
let blocks = document.querySelectorAll('#toolbox .block');
let workSpace = document.getElementById('workspace');
blocks.forEach(function(block){
block.addEventListener('click', function(){
let color = this.dataset.color;
let workBlock = '<div class="remove-block block ' + color + '"></div>';
workSpace.insertAdjacentHTML('beforeend', workBlock);
mobs.pinky.moveQueue.push( this.textContent.toLowerCase() );
});
});
document.getElementById('run_workspace').addEventListener('click', function () {
running = true;
runCode();
function runCode() {
for (let obj in mobs) { // mobile objects may be multiple
// Inside the loop, obj == mobs each key name. Here it's == "pinky"
let i = 0;
let pinky = mobs[obj];
localRun();
function localRun() {
let direction = pinky.moveQueue[i]; // getting direction key by array index.
move[direction](pinky); // calling the required function from storage.
if (pinky.moveQueue[++i] && running ) {
// self-calling again, if moveQueue has next element.
// At the same time increasing i by +1 ( ++i )
timeouts[obj] = setTimeout(localRun, stepTimeout);
}
}
}
}
});
document.getElementById("clear_workspace").addEventListener('click', function () {
workSpace.textContent = "";
});
workSpace.addEventListener('click', function (e) {
if( e.target.classList.contains('remove-block') ){
e.target.remove();
}
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
top: 400px;
left: 400px;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div data-color="red" class="block red">Left</div>
<div data-color="blue" class="block blue">Up</div>
<div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>
So I have a div wrap whose size is a percentage of the screen width. Inside this wrap is multiple .item divs. As the window gets smaller it breaks into new lines obviously.
I wrote some code which basically takes the width of the wrap and divides it by the sum of the widths of the .item boxes. But the flaw is that it looks at it thinking how many boxes could fit in total, were one to mix and match them perfectly like building blocks, but that's not how it works because the ordering is stagnant.
How could I make this logic work?
CodePen
jQuery:
var itemWidth = 0;
var lineCount = 1;
$(window).on('resize', function(){
var lineWidth = $('.line').width();
var itemWidthSum = 0;
lineCount=1;
$('.item').each(function(index, element) {
if(itemWidthSum < (lineWidth - $(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = 0;
}
});
});
HTML:
<div id="container">
<div class="rect">
<div class="line">
</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
</div>
<h1 class="answer"></h1>
CSS:
body {
padding:25px;
}
.answer {
position:fixed;
bottom:0;
left:0;
}
#container {
border: 1px solid rgb(200,200,200);
height: auto;
width: 30%;
margin:0 auto;
}
.item {
padding: 10px;
background-color: #aef2bd;
float: left;
}
.rect {
height: 100px;
width:100%;
position: relative;
}
.rect .line {
position:absolute;
height:50px;
width: 100%;
bottom:0;
border-top: 1px solid red;
}
Figured out my logic mistake by debugging each step.
The correct jQuery:
var itemWidth = 0;
var lineCount = 1;
$(window).on('resize', function(){
var lineWidth = $('.line').width();
var itemWidthSum = 0;
var list = [];
lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
});
HTML:
<div class="inline-wrapper">
<div class="inline-blocks" id="f">123</div>
<div class="inline-blocks" id="s">123</div>
<div class="inline-blocks" id="t">123</div>
<div class="inline-blocks" id="fo">123</div>
</div>
CSS:
html, body {
width: 100%;
height: 100%;
/* overflow: hidden;*/
}
.inline-wrapper{
width: 400%;
height: 100%;
font-size: 0;
position: relative;
}
.inline-blocks{
display: inline-block;
width: 25%;
height: 100%;
vertical-align: top;
position: relative;
}
>.inline-blocks:nth-child(1){
background-color: #000;
}
.inline-blocks:nth-child(2){
background-color: blue;
}
.inline-blocks:nth-child(3){
background-color: red;
}
.inline-blocks:nth-child(4){
background-color: green;
}
How can I slide them without ID?
In fact this is the work of the slider. But I can not understand the logic.
Want to understand how flipping without ID.
We must check the blocks and give them Ρurrent class.
Auto Slide
HTML:
<div class="inline-wrapper">
<div class="inline-blocks" id="f">123</div>
<div class="inline-blocks" id="s">123</div>
<div class="inline-blocks" id="t">123</div>
<div class="inline-blocks" id="fo">123</div>
</div>
jQuery:
(function () {
var numDivs = $('.inline-wrapper').children().length; //Count children ELements
var counter = 1;
function slide(time, counter) {
var $currentDiv = $('.inline-wrapper .inline-blocks:nth-child(' + counter + ')'); //get next element
var position = $currentDiv.position(); //get position of next element
if (numDivs > 1) {
$('html,body').animate({
scrollLeft: position.left
}, time / 2); //Animate to next element
}
};
$('.inline-blocks').on('click', function () {
counter = counter + 1;
slide(2000, counter);
});
})();
DEMO