It is my first post on SO, I am using it already quite a while, always found a solution via search. Now I'm starting to dig deeper into programming - right now learning Java Script - and I couldn't find the exact answer for my beginner problem:
I've created a simple photo gallery where the thumbnails point to the image via href. The images are not displayed by default. By clicking on a thumbnail, the corresponding image appears thanks to the :target pseudo element. This way I can bypass the cascading nature of my HTML structure and address elements higher in hierarchy.
See fiddle:
https://jsfiddle.net/ahu1kaqf/
The problem is, that this "hack" has the side effect of putting the image to the very top of the window due to its default anchor jump behavior.
So what I want to accomplish is to turn off or bypass just the jump behavior.
Therefore, solutions with JS like "preventDefault" or "return false" are not suitable as they turn off the complete anchor behavior.
My idea was to read the yScroll position just before the click and pass it to another function which triggers just after the page jump. By appending an onclick event on the anchor tag I found out that the function executes before the actual jump and I can read the current scrollY position:
function posY(){
console.log(window.scrollY);
scry = window.scrollY;
}
Then, after the anchor event has finished, I would like to pass the variable scry to another function which triggers just after the anchor jump to undo the jump:
function undoJump(){
window.scrollTo(0, scry);
}
It doesn't really work with a click event as the function triggers before the actual jump.
The js code in the fiddle is in script tags because putting just the functions into the js window (of course without script tags) shows an error in the console, I don't know why...
Sorry, I'm really a beginner, thank you all for your help!
https://jsfiddle.net/ahu1kaqf/1/
var classname = document.getElementsByClassName("thumb");
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener("click", posY);
}
function posY(e){
e.preventDefault();
console.log(window.scrollY);
}
Remove the onclick as it's just not the best way to do it. Add a class to the links OR use querySelectorAll based on the parent class. The benefit here is, you don't have to remember to add a class or a onclick. It's less code to deal with and easier to manage.
https://jsfiddle.net/ahu1kaqf/2/
In either case, you can stop the normal event behavior with e.preventDefault();
For the second part, you'll probably just want to set a global in this case. Set a global outside all of the functions and change it on click. You could probably get more complex with objects, and promises and such, but, honestly, it'd be just as easy to set a global value. It's good to try to avoid them, but they can be simple useful solutions depending on the overall complexity of the application in question.
Yes, you need to prevent the default action (which is a navigation action).
In modern browsers, that means you can do this (note I'm passing the global event object as a parameter):
<div class="thumb">thumb1</div>
Then in your js code you can do this:
function posY(e){
e.preventDefault()
console.log(window.scrollY);
}
Related
I have a website that I am creating and there are different divs each with their own content. All of them are hidden except the main one that shows up on the homepage. The transitions are pretty long, and I like it that way, but the problem is that if somebody spams the navbar buttons it opens up all those divs ontop of each other. So to prevent that I want to temporarily disable the onClick for an <a></a> element. Then enable it after the transition is done. Currently I am able to disable it, but cannot find a way to re-enable it.
function disable(){
$(".bar").unbind();
$(".bar").removeAttr("onClick");
}
I know how to call a function after a certain amount of time, but what is the "enable" equivalent to the code in this function?
The exact opposite would be to set the onClick back on the element.
$('.bar').attr('onClick', function() { alert('blah'); });
or with vanilla js
document.querySelector(".bar")
.setAttribute('onClick', function() {...});
However, this is difficult to manage for many elements with the same functionality. It would be easier to have this entirely managed with javascript (and jQuery in this case).
function clickEvent(event) {
var self = $(this);
// Unbind the event
self.off(clickEvent);
// Click logic here
// Rebind event
self.on('click', clickEvent);
}
$('.bar').on('click', clickEvent);
Instead of disabling the event on the DOM, you can just add an extra piece of logic to your dynamic divs:
$('#mydiv').click(function() {
if(!inTransition())
// DO A THING
else
// DON'T DO A THING
});
As a side note: If you're doing a lot of dynamic DOM manipulation, you may want to look into using a data binding framework such as Angular or Knockout. jQuery is nice for simple DOM manipulations, but it can quickly become messy and hard to maintain if you're doing something complex (which it sounds like you are).
As somewhat of an extension to nmg49's answer, I'd like to provide a solution that's a little more in depth.
Essentially what you'll want to do is create a flag to determine whether or not you are currently transitioning, and cancel the onClick if it is true (disabling it after the transition is complete).
var isTransitioning = false;
$('.bar').onClick(function(){
if(isTransitioning) return;
isTransitioning = true;
// DO TRANSITION
});
Once the transition is complete, you simply set isTransitioning to false (either in a callback, or at the end of your onClick function; which ever one applies to your code).
This will ensure that, no matter how many times they click the button, they will not be able to transition if they're already in transition.
Here is the jsFiddle: http://jsfiddle.net/JFwDw/2/
What I'm wanting to do is use links to change the font-size and line-height of paragraphs only within a division id'd "content". I've made another division to make sure it isn't changing anywhere else... can't get it to work after a while of playing around with it.
Thanks in advance.
You want to change which selector you're using. Instead of doing to all p tags, you just want the ones under #content
$("#content p, #content ul").css()
DEMO
Your links also link to <a href=""... which causes the page to reload. I changed it to href="#" so this doesn't happen. You could also prevent the default event from happening inside the functions.
function origText() {
event.preventDefault()
...
On a side note, I can't figure out why the functions are not working in the JS part of the fiddle...
http://jsfiddle.net/JFwDw/34/
This is working for me.
Edit: I think that this is what you're trying to achieve!
Well, for one, your links are being activated and reloading the page.
Typically when you write jQuery, you would attached the events using selectors, not using inline code. This let's you keep your JavaScript and HTML in separate files as well as allows jQuery to remove events when needed.
big text
$('#bigText').click( function(event) {
// code here
} );
Then to prevent the default action (following the link), you can use the jQuery method, prevent default action.
$('#bigText').click( function(event) {
event.preventDefaultAction();
// code here
} );
You may also what to wrap you event binding code withing a document ready event in order to make sure that the DOM is loaded before trying to attach events to it.
$(document).ready( function() {
$('#bigText').click( function(event) {
event.preventDefaultAction();
// code here
} );
} );
Also, you would typically want to add a class to change an element's styles rather than using jQuery to change the style. It's more performant. Also, if you want to only affect element within a container, you can use the jQuery "find" method to do so.
$('#someContainer').find('p').addClass('someClass');
I have a silly (and hopefully easily fixed) problem, which I will now attempt to describe.
The scenario-> I am trying to create a context menu using HTML / CSS / JS. Just a DIV with a high z-order that appears where a user right-clicks. Simple, and that portion works. The portion which does not is my attempt to make the menu disappear if the user clicks somewhere where a context menu is not supported; I am attempting to achieve this end with a general function in the BODY tag that fires onclick. Since the BODY tag is given a z-order of -1, and any other tags which might trigger the context menu to appear are given a higher z-order value, my hope was that if I right-clicked an element with a z-order of, say, 3, then it would fire the showMenu() function; instead, it appears that it does this, as well as passes the event to the underlying BODY tag, which causes the menu to become hidden again.
As you might imagine, it is incredibly frustrating. Does anyone know how to make prevent events from being passed down? (The INPUT button is what you may want to look at, the A anchor is something similar, but not coded to work just yet).
Here's the HTML code:
http://pastebin.com/YeTxdHYq
And here's my CSS file:
http://pastebin.com/5hNjF99p
This appears to be a problem with IE, Firefox, and Chrome.
A lot of DOM events "bubble" from the bottom object up through container objects, which means they'll eventually reach the body. But you can stop this - try adding the following code to the click handler on your element:
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
...where e is the variable you already have in your function representing the event object.
event.stopPropagation(); should work in modern browsers, but the old IE way was event.cancelBubble = true; - to be safe you can just do both (but as shown above check that .stopPropagation is defined before trying to call it).
With the above code added, if you click on the element your function will stop container objects (include the body) from seeing the click. If you click somewhere else your function isn't called so then the body will process the click.
There's more info about this at MDN and QuirksMode.org.
Note: I've ignored the z-order issue because in this case I think it is a non-issue - all elements are descendents of the body so (unless you stop it) I would expect events to bubble to the body regardless of z-order.
When I want some link to not do anything but only respond to javascript actions what's the best way to avoid the link scrolling to the top edge of the page ?
I know several ways of doing it, they all seem to work fine :
Hello
or
<a id="hello" href="#">Hello</a>
<script type="text/javascript>
$(document).ready(function() {
$("#toto").click(function(){
//...
return false;
});
});
</script>
and even :
<a id="hello" href="#">Hello</a>
<script type="text/javascript>
$(document).ready(function() {
$("#toto").click(function(event){
event.preventDefault();
//...
});
});
</script>
Do you have any preference ? why ? in which conditions ?
PS: of course the above examples assume you're using jquery but there's equivalents for mootools or prototype.
Binding:
javascript: URLs are a horror to be avoided at all times;
inline event handler attributes aren't brilliant either, but OK for a bit of rapid development/testing;
binding from script, leaving the markup clean, is typically considered a best practice. jQuery encourages this, but there is no reason you can't do it in any library or plain JS.
Responses:
In jQuery return false means both preventDefault and stopPropagation, so the meaning is different if you care about parent elements receiving the event notification;
jQuery is hiding it here but preventDefault/stopPropagation have to be spelled differently in IE usually (returnValue/cancelBubble).
However:
You have a link that isn't a link. It doesn't link anywhere; it's an action. <a> isn't really the ideal markup for this. It'll go wrong if someone tries to middle-click it, or add it to bookmarks, or any of the other affordances a link has.
For cases where it really does point to something, like when it opens/closes another element on the page, set the link to point to #thatelementsid and use unobtrusive scripting to grab the element ID from the link name. You can also sniff the location.hash on document load to open that element, so the link becomes useful in other contexts.
Otherwise, for something that is purely an action, it would be best to mark it up like one: <input type="button"> or <button type="button">. You can style it with CSS to look like a link instead of a button if want.
However there are some aspects of the button styling you can't quite get rid of in IE and Firefox. It's usually not significant, but if you really need absolute visual control a compromise is to use a <span> instead. You can add a tabindex property to make it keyboard-accessible in most browsers although this isn't really properly standardised. You can also detect keypresses like Space or Enter on it to activate. This is kind of unsatisfactory, but still quite popular (SO, for one, does it like this).
Another possibility is <input type="image">. This has the accessibility advantages of the button with full visual control, but only for pure image buttons.
The only advantage that I can think of to using javascript:void(0) is that it will be supported even by the oldest browsers. That said, I would use one of the other unobtrusive approaches you have mentioned:
For most uses, event.preventDefault() and return false can be used interchangeably.
event.preventDefault() will prevent the page from reloading, as desired, but will allow the click event to bubble up to the parent. If you want to stop the bubbling, you can use it in conjunction with event.stopPropagation.
return false will additionally stop the event from bubbling up to the parent.
I say 'interchangeably' in the first point above because much of the time we do not care whether or not an event bubbles up to the parent(s). However, when do we need some fine-tuning, we should consider points two and three.
Consider the following example:
<div>Here is some text Click!</div>
$("a").click(function(e) {
e.preventDefault();
});
$("div").click(function() {
$(this).css("border", "1px solid red");
});
Clicking on the anchor will prevent the default action of the event from being triggered, so the browser will not redirect to www.google.com. However, the event will still 'bubble up' and cause the div's click event to fire, which will add a border around it. Add e.stopPropagation() or just return false and the div's click event will not fire. You can mess with it here: http://jsfiddle.net/cMKsN/1/
Dreamweaver uses a nice little trick by default that I've started using.
<a href='javascript:;'></a>
It's small, it doesn't trip and anchors and it's library agnostic.
I tend to prefer using return false, as that gives the option to give the user a choice whether to continue that action, such as shown here, in quirksmode:
http://www.quirksmode.org/js/events_early.html#default
It's simple, it's old, but it works well, cross-browser, regardless of the version of javascript.
event.preventDefault() and return false; are one thing - they instruct the browser not to process the default action for the event (in this case, navigating to the href of the anchor tag that was clicked). href=javascript: and its ilk are something else - they're causing the default action to be 'do nothing'.
It's a question of style. Do you want to do all your work in the onclick, or do you want to be able to put actions in both the onclick and the href and rely on the capabilities of the browser to modulate between the two?
I like using href="javascript:void(0)" in the link as # implies jumping to the top of the page and that may in fact happen if for some reason your jQuery event does not load e.g. jQuery fails to load.
I also use event.preventDefault(); as it will not follow the link even if an error is encountered before return false; for example:
HTML:
<a id="link" href="http://www.google.com">Test</a>
jQuery Example 1:
$("#link").click(
function(){
alert("Hi");
invalidCode();
return false;
}
);
jQuery Example 2:
$("#link").click(
function(event){
event.preventDefault();
alert("Hi");
invalidCode();
return false;
}
);
Since invalidCode(); will throw an error return false is never reached and if jQuery Example 1 is used the user will be redirected to Google whereas in jQuery Example 2 he will not.
I think that I have seen as well javascript:; around as the web develops, is hard to keep track to the tricks that are available out there.. but this is mainly about accessability (besides javascript:void(0); ) and just a small correction is not javascript:void(0) but javascript:void(0); which means do nothing so pretty much as return false; although not sure if javascript:return false; does the same..
I always use and would suggest to use javascript:void(0); for a couple of reasons.. in my humble opinion, of course.
1.) I use it because of the same someone mentioned above.. href="#" is not appropriate as it might indicate going to the top and even in that case '#top' would be more adequate for that case. But also this can trigger something else in your code that makes use of # (hashes) so another reason is to avoid conflicts with other javascript that might be using #. And I tend to look for this when using a plugin for example, and replace them immediately.. href='#' to href='javascript:void(0);' or href='javascript:;'
2.) If I want to re-use a function for a group of specific Anchor tags, I can call it with the selector on any attribute without worrying about detecting the click event and preventing the default action and I do it without even thinking of it as a development preference.
3.) In most cases if you are doing link building using javascript:void(0); tries to make a link to not be followed as the old href= rel=nofollow so it avoid indexing links that are actions. I'm not so sure about this one merely because I heard that crawlers and robots can now read even Flash so would not be surprised if they can read javascript links
4.) Referring from 2.) you can target on a class like and forget about preventing the click event default action by using a href="javascript:void(0);" and then targetting the class directly from the selector at the jQuery function.
jQuery(function($)
{
//from the rel
$('a[rel="-your-rel-id"]') ... off('click').on('click',function()
//from the class
$('a.-the-class') ... off('click').on('click',function()
//from the id
$('a#-the-id').off('click').on('click',function()
{
--do something with this link
});
});
I rather feel more comfortable using the class as you can always do...
$(a#-your-id).hasClass(-yourclass-)
or any other interesting combination and affect many links.. so I really won't suggest to use the A as a selector solely..
Normally what I see in here being suggested is this:
jQuery(function($)
{
//from the rel
$('a[rel="-your-rel-id"]').on('click',function(event)
//do something
//prevent the click as is passed to the function as an event
event.preventDefault();
});
});
I'd rather not put JavaScript into the href because that's not what it's meant for. I prefer something like
Link
How do I send a click event (JS or JQuery) to a parent object that is an anchor? My basic HTML looks like:
<a href="javascript:myFunc(1,2,3)">
<img id="btn1" src="myimg.png">
</a>
So I can easily reference the anchor through button via:
document.getElementById('btn1').parentNode
However,
document.getElementById('btn1').parentNode.click
while it doesn't seem to raise an error in the console on firebug, the javascript function doesn't seem to be firing either. How do I send a click to this thing. By the way, I don't have control of the HTML so I can't just ad an ID to the anchor tag.
Gone are the days when it's okay to use the href="javascript:blah", especially if you're using a library like jQuery, Dojo, ExtJs or the rest. Event handlers should always be attached outside of the HTML.
$(function() {
$("#btn1").click(function() {
$(this).parent().click();
};
});
Here is a snippet that you can test on SO pages (copy+paste into Firebug)
$("#hlogo a").click(function() {
alert("a!");
return false;
});
$("#hlogo a img").click(function() {
alert("img!");
$(this).parent().click();
});
Normal Links with Normal HREF's
// assuming the link is always the immediate parent of #btn1
$("#btn1").parent().trigger("click");
Links with Javascript-Commands as HREF's
I note in your case though that your HREF value is a call to a javascript function, with parameters. For this, you may want to evaluate that HREF, rather than click the link:
// run the href-javascript from the parent anchor
eval($("#btn1").parent().attr("href"));
I've built a test-case and used firebug to try both methods. The first returns 1, showing the link was clicked, but the javascript is never executed. The second method actually executes the javascript found within the HREF value of the link itself. This should be an adequate solution to your specific need.
EDIT: ignore this answer as it's no good for links; see the comments below.
The click property of an a element is a function property, aka a method; all you are doing is referencing the property, not invoking it.
document.getElementById('btn1').parentNode.click();
(note the () to cause the method to be invoked) should do it, though if you are using jQuery already then Jonathan Sampson's answer will do what you need - there's no point in loading the library and then not using it :-)
Although Jonathan's answer can be shortened, as jQuery provides a click method:
$("#btn1").parent().click();
jQuery way maybe like this:
$(event.target).closest('a').trigger('click')
or in your words something like this
$('#bth1').closest('a').trigger('click')