Verify if there are DOM elements located within a DIV container, execute the functions associated with those elements sequentially

I am in the process of creating a game using HTML, CSS, and JavaScript. My focus right now is on manipulating DOM elements without relying on the canvas tag. The goal is to develop a pseudo graphical programming language, similar to the environment provided by Blockly. I have already added 3 clickable elements inside #toolbox that create duplicates in #workspace.

Now, my task is to assign functions to the elements within #workspace. When the Run button is clicked, these functions should execute in the order they appear, creating a sequence of commands to move the pink square inside #output_section.

However, I'm struggling with writing the function that can detect the presence of elements and execute the assigned functions for each element.

Any suggestions or ideas? :D

I am working with Jquery version 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>

Answer №1

Not tested, but when the run button is clicked, the following script might be executed:

$("#run_workspace").click(function() {
    $("#workspace .block").each(function(element) {
        if (element.hasClass("red")) {
            moveObjectLeft();
        }  else if (element.hasClass("green")) {
            moveObjectRight();
        }  else if (element.hasClass("blue")) {
            moveObjectUp();
        } 
    });
});

Answer №2

It's often recommended to organize all necessary data in arrays and objects, utilizing HTML solely for presenting the information.

In addition, if jQuery is already implemented - it can be used for all tasks)
Here are some enhancements:

let mobs = {
  pinky: {
    node: $('#moving_square'),
    coors: { top: 400, left: 400 },
    step: 30,
    moveQueue: [],
    // moveTimeout ??? 
  },
}; // All created moving objects kept here.
/* Each [moveQueue] array will store the sequence of movements, like ["up", "up", "left"]

You can match each movement "keyword" with the corresponding function by using the 'move' object */

let move = { // Consider simplifying this object and its functions. It's doable!)
  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 active timeouts here, and clear them as needed

$('#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() ); // Adaptable to any other selected object
});

$('#run_workspace').on('click', function () {
  running = true;
  runCode();

  function runCode() {
    for (let obj in mobs) { // Multiple mobile objects may exist
      // Inside the loop, obj corresponds to each key name in mobs. Currently, it's "pinky"
      
      let i = 0;
      let pinky = mobs[obj];

      localRun();
      
      function localRun() {
        let direction = pinky.moveQueue[i]; // Retrieve direction key by array index
        
        move[direction](pinky); // Call the necessary function from storage

        if (pinky.moveQueue[++i] && running ) {
          // If moveQueue has the next element, self-call again while incrementing i by +1
          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>

Although... jQuery was utilized primarily for handling clicks. Conversion 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) { // Possible presence of multiple mobile objects
      // Inside the loop, obj matches each key name in mobs. Here, it corresponds to "pinky"
      
      let i = 0;
      let pinky = mobs[obj];

      localRun();
      
      function localRun() {
        let direction = pinky.moveQueue[i]; // Extract the direction key based on the array index
        
        move[direction](pinky); // Invoke the relevant function from storage

        if (pinky.moveQueue[++i] && running ) {
          // Once there's a subsequent element in moveQueue, initiate self-calling while incrementing i by +1
          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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Question about Selecting Boxes

I'm looking for the name of the HTML tool that is used to create a list of objects from a select field. It typically consists of two boxes with an arrow in between them. For example, when creating a group, Box A would contain a list of users and you c ...

Having difficulties loading my stylus stylesheet onto my jade HTML page using expressjs

Within my express application, I am attempting to load the style properties from a styles module engine. Unfortunately, I am facing difficulties in loading my style. Here is the structure of my folders: myNodeApp -node_modules -styles - ...

One set of objects is active in retrieving data, while the other remains inactive

I'm working with an array of objects and here is what it looks like: const default_apps = [ { 'post_title': 'Excel', }, { 'post_title': 'Word', }, { 'post_title': 'SharePoi ...

Having trouble getting my Sequelize model to export properly

For my school project, I am developing an e-commerce website and encountering an issue with connecting my GoogleStrategy to my SQLite database. The goal is to store user data in a table, but whenever I try to call the variable in my passport-setup file, an ...

SignalR does not include cookies in the connection request

While working on a web application using ASP.NET Web API and SignalR, I encountered an issue that is proving to be quite challenging despite my understanding of HTTP. Currently, I have successfully set a cookie on all AJAX requests to the API, and subsequ ...

What is the best way to showcase the reading from a stopwatch on my screen?

Working on these codes has been quite a challenge for me. I have recently embarked on a JavaScript journey as a beginner and attempted to create a stopwatch project. However, it seems like I may have missed the mark with the logic or implementation somewhe ...

Assigning arbitrary hidden form data from dropdown selection

Would like to assign Layers Value as one of the following: GFS Meteogram 3day std or WRF 20 Global Meteogram 3day Std depending on the option selected from the dropdown menu <div><select id="myselect" class="productViewerParameter" name=" ...

How can labels be added when mapping over JSON data?

If I have JSON data structured like this: { "siteCode": "S01", "modelCode": "M001", "modelDesc": "Desc01", "price": 100 "status": "A", "startDate": "Ma ...

Click the button to trigger an AJAX request that sends the values from the forms within a while loop

Can someone help me figure out how to send input values through AJAX when a button is clicked? Below is my code. Appreciate any assistance. while { <form class="commentform"> <input type="hidden" class="proid" name="proid" value="<?= ...

Display a list next to a block of text and image using HTML and CSS styling

I am having trouble with keeping a navigation list aligned inline with a block of text that includes an image. My issue arises when I expand the browser to full screen size, causing the list to overlap the text block. Here is the HTML code snippet: <bo ...

The Chrome Extension is unable to recognize a portion of the URL following the # symbol in the contentscript.js code

I am currently developing an extension for a specific website that I don't have ownership of. The URLs on this site only change after a /#/. For instance, starting from the URL .../#/PF/charts/patients/419d3081-5e20-4347-a852-52b2c333ce85/summary W ...

Looking for insights on reading and presenting XML files from a URL? Learn how to achieve this effortlessly with the power

Currently, I'm in the process of developing an innovative Android application using PhoneGap. My main objective is to dynamically present the data stored within a customized XML file hosted on my website that follows the .php format. Do you happen to ...

Is the fs.watch method being triggered unexpectedly?

As a beginner in node.js and javascript, I've been experiencing an error with the following code snippet: fs.watch('F:/junk', (eventType, filename) => { if(filename && filename.split('.')[1].match("zip")) { ...

How can we access state data in a Vuex component once it is mounted?

My goal is to initialize a Quill.js editor instance in a Vue component once it is loaded using the mounted() hook. However, I am facing an issue where I need to set the Quill's content using Quill.setContents() within the same mounted() hook with data ...

Encountering an issue when trying to submit a post request: "Received an API resolution without a response for /api/comments, which could lead to delayed requests."

Hey, I recently started diving into Next.js and I'm facing an issue with making a POST request to the API. In my project structure, I have a comments folder nested inside the api folder. Within the comments folder, I've written the following cod ...

"Implementing a dynamic loading effect in Highcharts triggered by a button

Take a look at this sample highchart fiddle: http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/members/series-setdata/ $('#button').click(function () { var chart = $('#containe ...

Importing textures and loading mtl files in Three.js from various web addresses

Something strange is happening with my Roblox API integration. I'm trying to retrieve the OBJ file, MTL file, and Texture file using the API. The main API link I have is https://t2.rbxcdn.com/ef63c826300347dde39b499e56bc874b, which leads me to two cru ...

Ways to include margin right for a table

Here is the HTML code I am working with: <table width="100%;> <tr><hr style="width:100%;"></hr></tr> <tr> <span style="float:left">abc</span> <span class="noindex" ...

What could be the reason for the child element not occupying the full height of its parent container?

* { padding: 0; margin: 0; box-sizing: border-box; } body { margin: 50px; } .navbar { display: flex; align-items: center; justify-content: center; color: darkgreen; font-family: 'Vollkorn', serif; font-size: 1.2rem; font-w ...

Step-by-step guide for integrating a Twig file in Symfony using Angular's ng-include feature

Seeking guidance in Angular, as a newcomer to the platform. I attempted to load a template within an ng-repeat loop like so, but encountered an error. I received the following error message: "Cross origin requests are only supported for protocol schemes ...