Javascript innerHTML calls onclick function - javascript

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.

Related

How to change image when two buttons are clicked?

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>

event.target.parentNode... pointing to different parents in chrome and firefox?

In this project am working on I have button that has and image inside it for styling purposes... I am trying to implement the functionality such that when the button is clicked I use event.target.parentNode.parentNode... a number of times to get an HTML5 data attribute(postid) from one the topmost parent divs, in Firefox I need to call parentNode 4 times and it works in Chrome it does not work I need to call parentNode 5 times, this means the two browsers are referring to different parents. I added $(event.target).parent().parent().css('border','5px solid black'); to find out which target each browser is considering. I found Chrome considers the event.target to be the image(which is what is actually clicked) but Firefox considers the button to be the event.target(which is where the event was actually attached)..... How can I make this button and its event code portable on both browsers without removing the image inside the button tag(that worked).
The code looks like
$(document).on('click', '.opinion', function(event) {
try {
post_id = event.target.parentNode.parentNode.parentNode.parentNode.dataset['postid'];
//$(event.target).parent().parent().css('border','5px solid black');
url = $('#opinionUrl' + post_id).val();
token = $('#token').val();
} catch (e) {
alert(e);
}
///Some more code to do stuff
});
<button class="icon opinion">
<img class="icon" src="{{URL::asset('assets/icons/haha.png')}}">
</button>
Why use jQuery and chain parentNode or .parent()?
.closest() will do the job for you https://api.jquery.com/closest/
post_id = $(this).closest("[data-postid]").data().postid;

Why is eventListener being removed after removing parent child

I have three different event listeners, one for opening a lightbox, one for closing lightbox, and one for adding a watch later feature.
So when after clicking the close button none of the eventListeners exist anymore. the basic code example:
var a ={
open_lightbox:function(ele){
ele.addEventListener('click',function(){
//code that creates dynamic html and so forth.
},false);
},
close_lightbox:function(){
var closer = a.get('.lightbox_close')[0];
closer.addEventListener('click',function(){
var p = this.parentNode.parentNode.parentNode;
p.parentNode.removeChild(p);
},false);
},
watch_later:function(ele){
ele.addEventListener('click',function(){
//uses localStorage to save data and then adds parameters
},false);
},
get:function(ele){ return document.querySelectorAll(ele); }
};
var lightbox = a.get('.lightbox_button'),i;
for(i=0;i<lightbox.length;i++){
a.open_lightbox(lightbox[i]);
}
Now when ever I click the main event open_lightbox, I can't reopen the lightbox nor click the watch_later element. All the original eventListeners are removed, is it because of the false use capture? I haven't tried changing false to true though I will. I just need an explanation to why this is happening as this is my first time in years ever running into this issue.
Testing that replicates the issue:
http://jsfiddle.net/ES5h2/
I did more testing and it's not on the click of the close button but after the first click of the element to open the lightbox.
i would try not to delete the element, but to hide it
you could use
p.style.display = "none";
instead of
p.parentNode.removeChild(p);
I'm not 100% sure why this was canceling the Event Listener on each event, though I did figure out a more semantic way. Which is just doing...
document.addEventListener('click',function(e){
if(/lightbox_btn/gi.test(e.target.className)){
//perform the code
}
},false);
So really I just took it and added the event Listener to the document instead of the element itself. It works fine now

javascript onmouseout works also on mouse over

I'm trying to show/hide some of text in a button.
the button is
<button id="SOS" onmouseover="show()" onmouseout="hide();">
<p>S.O.S</p>
<div id="sos_left"> <?=$text_to_show_hide?></div>
</button>
and the javascript code is
<script type="text/javascript">
function show()
{
sos_left=document.getElementById('sos_left');
alert("mouseover");
sos_left.style.color = "red";
sos_left.style.fontSize = "28";
}
function hide(){
sos_left=document.getElementById('sos_left');
alert("mouseout");
sos_left.style.color = "blue";
sos_left.style.fontSize = "0";
}
</script>
the thing is that the mouse out alerts even when I'm mouse overing.
NOTE: I can't use jquery because the site is vbulletin based and I use this code on one of the templates.
The problem is that mouseover and mouseout events bubble up, and this means that when your cursor enters and exits from elements that are descendants of your button, the event listener defined on the button is triggered too.
What you can do is to check if the element that generated the event is actually the <button> element. Fix the DOM like this:
<button id="SOS" onmouseover="show(event)" onmouseout="hide(event);">...
Then your JS code:
function show(e) {
if ((e.target || e.srcElement).id !== "SOS") return;
...
function hide(e) {
var tgt = e.target || e.srcElement;
if (tgt.id !== "SOS") return;
// If the cursor enter in one of the descendants, mouseout is fired, but
// we don't want to handle this
if (tgt.contains) {
if (tgt.contains(e.relatedTarget || e.toElement)) return;
} else if (this.compareDocumentPosition)
if (tgt.compareDocumentPosition(e.relatedTarget)
& Node.DOCUMENT_POSITION_CONTAINS) return;
...
In Internet Explorer (and now in Opera too) there are these events mouseenter and mouseleave that behave very similarly, but don't bubble up. For other browsers they're emulated in common frameworks like jQuery.
On a final note, I'd suggest you to use some more modern method to attach your event listeners than the traditional one. Plus, the way you define sos_left implies that it becomes a global variable. Use the keyword var in front of the definition.
you dont hide anything..
use display:none to "remove" element, or visibility:hidden to hide element.
to "re-add" the element, use display: block or visibility:visible, if you used visibility attribute to hide.
try each both to see the difference.
another problem is,
you try to use sos_left as variable, but you didn't declare it as variable.
use var sos_left instead of.
That's because you apply the event to the div not the button. Try this:
sos_button=document.getElementById('SOS');

How to use javascript onclick on a DIV tag to toggle visibility of a section that contains clickable links?

Hi I've got a DIV section that has only its title visible initially. What I would like to achieve is that when the visitor clicks anywhere on the area of toggle_section the toggle_stuff div toggles between visible/hidden.
<div id="toggle_section"
onclick="javascript: new Effect.toggle('toggle_stuff', 'slide');">
<div id="toggle_title">Some title</div>
<div id="toggle_stuff">
some content stuff
Some link
</div>
</div>
However, the way it is set-up right now, if I have any <a> link within the toggle_section, clicking that link will also execute the onclick event.
Then my question is what would be the best way to set this type of behavior?
The most simple solution is to add an extra onclick handler to the link within your DIV which stops event propagation:
<div id="toggle_section"
onclick="javascript: new Effect.toggle('toggle_stuff', 'slide');">
<div id="toggle_title">Some title</div>
<div id="toggle_stuff">
some content stuff
<a href="/foo.php"
onclick="Event.stop(event);"
>Some link</a>
</div>
</div>
The above example uses Prototype's Event.stop() function in order to facilitate a cross browser event propagation stop.
As you use the inline onclick() handler, most (if not all) browser will traverse the event in the bubbling phase first (which is what you want).
A good guide to understanding the actual reasons behind this behaviour and the differences between event capturing and event bubbling can be found at the excellent Quirksmode.
in script :
function overlayvis(blck) {
el = document.getElementById(blck.id);
el.style.visibility = (el.style.visibility == 'visible') ? 'hidden' : 'visible';
}
activator link, followed by content (no reason that couldn't be else on the page):
<div onclick='overlayvis(showhideme)">show/hide stuff</div>
<div id="showhideme">
... content to hide / unhide ...
</div>
I got this from Modal window javascript css overlay - had to search for the source and was pleased to find it was this site. :)
After I posted my first question I could not wait to try to think about it once more and it seems that I have found a quite simple way to achieve this.
I have moved the onlick Effect.toggle into a separate function like:
function someClick(event) {
if (event.target.nodeName == 'A') {
return;
} else {
new Effect.toggle('toggle_stuff', 'slide');
}
}
I suppose this would only work for A tags and not anything else that is clickable though.
I don't really know if this would work, but try giving the link element a bigger z-index value than the toggle_section div.
something like :
#toggle_section a { z-index: 10; }
Add an onclick handler to stop event propagation.
With JQuery use:
onclick="event.stopPropagation()"
With Prototype use:
onclick="Event.stop(event)"

Categories