appendTo function not functioning - javascript

I am trying to code it such that when you hover and click one word(eg. chocolate, sugar or cocoa", it gives a sentence, click another word, another sentence. and then the rotating words continue rotating.
Any suggestions is deeply appreciated. Thanks, guys:)
checkout my jsfiddle: http://jsfiddle.net/hE2pk/
HTML:
<div id="steps">
<div id="receipe"></div>
<div id="text"></div>
</div>
JS:
var words = [
'<span id="pasta">Penne</span>',
'<span id="meat">Italian Sausage</span>',
'<span id="oil">Olive Oil</span>',
'<span id="onion">Onion</span>'
];
var index = 0;
$(document).ready(function rotate() {
document.getElementById('text').innerHTML =words[(index++)%(words.length)];
if($("#text").is(":hover")){
setTimeout(rotate, 500);
}
else{
setTimeout(rotate, 100);
}
})()
$(function(){
$('#pasta').on('click', function () {
$("<p>Cook 8 ounces of pasta, according to its package directions.</p>").appendTo('#receipe');
$("#steps").html('<div id="text"></div>');
});
});

Your code:
Appends <span id="pasta">…</span> to the DOM
Attaches a click handler to it
Replaces <span id="pasta">…</span> with <span id="meat">…</span> 100ms later
As soon as step #3 finishes, the #pasta span gets obliterated, along with the click handler!
The correct approach is to use event delegation. This is a technique where you attach an event handler higher up in the DOM (on something that you can reasonably expect not to be destroyed, like document), then listen for events that bubble up toward it. If the event originated from an element of interest, you fire your handler!
$(document).on('click', '#pasta', function() { ... });
Here's your example, fixed: http://jsfiddle.net/steveluscher/hE2pk/1/

Related

Running a script only for dynamic content?

I have a list of 10 items with a particular class. when the page scrolls to the end, the following 10 items are loaded.
I want to bind an event only for items that are loaded dynamically rather than for 10 indoor items.
My problem is that the items look exactly the same, I can not change any class or anything else.
any solution?
Create a Set containing first ten objects at the start of the page. Later bind event only to elements that are not in the set.
var s = new Set();
document.querySelectorAll('.aaa').forEach(el=>s.add(el));
setTimeout(function() {
ex.innerHTML += '<span class="aaa">aaa</span>';
ex.innerHTML += '<span class="aaa">aaa</span>';
ex.innerHTML += '<span class="aaa">aaa</span>';
ex.innerHTML += '<span class="aaa">aaa</span>';
document.querySelectorAll('.aaa').forEach(el=> {
if (!s.has(el)) {
el.addEventListener('click', function() {
alert('You clicked me');
});
}
});
}, 1000);
.aaa {
display: block;
}
<span class="aaa">aaa</span>
<span class="aaa">aaa</span>
<span class="aaa">aaa</span>
<span class="aaa">aaa</span>
<span class="aaa">aaa</span>
<span class="aaa">aaa</span>
<div id = "ex"></div>
Only last 4 elements have added click event listener.
Event delegation is how you deal with adding events to dynamic content. Since you did not show actual code, you get a generic answer.
$(document).on("click", ".yourClass", function () {
console.log(this);
});
This way you do not have to bind events every time the content is loaded. It will just listen on a parent element for the click.
It would be better to change document to a parent element that contains all of the elements you are listening to the click event on.

onload button in javascript

Via the link: http://boukestar.nl/ani-map/ you can see that I've set up a vector svg map that is animated.
My only problem is that I dont no how to deactivate or onload a button / country when you click on a other button / country. All the buttons stay active when you click on a other button.
That results in not correct information from a country that's loaded.
HTML
<button class="usa" onClick="usa()" class="hidden">Verendigde Staten</button><div id="landusa" class="hide"><img src="svg/infovs.svg" viewBox="0 0 1087 841.89"></div><div id="div1" style="display: none;"></div>
JS
(function() {
'use strict';
var svg,
button;
document.addEventListener('DOMContentLoaded', function init() {
button = document.querySelector('.usa');
svg = document.querySelector('svg');
button.addEventListener('click', clickHandler, false);
});
function clickHandler(e) {
svg.classList.toggle('usa');
e.target.classList.toggle('on');
}
}());
Has anybody an idea?
Many thanks!
Bouke
Here's my solution. If you put your code in a JSFiddle or CodePen then I can test it:
<script>
document.addEventListener("DOMContentLoaded", function init(){
var svg = document.querySelector("svg"),
currentCountry,
currentButton;
function toggle(clickedButtonCountry){
var clickedButton = document.querySelector("." + clickedButtonCountry);
currentButton.classList.remove("on");
clickedButton.classList.add("on");
clickedButton.classList.remove("hidden");
currentButton.classList.add("hidden");
svg.classList.remove(currentCountry);
svg.classList.add(clickedButtonCountry);
currentCountry = clickedButtonCountry;
currentButton = clickedButton;
}
});
</script>
<button class="usa hidden" onClick="toggle('usa')">Verendigde Staten</button>
<button class="brazil hidden" onClick="toggle('brazil')">Brazil</button>
<svg></svg>
This way Javascript "remembers" which country is currently displayed, and then when someone clicks on a button it "remembers" that country instead.
Some things to keep in mind:
usa() means you have function usa(){} somewhere, which you don't (and shouldn't). I think you were going for something like toggle('usa')
You can have multiple classes in one class attribute, like <div class="foo1 bar2"></div>
document.querySelector only returns one element. document.querySelectorAll returns many.
Using classList.toggle can get a little weird because it's not specific about whether the class should be added or removed. I prefer to explicitly use classList.add and classList.remove. classList.contains is very useful.

After click return to initial state

Hello I got a question regarding changing elements in the DOM. I got a situation that whenever I click on the button it will show a div. After 2 seconds the initial div is replaced by another div which also got a function call that removes the div again.
Now comes the tricky part. What I want is that whenever I hide the div again, the third click on the button will show the div again.
Let me explain a bit more. Imagine that I got the following situation:
First mouse click on button 1 (Result: shows red div)
Second mouse click on button 1 (Result: hide red div)
Third mouse click on button 1 (shows the div again)
The third bullet is the tricky one. How can I do that? Because when I click for the third time on button 1 it does not show anything anymore because I did not change it back to the original state
The code that I have so far JSFIDDLE
function Test(){
var target = window.event.target || window.event.srcElement;
console.log(target);
var content = arguments[0];
console.log(content);
$( "body" ).append( "<div class='red'>"+content+"</div>" );
setTimeout(function(){
$( ".press" ).replaceWith( "<button class='press' onclick='UnTest()'>button 1</button>" );
}, 2000);
}
function UnTest(){
$( ".red").remove();
}
Please note that due to implementation restrictions I can not check within my Function if the button is clicked (eq. $(".red").click())
There are a few ways you could accomplish this, but a quick solution might be just toggling the onclick attribute of the button (rather than replacing it entirely).
// In setTimeout
setTimeout(function(){
$('.press').attr('onclick', 'UnTest()');
}, 2000);
function UnTest(){
$( ".red").remove();
$('.press').attr('onclick', 'Test("one")');
}
https://jsfiddle.net/2mvqmtwq/1/
This will also allow you to add multiple .red divs (similar to the original fiddle) and then remove with a single click (which another answer does not take into account, instead treating it as a simple visibility toggle).
Edit: For multiple buttons/instances (per your comment), you'll need an identifier of sort. Your original code made it easy by declaring the target, which we can use. Let's say we have three buttons:
<button class="press" onclick="Test('one')">button 1</button>
<button class="press" onclick="Test('two')">button 2</button>
<button class="press" onclick="Test('three')">button 3</button>
Our updated JS doesn't change too much, other than referencing the string value we passed (which you declare as content):
setTimeout(function(){
$(target).attr('onclick', 'UnTest("' + content + '")');
}, 2000);
As well as referencing the target you've declared at the top (which allows us to keep each button instance unique).
Here's the updated fiddle with all the changes I made (additional parameters, scoped class names for the red boxes, etc):
https://jsfiddle.net/2mvqmtwq/9/
Use a variable to count the number of clicks, which is initially equal to 0. Then, each time you click the button, you increase the variable by 1 and check if the variable is odd or even. If it's odd, you add the div, if it's even you remove the div:
var clicked = 0;
function Test() {
clicked++;
var content = arguments[0];
if (clicked % 2 === 1) {
$("body").append("<div class='red'>" + content + "</div>");
} else {
$(".red").remove();
clicked = 0;
}
}
Fiddle: https://jsfiddle.net/2mvqmtwq/5/
Tip: you can reset the variable back to 0 when it's even.
Here's a dead simple fix. I think we can do this whole thing a lot more cleanly with some refactoring. But since you mention implementation restraints, I don't want to offer a solution that might break those restraints.
Simply add logic to your UnTest() function
function UnTest(){
$( ".red").remove();
$( ".press" ).replaceWith( "<button class='press' onclick='Test(\"hello\")'>button 1</button>" );
}
How about writing some clean code, avoiding inline event handlers?
What you could probably do is:
First click: add the div
Next click onwards: check if the div already exists. If yes, simply toggle it's display as opposed to removing it.
This is only a demo as to how this could be done. This one also works for multiple buttons/divs. As I said earlier, I have removed inline event handlers and added the div class and function params as data-attributes. Feel free to edit the code to suit your needs.
$(document).on("click", ".press", function() {
var $this = $(this);
var $div = $("div." + $this.data("class"));
if ($div.length) {
$div.toggle();
return;
}
$( "body" ).append( $("<div/>", {
'class': $this.data("class"),
'html': $this.data("param")
}) );
});
button{ margin:10px}
div {
width:200px;
height:50px;
}
.red {
background-color:red;
}
.blue {
background-color:blue;
}
.green {
background-color:green;
}
.orange {
background-color:orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="press" data-param="one" data-class="red">button 1</button>
<button class="press" data-param="two" data-class="blue">button 2</button>
<button class="press" data-param="three" data-class="green">button 3</button>
<button class="press" data-param="four" data-class="orange">button 4</button>

remove onclick when attached to children

I have the following code:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div", function(event) {
var floor;
console.log("floornum: " + this.dataset.floornum);
floor = parseInt(this.dataset.floornum);
...
$("#choose-floor").fadeOut();
$("#choose-apt").fadeIn();
});
later - based on data I'm getting back from the DB - I want to remove some of the .on("click", "div", ...) from only some of the divs. I already have the selector that is getting the right divs but I cannot figure out how to remove the click event. I have tried .off("click") after selecting the right div but it has no effect.
This issue here is because you are using a delegated event. You can add or remove the event for all child elements, but not individual ones given your div selector.
With that in mind the easiest way to do what you need is to add the event based on a class, then add and remove that class on the children as needed. Something like this:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div.clickable", function(event) {
// your code...
});
You can then enable/disable the event on the child div by adding or removing the .clickable class.
You can try like this :
Example :
<div id="test">
<div id="first">first</div>
<div id="second">second</div>
</div>
<div onclick="unbindSecondDiv();">UNBIND</div>
<script>
function unbindSecondDiv()
{
test = $("#second")
test.unbind("click");
alert('Selected Area Click is Unbind');
}
$(document).ready(function(){
//BIND SELECTED DIV CLICK EVENT
test = $("#test > div")
test.bind("click" , function(event) {
alert($(this).attr('id'));
});
});
</script>
In the above example , selected DIV elements click event is bind.
And after execute function unbindSecondDiv() , second DIV click event will be unbind.
Have a try , may helps you.

$(*).click event click it and all of its parent.

This is my code:
<p>
<div>
<div><span>Hello</span></div>
<span>Hello Again</span>
</div>
<div>
<span>And Hello Again</span>
</div>
</p>
<b>Click Hellos to toggle their parents.</b>
<script>
function showParents() {
$("div").css("border-color", "white");
var len = $("span.selected")
.parents("div")
.css("border", "2px red solid")
.length;
$("b").text("Unique div parents: " + len);
}
$("*").click(function () {
$("b").text($(this).parents().length);
});
</script>
The problem is when I click on a span, this shows 0 instead of 3!
I think the problem is *
Now the question is, how do I get the parent count when I don't know the type of the element?
The problem is event propagation(bubbling). The click event gets propagated to the root of the document from the clicked element triggering each of the click handler associated with those ancestor elements, so when the html element's click handler is triggered there is no more parents so you gets 0 as the result.
Demo: Fiddle - take a look at the console
Instead you can bind the click handler only to the document object then use the event's target property to find the element which triggered the click and find its parents
$(document).click(function (e) {
$("b").text($(e.target).parents().length);
});
Demo: Fiddle

Categories

Resources