Making a html element that acts like a window - javascript

I'm trying to make a window-like HTML element that functions like window.open but only works within the bounds of the page.
I've run into 3 problems:
The first being that I don't know how to change the size of it
How to open and close it I want to click on Icon and make it open and also how to close it. It's already draggable so that the one thing going for it.
How to set the initial position of it. if anyone has a better method cause I'm still super new to coding and just got this off of W3schools anything would be useful.
This is what I want my end goal to look like
//Make the DIV element draggagle:
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "header").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;
}
}

Size - to change the size of an element you can simply edit the its style.width and style.height. If you would like to have a draggable resizing cursor, like with a real window, you would need to create a transparent element that covers the resizing activation areas, and listen to its events like you listen to the window dragging.
Initial position - just like you set the dragged position, you can set an initial one.
As for the opening and closing, you would most likely need to restructure the app a bit and build some abstractions. Try to think of a way to have a createNewWindow function that accepts arbitrary HTML content and just shows a window. Within that function you would add a "header" to the content, add resizing areas, add close/minimize/maximize buttons, add the window to a global array of windows (so that you can display a bottom bar with window titles and unminimize when needed).
There's no single answer here, you can build an app like that in a million different ways. Focus on abstracting things away.

Related

Dragable element gets stuck after inserting second one

Hello I want to learn a bit more about javascript because i'm very new to javascript coding. I'm trying to create a small script that when you press a button a new Dom structure is created and it creates a small structure.
so far so good. After this my idea was to let those newly created structures be drageable.
I found some code from w3schools.com to create a dragable div.
now I'm running into a problem. when i create 1 new div structure I can drag this structure all around. after I create a 2nd one my entire javascript code seems to crash because I cannot move both the structures around my screen.
I think it got something to do with the creating of the div and that I name it 'mydiv'.
but this is just a guess (like I said i'm very new to Javascript coding)
DIV create code
function createDiv() {
let dom = '<div id="mydiv"><div id="mydivheader" class = "Filter"><button>test 1</button></div></div>';
let template = document.createElement("template");
template.innerHTML = dom;
document.body.innerHTML += template.innerHTML;
}
Dragable code
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "header").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;
}
}
HTML code Note: I added some jqueary scripts and other things like boodstrap in the hopes of getting it to work
<!DOCTYPE html>
<html lang="en">
<head>
<title>create dragable DOMS</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
</head>
<body>
<div>
<button onClick="createDiv()"> create </button>
</div>
<div>
</div>
</body>
<script> see code block </script>
Hey you forgot to add the css for us to see your draggable element !
First of all :
document.body.innerHTML += template.innerHTML;
Break all listeners when you execute that code , innerHTML parse the html code into string before adding a content and parses again to HTML Objects... losing all events associated in the page ..
So we gonna use :
document.body.appendChild()
Also , the element template doesnt works well for this ! Turns what is inside into document fragment . I'll use div in this example .
let myDiv = document.createElement("div")
Also made an 'counter' for you manage better all this .
See in action :
<!DOCTYPE html>
<html lang="en">
<head>
<title>create dragable DOMS</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<style>
#myDiv {
position: absolute;
width: 100px;
}
#mydivheader {
background: #9494fd;
}
#mydivheader > button {
margin-top: 20px;
width: 100%;
}
</style>
</head>
<body>
<div>
<button onClick="createDiv()"> create </button>
</div>
</body>
<script>
function createDiv() {
const counter = document.getElementsByClassName('myDiv').length;
let dom = '<div id="mydivheader" class = "Filter"><button>test '+counter+'</button></div>';
let myDiv = document.createElement("div");
myDiv.id = 'myDiv';
myDiv.className = 'myDiv';
myDiv.innerHTML = dom;
document.body.appendChild(myDiv);
myDiv.addEventListener('click', dragElement(myDiv), true);
}
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "header").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;
}
}
</script>

Vanilla javascript draggable div within parent

I want to achieve a draggable element in vanilla javascript.
I want to make a small circular div draggable within a square div.
To make myself a bit more clear, I do NOT want to:
Create drag and drop,
Use jQuery UI or any other library or plugin to achieve this, just vanilla javascript
I already have a few events for handling dragging:
parent.addEventListener("mousedown", ..),
document.addEventListener("mouseup", ..)
and
document.addEventListener("mousemove", ..)
My question is how can I keep the draggable inside the given bounds of its parent?
Reference: https://codepen.io/ChickenFlavored/pen/rNxRXGo
You may use getBoundingClientRect that gives DOMRect object(an invincible rectangle that encompass the object) with eight properties: left, top, right, bottom, x, y, width, height.
var parent = document.querySelector('.parent');
var parentRect = parent.getBoundingClientRect();
var draggable = document.querySelector('.draggable');
var draggableRect = draggable.getBoundingClientRect();
You can get the mouse (X,Y) coordinates anytime by using e.clientX and e.clientY, so just check if they are outside the bounding rectable of .parent div if so then only update the draggable div's left and top properties
if( (e.clientX >= parentRect.left && (e.clientX+draggableRect.width <= parentRect.right)) &&
(e.clientY >= parentRect.top && (e.clientY+draggableRect.height <= parentRect.bottom))
//+draggableRect.height and +draggableRect.height accounts for the size of ball itself
){
draggable.style.left = `${e.clientX}px`;
draggable.style.top = `${e.clientY}px`;
}
Note that numbers increase down and towards right in graphics world
https://codepen.io/vsk/pen/PozVryr
UPDATE:
To fix the issue mentioned in comment use this
if(/* mouse was moved withing red container's bounds*/)
else{
//if mouse went out of bounds in Horizontal direction
if(e.clientX+draggableRect.width >= parentRect.right){
draggable.style.left = `${parentRect.right-draggableRect.width}px`;
}
//if mouse went out of bounds in Vertical direction
if(e.clientY+draggableRect.height >= parentRect.bottom){
draggable.style.top = `${parentRect.bottom-draggableRect.height}px`;
}
}
And assign mousemove to document insted of the div container
I hope you could provide a code snippet to try to simulate what you want, a codepen url, codesandbox or similar.
I made this sample using what you provided : )
let x = event.clientX - element.offsetLeft
const elementWidth = element.clientWidth
const fullX = x + elementWidth
const containerW = yourContainer.clientWidth
if(fullX > containerW){
//If element will be out of container
x = containerW - elementWidth // So it will be never out of container
}
element.style.transform = "translate("+x+"px, "+y+"px)"

Scroll the page when the user's mouse reaches the top/bottom of the page

I'm trying to create drag-and-drop and I want my window to be scrolled in case I start the drag and reach the top / bottom of my page until I come out of the top/bottom "zone". So far what I have written works differently and I can't figure out a way to make it work the way I want.
Is there any way to do so using vanilla JS?
let mouseDown = true;
function mousedown() {
mouseDown = true;
}
function mouseup() {
mouseDown = false;
}
if (!document.querySelector(".arrow-timeline")) {
this.element.addEventListener('mousemove', function() {
let x, y;
function handleMouse(e) {
// Verify that x and y already have some value
if (x && y && mouseDown) {
// Scroll window by difference between current and previous positions
window.scrollBy(e.clientX - x, e.clientY - y);
}
// Store current position
x = e.clientX;
y = e.clientY;
}
// Assign handleMouse to mouse movement events
document.onmousedown = mousedown;
document.onmousemove = handleMouse;
document.onmouseup = mouseup;
})
}

Javascript code getElementByID with C# loop

I'm trying to use draggable HTML/JS on my code, but I get an issue when I try to loop over each element.
I don't overcome to convert my code from a single element to a foreach loop.
This is my code:
# CSS CODE
<style>
#mydiv {
position: absolute;
z-index: 9;
background-color: #f1f1f1;
text-align: center;
border: 1px solid #d3d3d3;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
</style>
# HTML CODE
<div id="mydiv">
<div id="mydivheader">
Firstname Lastname
</div>
</div>
# JAVASCRIPT CODE
<script>
//Make the DIV element draggagle:
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "header").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;
}
}
</script>
It works for one element like the example above.
But I would like to loop like this:
# HTML CODE
#foreach (var player in Model.PlayersToMatchs)
{
<div id="mydiv#(player.Player.PlayerID)">
<div id=" mydivheader#(player.Player.PlayerID)">
#player.Player.Firstname #player.Player.Lastname
</div>
</div>
}
I tried to modify my Javascript part by changing the first line to take into account the partial id:
dragElement(document.querySelector('[id^="mydiv"]').id);
But How I can rewrite this part:
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
/* otherwise, move the DIV from anywhere inside the DIV:*/
elmnt.onmousedown = dragMouseDown;
}
Thank you !
As Heretic Monkey said, querySelector only returns the first element, you need to use querySelectorAll to get all elements and then loop the elements array to call the dragElement function.
var elements = document.querySelectorAll('[id^="mydiv"]');
elements.forEach(element=> {
dragElement(element);
}
);

drag&drop of div element

I have a rectangular div element on a page with image and text span inside.
Div has 2px border to make it actually visible.
Then I add dragstart event listener to my div element.
dragstart event fires always if I start dragging the image inside div but it is very problematic if I start dragging by clicking on text span or blank place:
In Google Chrome dragging is very unstable. It can work a few times then stops firing, then work again and so on.
In Mozilla Firefox it doesn't work at all.
How to fix it and allow drag by clicking on any point inside bound rect of my div?
<div class="item">
<img src="https://www.wigwam3d.com/previews/1f/1ffbf8da-a4d0-4e40-b9e1-0329220969dc.jpg">
<div>Element</div>
</div>
Plunker: http://plnkr.co/edit/673ytif50cViE5dTv3df?p=preview
Use this code , you can drag div anywhere on the window. Also fix width and height of the div.
$(function(){
$("#animation").css({"cursor":"move"})
// mousedown:fn(){dragging = true;}
var dragging = false;
var iX, iY;
$("#animation").mousedown(function(e) {
dragging = true;
iX = e.clientX - this.offsetLeft;
iY = e.clientY - this.offsetTop;
this.setCapture && this.setCapture();
return false;
});
// mouseover:fn(){dragging = tru;}
document.onmousemove = function(e) {
if (dragging) {
var e = e || window.event;
var oX = e.clientX - iX;
var oY = e.clientY - iY;
$("#animation").css({"left":oX + "px", "top":oY + "px"});
return false;
}
};
// mouseup:fn(){dragging = false;}
$('#animation').mouseup(function(e) {
dragging = false;
this.releaseCapture && this.releaseCapture();
e.cancelBubble = true;
})
})
Just found a simple solution: add attribute draggable=true on div element! That's all!

Categories

Resources