Making an Element draggable without ID - javascript

I'm trying to make divs created with .createElement be draggable. It works fine with divs that are already created like below:
<div>
This can be dragged around, but outputs cannot?!
</div>
but when I create new divs with the function addElement(), it doesn't work.
In more detail here is what my code aims to do:
user inputs text -> clicks input button and the user input(s) are outputted on the screen and can be dragged.
Full code:
function addElement () {
var text = document.getElementById("input").value;
// create a new div element
var newDiv = document.createElement("div");
// and give it some content
var newContent = document.createTextNode(text);
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
document.getElementById("input").value = " ";
}
$( function() {
var div = document.getElementsByTagName('div');
$( div ).draggable();
} );
div { width: 150px; height: 150px; padding: 0.5em; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<input id="input"type="text" placeholder=" text">
<button onclick="addElement()" >Input</button>
<p>Outputs:</p>
<script src="script.js"></script>
</body>
</html>
<div>
This can be dragged around, but outputs cannot?!
</div>
</body>
</html>

When you load the page, the draggable gets attached to the div element which is already loaded. But when you dynamically create a new element, the draggable is not re-attached to the new div. So, whenever you add a new div, you need to re-attach the draggable event to it:
function addElement() {
var text = document.getElementById("input").value;
// create a new div element
var newDiv = document.createElement("div");
// and give it some content
var newContent = document.createTextNode(text);
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
$(function() {
var div = document.getElementsByTagName('div');
$(div).draggable();
});
document.getElementById("input").value = " ";
}
$(function() {
var div = document.getElementsByTagName('div');
$(div).draggable();
});
div {
width: 150px;
height: 150px;
padding: 0.5em;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<input id="input" type="text" placeholder=" text">
<button onclick="addElement()">Input</button>
<p>Outputs:</p>
<script src="script.js"></script>
</body>
</html>
<div>
This can be dragged around, but outputs cannot?!
</div>
</body>
</html>

When you load the page, the draggable gets attached to the div element which is already loaded. But when you dynamically create a new element, the draggable is not attached to the new div. Whenever you add a new div, you need to re-attach draggable event to it.

You only run
$( function() {
var div = document.getElementsByTagName('div');
$( div ).draggable();
} );
when your app loads for the first time, therefore newly created divs are not draggable.
When you want the new divs to be draggable, you have to add $( newDiv ).draggable() to your addElement() function.

You are using $(callback), which only calls the function once when the DOM is loaded.
However, when you add new elements, they will not be made draggable since the function that does it has already run.
To make the new elements draggable too, you will need to call jQuery.draggable() on them as well after creating them.
This means, you should add newDiv.draggable() inside your function that creates the elements.
Sidenote
When using an API like jQuery, you should try to stick to it rather than the native methods to make understanding it easier, since one wouldn't have to go back and forth in their mindsets.
Subnotes
You have incorrect HTML since you have a <div> after closing both <body> and <html>, and are trying to close them again at the end. Since HTML disallows elements outside of <body>, most browsers automatically correct this mistake. However, you should format the HTML correctly yourself.
Creating jQuery-elements using $(document.createElement('div')) instead of using $('<div>') is (minimally) faster, hence I use it below
Do not add the onclick-listener in the HTML, instead, add it using JavaScript. Adding the listener inline would require the function to be exposed in the global scope, and would pollute the global namespace. Listeners do not require to be named, and can easily be added in JS, allowing to not expose the functions to the global scope.
Making your code use mostly jQuery would make it look like this:
$(function() { // Executed once DOM loaded
// Make all pre-existing 'div's draggable
$('div').draggable();
// Add the 'onclick'-listener using jQuery
$('button').click(function() {
// Creating jQuery-element this way; read about the reason in the sub-notes
var newDiv = $(document.createElement("div"));
newDiv.text($('#input').val()); // Set the text to the value of 'input'
newDiv.draggable(); // Make it draggable
$('body').append(newDiv); // Append it to the body
$('#input').val(''); // Set 'input's value to ""
});
});
div {
width: 150px;
height: 150px;
padding: 0.5em;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<input id="input" type="text" placeholder="text">
<button>Input</button>
<p>Outputs:</p>
<div>
This can be dragged around, but outputs cannot?!
</div>
</body>
</html>

Related

Why the JavaScript function doesn't work?

If you click the button, it should have showed, but it doesn't.
Is any wrong here?
I have written many JavaScript files in this way, and tried many ways like changing the position of JavaScript code anywhere. But all the files I wrote don't work
Thanks in advance!
An instance :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Debug</title>
</head>
<style>
.debug {
display : none;
}
</style>
<body>
<div class = "debug">
<p>Welcome!</p>
</div>
<button class = "show" onclick = "JavaScript : show();">Show</button>
<script type = "text/JavaScript">
function show() {
document.querySelector("debug").style.display = "flex";
}
</script>
</body>
</html>
Thanks to all of you!
About .querySelector()
The Document method querySelector() returns the first Element within the document that matches the specified selector. [...] The selector is a CSS selector string.
- MDN web docs
You should, therefore, put in your code:
document.querySelector(".debug")
You can also select HTML elements by their tags, for example, you want to select the first div:
document.querySelector("div")
document.querySelector("div").style.color = "lightgreen"
<div>Hello World</div>
Imagine you had your own HTML tag: <hello>, then you can select all hello elements with:
document.querySelector("hello")
document.querySelector("hello").style.color = "lightblue"
<hello>Hello World</hello>
Side note on inline eventListeners
Also in HTML for inline event listener instead of:
<button class = "show" onclick = "JavaScript : show();">Show</button>
you can simply write:
<button class = "show" onclick = "show();">Show</button>
It is recommended to use JavaScript to initiate these eventListeners instead of having them inline inside your HTML markup. Use the .addEventListener() method:
document.querySelector(".show").addEventListener('click', show)
↑ ↑
event function
type
Back to your code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Debug</title>
</head>
<style>
.debug {
display : none;
}
</style>
<body>
<div class = "debug">
<p>Welcome!</p>
</div>
<button class ="show">Show</button>
<script type = "text/JavaScript">
document.querySelector(".show").addEventListener("click", show)
function show() {
document.querySelector(".debug").style.display = "flex";
}
</script>
</body>
</html>
Last thing
Also it's better to keep HTML, JavaScript and CSS all in separate files, for instance:
- index.html
- style.css
- script.js
And call the CSS and JavaScript files in your HTML file with the link (preferably inside <head>) and script (at the bottom of <body>) tags:
<link rel="stylesheet" type="text/css" href="style.css">
And
<script src="script.js"></script>
For class selector you need to add a dot (.) e.g. .debug
Also, in HTML, you can simply have onclick as onclick="show();"
function show() {
document.querySelector(".debug").style.display = "flex";
}
.debug {
display: none;
}
<div class="debug">
<p>Welcome!</p>
</div>
<button class="show" onclick="show();">Show</button>
You were not passing class to querySelector. Set ".debug" instead of "debug".
Below is working code:
function show() {
document.querySelector(".debug").style.display = "flex";
}
.debug {
display: none;
}
<div class="debug">
<p>Welcome!</p>
</div>
<button class="show" onclick="JavaScript : show();">Show</button>
queryselectors requires . and # for class and ID selector:
querySelector(".debug")

Setting and removing the onclick attribute

So I am trying to remove the onclick attribute from the div "#link". It will not remove. It also will not work with setting an attribute for onclick. Anything that seems to edit onclick doesn't seem to effect it. I need it to remove the attribute of "of onclick" and set it to another one. Thanks
$(document).ready(function() {
var attribute = $('#link').attr("onclick");
var linklength = (attribute.split("'").length - 1);
if (linklength > 5) {
$('#link').removeAttr("onclick");
$('#link')[0].setAttribute('onclick', 'test');
console.log(attribute);
console.log(linklength);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="link" onclick="skinPopup('UserDirectory','for name ','#userBio');">
</div>
<p id="title">Te'st</p>
Not sure what you are trying to achieve, as you already using jQuery you could simplify things. Something like this
$(document).ready(function() {
var $link = $("#link");
function skinPopup(directory, statement, id){
console.log(directory, statement, id);
}
$link.on('click', function(){
skinPopup('UserDirectory','for name ','#userBio');
});
//removing click event after 3s
setTimeout(function(){
$link.addClass('red');
$link.off('click');
// attaching mouseover and mouseout event
$link.on('mouseover', function(){
$(this).removeClass('red');
}).on('mouseout', function(){
$(this).addClass('red');
})
}, 3000)
});
.red{
background: red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="link">
Link
</div>
<p id="title">Te'st</p>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>
Note, instead of removing click event on condition I removed it after a particular time, you could add condition based on your requirements. Both attribute and linklength seemed unnecessary, that's why I removed it.
To learn more about event listeners
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
http://api.jquery.com/on/
http://api.jquery.com/off/
Hope this helps, let me know if you have any questions.

remove <style> from div class with jquery/js

I want erase a inline CSS <style> element in a <div> element. This <style> element is output from a JavaScript file.
This is the document:
<div id="rmid" class="rm">
<script type="text/javascript" src="http://domain.com/file.js"></script>
</div>
Loading this JavaScript file creates additional elements (editor's note: presumably via document.write()) , resulting in HTML markup like the following example:
<div id="rmid" class="rm">
<script type="text/javascript" src="http://domain.com/file.js"></script>
<style> ............. </style>
various content
</div>
How can I remove this when loading the page ?
If you are using jquery,
you could use
$(document).ready( function() { $( '#rmid > style' ).remove(); } );
If you plan to not use jQuery, the things changes a little bit:
var parent = document.getElementById("rmid");
parent.querySelector("style").innerHTML = "";
You can call the function <body onload="removeStyles()" This will select all the styles in your above mentioned div with #id = id.
function removeStyles(){
var sty = document.querySelectorAll('div#id style');
for(var i=0; i<sty.length; i++){
sty.item(i).remove();
}
}

Changing colour of a div using jQuery

I'm trying to change the colour of a singular div using jQuery. I'm 80% sure my code should work but I'm not sure why it's not working. I've tried to use loads of different methods such as mouseenter, hover, addClass, toggleClass etc. But for the life of me I can't figure out what's going on. Help please?
JAVASCRIPT
$(document).ready(function(){
blackMode();
genDivs(10);
});
/* Black mode - changes colours of cells to black */
function blackMode() {
$('.cell').hover(
function (){
$(this).css({"background-color":"black"});
},
function (){
$(this).css({"background-color":"white"});
});
}
/* creates the divs in a 10x10 grid */
function genDivs(v) {
var e = document.getElementById('container'); //This is what we want to append the rows
for (var i = 0; i < v; i++) {
var row = document.createElement("div"); // This creates each row that is selected.
row.className="row"; // This declares the class name for the created div.
for(var j = 0; j < v; j++) {
var cell = document.createElement("div");
cell.className="cell";
row.appendChild(cell);
}
e.appendChild(row);
}
}
HTML
<html>
<head>
<script type="text/javascript" src="jquery-1.11.3.min.js"></script>
<script src="Script.js"></script>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Raleway" />
<link rel="stylesheet" type="text/css" href="Stylesheet.css"></link>
</head>
<body>
<h1 class="title">Etch-a-Sketch</h1>
<div id="container">
</div>
</body>
UPDATE:
Sorry, I haven't notice you are in fact using .cell class on element you're inserting dynamically - but still give them some height and more important -> first insert elements and then use jQuery to bind events:
$(document).ready(function(){
genDivs(10);
blackMode();
});
another fiddle
The version you had before didn't work because by the time you called blackMode function that applied hover handlers none elements with class .cell were in DOM.
ORIGINAL ANSWER:
You are applying hover functions on elements that have cell class, but you haven't used that in your HTML. Also when your div has no contents it'll have 0px height and effect won't be visible.
Add .cell class to you div:
<div class="cell">
</div>
And give it some height via CSS (or add sth inside):
.cell {
height: 400px;
}
jsfiddle

pass CSS .class as a parameter to javascript function

the goal here is onclick of 1.gif, everything with .panel1 class disappears(style.display.none), and everything with a .panel2 class becomes visable (style.display.inline)
I'm new at this..so I think its just a syntax issue with ' ' or maybe " "
<!DOCTYPE html>
<html>
<head>
<title>main</title>
<meta charset="utf-8">
<style type="text/css">
.panel1 {display:inline;}
.panel2 {display:none;}
</style>
<script type="text/javascript">
function panelTransition(panelOut,panelIn)
{
document.getElementByClass(panelIn).style.display="inline";
document.getElementByClass(panelOut).style.display="none";
}
</script>
</head>
<body>
<img class="panel1" src=1.gif onclick="panelTransition(panel1,panel2)" />
<img class="panel2" src=2.gif />
</body>
</html>
There is no getElementByClass. It's getElementsByClassName, and it returns an array of items, so you'll need to modify your code to loop through them.
function panelTransition(panelOut, panelIn) {
var inPanels = document.getElementsByClassName(panelIn);
for (var i = 0; i < inPanels.length; i++) {
inPanels[i].style.display = 'inline';
}
var outPanels = document.getElementsByClassName(panelOut);
for (var i = 0; i < outPanels.length; i++) {
outPanels[i].style.display = 'none';
}
}
If you were using a JavaScript library, like jQuery, this would be much easier to do. Also, as has been mentioned, you need quotes around your arguments to panelTransition.
<img class="panel1" src=1.gif onclick="panelTransition('panel1', 'panel2')" />
<img class="panel2" src=2.gif />
<img class="panel1" src=1.gif onclick="panelTransition('panel1','panel2')" />
I think you need quotes there
<html>
<head>
<title>main</title>
<meta charset="utf-8">
<style type="text/css">
.panel1 {display:inline;}
.panel2 {display:none;}
</style>
<script type="text/javascript">
function panelTransition(panelOut,panelIn)
{
// panelIn gets turned on
setDisplay(panelIn,"inline");
// panelOut gets turned off
setDisplay(panelOut,"none");
}
function setDisplay(className,displayState)
{
// retrieve a list of all the matching elements
var list = document.getElementsByClassName(className);
// step through the list
for(i=0; i<list.length; i++) {
// for each element, set the display property
list[i].style.display = displayState;
}
}
</script>
</head>
<body>
<img class="panel1" src="1.gif" onclick="panelTransition('panel1','panel2')" />
<img class="panel2" src="2.gif" onclick="panelTransition('panel2','panel1')" />
</body>
</html>
Or you can accomplish the same in jQuery
// fires when the page is up and running
$(document).ready(function(){
// find all the panel1 elements,
// attach an on click handler
$(".panel1").bind("click", function(){
// find all the panel1 elements
// set their css display property to inline
$(".panel1").css("display","inline");
// find all the panel2 elements
// set their css display property to none
$(".panel2").css("display","none");
});
$(".panel2").bind("click", function(){
$(".panel2").css("display","inline");
$(".panel1").css("display","none");
});
});
You can learn all about jQuery here : http://www.jquery.com/
You'll only be able to get your code to run once, as soon as you click a panel1 image all of the panel2 images will disappear, you won't be able to click them back on ever again.

Categories

Resources