RhumB
RhumB

Reputation: 141

Move buttons on a page using JavaScript

My button can move, but weirdly, I can't figure out if it's something wrong with the offset.

I want my buttons to move with my mouse cursor, but now it's moving not in a way that I want and sometimes it disappears.

Also, the new buttons created are overlapping, I don't know how to solve that and have a nicer look.

var coorA;
var coorB;
var btn = null;

function mousedown() {
    if (event.target.tagName === "BUTTON") {
        btn = event.target;
        coorA = btn.offsetTop;
        coorB = btn.offsetLeft;
    }
}

function mouseup() {
    btn = null;
}

function mousemove() {
    if (btn !== null) {
        btn.style.top = (event.clientY - coorA) + "px";
        btn.style.left = (event.clientX - coorB) + "px";
    }
}

function createButton() {
    var button = document.createElement("BUTTON");
    var msg = document.getElementById("word").value;
    if (msg.length > 0) {
        var t = document.createTextNode(msg);
        button.appendChild(t);
        document.body.appendChild(button);
    }
    document.getElementById("word").value = "";
}
document.getElementsByTagName("body")[0].addEventListener("mousedown", mousedown);
document.getElementsByTagName("body")[0].addEventListener("mousemove", mousemove);
document.getElementsByTagName("body")[0].addEventListener("mouseup", mouseup);
body {
    background-color: black;
}
#word {
    padding: 10px 30px;
    font-size: 14px;
}

button {
    position: absolute;
    background-color: #e7e7e7;
    color: #000;
    font-weight: 700;
    padding: 10px 30px;
    font-size: 14px;
    border: 1px solid gray;
}

#add {
    position: relative;
    background-color: #e7e7e7;
    color: #000;
    font-weight: 700;
    padding: 10px 30px;
    font-size: 14px;
}
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <title>Poetry-yuc217</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        

    </head>
    <body>
        <div>
            <form>
                <input id = "word" type = "text" name = "word">
                <input id = "add" type = "button" value = "Add Word" onclick = "createButton()">
                <br>
                
            </form>
            <button type="button" >this</button>
               

        </div>


        
   

enter code here
    </body>
</html>

Upvotes: 3

Views: 2246

Answers (2)

DROP DATABASE
DROP DATABASE

Reputation: 46

Answer to your question in the comments:

Thanks so much! I am still little confused about what "event" actually refers to. From what I learned, event is all the actions on the page. And that is not so clear...

In your code you have referenced the event object but haven't passed it as an argument. I believe you confusion may stem from this. Well, I was curios myself, and oh boy, down the rabbit hole I went...

I'll try to be as simple & general as I can, as I myself have yet completely wrapped my understanding of this.

OK, so there are different types of events in the browser. You probably know some of the standard ones such as "click, "onload", "keydown" etc. If you wish your code to do something when such an event occurs, you'll choose a DOM element such as <button>, <div> etc (generally speaking, because there are also non-DOM related events, you can read all about it here https://developer.mozilla.org/en-US/docs/Web/Events). You then attach this element to a function that will be invoked when the said event is triggered.

There are different ways of attaching such a function (which BTW is also called the event handler or event listener). When attaching the event handler, something called the EventListener interface is being implemented. A function that was triggered through an event will get an argument, a Event object, courtesy of the interface (https://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#glossary-event-handler).

BUT!!! If you attach an event using the inline method i.e <a onclick="myFunc();" /> your function will receive the argument (the event) only if "event" is written inside the function, i.e <a onclick="myFunc(event);" />.

You can observe this odd behavior and the different types of event attaching in this JSFiddle:

https://jsfiddle.net/duwed8kg/

I am uncertain as to why this happens, but it's a damn good subject for new question.

P.S, Regarding your code and the main question (for which I only provided the code, sans an explanation) -- It is problematic in different ways (the inline event attaching, element selection via tag names for ex), I focused on solving your problem with minimal changes to your code/style, but please be aware of it.

var coorA;
var coorB;
var btn = null;
var lastMouseX;
var lastMouseY;

function mousedown() {
    if (event.target.className.indexOf("listButton") > -1) {
        btn = event.target;
        if(btn.style.top === "" || btn.style.left === "") {
          btn.style.position = "absolute";
          btn.style.top = btn.offsetTop + "px";
          btn.style.left = btn.offsetLeft + "px";
        }
        coorA = btn.offsetTop;
        coorB = btn.offsetLeft;
    }
}

function mouseup() {
    btn = null;
}

function mousemove() {
    if (btn !== null) {
        btn.style.top = parseInt(btn.style.top) + (event.clientY - lastMouseY) + "px";
        btn.style.left = parseInt(btn.style.left) + (event.clientX - lastMouseX) + "px";
    }
    lastMouseX = event.clientX;
    lastMouseY = event.clientY;
}

function createButton() {
    var button = document.createElement("BUTTON");
    var msg = document.getElementById("word").value;
    if (msg.length > 0) {
        var t = document.createTextNode(msg);
        button.appendChild(t);
        button.classList.add("listButton");
        document.getElementsByClassName("container")[0].appendChild(button);
    }
    document.getElementById("word").value = "";
}
document.getElementsByTagName("body")[0].addEventListener("mousedown", mousedown);
document.getElementsByTagName("body")[0].addEventListener("mousemove", mousemove);
document.getElementsByTagName("body")[0].addEventListener("mouseup", mouseup);
document.getElementById("add").addEventListener("click", createButton);
body {
    background-color: black;
}

.container {
  position:relative;
  height:1000px;
}

#word {
    padding: 10px 30px;
    font-size: 14px;
}

button {
    background-color: #e7e7e7;
    color: #000;
    font-weight: 700;
    padding: 10px 30px;
    font-size: 14px;
    border: 1px solid gray;
}

.listButton {
    margin-right: 5px;
    margin-top: 5px;
    float: left;
}
#add {
    position: relative;
    background-color: #e7e7e7;
    color: #000;
    font-weight: 700;
    padding: 10px 30px;
    font-size: 14px;
}
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <title>Poetry-yuc217</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        

    </head>
    <body>
        <div class="container">
            <form>
                <input id = "word" type = "text" name = "word">
                <input id = "add" type = "button" value = "Add Word">
                <br>
                
            </form>
            <button type="button" class="listButton">this</button>
               

        </div>


        
   

enter code here
    </body>
</html>

Upvotes: 3

Devnsyde
Devnsyde

Reputation: 1347

To fix the over-lap create an un-ordered list and then append<li><button type="button" >fieldValue</button></li>to the un-ordered list.

<ul id="buttonList">
     <li><button type="button" >this</button></li>
     <li><button type="button" >that</button></li>
     <li><button type="button" >the other</button></li>
</ul>

As for the moving button I wasn't able to replicate, they had some lag but they were moving fine for me, maybe if you need additional assistance you can prepare a demo using jsfiddle.

Upvotes: 1

Related Questions