Loop Toggle for different ID Element - javascript

I have this following script to toggle (show and hide):
function btnClass1(where, pval, nval){
var x=$("#btn1-Bln ").val();
if (x == 'Show '){
where.title='Show ';
}
else{
where.title='Hide ';
}
where.value=(where.value == nval) ? pval : nval;
container=document.getElementById("containerXd");
container.style.display=(container.style.display == 'inline-block') ? 'none' : 'inline-block';
container.style.visibility=(container.style.visibility == 'visible') ? 'hidden' : 'visible'
;
I have many IDs to toggle, say, it's about 24 different IDs.
When I use the code it works fine, I just change #btnClass1 to #btnClass2 and 3, etc as well as #btn1-Bln, and containerXd.
But, I feel it's not efficient to build every IDs with new block of the script (again and again).
In this case, I need a simple script to represent all IDs in a web page.
Do you have other best suggestion for me, please

You just need to add two new params to your function for the buttonSelector and the containerSelector. In your example, you would pass in "#btn1-Bln" and "containerXd" for these new params, respectively. Then, use these new variables rather than the hard-coded strings in your function body. This will allow you to use your single existing function with any buttons and containers.

Related

JavaScript toggle class on current element

Just want to understand a principle of JavaScript, I'm a bit new to this.
I'm adding some styling to some element which are slides which I'm scrolling through.
The "current" div have a transform: none applied, the two others get styled depending on where I am on the slider.
I'm using this code which is working fine.
el.style.transform = i === e.current ? 'none' : i > e.current ? 'translateX(100%)' : 'translateX(-100%)'
My question is how do I add / toggle a class to the current el, and remove it back when it's not the current anymore.
I've tried some couple options using the same principle but can't find the right way to achieve it.
el.classList = i === e.current.toggle('classname') : i > ? e.current.toggle('classname')
el.classList.toggle() = i === e.current ? 'active' : i > e.current ? 'prev' : 'next'
Can somebody give me a heads up on how to achieve what i want to do? I've tried to go through some others post on Stack Overflow and to look on element.classList docs everywhere i could find it, but I'm stuck at this point and JS knowledge is not my strong point.
Thanks!
toggle takes the class name e.g. el.classList.toggle('classname'). You don't pass a variable to a function like this el.classList.toggle() = 'classname'. But you might be better off calling add or remove depending on if the item is the current one since you also need to ensure the other classes aren't still there.
el.classList[i === e.current ? 'add' : 'remove']('active');
However since you also want prev and next probably best not to try and be too clever with ternaries and make it readable:
if (i > e.current) {
el.classList.remove('current', 'prev');
el.classList.add('next');
} else if (i < e.current) {
el.classList.remove('current', 'next');
el.classList.add('prev');
} else {
el.classList.remove('prev', 'next');
el.classList.add('current');
}
If you aren't worried about overwriting other classes you could simplify this using className as it overwrites any existing classes:
if (i > e.current) {
el.className = 'next';
} else if (i < e.current) {
el.className = 'prev';
} else {
el.className = 'current';
}

For loop with eval not working

My first time writing my own javascript/jQuery for-loop and I'm running into trouble.
Basically, I have a series of divs which are empty, but when a button is clicked, the divs turn into input fields for the user. The input fields are there at the outset, but I'm using CSS to hide them and using JS/jQuery to evaluate the css property and make them visible/hide upon a button click.
I can do this fine by putting an id tag on each of the 7 input fields and writing out the jQuery by hand, like this:
$('#tryBTN').click(function(){
if ( $('#password').css('visibility') == 'hidden' )
$('#password').css('visibility','visible');
else
$('#password').css('visibility','hidden');
}
Copy/pasting that code 7 times and just swapping out the div IDs works great, however, being more efficient, I know there's a way to put this in a for-loop.
Writing this code as a test, it worked on the first one just fine:
$('#tryBTN').click(function() {
for(i = 1; i <= 7; i++) {
if($('#input1').css('visibility') == 'hidden')
$('#input1').css('visibility', 'visible');
}
});
But again, this only works for the one id. So I changed all the HTML id tags from unique ones to like id="intput1" - all the way out to seven so that I could iterate over the tags with an eval. I came up with this:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
if ($(eval('input' + i)).css('visibility') == 'hidden')
$('input' + i).css('visibility', 'visible');
}
});
When I put in the eval stuff - it doesn't work. Not sure what I'm doing wrong. A sample of the HTML looks like this:
<form>
<div class="form-group">
<label for="page">Description: Specifies page to return if paging is selected. Defaults to no paging.</label>
<input type="text" class="form-control" id="input7" aria-describedby="page">
</div>
</form>
You were forgetting the #:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
var el = $('#input' + i); // <-- The needed `#`
if (el.css('visibility') == 'hidden') {
el.css('visibility', 'visible');
}
}
});
#Intervalia's answer explains the simple error in your code (the missing #), and the comments explain why you should never use eval() unless you absolutely know it's the right tool for the job - which is very rare.
I would like to add a suggestion that will simplify your code and make it more reliable.
Instead of manually setting sequential IDs on each of your input elements, I suggest giving them all a common class. Then you can let jQuery loop through them and you won't have to worry about updating the 7 if you ever add or remove an item.
This class can be in addition to any other classes you already have on the elements. I'll call it showme:
<input type="text" class="form-control showme" aria-describedby="page">
Now you can use $('.showme') to get a jQuery object containing all the elments that have this class.
If you have to run some logic on each matching element, you would use .each(), like this:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
if( $(element).css('visibility') == 'hidden' ) {
$(element).css( 'visibility', 'visible' );
}
});
});
But you don't need to check whether an element has visibility:hidden before changing it to visibility:visible. You can just go ahead and set the new value. So you can simplify the code to:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
$(element).css( 'visibility', 'visible' );
});
});
And now that the only thing we're doing inside the loop is setting the new visibility, we don't even need .each(), since jQuery will do the loop for us when we call .css(). (Thanks #TemaniAfif for the reminder.)
So the code becomes very simple:
$('#tryBTN').click( function() {
$('.showme').css( 'visibility', 'visible' );
});

jQuery: Add class to filter item containing active term, accounting for pagination

I'm working on an events page in a WordPress site that uses a set of filters to query posts; the markup for the filters is as follows:
<div class="event-filter">
All Events
Conferences
Webinars
Learning
Past Events
</div>
I'm using jQuery to add an active class to whichever filter is currently in use, the simple code for which is as follows:
$('.event-filter a').each(function() {
if (this.href == window.location.href) {
$(this).addClass("active");
}
});
This works perfectly fine except in the case that the resulting posts are paginated, as the url changes to reflect the current page, i.e. /events/page/2/?event-type=conference. How can I modify my JS to add the active class to the current filter if the URL contains the respective event-type term but also accounts for "All Events", and thus appends the class to "All Events" when the other filters are not in use? A couple notes: the "Past Events" option just links to an archive page that is a separate template from the main, filterable "Events" page; also, these filters are not using Ajax, they're just altering the WordPress query by URL parameter. Thanks for any insight here!
By the looks of it you will have to do a two part check, I would try something like:
$('.event-filter a').each(function() {
var currentHref = window.location.href.split('?'); // ['https://myexamplesite.com/events/page/2', 'event-type=conference']
var thisHref = this.href.split('?'); // ['https://myexamplesite.com/events', 'event-type=conference']
var currentHrefHasQuery = currentHref.length > 1 ? true : false; // true
var thisHrefHasQuery = thisHref.length > 1 ? true : false; //true
if (currentHrefHasQuery != thisHrefHasQuery) {
return; // they don't match
}
if (currentHrefHasQuery && currentHref[1] == thisHref[1]) { // if they have a query and the query is the same, it's a match!
$(this).addClass("active");
} else if (!currentHrefHasQuery && currentHref[0].indexOf(thisHref[0]) > -1) { //check to see if the current href contains this' href
$(this).addClass("active");
}
});
This could definitely be simplified, but hopefully this is fairly easy to read.
Fiddle: https://jsfiddle.net/m0hf3sfL/

Stmixing string with array variable to assign an id for an element in javascript

I´m trying to mix a string to assign variable(array) I don´t know what´s wrong I can not get it work.
in php I will send array of id to javascript via json_encode();
I will get like :key= 1, 2, 3 etc.
Here is aline of those div:
text
Then in javascript with a conditon like this:
$("#swas"+key).removeClass('colorme');
function xx(key, arr) {
for (var v in arr) { //LOOP
var k = arr[v];
if ($("#swas" + k) != key) {
$("#swas" + k).addClass('colorme');
}
}
}
What have I done wrong ?
UPDATE
The reason I want to mix "swas" with array because in php page there´re alot of div that name
swas1, swas2, swas3, swas4.........>etc
And "key" is the id of current div that will be clicked. and "key" value : 001, 002, 003, 004 etc
What I want to do is to make the other div (that´s not the current div )to not change color.
that´s why I have to mix the word "swas" with the "key" in javascript.
UPDATE2
Now It work with script above but new probelm, it not remove the class when clicked :S
UPDATE3
Now everything just work fine after I move the $("#swas"+key).removeClass('colorme');
To the bottom :) S
You mention swas1 swas2 etc, but then you mention arr being 001 002 etc. These will not match.
It would be so much easier if you used jquery
$('#swas' + k).addClass('colorme');
You can use something like Firebug to ensure that your selection is correct.
If you want to use javascript then test to see if the Div already has a class before appending
var el = document.getElementById('hello');
if(el) {
el.className += el.className ? ' someClass' : 'someClass';
}

Expand only one row in javascript code

hey guys having trouble figuring out how to make it so that i can make it only open one table at once, once you open another the other should close any help here?
function showRow(cctab){
if (document.getElementById(cctab)) {
document.getElementById(cctab).style.display = '';
}
}
function hideRow(row1){
if (document.getElementById(cctab)) {
document.getElementById(cctab).style.display = 'none';
}
}
function toggleRow(cctab){
if (document.getElementById(cctab)) {
if (document.getElementById(cctab).style.display == 'none') {
showRow(cctab)
} else {
hideRow(cctab)
}
}
}
Now I want to make it so that only one table "cctab" opens after I suggest the onClick="javascript:toggleRow(cctab);" anyhelp?
Well you could save a reference to the previously shown item and hide it when another is shown:
var currentTab;
function showRow(cctab){
if (document.getElementById(cctab))
document.getElementById(cctab).style.display = '';
if (currentTab && currentTab != cctab)
hideRow(currentTab);
currentTab = cctab;
}
Note that doing inline event handler attributes is so 1999, but assuming you're sticking with it for whatever reason you don't need the javascript: in onClick="javascript:toggleRow(cctab);". (Just say onClick="toggleRow(cctab);")
First you need to store the old row somewhere.
What you've got is a system where you're using <element onclick="..."> to pass the id of the current element into the controller that shows or hides the row.
But if you look at that, what you're missing is a way of telling what the last open row was.
So what your code will need is a central object, or variables which store the old element and the new element.
How you do this is up to you, but if you did something like this:
var table_rows = { current : null /* or set a default */, previous : null };
function rowController (cctab) {
var newRow = document.getElementById(cctab);
if (newRow === table_rows.current) { toggleRow(newRow); }
else {
table_rows.previous = table_rows.current;
table_rows.current = newRow;
showRow(table_rows.current);
hideRow(table_rows.previous);
}
}
Note:
This deals with elements directly, so you don't have to do getById in your functions;
that's handled one time, and then that element is passed around and saved and checked against.
It assumes that the click is happening on the row itself, and not on anything inside of the row;
that's a separate issue that your code has.
Unless it's obvious and easy to click on the row, and not the cells inside of the row, it's difficult to tell how you want users to be able to open and close rows.
What I mean is if only the table-row has an onclick, and somebody clicks on a table-column, then then onclick isn't going to fire.

Categories