How to change image when two buttons are clicked? - javascript

I want to make jQuery script where I will have 10 buttons all with different colors and after user clicks on two different buttons, combination of the clicked buttons colors will be made and switch the image frame with already prepared images based on color combinations.
My question is how to put conditions for two buttons(or links) clicked.
switch me
<img src="http://placehold.it/333/fe3/img/picture2.jpg" id="bg" />
$(function() {
$('.menulink').click(function(e){
e.preventDefault();
$("#bg").attr('src',"http://placehold.it/333/3ef/img/picture1.jpg");
});
});
I want to achieve something like this but I want image to change when two buttons (or links) are clicked.
http://jsfiddle.net/maniator/Sevdm/

provided you wanted to make sure the buttons were unique when clicked, you'll want a way of tracking which have been seen. I'm using a JS Object like a Set here for compat with older browsers.
var clickCount = 0;//count the clicks
var clickTracker = {};//track which id's were clicked
var clickThreshold = 2;//the number of clicks we want before executing the if block
function clickHandler(){//callback function for the event
if(clickTracker[this.id] === undefined){//we haven't seen this id yet
clickCount++;//increment the number of buttons clicked
clickTracker[this.id] = 1;//flag for tracking the click
if(clickCount >= clickThreshold){//we saw at least clickThreshold clicks
console.log(clickCount + 'unique clicks happened!');
//your work here
}
}
}
$('.cls').click(clickHandler);//bind events
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='btn1' class='cls'>1</button>
<button id='btn2' class='cls'>2</button>
<button id='btn3' class='cls'>3</button>
<button id='btn4' class='cls'>4</button>
<button id='btn5' class='cls'>5</button>

You can use event delegation to track clicks on .menulink elements. using e.delegateTarget we can have the parent container hold a variable that determines if a .menulink element has been clicked previously, and if it has, we can have it change the background.
To do this I switched the click method to an on method. The on methods parameters are:
$(element).on(event, delegated selector, function)
JQuery .on documentation
Delegation simply means that instead of checking if each button has been clicked by placing an event on the button, we place an event on the container of the buttons and ask if the element that caused the event matches our delegated selector. If it does the provided function is fired. To access the parent of the delegated element within the code we can use the passed back event object, or in this case e.delegateTarget
JQuery delegateTarget documentation
Since everything in JavaScript is an Object, we can assign new properties and methods to anything that is not explicitly part of the Browser's most base architecture. This absolutely includes the body of a page.
In the code below, I place a new property clicked on the body of the page. This is added on click of the first .menulink element, and is checked upon each subsequent click.
Because of this we can know if it is a second click by determining if body.clicked is true. If it is we tell the script to change the background image.
$(function() {
$('body').on("click", ".menulink", function(e){
if(e.delegateTarget.clicked) $("#bg").attr('src',"http://placehold.it/333/3ef/img/picture1.jpg");
else e.delegateTarget.clicked = true;
e.preventDefault();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
switch me
switch me
<img src="http://placehold.it/333/fe3/img/picture2.jpg" id="bg" />

This is what I was looking for
<script>
$(document).ready(function() {
var chosenColors = [];
$(".colors button").click(function() {
chosenColors.push($(this).text())
check();
});
function check() {
if (chosenColors.length === 2) {
$(".pretty-picture").attr("src", chosenColors.sort().join("-") + ".png")
chosenColors = [];
}
}
});
</script>
<body>
<div class=colors>
<button type="button">red</button>
<button type="button">yellow</button>
<button type="button">blue</button>
</div>
<img class="pretty-picture">
</body>

Related

Trying to add EventListener to dynamically created object

I am attemping to load HTML from an external file. However upon doing so the input elements are non-interactable. I have tried this using vanilla JavaScript to no avail and just imported jQuery. My current progress is as follows:
I have a page with a static element and a menu bar. When clicking on the menu bars icons the elements content gets updated through JS/JQ. This is my HTML and jQuery for loading the view:
settings.html:
<section class="settings">
<div class="container">
# some elements here
<div id="graph-settings" class="settings-card">
<i class="fa fa-chart-line fa-3x"></i><h1>Graph Settings</h1>
<p>Web Interface Refresh Rate</p>
<form>
<input type="text" name="graphInterval" id="graphInterval" placeholder="E.g. 2000">
</form>
</div>
# more elements here
</div>
</section>
jQuery:
$.get("./pages/settings.html", (data) => {
$("#main").append(data);
});
$(document).on("click", "#graphInterval", function() {
// do something...
console.log("test");
});
The content seems to be loaded correctly into the page but is not markable/interactable (dynamically added to DOM etc.). However my jQuery does not seem to find the #graphInterval element as I get no logged output from the console.
Any way to get the input fields working would be a solution. All they're needed for is to edit and retrieve it's value. I will use JavaScript to add/interact with buttons later on, no posting forms will be used, hence why the form has no "action=''".
If you use event delegation (where you set the event listener at a high level DOM object and let all events triggered from decedents of that high level element bubble up to the high level element, any new elements added in will trigger events caught higher up. Then, in the listener, you can check to see which element actually triggered the event and act accordingly. So, in your case, remove the id from the .on() method call and then check the event.target inside the listener:
// Set the event listener on a high level element and capture the event
$(document).on("click", function(event) {
// You can find out what exact element triggered the event with event.target
console.log("event triggered by: " + event.target);
// Now you can proceed as you need to:
if(event.target.id === "heading1"){
console.log("You clicked the heading");
} else if(event.target.id === "para1"){
console.log("You clicked the paragraph");
}
});
// Create new elements
let data1 = "<h1 id='heading1'>Some new data (click me)</h1>";
let data2 = "<p id='para1'>Some new data (click me)</p>";
// Dynamically add elements to document
$(document.body).append(data1);
$(document.body).append(data2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

jQuery .html() not setting html at all

I have a simple thing. When a user clicks on the edit link it turns the previous element into an input element for editing and the edit into a cancel. If the user decides not to edit he can click on cancel and everything should revert to its initial state.
Right now this is not working at all:
$('.cancel').on('click', function() {
$(this).parent().html("<a href='#'>edit</a>");
});
HTML:
<div class='photo-section'>
<div class='photo-head'>
<div class='photo-info'>
Photo Name : <span class='photo-name'>Work selfie</span>
<span class='title-edit'><a href='#'>edit</a></span>
</div>
</div>
<div class='photo'>
<img src='' alt='' title=''>
</div>
<div class='tag-section'>
<div class='tags'>Photo Tags:
<span>#code#coffee#late#night</span>
<span class="tags-edit">edit</span>
</div>
</div>
</div>
CSS:
// JavaScript to handle photo operations
$(document).ready(function() {
// show/hide edit option
$('.photo-info, .tags').hover(function() {
$(this).find('.title-edit > a, .tags-edit > a').addClass('visible');
}, function() {
$(this).find('.title-edit > a, .tags-edit > a').removeClass('visible');
});
// show editable area
$('.title-edit, .tags-edit').on('click', function () {
edit(this);
});
});
function edit(elem) {
// change element into an input elemnt for editing
var $item = $(elem).prev();
var text = $item.text();
$item.html("<input type='text'>").find('input').attr('value', text);
// change edit to cancel if input element present
if ($('input').length) {
$item.next().html("<a href='#' class='cancel'>cancel</a>");
}
// change cancel back to edit
if ($('.cancel').length) {
$('.cancel').on('click', function() {
$(this).parent().html("<a href='#'>edit</a>");
});
}
}
Result: https://jsfiddle.net/hgwkxygz/6/
Any help would be great!
This is a very common case of attaching event at wrong time in javascript.
Actually you are removing and re-adding a DOM element. So the already attached event to .cancel won't work this time. You again have to write event listener on .cancel whenever you attach a new DOM element after clicking on edit button.
Basically it means whenever you do .html(), you have to re-add event listener for click.
There are various approach to solve this problem.
1) make a function which attach the DOM element as well as click event to that DOM element. Call that function only on click events.
2)Do event delegation.
3)Do not remove DOM elements on click events, rather hide and show elements so that you wont loose your event listeners.
4)If you really have to do remove and re-add DOM elements then in my opinion, best approach is to make a class, where you make DOM elements, add event listeners privately in that class, and on click events just make new instance of that class.
You can check out these options in detail on web.

Javascript - Stop scrolling on certain links

For example,
Foo
Bar
...
<div id="foo"></div>
<div id="bar"></div>
Is there a way to selectively stop scrolling for certain elements?
In the example, above, what if I want the browser to not scroll to the #bar element if the anchor that has `href="#bar" is clicked?
Is this possible?
Use a click handler that returns false, which prevents the default click action.
Bar
yes, what you are looking for is how to prevent browser default behaviour
example (using jQuery)
$('a').on('click', function(event){
if($(this).attr('href') == '#bar'){
event.preventDefault();
}
});
Well, one of thr ways that I can suggest is to remove the href attribute in some specific circumstances. But removing href attribute may result in the anchor appear to be not clickable anymore...
If you want your anchor to still appear to be clickable:
'$("a").removeAttr("href").css("cursor","pointer");'
You may specify ids for specific anchor elements.
If you add a class or id to links that you don't want to scroll, you can then add an event listener to those links and prevent the default action on click.
HTML
Foo
Bar
...
<h2 id="foo">Foo</h2>
<h2 id="bar">Bar</h2>
Javascript
var blockedLinks = document.getElementsByClassName('blockedLink');
for (var i = 0; i < blockedLinks.length; i++) {
blockedLinks[i].addEventListener('click', function (e) {
e.preventDefault();
}, false);
}
Demo

Javascript innerHTML calls onclick function

I'm trying to change the text of the link when it's clicked and show a DIV. After the user clicks on the modified link (same one) it should hide the DIV.
It works with showing it, but for some reason when I click "Hide older news" the DIV is hidden for like half a second and then it shows again.
It happens on the line where I'm changing the link's text to the default one ("View older news...")
<script>function showoldnews()
{
document.getElementById('oldnews').style.display = "block";
document.getElementById('oldnewslinkid').innerHTML = 'Hide older news';
}
function hideoldnews()
{
document.getElementById('oldnewslinkid').innerHTML = 'View older news...'; //it calls showoldnews() function for some reason on this line
document.getElementById('oldnews').style.display = "none";
}
</script>
Link
View older news...
I believe this is happening because you are inserting a second link inside your first link, and the click event is firing for the parent anchor, instead of the child.
Your markup:
<a href="#" id="oldnewslinkid" onclick="showoldnews(); return false;">
Hide older news
</a>
There are several ways around this:
Wrap your controls in a containing div, and append a new anchor to its innerHTML
Include both sets of controls in the dom on load, hide your hideOldNews() control via css, and toggle them via js
Attach an event listener to one element, and use it to "toggle" your news div:
HTML
<div id="oldnews">Old News...</div>
View older news...
JS
var toggle = document.getElementById('toggle')
toggle.addEventListener('click', function(e){
e.preventDefault()
var target = document.getElementById("oldnews"); // href="oldnews"
console.log(target);
target.style.display = (target.style.display == 'none') ? 'block' : 'none';
});
codepen
My suggestion would be to use an event handler, it will make your life a lot simpler, as you are not having to edit single line JS nested inside ofHTML elements.
There are are some slight cross browser issues with addEventListener (IE8 uses a special attachEvent handler), bit there are some simple ways to get around that.

MooTools event listener disappears after element.innerHTML is changed

I am trying to achieve this task using MooTools.
Description:
I attached an event listener to myButton link. A click on this link initiates an AJAX request and updates myDiv content based on the response text.
During this request a POST variable is being sent to "button.php", but it's not used at the moment.. (i wish to use it later)
OK, as a result, myDiv gets exactly the same link with the same ID (myButton) + a random number, so that we could see that each click generates a new number.
The problem:
After the first click on myButton, myDiv updates correctly, showing a random number. When I click myButton for the second time (this time in newly updated div), the div does not refresh anymore.
Please note that I need myButton to be inside myDiv, and myDiv must be updated (refreshed) after each click without having to refresh the entire page.
Can somebody show me how to achieve this task based on this simplified code example?
index.html
<html>
<head>
<script type="text/javascript" src="mootools-1.2.4-core-nc.js"></script>
<script>
window.addEvent('domready', function() {
$('myButton').addEvent('click', function(e) {
e.stop();
var myRequest = new Request({
method: 'post',
url: 'button.php',
data: {
action : 'test'
},
onRequest: function() {
$('myDiv').innerHTML = '<img src="images/loading.gif" />';
},
onComplete: function(response) {
$('myDiv').innerHTML = response;
}
});
myRequest.send();
$('myButton').removeEvent('click');
});
});
</script>
</head>
<body>
<div id="myDiv">
<a id="myButton" href="#">Button</a>
</div>
</body>
</html>
button.php
<a id="myButton" href="#">Button</a> clicked <?php echo rand(1,100); ?>
Look at Element.Delegation to setup the event on the myDiv container one time, so you don't have to re-attach handlers each time the contents are updated. You need to include this MooTools-More extension in your scripts as it's not part of core yet, but will be starting from version 1.3.
$("myDiv").addEvent("click:relay(a)", function() {
...
);
If you have multiple <a> links inside, and you only want to delegate a specific subset of those, add a class or some other property to distinguish them. You can use almost any selector inside relay(..). Let's say all links had a class updateTrigger added to them:
<a class="updateTrigger" id="myButton" href="#">Button</a>
the syntax would then be:
$("myDiv").addEvent("click:relay(a.updateTrigger)", function() {
...
});
See this working example where links are replaced every 5 seconds. There is only one event setup on the myDiv container and it handles all clicks to all <a>s, even the dynamic ones.
you are attaching an event to an element that you are replacing. the dom has no way of knowing that to you, the old and the new button are identical. The old button is deleted (and the event listener with it) and the new button created. So you need to re-attach the event to the new button.
That said: why does the button have to be inside the div? The mind boggles. You can always update the button text from javascript, there's no need to replace it and keep creating new listener objects.

Categories