I'm using JavaScript to hide and show some elements onclick events
Using this code
function showPreOne() {
document.getElementById('SecandModalFilter').classList.add('d-none');
document.getElementById('FirstModalFilters').classList.add('d-none');
document.getElementById('colocation').classList.add('d-none');
document.getElementById('coloc-row').classList.add('d-none');
document.getElementById('preFirstModalFilter').classList.remove('d-none');
document.getElementById('FirstModalFiltersa').classList.add('d-none');
}
I don't think this is the correct way! ? specially if I have a very large page with a lot of tabs and elements ?
Thank you
You could add a class on all the element that can be hidden (I assume you are handling a tab system), and just show the one you want to be visible:
function showPreOne() {
document.querySelectorAll('.tab').forEach(elt => elt.classList.add('d-none'))
document.querySelector('#SecandModalFilter').classList.remove('d-none');
}
Otherwise, your current method is not wrong per-say.
If the class is display: none, there's nothing wrong with that approach. Although the code would be more maintainable if you managed the add/remove elements with arrays of ids instead of doing it line by line.
Your approach can be a bit better, if you are showing/hiding elements I suggest you to use the toggle functionnality.
This way you can use only one function that will manage your click event and hide/show your elements, just be sure that the initial state (d-none class present or not) is correct :
function showHide() {
document.getElementById('SecandModalFilter').classList.toggle('d-none');
document.getElementById('FirstModalFilters').classList.toggle('d-none');
document.getElementById('colocation').classList.toggle('d-none');
document.getElementById('coloc-row').classList.toggle('d-none');
document.getElementById('preFirstModalFilter').classList.toggle('d-none');
document.getElementById('FirstModalFiltersa').classList.toggle('d-none');
}
More informations here Toggle specification
Related
I have a set of links with a class app-context-link on my page – just some <a> menu elements.
They are generated when the page is loaded from some data that the page receives from a JSON.
I then apply the following on click jQuery function, to make sure that when a user clicks on one of those elements, a certain procedure is performed:
$(".app-context-link").on('click', function(e) {
e.preventDefault();
// do something
}
The problem is that when the user clicks on one of the items, I want to highlight the item they clicked, perform some action on the JSON, and then return a new menu to the user that has other elements of the same class app-context-link – in this case the "old" onclick function does not apply to the newly added items, right? And then I can't get them to behave in the same way because of that.
Does anyone have an idea how I could resolve it?
I know I probably have to rewrite everything very carefully with callbacks, etc. but maybe there's an easier solution already inside jQuery and I'm just missing something?
And as a bonus track – if I decided to leave the menu as it is and just to highlight the element clicked (through appending a class), how would I do that? Sorry if that last question sounds stupid, but I'm a novice and feel a bit confused...
Thank you!
You need to delegate event, e.g:
$(document).on('click', ".app-context-link", function(e) {
e.preventDefault();
// do something
});
Now selector will be filtered on each click.
document is an example, usually, you'd prefer to bind it to closest static container
function bindLink() {
$(".app-context-link").click(function() {
// do something
});
}
Now, everytime you change your data, you can call your bind function (bindLink()).
I have bunch of images in a wrapper div. I need to hide all of them except the one user clicks on.
What is the most performance concise way of doing that?
Should I apply class on all of them to hide them all and than filter out the one that was clicked and show only that one or should I loop over them all hiding them as loop progresses with exception of the one that was clicked or something else?
Tnx
In modern desktop browsers you won't see any difference. Browsers are tuned so that they are blazing fast in rendering any changes is DOM three. Guts tell me that it might be sligtly faster to loop through all images and set visibility depending on item clicked using style attribute and not using class. In that way you have to process only N elements and no external CSS files are involved. If you hide all and show the element with was clicked, you process N + 1 elements.
In your situation I would use solution that is fastest, more managable and clean from the developers standpoint as there won't be much difference in the final result if you use one method or another.
PS: If you're using jquery, you can use the following:
Lets say, your div has id='test-div', and there are several images in it. All these images can be accessed as:
$('#test-div img')
Now, lets assume you know the id of image which got clicked. Lets assume id='my-image'.
You can execute the following to hide all other images (except 'my-image'):
$('#test-div img').not('#my-image').addClass('hide')
One of the most performant ways would be to let CSS do the visibility. It sounds to me like you're only displaying one at a time, in which case you can do it with two DOM operations by using classes;
// scope above
var lastClicked = null;
// then in click listener, 1st param `e`
if (lastClicked) lastClicked.className = ''; // remove visible class
lastClicked = e.target; // get clicked node
lastClicked.className = 'visible'; // add visible class
I'm assuming event.target but depending how the listener is attached, you might want to use this or some other logic. Further, if you expect element.classList support, you can use add and remove from that.
Example CSS of how to show only nodes with class token visible.
selector:not(.visible) {
display: none;
}
I have two custom dropdown lists that have the same markup. I need to have only one show at a time. Right now, I'm able to open both at the same time. Both should also close when I click off the list.
The same markup for both lists is required, so I can't use unique ID's or additional classes to make this happen.
Here is a link to my fiddle example: http://jsfiddle.net/dg7Lc/29/
Any help would be greatly appreciated, thanks!
-D
Consider adding a data attribute such as 'active' via jquery when you click on one of them, then hide all those that have that attribute.
$('.custom-select').eq(0).hide() will hide the first one.
Use .show() instead of .hide() to show (obviously) and change the index to (1) to get the second one.
First thought would be if you could wrap a span or div around either or both and use that to get around the "same markup" limitation. Other than that, though, I'd suggest using order in page - use .next() and .prev() to get between them, and something like
$("div.custom-select").get(0)
or
$("div.custom-select").get(1)
to select them from outside.
edit: if you can run them off of something like an onmouseover, onchange, or whatnot, it's even easier - the one that's changing will be passed into the function as the "this" parameter. Just hide both, and show this, or show both and hide this.
edit2: similarly, once you have one of them hidden properly - well, that one will be hidden, and respond to the ":hidden" selector. Use that to distinguish between them (and save the distinction as a jquery variable) before you go showing or hiding anything else
Hide the first:
$('.custom-select').first().hide();
Hide the second:
$('.custom-select').last().hide();
And then put these lines of code where needed.
http://jsfiddle.net/dg7Lc/31/
Basically, closing the others:
$('.custom-select').not(this).find('ul').slideUp('fast');
And for closing when clicking outside the box, I used this piece of code but it's a bit dirty:
$("body").click(function(e) {
var should = true;
for($e = $(e.target); should && $e.length; $e = $e.parent()) {
should = !$e.is(".custom-select");
}
if(should) {
$('.custom-select').find('ul').slideUp('fast');
}
});
You can bind a click to the document, that looks to see if they clicked on the custom-select or the document outside it and hides any open lists as it should:
$(document).click(function(ev){
if(!$(ev.target).is('.custom-select span')){ $('.custom-select').find('ul').slideUp('fast'); }
});
Updated JSFiddle
I want to add a slide up affect with jQuery to a DIV when a link inside of the DIV is clicked, but the problem i am running into is the class of the DIV's are defined by a loop. So, i can't define the DIV class in the jQuery line, because each DIV class is different and i cannot determine ahead of time what they are. I am trying to use .parent and .child but I am not sure how to go about this. Is this making any sense?
Bind to the click of the element you want (in this case I just used a simple anchor element). Then find the first parent that is a div and perform the slideUp() effect.
$('a').click(function() {
$(this).parents('div:first').slideUp();
});
You can see it work here: http://jsfiddle.net/XNnSp/
Let me know if that's what you are looking for http://jsbin.com/ehoza3
$('a').click(function() {
$(this).parent().slideUp();
});
Two (most obvious) ways
FIRST
If your tree is always defined in terms of depth you could access your parent DIV doing just that:
$(this).parent().parent().parent().slideUp();
SECOND
Add an additional class that doesn't clash with dynamic ones and do this:
$(this).closest(".some-custom-class").slideUp();
I write a lot of dynamically generated content (developing under PHP) and I use jQuery to add extra flexibility and functionality to my projects.
Thing is that it's rather hard to add JavaScript in an unobtrusive manner. Here's an example:
You have to generate a random number of div elements each with different functionality triggered onClick. I can use the onclick attribute on my div elements to call a JS function with a parameter but that is just a bad solution. Also I could generate some jQuery code along with each div in my PHP for loop, but then again this won't be entirely unobtrusive.
So what's the solution in situations like this?
You need to add something to the divs that defines what type of behaviour they have, then use jQuery to select those divs and add the behaviour. One option is to use the class attribute, although arguably this should be used for presentation rather than behaviour. An alternative would be the rel attribute, but I usually find that you also want to specify different CSS for each behaviour, so class is probably ok in this instance.
So for instance, lets assume you want odd and even behaviour:
<div class="odd">...</div>
<div class="even">...</div>
<div class="odd">...</div>
<div class="even">...</div>
Then in jQuery:
$(document).load(function() {
$('.odd').click(function(el) {
// do stuff
});
$('.even').click(function(el) {
// dostuff
});
});
jQuery has a very powerful selector engine that can find based on any CSS based selector, and also support some XPath and its own selectors. Get to know them! http://docs.jquery.com/Selectors
I would recommend that you use this thing called "Event delegation". This is how it works.
So, if you want to update an area, say a div, and you want to handle events unobtrusively, you attach an event handler to the div itself. Use any framework you prefer to do this. The event attachment can happen at any time, regardless of if you've updated the div or not.
The event handler attached to this div will receive the event object as one of it's arguments. Using this event object, you can then figure which element triggered the event. You could update the div any number of times: events generated by the children of the div will bubble up to the div where you can catch and handle them.
This also turns out to be a huge performance optimization if you are thinking about attaching multiple handlers to many elements inside the div.
I would recommend disregarding the W3C standards and writing out HTML-properties on the elements that need handlers attached to them:
Note: this will not break the rendering of the page!
<ul>
<li handler="doAlertOne"></li>
<li handler="doAlertTwo"></li>
<li handler="doAlertThree"></li>
</ul>
Declare a few functions:
function doAlertOne() { }
function doAlertTwo() { }
function doAlertThree() { }
And then using jQuery like so:
$("ul li").each(function ()
{
switch($(this).attr("handler"))
{
case "doAlertOne":
doAlertOne();
break;
case ... etc.
}
});
Be pragmatic.
It's a bit hard to tell from your question, but perhaps you can use different jQuery selectors to set up different click behaviours? For example, say you have the following:
<div class="section-1">
<div></div>
</div>
<div class="section-2">
<div></div>
</div>
Perhaps you could do the following in jQuery:
$('.section-1 div').onclick(...one set of functionality...);
$('.section-2 div').onclick(...another set of functionality...);
Basically, decide based on context what needs to happen. You could also select all of the divs and test for some parent or child element to determine what functionality they get.
I'd have to know more about the specifics of your situation to give more focused advice, but maybe this will get you started.
I haven't don't really know about JQuery, but I do know that the DOJO toolkit does make highly unobtrusive Javascript possible.
Take a look at the example here: http://dojocampus.org/explorer/#Dojo_Query_Adding%20Events
The demo dynamically adds events to a purely html table based on classes.
Another example is the behaviour features, described here:http://dojocampus.org/content/2008/03/26/cleaning-your-markup-with-dojobehavior/