Sequential Arrangement of JavaScript Functions

Does anyone know how to create an HTML element and then drag it across the screen?

I have a function that defines the movement of the element, and I can click on the header to drag the div wherever I want. Additionally, I created a button to add a new div item. Even though the new div appears correctly with the applied styles, there is an issue when trying to use both functions together.

The console error 'Cannot set property 'onmousedown' of null at dragElement' keeps appearing regardless of whether the div item is created before or after running the function.

I've attempted invoking the newHTMLitem() function within dragElement(), but it doesn't solve the problem. On the contrary, if newHTMLitem() is invoked at the end of the script, the HTML item does not show up at all. Any suggestions on how to resolve this issue?

document.getElementById('addItem').addEventListener('click',function newHTMLitem(){
  
  let div = document.createElement('div');
  div.classList.add('mydiv');
  let header = document.createElement('div');
  header.classList.add('mydivheader');
  let body = document.createElement('p');

  div.appendChild(header);
  div.appendChild(body);

  document.body.appendChild(div);
}
);

//Make the DIV element draggagle:
dragElement(document.querySelector(".mydiv"));

function dragElement(elmnt) {


  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.querySelector(".mydivheader")) {
    /* if present, the header is where you move the DIV from:*/
    document.querySelector(".mydivheader").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
  
} 

Answer №1

There were a few mistakes that needed to be addressed,

e.target.style.top = (e.target.offsetTop - pos2) + "px";
e.target.style.left = (e.target.offsetLeft - pos1) + "px";

You originally had elmt.style.top, however, the correct way is to use event.target in event listeners.

In addition, you forgot to attach your event listener to the newly created element and also needed to move 3 functions to the top as they are used by the listeners. Here's what I added:

  div.onmousedown = dragMouseDown;

I created some additional functions for better functionality:

function dragMouseDown(e) {
  e = e || window.event;
  e.preventDefault();
  // get the mouse cursor position at startup:
  pos3 = e.clientX;
  pos4 = e.clientY;
  document.onmouseup = closeDragElement;
  // call a function whenever the cursor moves:
  document.onmousemove = elementDrag;
}

function elementDrag(e) {
  e = e || window.event;
  e.preventDefault();
  // calculate the new cursor position:
  pos1 = pos3 - e.clientX;
  pos2 = pos4 - e.clientY;
  pos3 = e.clientX;
  pos4 = e.clientY;
  // set the element's new position:
  e.target.style.top = (e.target.offsetTop - pos2) + "px";
  e.target.style.left = (e.target.offsetLeft - pos1) + "px";

}

function closeDragElement() {
  /* stop moving when mouse button is released:*/
  document.onmouseup = null;
  document.onmousemove = null;
}

document.getElementById('addItem').addEventListener('click', function newHTMLitem() {

  let div = document.createElement('div');
  div.classList.add('mydiv');
  let header = document.createElement('div');
  header.classList.add('mydivheader');
  let body = document.createElement('p');

  div.appendChild(header);
  div.appendChild(body);

  document.body.appendChild(div);
  div.onmousedown = dragMouseDown;
});

//Make the DIV element draggable:
dragElement(document.querySelector(".mydiv"));

function dragElement(elmnt) {
  var pos1 = 0,
    pos2 = 0,
    pos3 = 0,
    pos4 = 0;
  if (document.querySelector(".mydivheader")) {
    /* if present, the header is where you move the DIV from:*/
    document.querySelector(".mydivheader").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }


}
.mydivheader {
  background: #ccc;
  padding: 20px;
  position: absolute;
}

#addItem {
  margin-top: 60px;
}
<div class="mydivheader">Header</div>
<button id='addItem'>Add item</button>

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

Tips for effortlessly moving content by dragging and dropping it into a text box

Before attempting to create something, I want to verify its feasibility. Begin with a text area that can be pre-filled with text and allow users to add or delete text. Alongside the text area, there are small elements that can be images or HTML components ...

Concealing elements using react navigation

Just diving into React.js and I've got a question regarding react router. I'm a bit confused about nested routes in react router. Let's say we have the following code snippet (taken from react-router's github page) <Router> < ...

Error encountered while fetching files from Google Cloud bucket using Firebase functions: RangeError - Maximum call stack size exceeded

I'm currently trying to access Firestore backup files stored in a Google Cloud bucket: export const retrieveFirestoreBackup = functions.https.onCall( async (data: RetrieveFirestoreBackupPayload, context) => { try { return await sto ...

How can I position a div to always display directly above another div?

I am currently working on centering a div and would like to utilize this jQuery function... jQuery.fn.center = function () { this.css("position","absolute"); this.css("top", (($(window).height() - this.outerHeight()) / 2) + ...

Disregarding NPM dependencies for individual packages

I need to include a package (d3.js) in my project's package.json. However, when I run npm install, I do not want npm to install any dependencies related to d3.js or run any install scripts for it. Essentially, I want npm to only fetch and unpack the p ...

Achieving CommonJS imports compilation with Typescript

In my TS file, I've included a 3rd party package using import XXX { YYY, ABC, 123 } from 'XXX'; While it compiles to CommonJS without any issues, I'd prefer to have it compiled to an ESModule instead. I tried changing the target and mo ...

When using next.js, a warning may be encountered that states: "A value of NaN was received for the `children` attribute. To resolve this, ensure the value is cast as

I am currently tackling my first Next.js project and have created a file called myCart.js. Below is the code snippet: function orderCard(arr1) { //Code here... } let noRefresh; function makeGetRequest() { //Code here... } export default makeGetReques ...

Issue with Moment.js incorrectly formatting date fields to a day prior to the expected date

Currently, I am attempting to resolve a small issue in my code related to a tiny bug. In my React component, I have set an initial state as follows: const initialFormData = Object.freeze({ date: Moment(new Date()).format('YYYY-MM-DD'), pr ...

Transform your VML files into high-quality PDF documents

How can I convert VML (SVG on IE browsers) formats to PDF format using either PHP or JavaScript? ...

The date format in AngularJS is not being displayed correctly according to the request

My goal is to retrieve the date in the format of dd/MM/yyyy and pass it along to my URI. However, I am encountering an issue where the date is not being passed in the requested format. Below is the snippet of my HTML code: <script type="text/ng-templat ...

Using JavaScript, display JSON data retrieved from a PHP file

Currently, I am in the process of developing a web application that displays tweets based on a city inputted by the user through an HTML form. The city value is stored in the $_SESSION['city'] variable after the form is submitted. Subsequently, ...

When referencing a particular React commit in package.json, it may result in the installation of react-tools instead of react itself

After including the following line in my package.json: "react": "git://github.com/facebook/react.git#08e4420019f74b7c93e64f59c443970359102530" When I execute npm install, I notice that node_modules/react-tools has been installed instead of node_modules/r ...

Combine an array of objects that are dynamically created into a single object

Having trouble transforming the JSON below into the desired JSON format using JavaScript. Current JSON: { "furniture": { "matter": [ { "matter1": "Matter 1 value" }, { "matter2": "Matter 2 value" }, { ...

Creating a unique texture for a custom geometry mesh using Three.js

I'm currently working on constructing a house geometry and applying various textures to the faces of the geometry. The framework I'm using is r55. However, I'm facing an issue where faces with materials generated from textures are not appear ...

What steps should I take to either combine my two functions in my script or ensure they are executed in a specific sequence?

I'm attempting to incorporate a script into an HTML file (based on the solution provided by "skara9" in this post) and customize it to suit my requirements. However, I'm struggling to figure out how to make it work as intended. The script consis ...

Incorporate an external JavaScript script using code

I'm currently working on integrating a map widget from 'Awesome Table' into the codebase of an open-source CRM platform. The specific code snippet I need to add is <div data-type="AwesomeTableView" data-viewID="-KLtnY5OHJPgnEOX1bKf"> ...

The implementation of a custom event for jQuery rows is not functioning as expected

I need assistance with jQuery code to add click events only to columns in a row that have text in the first column. Specifically, I want to hide rows containing "1/" in the first column when clicked on for the first row. <table class="results"> < ...

Losing focus issue with Material-UI TextField occurs constantly with every onChange event

I am in the process of developing a new component: https://i.stack.imgur.com/czM9i.png This component will consist of an array of objects, each representing a prescription. Each object will include the medicine name selected from a dropdown and a text fi ...

The appearance of an unforeseen * symbol caused a

Having issues with this particular line of code, import * as posenet from '@tensorflow-models/posenet' The error 'Uncaught SyntaxError: Unexpected token *' keeps popping up, I have the latest version of Chrome installed and I've ...

What is the best way to use jQuery to fill a dropdown menu with options from a JSON object?

Looking to populate a dropdown box #dropdown with values from a json object stored in a JavaScript string variable. How can I access each element as value/label pairs and insert them into the dropdown? The structure of the json string is as follows: [{"n ...