Is there a way to combine multiple divs into one - javascript

I have a dynamic group of n by m divs to form a grid. The items in this grid can be selected. The end result which I am hoping to achieve is to be able to combine and split the selected divs.
I have managed to get the divs to show correctly and select them, storing their id's in a list. Is there a way I could combine the selected divs, keeping the ones around it in their place?
#(Html.Kendo().Window()
.Name("window") //The name of the window is mandatory. It specifies the "id" attribute of the widget.
.Title("Dashboard Setup") //set the title of the window
.Content(#<text>
<div id="divSetup">
<div class="dvheader">
<b>Dashboard Setup</b>
</div>
<div>
<p>Enter the number of columns and rows of dashboard elements. This will create an empty dashboard with a set number of items which can be filled with KPI charts.</p>
<br />
<div class="dvform">
<table>
<tr style="margin-bottom: 15px;">
<td>
#Html.Label("Number of Columns: ")
</td>
<td>
<input type="number" name="NumColumns" id="NoColumns" min="1" max="20" />
</td>
</tr>
<tr style="margin-bottom: 15px;">
<td>
#Html.Label("Number of Rows: ")
</td>
<td>
<input type="number" name="NumRows" id="NoRows" min="1" max="20" />
</td>
</tr>
</table>
</div>
</div>
<div style="float: right">
<button id="btnSave" class="k-primary">Save</button>
<button id="btnClose">Close</button>
</div>
</div>
</text>)
.Draggable() //Enable dragging of the window
.Resizable() //Enable resizing of the window
.Width(600) //Set width of the window
.Modal(true)
.Visible(false)
)
<div id="dashboard">
</div>
<button id="combine" title="Combine">Combine</button>
<script>
$(document).ready(function () {
debugger;
$("#window").data("kendoWindow").open();
$("#btnClose").kendoButton({
click: close
});
$("#btnSave").kendoButton({
click: Save
});
$("#combine").kendoButton();
});
var array = [];
function clicked(e)
{
debugger;
var selectedDiv = "";
var x = document.getElementsByClassName('column')
for (var i = 0; i < x.length; i++)
{
if (x[i].id == e.id)
{
x[i].classList.add("selected");
array.push(x[i]);
}
}
for (var x = 0; x < array.length - 1; x++) {
array[x].classList.add("selected");
}
}
function close() {
$("#window").hide();
}
function Save()
{
debugger;
var col = document.getElementById("NoColumns").value;
var row = document.getElementById("NoRows").value;
for (var x = 1; x <= row; x++)
{
debugger;
document.getElementById("dashboard").innerHTML += '<div class="row">';
debugger;
for (var i = 1; i <= col; i++)
{
document.getElementById("dashboard").innerHTML += '<div onclick="clicked(this)" id="Row ' + x + ' Col ' + i + '" class="column">' + i + '</div>';
}
document.getElementById("dashboard").innerHTML += '</div>';
}
}
<style>
.selected {
background-color: #226fa3;
transition: background-color 0.4s ease-in, border-color 0.4s ease-in;
color: #ffffff;
}
#dashboard {
width: 80%;
margin: auto;
background-color: grey;
padding: 20px;
}
* {
box-sizing: border-box;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
padding: 20px;
border: 1px black solid;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
Below is an image of the selected blocks I would like to combine into one, while keeping it's place

If you were using a table it would be much easier, for div's, I can think of a solution if the style position is absolute, maybe it would help you start at least.
<div id="container"></div>
<button id="combine" title="Combine" disabled="disabled">Combine</button>
<div id="output"></div>
the script:
<script>
var cc;
function group() {
var xx = $(".selected").map(function () { return $(this).attr("data-x"); }).get();
var yy = $(".selected").map(function () { return $(this).attr("data-y"); }).get();
this.minX = Math.min.apply(Math, xx);
this.minY = Math.min.apply(Math, yy);
this.maxX = Math.max.apply(Math, xx);
this.maxY = Math.max.apply(Math, yy);
this.selectedCount = $(".selected").length;
this.CorrectGroup = function () {
var s = this.selectedCount;
return s == this.cellsCount() && s > 1;
}
this.width = function () {
return this.maxX - this.minX + 1;
}
this.height = function () {
return this.maxY - this.minY + 1;
}
this.cellsCount = function () {
return this.width() * this.height();
}
}
function cell(x, y, g) {
this.x = x;
this.y = y;
this.g = g;
this.spanX = 1;
this.spanY = 1;
this.visible = true;
var cellWidth = 80;
var cellHeight = 50;
this.div = function () {
var output = jQuery('<div/>');
output.attr('id', 'y' + y + 'x' + x);
output.attr('data-x', x);
output.attr('data-y', y);
output.attr('style', this.left() + this.top() + this.width() + this.height());
output.addClass('clickable');
output.html('(y=' + y + ' x=' + x + ')')
return output;
}
this.left = function () {
return 'left:' + (x * cellWidth) + 'px;';
}
this.top = function () {
return 'top:' + (100 + y * cellHeight) + 'px;';
}
this.width = function () {
return 'width:' + (this.spanX * cellWidth) + 'px;';
}
this.height = function () {
return 'height:' + (this.spanY * cellHeight) + 'px;';
}
}
function cells(xx, yy) {
this.CellWidth = xx;
this.CellHeight = yy;
this.CellList = [];
for (var y = 0; y < yy; y++)
for (var x = 0; x < xx; x++) {
this.CellList.push(new cell(x, y, 1));
}
this.findCell = function (xx, yy) {
return this.CellList.find(function (element) {
return (element.x == xx && element.y == yy);
});
}
this.displayCells = function (container) {
container.html('');
for (var y = 0; y < yy; y++)
for (var x = 0; x < xx; x++) {
var cell = this.findCell(x, y);
if (cell.visible)
cell.div().appendTo(container);
}
}
}
$(document).ready(function () {
$('#combine').click(function () {
$(".selected").each(function () {
var x = $(this).data('x');
var y = $(this).data('y');
var cell = cc.findCell(x, y);
cell.visible = false;
cell.g = 'y';
});
var first = $(".selected").first();
var xx = $(first).data('x');
var yy = $(first).data('y');
var cell = cc.findCell(xx, yy);
var g = new group();
cell.visible = true;
cell.g = xx + '_' + yy;
cell.spanX = g.width();
cell.spanY = g.height();
cc.displayCells($('#container'));
});
//make divs clickable
$('#container').on('click', 'div', function () {
$(this).toggleClass('selected');
if (CheckIfSelectedAreGroupable())
$('#combine').removeAttr("disabled");
else
$('#combine').attr("disabled", "disabled");
});
cc = new cells(12, 10);
cc.displayCells($('#container'));
});
function CheckIfSelectedAreGroupable() {
var g = new group();
return g.CorrectGroup();
}
</script>
Style:
<style>
.selected {
background-color: #226fa3 !important;
transition: background-color 0.4s ease-in, border-color 0.4s ease-in;
color: #ffffff;
}
.clickable {
border: 1px solid lightgray;
margin: 0px;
padding: 0px;
background-color: lightyellow;
position: absolute;
}
</style>
Im starting the divs by the following line, you can hock your form to trigger something similar.
cc = new cells(12, 10);
the combine button will not activate if you dont select a correct group, a rectangle shape selection.
the split will not be hard too but I did not have time to put it together, if this solution help, I can update it for the split.
Note: I wrote this quickly so its not optimized.
to try the solution use :
jsfiddle

Related

Unable to update image position in css using javascript

There are some runner(animation-image) in my program which move from position x to y when clicked on start button, i want to add a (reverse)button on completion that when clicked on that the image moves from y to x.
Here is the link of my js-fiddle: https://jsfiddle.net/o6egL4qr/
I have added the reverse button but when clicked on that the image doesn't move at all.
class raceManager {
raceCount = 0;
races = [];
addRace() {
var mainContainer = document.getElementById('mainContainer');
mainContainer.appendChild(document.createElement('br'));
var race = new raceClass(this.raceCount);
this.races.push(race);
this.raceCount++;
}
}
class raceClass {
runners = [];
count;
runnerCount = 0;
raceDiv = document.createElement('div');
raceNum = document.createElement('div');
startRaceButton = document.createElement('input');
addRunnerButton = document.createElement('input');
revRaceButton = document.createElement('input');
tableDiv = document.createElement('div');
tableNum = document.createElement('div');
startInterval;
startTime;
revStartTime;
reverseInterval;
constructor(number) {
// store the race no.
this.count = number;
// delcare the race div id
this.raceNum.id = 'raceNum' + this.count;
// delcare the table div id
this.tableNum.id = 'tableNum' + this.count;
// Add raceDiv to the race
document.getElementById('races').appendChild(this.raceDiv);
// Add tableDiv to the race
document.getElementById('tables').appendChild(this.tableDiv);
this.applyDivProperty();
this.initializeButtons();
}
applyDivProperty() {
// apply properties to the tableNum
this.tableNum.style.display = "inline-block";
// apply properties to the raceDiv
this.raceDiv.id = "Race" + this.count;
document.getElementById(this.raceDiv.id).classList.add("raceDivClass");
this.raceDiv.appendChild(this.raceNum);
document.getElementById(this.raceNum.id).innerHTML = '<p>Race: ' + this.count + '</p>';
// append the add race button
this.raceDiv.appendChild(this.addRunnerButton);
// apply properties to the tableDiv
this.tableDiv.id = "Table" + this.count;
document.getElementById(this.tableDiv.id).classList.add("tableClass");
this.tableDiv.appendChild(this.tableNum);
document.getElementById(this.tableNum.id).innerHTML = '<p>Table: ' + this.count + '</p>';
}
initializeButtons() {
// initialize add runner button
this.addRunnerButton.type = 'Button';
this.addRunnerButton.value = 'Add Runner';
this.addRunnerButton.id = 'AddRunner' + this.count;
this.addRunnerButton.onclick = this.addRunner.bind(this);
// initialize start race buttton
this.startRaceButton.type = 'Button';
this.startRaceButton.value = 'Start Race';
this.startRaceButton.id = "startRaceButton" + this.count;
this.startRaceButton.onclick = this.startRace.bind(this);
// initialize reverse race buttton
this.revRaceButton.type = 'Button';
this.revRaceButton.value = 'Reverse Race';
this.revRaceButton.id = "revRaceButton" + this.count;
this.revRaceButton.onclick = this.revRace.bind(this);
}
addRunner() {
var track = new Runner(this); //Initialize the runner object
this.runners.push(track); //Store the runner object in runners array of Race class
if (this.runnerCount > 0) {
// append the start race button
this.raceDiv.appendChild(this.startRaceButton);
}
this.runnerCount++;
}
startRace() {
this.startTime = Date.now();
this.startInterval = setInterval(() => {
this.runners.forEach(function(element) {
element.animate();
});
document.getElementById(this.startRaceButton.id).disabled = "true";
document.getElementById(this.addRunnerButton.id).disabled = "true";
}, 50);
}
stop() {
clearInterval(this.startInterval);
// append the start race button
this.raceDiv.appendChild(this.revRaceButton);
}
revRace() {
this.revStartTime = Date.now();
this.reverseInterval = setInterval(() => {
this.runners.forEach(function(element) {
element.animateReverse();
});
document.getElementById(this.revRaceButton.id).disabled = "true";
}, 50);
}
stopRev() {
clearInterval(this.reverseInterval);
}
}
class Runner {
count = 0;
parent;
track;
sprite;
timeTaken;
trackWidth;
element;
speed;
table;
printCount = 1;
stepCount = 1;
trackNum;
tbl;
lastStep;
constructor(race) {
// initialize the divs
this.parent = race;
this.track = document.createElement('div');
this.sprite = document.createElement('div');
this.table = document.createElement('table');
// assigns #id to table and track corresponding with parent div.
this.table.id = race.tableNum.id + '_Table_' + this.parent.runnerCount;
this.track.id = race.raceNum.id + '_Track_' + this.parent.runnerCount;
this.createUI();
this.timeTaken = ((Math.random() * 5) + 3);
this.speed = this.trackWidth / (this.timeTaken * 1000);
console.log(this.trackWidth, this.timeTaken);
console.log(this.timeTaken * 100);
}
createUI() {
this.count = this.parent.runnerCount;
this.createTable();
this.createTrack();
this.createSprite();
}
createTable() {
var parentDiv1 = document.getElementById(this.parent.tableNum.id);
parentDiv1.appendChild(this.table);
this.table.setAttribute = "border"
this.table.border = "1";
document.getElementById(this.table.id).classList.add("tableClass");
this.tbl = document.getElementById(this.table.id);
this.addRow("Track " + (this.count + 1), "");
this.addRow("Time", "Distance");
}
addCell(tr, val) {
var td = document.createElement('td');
td.innerHTML = val;
tr.appendChild(td)
}
addRow(val_1, val_2) {
var tr = document.createElement('tr');
this.addCell(tr, val_1);
this.addCell(tr, val_2);
this.tbl.appendChild(tr)
}
createTrack() {
var parentDiv = document.getElementById(this.parent.raceNum.id);
parentDiv.appendChild(this.track);
this.track.appendChild(this.sprite);
document.getElementById(this.track.id).classList.add("trackClass");
this.trackWidth = this.track.getBoundingClientRect().width;
}
createSprite() {
this.sprite.id = this.track.id + "_Runner";
document.getElementById(this.sprite.id).classList.add("spriteClass");
this.element = document.getElementById(this.sprite.id);
}
animate() {
// declare time variables
var timeNow = Date.now();
var timespent = timeNow - this.parent.startTime;
var diff = Math.floor(this.timeTaken * 100);
// step is position of sprite.
var step = timespent * this.speed;
// Print table for all tracks with 10 laps.
if ((Math.round(timespent / 50) * 50) == (Math.round(((diff - 25) * this.printCount) / 50) * 50)) {
this.addRow(this.printCount + ": " + timespent, (Math.floor(step)));
this.printCount++;
}
// check condition to stop
if (step > this.trackWidth - 23) {
document.getElementById(this.parent.raceNum.id).innerHTML += 'Winner: Runner' + (this.count + 1);
this.parent.stop();
}
this.element.style.left = step + 'px';
// ------------sprite animation----------------
// start position for the image slicer
var position = (3 - (Math.floor(step / 6.5) % 4)) * 25;
// we use the ES6 template literal to insert the variable "position"
this.element.style.backgroundPosition = `${position}px 0px`;
}
animateReverse() {
// declare time variables
var timeNow = Date.now();
var timespent = timeNow - this.parent.revStartTime;
var diff = Math.floor(this.timeTaken * 100);
console.log(this.count + " position of step " + this.element.style.left);
while (this.stepCount < 2) {
this.lastStep = parseFloat(this.element.style.left);
this.stepCount++;
}
console.log(this.count + " this is lastStep " + this.lastStep);
// step is position of sprite.
var step = this.lastStep - (this.speed * timespent);
// Print table for all tracks with 10 laps.
if ((Math.round(timespent / 50) * 50) == (Math.round(((diff - 25) * this.printCount) / 50) * 50)) {
this.addRow(this.printCount + ": " + timespent, (Math.floor(step)));
this.printCount++;
}
// check condition to stop
if (step < 25) {
document.getElementById(this.parent.raceNum.id).innerHTML += 'Winner: Runner' + (this.count + 1);
this.parent.stopRev();
}
this.element.style.left = step + 'px';
// ------------sprite animation----------------
// start position for the image slicer
//var position = (3 - (Math.floor(step / 6.5) % 4)) * 25;
//this.element.style.backgroundPosition = position + 'px 0px';
}
}
manager = new raceManager();
#tableContainer {
float: left;
}
#addRaces {
text-align: center;
}
.raceDivClass {
margin: 1% auto;
width: 60%;
text-align: center;
border: 1px solid;
}
.tableClass {
text-align: center;
border: 1px solid;
margin: 5px;
float: left;
}
.trackClass {
background-color: black;
height: 30px;
width: 98%;
margin: 1%;
position: relative;
}
.spriteClass {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAeCAYAAADAZ1t9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAASwSURBVGhD7Zq/axRBFMfv9u4MxATUSgsVm3QWigYbexuxUkiaKIqNoIUiwRSJoJLCxpSCaJoEYimo/4AgQVRIZxdBEIREYwzc5X74vndvlrm5mdnZ3dm9oPnAsDubu52Z93373pvNFQsJOXO9NUKHsU4vZPH90+IXPt/FA2kEmqbDTKcX8pza7K5I/vAtEJghge7zeSrwlDYbtYlmfWuILxWC8uBmUNoz/784wY4WaPRq9SGJcY+7Mt7GEOzUkB0pkGHi4Ci1K53TEK8h7tTE+pPywL6b3JXJQqBcQ7arQwR87AE34ElPUsPE1ZapODsErFHnnD7AfVWb9oylFYjVFcKoQuQC5kD55hB3Qxrbf17RYbHT+/fpCXGSOEmEaYcevofwhkRxXM0/VCi8azXr3+q1Xw8+LRxZ4cte4PneoHaQ2iVck0gVThVbyOhSRM9YOoFMyR9eW6KmLkAGYW6Vmjx47AViUfSkPC5V9p7nS23q1Z9zH+b33+KuF9iAOocUa0lcKFjubQJ2h51D5zbmIAVM9gc1mzgAE0kdFlFaq+JkQYQBV+FYOYoDGy9Tw3dgQ7QxnUBQUHxAtJfUhqllDhbWam4f525mJDCgMynufZFa13d6BILHsOeEjS6PUjMNtsRHFXgExI2V0PN6egiEkTzFMdlJgM/3zMd1H2Tzhjlqa53TLhLFbsvep9Cob70uFsuffbxJoHWZcq1A5CCZyDUZ7gtxotKDCsafdRHIZSFe9j9wBl1xoIJSuxhUVpIK5eB0JiILHo29EouDtVmLBF4IKjIbWOQkfzYVruENn+ESXFe+upBJeDMQVfWiyXQ5fFQV57oQLyLJL0VlsAfi06yJyhMuIOci7Efdqy0ENzxxonVFI22IY0NDHN1mykaX+nHAmKbw1qhtLLVaze8U1o6Jv9OmdaEYlI1lsLQGGVGwmMKbKZ8KXHIQxnUJn062CgVSFmQTRjySpr8n2nlb3lxTztl8W6+u3x0YOlylrpij1Vi0Hl3uxNx/U9MWIYSPtwZxclukSG2B4qreOTV+3skzBBgbuafVrJ0sVYbO8eUe4r5FMAgEbEnbSSC2l/p0grgRB1jHDGKqjt019kkwvoid4okS4D7O+Qji4MmxiQMonI2cGP/qYwMbt6LSAXFEzpCbyYaJcxuKBAwWJQ5EwATCTScLBeUhVGKRTIWBCgQsVYavcdcF8UZEnVveYPwXfIwNBMJCdF/GNeEZCFnahMzX1A0dgEi6MJALigP1SyiMCdu9wZH7sZBzkGpM5zcBljAZGdNPX964UAhKt0vlwbN8SQs2p/Xq2lTSfzU4hvK0OUily4b0PV1etI4Z+SbBFYMBrIPjO1QuT1N+GedLbVC1FYM9Hyk31fgScHYYE5JhD1Dz/r+fKPoqEJAMILAa1VRaU+HwaPnZwBR3vWJwJCDCUSonsKERKHJMrwLFAYbSbUwRyujanawMZfBikPXTEzvCgKhXPZmhe+/W2ZCuTWXpxQbgyWGFmhGILLb8p6V/AmnKa+Qd3783cCDz0JaGvgmEX4jyaRu8W6N8NM/dPGlvvvk8T5ye2r7mIIQ5PEl5/pyXc4FzIeOLZOMWCn8Bh1eBvOSZzIIAAAAASUVORK5CYII=');
position: absolute;
height: 30px;
width: 25px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="mainContainer">
<div id="addRaces">
<input type="Button" value="Add Race" onclick="manager.addRace()">
</div>
<div id="races">
</div>
<br>
</div>
<div id="tableContainer">
<div id="tables"></div>
</div>
</body>
</html>
I expect it to move from y to x after clicking the reverse button, but it is not moving.
When you run the reverse function the elements are no longer referencing the dom elements.
I am actually not sure why that is, maybe someone else can chime in.
Anyway, this will fix your problem:
Replace this.element.style.left = step + 'px';
With: document.getElementById(this.element.id).style.left = step + 'px';

Trouble with jquery mouse events

I am currently working on making a grid of squares for a tile map. I have it set up so clicking on a tile changes its state to explored from unexplored. I am attempting to have it so that dragging with the mouse down will change the state of all underlying tiles, however I can't seem to get it to work.
I have tried using mousedown and mouseup events to set a down boolean value which I then check inside of a mouseover. I have tried going about this in several ways (i.e. the commented out code). The current code will work for clicking but I really want to be able to do a drag to change multiples feature.
var tableString;
var width = 35;
var height = 15;
var cells = [];
var localX;
var localY;
function cell(x, y, c) {
positionX = x;
positionY = y;
category = c;
}
function createMap() {
for (var i = 0; i < height; i++) {
var row = [];
for (var j = 0; j < width; j++) {
let c = new cell();
c.category = "unexplored";
c.positionX = j;
c.positionY = i;
row.push(c);
}
cells.push(row);
}
}
function drawMap() {
tableString = "<table draggable='false'>";
for (var i = 0; i < height; i++) {
tableString += "<tr draggable='false'>";
for (var j = 0; j < width; j++) {
tableString += '<td draggable="false" class="' + cells[i][j].category + '" data-row="' + j + '" data-column="' + i + '"></td>';
}
tableString += "</tr>";
}
tableString += "</table>";
$("#mainContainer").html(tableString);
console.log("drew it");
}
function updateCellCategory(x, y, c) {
cells[x][y].category = c;
drawMap();
}
$(document).ready(function() {
createMap();
drawMap();
// var down = false;
// $(document,"td").mousedown(function () {
// down = true;
// })
// $(document,"td").mouseup(function () {
// down = false;
// });
// $(document,"td").on('mouseover','td',function () {
// if (down) {
// console.log("hovering and holding");
// localX = $(this).attr("data-row");
// localY = $(this).attr("data-column");
// updateCellCategory(localY, localX, "explored");
// }
// });
});
// $(document).on('mousedown',"td, documen",(function () {
// down = true;
// console.log(down);
// }));
// $(document).on('mouseup',"*",(function () {
// down = false;
// console.log(down);
// }));
// $(document).on('mouseover','td',function () {
// if (down) {
// console.log("hovering and holding");
// localX = $(this).attr("data-row");
// localY = $(this).attr("data-column");
// updateCellCategory(localY, localX, "explored");
// }
// });
$("*").delegate('td', 'click', function() {
localX = $(this).attr("data-row");
localY = $(this).attr("data-column");
updateCellCategory(localY, localX, "explored");
});
html,
body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#mainContainer {
max-width: 100%;
max-height: 90%;
width: 100%;
height: 90%;
display: flex;
align-items: center;
justify-content: center;
}
td {
width: 25px;
height: 25px;
border: .05px solid black;
}
.explored {
background-color: lightblue;
}
.unexplored {
background-color: lightcoral;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id="mainContainer">
</div>
</body>
</html>
The main issue I found when working on this is that some of the commented code works sometimes, but the second a drag event happens on a td the code breaks and the mouseup is not recognized causing the mouse cursur to continue affecting tiles even though the mouse was not held down.
OK. Using the click event is not what you want, since that involves pressing the mouse and releasing it.
Instead use, the mousemove, mousedown and mouseup events. Also, keep track of whether the mouse is down or not using a variable.
var tableString;
var width = 35;
var height = 15;
var cells = [];
var localX;
var localY;
var mouseDown = false;
function cell(x, y, c) {
positionX = x;
positionY = y;
category = c;
}
function createMap() {
for (var i = 0; i < height; i++) {
var row = [];
for (var j = 0; j < width; j++) {
let c = new cell();
c.category = "unexplored";
c.positionX = j;
c.positionY = i;
row.push(c);
}
cells.push(row);
}
}
function drawMap() {
tableString = "<table draggable='false'>";
for (var i = 0; i < height; i++) {
tableString += "<tr draggable='false'>";
for (var j = 0; j < width; j++) {
tableString += '<td draggable="false" class="' + cells[i][j].category + '" data-row="' + j + '" data-column="' + i + '"></td>';
}
tableString += "</tr>";
}
tableString += "</table>";
$("#mainContainer").html(tableString);
//console.log("drew it");
}
function updateCellCategory(x, y, c) {
cells[x][y].category = c;
drawMap();
}
$(document).ready(function() {
createMap();
drawMap();
});
$("*").on("mousedown", 'td', function()
{
mouseDown = true;
});
$(document).on("mouseup", function()
{
mouseDown = false;
});
$("*").on("mousemove", 'td', function()
{
if(!mouseDown)
return;
localX = $(this).attr("data-row");
localY = $(this).attr("data-column");
updateCellCategory(localY, localX, "explored");
});
html,
body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#mainContainer {
max-width: 100%;
max-height: 90%;
width: 100%;
height: 90%;
display: flex;
align-items: center;
justify-content: center;
}
td {
width: 25px;
height: 25px;
border: .05px solid black;
}
.explored {
background-color: lightblue;
}
.unexplored {
background-color: lightcoral;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id="mainContainer">
</div>
</body>
</html>
You can check whether or not the mouse is down using the event parameter of the event handler. Look at the last few lines of the snippet.
var tableString;
var width = 35;
var height = 15;
var cells = [];
var localX;
var localY;
function cell(x, y, c) {
positionX = x;
positionY = y;
category = c;
}
function createMap() {
for (var i = 0; i < height; i++) {
var row = [];
for (var j = 0; j < width; j++) {
let c = new cell();
c.category = "unexplored";
c.positionX = j;
c.positionY = i;
row.push(c);
}
cells.push(row);
}
}
function drawMap() {
tableString = "<table draggable='false'>";
for (var i = 0; i < height; i++) {
tableString += "<tr draggable='false'>";
for (var j = 0; j < width; j++) {
tableString += '<td draggable="false" class="' + cells[i][j].category + '" data-row="' + j + '" data-column="' + i + '"></td>';
}
tableString += "</tr>";
}
tableString += "</table>";
$("#mainContainer").html(tableString);
console.log("drew it");
}
function updateCellCategory(x, y, c) {
cells[x][y].category = c;
drawMap();
}
$(document).ready(function() {
createMap();
drawMap();
// var down = false;
// $(document,"td").mousedown(function () {
// down = true;
// })
// $(document,"td").mouseup(function () {
// down = false;
// });
// $(document,"td").on('mouseover','td',function () {
// if (down) {
// console.log("hovering and holding");
// localX = $(this).attr("data-row");
// localY = $(this).attr("data-column");
// updateCellCategory(localY, localX, "explored");
// }
// });
});
// $(document).on('mousedown',"td, documen",(function () {
// down = true;
// console.log(down);
// }));
// $(document).on('mouseup',"*",(function () {
// down = false;
// console.log(down);
// }));
// $(document).on('mouseover','td',function () {
// if (down) {
// console.log("hovering and holding");
// localX = $(this).attr("data-row");
// localY = $(this).attr("data-column");
// updateCellCategory(localY, localX, "explored");
// }
// });
$("*").delegate('td', 'mousedown', function() {
localX = $(this).attr("data-row");
localY = $(this).attr("data-column");
updateCellCategory(localY, localX, "explored");
});
$("*").delegate('td', 'mouseenter', function(event) {
if (event.buttons) {
localX = $(this).attr("data-row");
localY = $(this).attr("data-column");
updateCellCategory(localY, localX, "explored");
}
event.stopPropagation();
});
html,
body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#mainContainer {
max-width: 100%;
max-height: 90%;
width: 100%;
height: 90%;
display: flex;
align-items: center;
justify-content: center;
}
td {
width: 25px;
height: 25px;
border: .05px solid black;
}
.explored {
background-color: lightblue;
}
.unexplored {
background-color: lightcoral;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id="mainContainer">
</div>
</body>
</html>

im having problems to edit css using javascript

for some reason when i use JavaScript to edit the css of batata[y] nothing happens. The objective of the code is to create multiple blocks and move then from the top to the button of the page.
var p1
var p2 = [];
var y = 0;
var x = 0;
var telaJogo, telaJogo2, telaInicio;
var balao = [];
var a = 0;
var batata;
function ola() {
var bola = setInterval(addBalao, 1000);
}
function addBalao() {
telaJogo2 = document.getElementById('telaJogo2');
p2.push(0);
balao.push(0);
p1 = Math.floor(Math.random() * 445);
batata = "balao" + y;
balao[y] = document.createElement('div'); //create the block
balao[y].setAttribute("id", batata);
telaJogo2.appendChild(balao[y]);
balao[y].style = "top:" + p2[y] + "px;";
balao[y].style = "left:" + 30 + "px;";
balao[y].style = "background-color: red;";
balao[y].style = "height: 50px;";
balao[y].style = "width: 50px;";
balao[y].style = "position: absolute";
console.log("p2[y]" + p2[2]);
setInterval(ola2, 100);
y++;
}
function ola2() {
// move block
for (x = 0; x < y; x++) {
p2[x]++;
atualiza();
}
a = 0;
//console.log(p2);
}
function atualiza() {
// update the frame
balao[x].setAttribute("style", "top:" + p2[x] + "px;");
}
#telaJogo2 {
height: 800px;
width: 445px;
background-color: #90ee90;
}
<body onLoad="ola()">
<script type="text/javascript">
</script>
<div id="telaJogo2">
<div id="barra1"></div>
</div>

How to animate the following quicksort algorithm in javascript?

I'm trying to learn more about programing and sorting algorithms in general and i wanted to create an animation of a quicksort algorithm using div's with different heights. I've created the sorting algorithm.
Running the code snippet will help you understand what i'm trying to do.
Here is the code but after the sorting is done it only shows the final result and not the whole process:
function createColumns() {
$('.column').remove();
var content = $('#content');
var columnNumber = $('input:text').val();
var columnWidth = ((content.width() * 99 / 100) / columnNumber) + 'px';
for (var i = 0; i < columnNumber; i++) {
var randomColor = '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6);
var columnHeight = Math.floor(Math.random() * (columnNumber - 1)) + 1;
$('<div/>', {
'class': 'column'
}).css({
'height': columnHeight + 'px',
'width': columnWidth,
'background-color': randomColor
}).appendTo(content);
}
}
function quickSort(columns, left, right) {
var index;
if (columns.length > 1) {
index = partition(columns, left, right);
if (left < (index - 1)) {
quickSort(columns, left, (index - 1));
}
if (index < right) {
quickSort(columns, index, right);
}
}
return columns;
}
function partition(columns, left, right) {
var pivot = $(columns[Math.floor((right + left) / 2)]),
i = left,
j = right;
while (i <= j) {
while ($(columns[i]).height() < pivot.height()) {
i++
}
while ($(columns[j]).height() > pivot.height()) {
j--;
}
if (i <= j) {
swap(columns, i, j);
i++;
j--;
}
}
return i;
}
function swap(columns, firstIndex, secondIndex) {
var temp, visualTemp;
visualTemp = columns[secondIndex];
$(columns[firstIndex]).insertAfter($(columns[secondIndex]));
$(visualTemp).insertBefore($(columns[firstIndex + 1]));
temp = columns[firstIndex];
columns[firstIndex] = columns[secondIndex];
columns[secondIndex] = temp;
}
$('input').change(function() {
createColumns();
});
$('#quickSort').click(function() {
var columns = $('.column');
var left = 0,
right = columns.length - 1;
quickSort(columns, left, right);
});
createColumns();
body {
padding: 2em;
}
#content {
width: 100%;
height: 200px;
border: 2px solid black;
position: relative;
overflow: hidden;
}
.column {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Number of columns: <input type="text" value="100" />
<div id="content">
</div>
<input type="button" id="quickSort" name="QuickSort" value="Quick Sort">
While it's not quite animated, you can slow the sorting process down a bit if you wrap the internals of your quickSort function in a setTimeout with a small delay (i've chosen 750ms) to see each step.
function createColumns() {
$('.column').remove();
var content = $('#content');
var columnNumber = $('input:text').val();
var columnWidth = ((content.width() * 99 / 100) / columnNumber) + 'px';
for (var i = 0; i < columnNumber; i++) {
var randomColor = '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6);
var columnHeight = Math.floor(Math.random() * (columnNumber - 1)) + 1;
$('<div/>', {
'class': 'column'
}).css({
'height': columnHeight + 'px',
'width': columnWidth,
'background-color': randomColor
}).appendTo(content);
}
}
function quickSort(columns, left, right) {
var index;
setTimeout(function() {
if (columns.length > 1) {
index = partition(columns, left, right);
if (left < (index - 1)) {
quickSort(columns, left, (index - 1));
}
if (index < right) {
quickSort(columns, index, right);
}
}
return columns;
}, 750);
}
function partition(columns, left, right) {
var pivot = $(columns[Math.floor((right + left) / 2)]),
i = left,
j = right;
while (i <= j) {
while ($(columns[i]).height() < pivot.height()) {
i++
}
while ($(columns[j]).height() > pivot.height()) {
j--;
}
if (i <= j) {
swap(columns, i, j);
i++;
j--;
}
}
return i;
}
function swap(columns, firstIndex, secondIndex) {
var temp, visualTemp;
visualTemp = columns[secondIndex];
$(columns[firstIndex]).insertAfter($(columns[secondIndex]));
$(visualTemp).insertBefore($(columns[firstIndex + 1]));
temp = columns[firstIndex];
columns[firstIndex] = columns[secondIndex];
columns[secondIndex] = temp;
}
$('input').change(function() {
createColumns();
});
$('#quickSort').click(function() {
var columns = $('.column');
var left = 0,
right = columns.length - 1;
quickSort(columns, left, right);
});
createColumns();
body {
padding: 2em;
}
#content {
width: 100%;
height: 200px;
border: 2px solid black;
position: relative;
overflow: hidden;
}
.column {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Number of columns: <input type="text" value="100" />
<div id="content">
</div>
<input type="button" id="quickSort" name="QuickSort" value="Quick Sort">

JavaScript Boolean is not working and looping goes wrong

The demo created is to illustrate the working of the logic described below -
I have created 4x4 tiles using JavaScript instead of hard coding into html
Code highlight the columns one by one in a infinite loop which is achieved by setInterval(colScan,1000)
When user press the mouse on html body, it changes the column scan --> row scan in the selected column which is also achieved by setInterval(rowScan,1000)
When user clicks again on the html body, it changes the row scan --> col scan
Problem:
No matter what, colScan is always activated which you can see in the console log that the column is always increasing.
When user clicks the second time it doesn't reset to column scan.
part of the code where I think the problem is occurring
createtiles();
var k = 0,
m = 0,
selected_col = "",
mousePressed = false,
col_scan = true,
row_scan = false;
scanSelector();
function scanSelector() {
if (col_scan) {
setInterval(colScan, 1000);
} else if (row_scan) {
setInterval(rowScan, 1000);
}
}
document.body.onmousedown = function() {
mousePressed = true;
}
function colScan() {
if (k > 2) k = 0;
else k++;
console.log("col " + k);
var col = ".j_" + k;
$(".tiles").removeClass('highlighter');
$(col).addClass('highlighter');
if (mousePressed) {
mousePressed = false;
col_scan = false;
row_scan = true;
selected_col = col;
scanSelector();
}
}
function rowScan() {
if (m > 2) m = 0;
else m++;
console.log("row " + m);
var row = selected_col + (".i_" + m);
$(".tiles").removeClass('highlighter');
$(row).addClass('highlighter');
if (mousePressed) {
mousePressed = false;
col_scan = true;
row_scan = false;
selected_col = "";
scanSelector();
}
}
function createtiles() {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var divTile = $('<div>', {
class: 'tiles ' + ("j_" + j) + " " + ("i_" + i)
});
divTile.appendTo('.comtile');
}
}
}
DEMO -> https://codepen.io/xblack/pen/BdGzYx
createtiles();
var k = 0,
m = 0,
selected_col = "",
mousePressed = false,
col_scan = true,
row_scan = false;
scanSelector();
function scanSelector() {
if (col_scan) {
setInterval(colScan, 1000);
} else if (row_scan) {
setInterval(rowScan, 1000);
}
}
document.body.onmousedown = function() {
mousePressed = true;
}
function colScan() {
if (k > 2) k = 0;
else k++;
console.log("col " + k);
var col = ".j_" + k;
$(".tiles").removeClass('highlighter');
$(col).addClass('highlighter');
if (mousePressed) {
mousePressed = false;
col_scan = false;
row_scan = true;
selected_col = col;
scanSelector();
}
}
function rowScan() {
if (m > 2) m = 0;
else m++;
console.log("row " + m);
var row = selected_col + (".i_" + m);
$(".tiles").removeClass('highlighter');
$(row).addClass('highlighter');
if (mousePressed) {
mousePressed = false;
col_scan = true;
row_scan = false;
selected_col = "";
scanSelector();
}
}
function createtiles() {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var divTile = $('<div>', {
class: 'tiles ' + ("j_" + j) + " " + ("i_" + i)
});
divTile.appendTo('.comtile');
}
}
}
html,
body {
margin: 0px;
padding: 0px;
height: 100%;
min-height: 100%;
overflow: hidden;
font-family: 'Roboto', sans-serif;
background: white;
}
* {
box-sizing: border-box!important;
}
.conatiner {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-template-area: "menu" "comContent";
}
.menu {
grid-area: menu;
height: 5vh;
padding: 2vh;
}
.comtile {
grid-area: comContent;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto;
grid-gap: 0.5vh;
height: 95vh;
padding: 2vh;
}
.tiles {
background: #F7F7F7;
border-radius: 0.4vh;
border: 1px solid #EEEBEB;
}
.highlighter {
box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
transition: box-shadow 0.3s cubic-bezier(0.38, -0.76, 0, 1.69);
border: 1px solid silver;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="menu">MAIN MENU</div>
<div class="comtile"></div>
</div>
You need to make the following changes:
Replace setInterval with setTimeout for reasons stated by #ASDFGerte.
function scanSelector() {
if (col_scan) {
// Replace setInterval with setTimeout
setTimeout(colScan, 1000);
} else i f (row_scan) {
// Replace setInterval with setTimeout
setTimeout(rowScan, 1000);
}
}
Move the scanSelector() lines in rowScan and colScan. The change is the same for both methods, I will only show the change in rowScan.
function rowScan() {
if (m > 2) m = 0;
else m++;
console.log("row " + m);
var row = selected_col + (".i_" + m);
$(".tiles").removeClass('highlighter');
$(row).addClass('highlighter');
if (mousePressed) {
mousePressed = false;
col_scan = true;
row_scan = false;
selected_col = "";
// Remove this line
// scanSelector();
}
// Because you're no longer using setInterval you need to call
// this method after each timeout.
scanSelector();
}
Every time you were calling scanSelector() it would create another interval. The initial interval will highlight the columns, after the first click you have two intervals running side-by-side: the original interval and an interval to highlight rows. After each click you're only adding intervals.
You could store the interval ID, the result of setInterval and clear this interval when you change from column to row highlight and vice versa. The easier solution is moving from setInterval to setTimeout as outlined in the changed I've shown you above.

Categories

Resources