Toggling elements with JavaScript - javascript

I want to toggle a div element (expand/collapse) when clicked.
I have many div elements, on click to new element, I want to collapse the previous one and expand the current clicked one.
I tried using static type variable to save the instance of previous div tag and compared with the current selection, but I don't know why is it not working.
Searching about this, I got similar code idea to collapse all div and then expand the current selected only, but I want to just toggle the previous one with new one, not collapse all div and expand the selected (though I would be using it if other way is not possible)
Can it be done using static variables of js?

At its simplest, you can simply do something like this:
var divs = document.getElementsByTagName('div'),
collapseClass = 'collapsed',
current = divs[0];
// Hide all elements except first, add click event hander
for(var i = 0, len = divs.length; i < len; i++){
divs[i].onclick = function(){
if(this !== current){
toggle(this, current);
current = this;
}
};
if(i > 0) toggle(divs[i]);
}
This will store the current element in a variable, then toggle it when another element is clicked. It also uses an if statement to check if the currently clicked element is the one currently visible element, and only toggles if its not.
See a working demo of this here: http://jsfiddle.net/GaxvM/

You can assign a unique ID to each of the elements and use document.getElementById to identify both elements, and then collapse one/expand the other.
If you number them sequentially (like div1, div2, div3, etc) you could do something like:
function colexp(div_id){
div_2_collapse = document.getElementById(div_id);
next_div = div_id.substr(0,3) + parseInt(div_id.substr(3))+1;
div_2_expand = document.getElementById(next_div);
hide(div_2_collapse);
show(div_2_expand);
}

Related

Continuously changing id of div based on button click

I need to change the ID of a div based on the buttons being clicked. This is what my buttons look like:
var id; // global variable
holding = "holder";
var counter = 1;
function sendData(valueId) {
id = valueId;
if (counter <= 1) {
document.getElementById(holding).setAttribute("id", id);
counter++;
holding = id;
} else {
document.getElementById(holding).setAttribute("id", id);
holding = id;
}
console.log(holding);
console.log(id);
}
<button id="republic" onclick="sendData('republic')">Republic</button>
<button id="ndtv" onclick="sendData('ndtv')">NDTV</button>
<button id="cnnnews18" onclick="sendData('cnnnews18')">CNN</button>
My div to be targeted is just an empty, <div id="holder"></div>. However, when I try to run this I see the div change the first time but it remains on the same ID for every other click. How can I fix this?
The trouble is that when you press one of the buttons, you're creating multiple elements with the same id. The "holder" div will be assigned the id of one of the buttons.
Ids are meant to be unique. When this isn't the case, the behavior of getElementById is undefined, so the browser likely just returns the first element it finds that qualifies. In your example, this will be one of your buttons, rather than the "holder" div.
To get the code to work, make sure the ids of your buttons and the valueId variables in your code are different.
Bladeski's suggestion to use
const holding = document.getElementById('holder');
is great. But you should also make sure the ids in your document stay unique, just to conform to the HTML standard and avoid any other undefined behavior.
Create a reference to the 'holding' div in a constant and the use this for changing the attribute. For example, at the start of the code:
const holding = document.getElementById('holder');
Then, whenever you need to update the element, use:
holding.setAttribute(...);
This also happens to be more efficient as it means that the DOM is not being queried every time the element needs to be accessed since the holding constant provides a direct reference to it.
You need to remove the ids from the buttons.
<button onclick="sendData('republic')">Republic</button>
<button onclick="sendData('ndtv')">NDTV</button>
<button onclick="sendData('cnnnews18')">CNN</button>
The first click only one element with id 'holder' would be available in dom. But in the next we would have two since both div and button would have republic/ndtv/cnnnews18 and getElementById returns the button and this goes on.
But instead of this having the reference holder div at root would be a better approach. The code would be:
var id; // global variable
holding = document.getElementById('holder');
var counter = 1;
function sendData(valueId) {
id = valueId;
if (counter <= 1) {
holding.setAttribute("id", id);
counter++;
} else {
holding.setAttribute("id", id);
}
console.log(id);
}

Javascript: Get click target of arbitrary element within div tag

So, the situation is the following.
I have a div element which serves as a container for all kind of other elements (especially <a hre0="..."><img ...></img></a> and <iFrame> tags):
<div id="myDiv">
So basically, what i wanna do is to get the click target (if applicable) for all kind of elements within this div tag, under the assumption that there is always only one click with target specified.
Speaking UI wise: I want to see the target link that the user sees when he hovers with the cursor over the element.
Is there a generic approach to achieve this?
It sounds like what you want to do is find all the child elements of your wrapper div, then loop through them getting the 'href' property. Something like:
var children = document.getElementById('myDiv').children;
for (var i = 0; i < children.length; i++) {
var childElement = children[i];
var destination = childElement.href;
// do whatever you want with destination here. You can also get the associated IDs etc.
}
Untested but should work.

Multiple fadeToggle()'s in a for loop?

I have a "projects" object. Each project has a div and another div inside it, which is hidden. I want to create multiple fadeToggle() effects, so that for each project - clicking the first div will make the one inside it show up.
I tried to do this with a simple for loop.
projects.display = function() {
for (var i = 0; i < projects.length; ++i) {
var projectID = "#projects-" + i;
var moreInfoID = "#projects-" + i + "-more";
// assign IDs for current project
$(projectID).click(function() {
$(moreInfoID).fadeToggle();
});
}};
The result of this code is that clicking any of the main div's triggers the hidden div of the LAST project to show up.
How can I make it so that clicking a main div will call fadeToggle() for the designated hidden div?
Do not believe for loop is necessary. You should be able to substitute attribute starts with and attribute ends with selectors, :has() or :not()
$("[id^=projects]:has([id$=more])").click(function() {
$("[id$=more]", this).fadeToggle()
})

Bring to front with appendChild - can't use text field (JavaScript)

I want to use appendChild to bring div elements to front in a simple web application. I listen for click or mousedown (I have tried both) and then reappend whatever has been clicked to the main div container. Like this:
JavaScript
document.querySelector("#container").addEventListener("click", function(event) {
for (var i = 0; i < this.children.length; i += 1) {
if (this.children[i].contains(event.target)) {
this.appendChild(this.children[i]);
}
}
});
However, when I try this in Firefox the text fields in the div elements becomes unselectable. You can't put the marker in the text fields. It works in Chrome but not in Firefox. What could be the cause of this and how can I fix it?
Currently, because of this problem, I am using a different method with z index. But I would prefer to use appendChild as it has other advantages.
Thanks in advance.
This is a direct consequence of the appendChild which temporarily removes from DOM the child that contains the clicked Element (including when clicking to select text or to put caret / focus in a text input field), to re-append it at the end of the div children (but the text selection is now gone).
A simple workaround would be to leave the clicked child in DOM, but move its below siblings up until the clicked one is the last child.
document.querySelector("#container").addEventListener("click", function(event) {
var found,
children = this.children;
for (var i = 0; i < children.length; i += 1) {
if (children[i].contains(event.target)) {
//this.appendChild(children[i]); // Do not detach from DOM.
found = children[i]; // Leave it in place.
} else if (found) {
this.insertBefore(children[i], found); // Swap with found sibling.
}
}
});
Demo: https://jsfiddle.net/x53eh5b3/1/

How to swap placement of two elements, including their classes/ids with onclick?

I'm trying to switch the positions of two divs with an onclick event.
The divs have the same basic format (width, height), but an additional class and id change the way they look.
So, I have two functions that successfully change the id and class names, but there is no visual change.
Here they are:
function whenClickedFilled(){
console.log("filled");
this.firstElementChild.id = "empty";
this.firstElementChild.className = "puzzlepiece emptyDivClass";
}
function whenClickedEmpty(){
console.log("empty");
this.firstElementChild.id = "filled";
this.firstElementChild.className = "puzzlepiece";
}
I'd like to know what the best way is to alternate between classes/ids onclick.
Here is my js fiddle.
I think what you're really looking to do is not swaping the class and id, but swap the elements themselves. This will make sure the numbers contained within the div's is also transfer with the swap.
You still need to implement the logic checks to see if the element should be able to swap with the empty block and there looks like theres a bug when you click empty space itself. But, this should get you on the right track. I recommend placing a debugger statement to step through the code with dev tools open. It will help understand whats taking place. Good luck.
function whenClickedFilled(){
console.log("filled");
//Get the div element and parent
//Then determine the parent of the empty div
var clickedDiv = this.firstChild; //this refers to the TD clicked, get the child div element
var clickedDivParent = this; //this is TD
var emptyDivParent = emptyDiv.parentElement; //stored the empty div reference into a global, retrieve the parent as this could change
//Remove the empty and clicked div's from their container
emptyDivParent.removeChild(emptyDiv)
clickedDivParent.removeChild(clickedDiv);
//Add the elements back to the containers but swapped
clickedDivParent.appendChild(emptyDiv);
emptyDivParent.appendChild(clickedDiv);
}
http://jsfiddle.net/tWrD2/
I'm trying to switch the positions of two divs with an onclick event
If you want to swap two adjacent nodes, you can do something as simple as:
function swapAdjacent(el0, el1) {
el0.parentNode.insertBefore(el1, el0);
}
If you want to swap any two elements in the DOM, you can do something like:
// Swap the postion in the DOM of el0 and el1
function swapElements(el0, el1) {
// Create a temp node that can replace el0
var tmp = el0.cloneNode(false);
// Replace el0 with tmp
el0.parentNode.replaceChild(tmp, el0);
// Replace el1 with el0
el1.parentNode.replaceChild(el0, el1);
// Replace temp node with el1
tmp.parentNode.replaceChild(el1, tmp);
}
and some test markup:
<div id="d0">div 0</div>
<div id="d1">div 1</div>
<button onclick="
swapElements(document.getElementById('d0'), document.getElementById('d1'));
">Swap d0, d1</button>
<button onclick="
swapAdjacent(document.getElementById('d0'), document.getElementById('d1'));
">Swap adjacent</button>
Of course the two elements to swap must be consistent with the surrounding elements, e.g. you can't swap an option element with a div and expect everything to work, but you can probably swap a span with a div.
If you want to swap elements by clicking on one or the other:
<div id="d0" onclick="swapElements(this, document.getElementById('d1'))">div 0</div>
<div id="d1" onclick="swapElements(this, document.getElementById('d0'))">div 1</div>
I found a nice solution provided by fuell when I was searching fo an actual html swap:
<div id="div_1">THIS IS DIV 1</div>
<div id="div_2">THIS IS DIV 2</div>
Go Swap!
$(document).ready(function() {
$(".go-swap").click(function() {
$("#div_1").removeAttr("style");
$("#div_2").removeAttr("style");
var tmp = $("#div_1").html();
$("#div_1").empty().append($("#div_2").html());
$("#div_2").empty().append(tmp);
});
});

Categories

Resources