For Loop not working and cloning Javascript - javascript

I've tried all sorts of things to figure out why my code isn't however, I can't seem to find out why. `
var numberOfFaces = 5;
var theleftside = document.getElementById ("leftSide");
var top_position = Math.floor((Math.random() * 400) + 1);
var left_position = Math.floor((Math.random() * 400) + 1);
var theRightSide = document.getElementById("rightSide");
function generatefaces () {
for (var i = 1; i < numberOfFaces; i++) {
var img = document.createElement("img");
img.src = "smile.png";
img.style.top = top_position + "px";
img.style.left = left_position + "px";
theleftside.appendChild(img);
}
}
<style media="screen">
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 2px solid black;
}
</style>
<h1>The Matching Game</h1>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide">
</div>
<div id="rightSide">
</div>
`
I am trying to generate 5 images (smiley faces) on the lefside div at different positions, then trying to clone it to the right hand side,
I'm new with JS, so hints and tips would be much appreciated.

Because you just implemented a function but did not call it. Try adding
generatefaces();
at the end.

Two fold firstly you need to, as burkay says, call the function generatefaces().
Secondly you need to create a second element for the right side using img.cloneNode(true) this creates a duplicate so you can then append that to the right side.
Also you are generating the random position outside of the loop so the same random position is used for each img you instead need to create a random position for every img by moving it inside the loop.
Example:
var numberOfFaces = 5;
var theleftside = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
// You need to call this function
generatefaces()
function generatefaces() {
for (var i = 1; i < numberOfFaces; i++) {
// Generate the new random position for each img
var top_position = Math.floor((Math.random() * 400) + 1);
var left_position = Math.floor((Math.random() * 400) + 1);
var img = document.createElement("img");
// The location of your face image
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Emojione_1F60E.svg/64px-Emojione_1F60E.svg.png";
img.style.top = top_position + "px";
img.style.left = left_position + "px";
// Creates a duplicate version of the image
var imgright = img.cloneNode(true);
theleftside.appendChild(img);
// Appends the duplicate image to the right side
theRightSide.appendChild(imgright);
}
}
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 2px solid black;
}
<h1>The Matching Game</h1>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide">
</div>
<div id="rightSide">
</div>
Hope this helps!

Related

Dom html javascript about onclick

I want to generate five image imgs first in left side, then remove the lastchild of it and copy the rest to the right side. If user clicks the extra img in left side, then clear all and generate more 5(10) img in left and copy 9 to the right side, and so on. If user clicks the wrong place, alert ("game over").Here is my code:
<html>
<head>
<style>
img{
position: absolute;
}
div{
position: absolute;
width: 500px;
height: 500px;
}
#rightSide { left: 500px;
border-left: 1px solid black;
}
</style>
<script>
var numberOfFaces = 5;
function generateFaces(){
var theLeftSide = document.getElementById("leftSide");
for (var i = 0; i < numberOfFaces; i++){
var img = document.createElement("img");
img.src = "smile.png";
var randomTop = Math.random() * 400;
var randomLeft = Math.random() * 400;
img.style.top = randomTop + "px";
img.style.left = randomLeft + "px";
theLeftSide.appendChild(img);
}
var theRightSide = document.getElementById("rightSide");
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightSide").appendChild(leftSideImages);
var theBody = document.getElementByTagName("body")[0];
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
while (theBody.firstChild){
theBody.removeChild(theBody.firstChild);
}
numberOfFaces += 5;
generateFaces();
}
theBody.onclick = function gameover(){
alert("Game Over");
thBody.onclick = null;
theLeftSide.lastChild.onclick = null;
}
}
window.onload = generateFaces;
</script>
</head>
<body>
<h1>Matching Game</h1>
<p>click on the extra smiling face on the left</p>
<div id = "leftSide">
</div>
<div id = "rightSide">
</div>
</body>
</html>
I could generate and clone at first time, but when I click, nothing happens, so what is the problem?
This may be a typing error.
var theBody = document.getElementsByTagName("body")[0];
your code: var theBody = document.getElementByTagName("body")[0];
I suggest to use a good editor for html. I fixed the error with Jetbrain phpStorm but better ones may exist.
Bellow is a modified version that worked for me. Notice that in this version I added the events on all children instead of the whole document body. I don't know but for me it feels more accurate not to end the game on a user clicks on a white space for example.
<html>
<head>
<style>
img{
position: absolute;
}
div{
position: absolute;
width: 500px;
height: 500px;
}
#rightSide { left: 500px;
border-left: 1px solid black;
}
</style>
<script>
var numberOfFaces = 5;
var theBody;
var theLeftSide;
var theRightSide;
function generateFaces(){
theBody = document.getElementsByTagName("body")[0];
theLeftSide = document.getElementById("leftSide");
theRightSide = document.getElementById("rightSide");
for (var i = 0; i < numberOfFaces; i++){
var img = document.createElement("img");
img.src = "smile.png";
var randomTop = Math.random() * 400;
var randomLeft = Math.random() * 400;
img.style.top = randomTop + "px";
img.style.left = randomLeft + "px";
if(theLeftSide != null)
theLeftSide.appendChild(img);
else
{
alert("Game Over");
return;
}
}
var leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightSide").appendChild(leftSideImages);
addEvents();
}
function addEvents(){
for(var i=0; i < theLeftSide.childNodes.length; i++){
theLeftSide.childNodes[i].onclick = nextLevel;
}
}
function removeEvents(){
for(var i=0; i < theLeftSide.childNodes.length; i++){
theLeftSide.childNodes[i].onclick = null;
}
}
function nextLevel(event){
if(this == theLeftSide.lastChild){
event.stopPropagation();
theLeftSide.innerHTML = "";
theRightSide.innerHTML = "";
numberOfFaces += 5;
generateFaces();
}
else
{
alert("Game Over");
removeEvents();
}
}
window.onload = generateFaces;
</script>
</head>
<body>
<h1>Matching Game</h1>
<p>click on the extra smiling face on the left</p>
<div id = "leftSide">
</div>
<div id = "rightSide">
</div>
</body>
</html>

Appending mutiple image on a div

I am trying to add the same image on a div five times but when I open my web page in Chrome or any browser it only shows one smiley.png image when it supposed to show five smiley.png on different coordinates on a the leftSide div. I am not sure what is the problem with my code below:
<!DOCTYPE html>
<html>
<head>
<title>Web Practice 2</title>
<style type="text/css">
img {
position: absolute;
}
div {
width: 500px;
height: 500px;
position: absolute;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script type="text/javascript">
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
function generate() {
for (i = 0; i < numberOfFaces; i++) {
var img = document.createElement("img");
img.setAttribute("src", "smile.png");
img.style.top = Math.floor(Math.random()*450);
img.style.left = Math.floor(Math.random()*450);
theLeftSide.appendChild(img);
}
}
window.onload = generate();
</script>
</body>
</html>
There actually are five images, but it only appears like there is one because your position randomization is not working correctly (in other words, the images are all being stacked on top of each other). The CSS top and left attributes require units, so you should append "px" to both.
Also, note that since the necessary DOM has already loaded by the time your script begins executing, you don't need to use window.onload at all.
Lastly, you might be pleased to know that you can use the shortcut img.src = ... instead of calling img.setAttribute("src", ...) in your script.
Demo Snippet:
<!DOCTYPE html>
<html>
<head>
<title>Web Practice 2</title>
<style type="text/css">
img {
position: absolute;
}
div {
width: 500px;
height: 500px;
position: absolute;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script type="text/javascript">
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
function generate() {
for (i = 0; i < numberOfFaces; i++) {
var img = document.createElement("img");
img.src = "smile.png";
img.alt = "Smile!"
img.style.top = Math.floor(Math.random() * 450) + "px";
img.style.left = Math.floor(Math.random() * 450) + "px";
theLeftSide.appendChild(img);
}
}
generate();
</script>
</body>
</html>
There are 2 problems in your code:
You need to assign a function reference to window.onload. When you're using generate(), you're invoking the function and since it doesn't return anything you're effectively doing window.onload = undefined.
You're assigning theLeftSide before the DOM is ready, hence it will always be null and will throw upon your appendChild() calls.
Try this instead:
var numberOfFaces = 5;
function generate() {
var theLeftSide = document.getElementById("leftSide");
for (i = 0; i < numberOfFaces; i++) {
var img = document.createElement("img");
img.setAttribute("src", "smile.png");
img.style.top = Math.floor(Math.random() * 450);
img.style.left = Math.floor(Math.random() * 450);
theLeftSide.appendChild(img);
}
}
window.onload = generate;
See Fiddle
You forgot to add units of measure ("px" for pixels) to the coordinates. Without units specified, the property values are invalid.
Also, you are calling generate immediately, rather than referring to the function.
I have modified your sizes to fit better in the stack overflow snippet space and also used the more correct .addEventListener method for setting up your load event handler. Also, I have added a temporary background color to the div elements to better see the layout of the pictures in the leftSide element.
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
function generate() {
for (i = 0; i < numberOfFaces; i++) {
var img = document.createElement("img");
img.setAttribute("src", "smile.png");
img.style.top = Math.floor(Math.random()*250) + "px";
img.style.left = Math.floor(Math.random()*250) + "px";
theLeftSide.appendChild(img);
}
}
window.addEventListener("load", generate);
img {
position: absolute;
}
div {
width: 300px;
height: 300px;
position: absolute;
background-color:#ff0;
}
#rightSide {
left: 350px;
border-left: 1px solid black;
}
<div id="leftSide"></div>
<div id="rightSide"></div>
I have resolved my issue, I just changed <!DOCTYPE html> to <html> and it worked but I am not sure why though.

Why do the elements not appear in random places but they are staying aligned on top of the div?

The code is supposed to generate 5 elements one by one so that when the page is downloaded all we`ll see 5 elements (newFace) in random places.
This code generates all 5 elements but they are staying aligned one by one instead of appearing in random position as wished
function generate_faces() {
var theLeftSide = document.getElementById("leftSide");
var number_of_faces = 0;
while (number_of_faces < 5){
var top_position = Math.floor(Math.random()*300);
var left_position = Math.floor(Math.random()*300);
newFace = document.createElement("img");
newFace.setAttribute(
"src",
"http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png"
);
newFace.style.top = top_position+"px";
newFace.style.left = left_position+"px";
theLeftSide.appendChild(newFace);
number_of_faces = number_of_faces + 1;
}
}
Try this.
<!DOCTYPE html>
<html>
<head></head>
<style>
html, body, leftSide {
width: 100%;
height: 100%;
position: relative;
}
#leftSide {
position: relative;
}
#leftSide img {
position: absolute;
}
</style>
<body onclick="generate_faces()">
<div id="leftSide">
</div>
</body>
</html>
<script>
function generate_faces() {
var theLeftSide = document.getElementById("leftSide");
var number_of_faces = 0;
while (number_of_faces < 5){
var top_position = Math.floor(Math.random()*300);
var left_position = Math.floor(Math.random()*300);
newFace = document.createElement("img");
newFace.setAttribute(
"src",
"http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png"
);
newFace.style.top = top_position+"px";
newFace.style.left = left_position+"px";
theLeftSide.appendChild(newFace);
number_of_faces = number_of_faces + 1;
}
}
</script>

How to clone the contents of a div into another div with JavaScript?

I want to clone the images of the div leftSide into the div rightSide. On each click on the body the images on the left div should be cloned into the right div. But I can't get the result with the code I'm doing. Is there any mistake in my code? I want to use JavaScript.
Here's my code:
var theLeftSide = document.getElementById("leftSide");
var width = 500; var height = 500;
top_position = 0; var left_position = 0,
var numberOfFaces = 5;
var theRightSide = document.getElementById("rightSide");
var leftSideImages = theLeftSide.cloneNode(true);
document.getElementById("rightSide").appendChild(leftSideImages);
for (var i = 0; i < 5; i++) {
createElement(i);
numberOfFaces += 5;
function createElement() {
var image = document.createElement('img');
image.src = "smile.png";
image.style.position = 'absolute';
image.style.top = top_position + "px";
image.style.left = left_position + "px";
theLeftSide.appendChild(image);
top_position = Math.random() * 500 ;
left_position = Math.random() * 500 ;
Here is a simple example that clones an HTMLElement in vanilla javascript:
additional information can be found in MDN
function CloneCtrl() {
'use strict';
var self = this;
self.source = document.querySelector('.source');
self.target = document.querySelector('.target');
self.cloneSource = function(event) {
var clone = self.source.cloneNode(true);
self.target.appendChild(clone);
}
document
.getElementById('cloneBtn')
.addEventListener('click', self.cloneSource)
;
}
document.addEventListener('DOMContentLoaded', CloneCtrl);
.source {
background: lightseagreen;
width: 100px;
height: 100px;
line-height: 100px;
overflow: hidden;
margin: 5px;
display: inline-block;
text-align: center;
color: #fff;
}
.target {
border: 1px solid lightcoral;
min-height: 110px;
}
<div><button id="cloneBtn">Clone Source</button></div>
<div class="source">SOURCE</div>
<hr>
<div class="target"></div>
With jQuery, you can do it kike that:
$('#div2').html($('#div1').html());
which is found from this question: Copy the content of a div into another div.
You don't actually provide many details, thus the best I can post, hope it helps!!
you could simply try this if you have second div on page.
document.getElementById("SecondDv").innerHTML = document.getElementById("FirstDv").innerHTML;
This will copy whatever is there in FirstDiv to Second. lmk if it works.

Draggable Columns With Pure JavaScript

I'm trying to build a draggable column based layout in JavaScript and having a bit of hard time with it.
The layout comprises of 3 columns (divs), with two dragable divs splitting each. The idea is that they are positioned absolutely and as you drag the draggers, the columns' respective widths, and left values are updated.
The three columns should always span the full width of the browser (the right most column is 100% width), but the other two should remain static by default when the browser is resized (which is why i'm using px, not %).
My code isn't working as of yet, I'm relatively new to JavaScript (which is why I don't want to use jQuery).
Having said that, there must be a more efficient (and cleaner) way of achieving this with less code that works (without reaching for the $ key).
If anyone with some awesome JS skills can help me out on this I'd be super-appreciative.
Here's the fiddle I'm working on http://jsfiddle.net/ZFwz5/3/
And here's the code:
HTML
<!-- colums -->
<div class="col colA"></div>
<div class="col colB"></div>
<div class="col colC"></div>
<!-- draggers -->
<div class="drag dragA" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left:100px;"><div></div></div>
<div class="drag dragB" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left: 300px;"><div></div></div>
CSS:
body {
overflow:hidden;
}
.col {
position: absolute;
height:100%;
left: 0;
top: 0;
overflow: hidden;
}
.colA {background:red;width:100px;}
.colB {background:green; width:200px; left:100px;}
.colC {background:blue; width:100%; left:300px;}
.drag > div {
background: 0 0;
position: absolute;
width: 10px;
height: 100%;
cursor: col-resize;
left: -5px;
}
and my terrible JavaScript:
//variabe columns
var colA = document.querySelector('.colA');
var colB = document.querySelector('.colB');
var colC = document.querySelector('.colC');
//variable draggers
var draggers = document.querySelectorAll('.drag');
var dragA = document.querySelector(".dragA");
var dragB = document.querySelector(".dragB");
var dragging = false;
function drag() {
var dragLoop;
var t = this;
var max;
var min;
if (dragging = true) {
if (this == dragA) {
min = 0;
max = dragB.style.left;
} else {
min = dragA.style.left;
max = window.innerWidth;
}
dragLoop = setInterval(function () {
var mouseX = event.clientX;
var mouseY = event.clientY;
if (mouseX >= max) {
mouseX = max;
}
if (mouseY <= min) {
mouseY = min;
}
t.style.left = mouseX;
updateLayout();
}, 200);
}
}
function updateLayout() {
var posA = dragA.style.left;
var posB = dragB.style.left;
colB.style.paddingRight = 0;
colA.style.width = posA;
colB.style.left = posA;
colB.style.width = posB - posA;
colC.style.left = posB;
colC.style.width = window.innerWidth - posB;
}
for (var i = 0; i < draggers.length; i++) {
draggers[i].addEventListener('mousedown', function () {
dragging = true;
});
draggers[i].addEventListener('mouseup', function () {
clearInterval(dragLoop);
dragging = false;
});
draggers[i].addEventListener('mouseMove', function () {
updateLayout();
drag();
});
}
I see a couple of things wrong here. First of all, the mousemove event only fires on an element when the mouse is over that element. You might have better luck registering a mousemove listener on the parent of your div.drag elements, then calculating the mouse's position inside that parent whenever a mouse event happens, then using that position to resize your columns and your draggers.
Second, I'm not quite sure what you're trying to do by registering a function with setInterval. You're doing pretty well with registering event listeners; why not continue to use them to change the state of your DOM? Why switch to a polling-based mechanism? (and the function you pass to setInterval won't work anyway - it refers to a variable named event, which in that context is undefined.)
This is just a little example... I hope it can help you :)
window.onload = function() {
var myDiv = document.getElementById('myDiv');
function show_coords(){
var monitor = document.getElementById('monitor');
var x = event.clientX - myDiv.clientWidth / 2;
var y = event.clientY - myDiv.clientWidth / 2;
monitor.innerText = "X: " + x + "\n" + "Y: " + y;
myDiv.style.left = x + "px";
myDiv.style.top = y + "px";
}
document.onmousemove = function(){
if(myDiv.innerText == "YES"){show_coords();}
}
myDiv.onmousedown = function(){
myDiv.innerText = "YES";
}
myDiv.onmouseup = function(){
myDiv.innerText = "NO";
}
}

Categories