So i am trying to hide multiple html elements with one checkbox.
hiding one element works like a charm, but as soon as i have two it hides only the fist one what matches.
Fast demo what i am trying to do :
Checkbox :
<input type="checkbox" id="kaartCheck" onclick="kliendikaartF()">
Element what i am able to show:
<p id="kliendi_kaart_olemas_p" style="display:none">Kliendikaart on olemas!</p>
and element what i am not able to show : (Basicly the same what is first
<p id="kliendi_kaart_olemas_p" style="display:none">Second element shoult apear</p>
and js what i am using for that :
function kliendikaartF() {
var checkBox = document.getElementById("kaartCheck");
var text = document.getElementById("kliendi_kaart_olemas_p");
if (checkBox.checked == true){
text.style.display = "block";
} else {
text.style.display = "none";
}
}
So long story short, i have multiple elements what i would like to hide with one click, i would give them all the same ID : kliendi_kaart_olemas_p and show / hide them with one checkbox.
I think you have to use querySelectorAll() method for select all element by attribute. This will returns array of all element which is matched by attribute and its value. then you have to iterate all one by one in for loop.
function kliendikaartF() {
var checkBox = document.getElementById("kaartCheck");
var allElements= document.querySelectorAll('[id="kliendi_kaart_olemas_p"]');
var new_display_value="none";
if (checkBox.checked == true){
new_display_value = "block";
}
for(i=0;i<allElements.length;i++){
allElements[i].style.display=new_display_value;
}
}
document.getElementById will only return the first element matching that id.
If you want to select all IDs or classes, use document.querySelector('#idhere')
Use a classs name as kliendi_kaart_olemas_p beacuse here You have created id and id is the unique name of an item in the whole page. If you take the id and modify that element It will only update the element which found first.
<p class="kliendi_kaart_olemas_p" style="display:none">Kliendikaart on olemas!/p>
and
<p class="kliendi_kaart_olemas_p" style="display:none">Kliendikaart on olemas!/p>
then initailize you varibale like
var text = document.getElementsByClassName("kliendi_kaart_olemas_p");
Your problem will be solved
Related
I want to select an element if it has a css as display block then do this function. If the element has the css as display block then remove ('hide') class from the header class.. This is what I want to do.. Any help?
Well, there are two solutions depending on what you want:
Solution 1
Looping through all elements and removing hide class from the current element if it has display block value in its style.
var elements = document.getElementsByTagName("*");
for(let i = 0; i < elements.length; i++) {
if(elements[i].style.display == "block") {
elements[i].classList.remove("hide");
}
}
Solution 2
Getting the reference of the element via HTML id.
var element = document.getElementById("YourElementID");
if(element.style.display == "block") {
element.classList.remove("hide");
}
You can define an id like this in your HTML file:
<div id="YourElementID">Div</div>
I am assuming that you want to determine if the element has the "hide" class by checking its display style. you don't need to do that, you can easily check its class list by using the following code:
element.classList.contains("hide");
There are several ways of collecting all the elements with display: block and i am not sure, which one performs best - or whether it performs good at all.
If you want all the Element instances of the page, which have a computed style of display: block you can do something like:
var $els = Array.from(document.body.querySelectorAll('*')).filter(function($el) {
return getComputedStyle($el).display === 'block';
});
Or ES6:
const $els = Array.from(document.body.querySelectorAll('*')).filter($el => getComputedStyle($el).display === 'block');
If you want the Element instances which have display: block literally set in the style-attribute, you have to do something like this:
var $els = Array.from(document.body.querySelectorAll('*')).filter(function($el) {
return $el.style.display === 'block';
});
I think it would perform better, if the selector in querySelectorAll() would be a little more specific.
Another option would be to use the TreeWalker API, but then you have to do a mutation, because you have to iterate over all the elements and push them to an array:
var $els = [];
walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);
while (walker.nextNode()) {
if (getComputedStyle(walker.currentNode).display === 'block') {
$els.push(walker.currentNode);
}
}
Once you have all your elements, you can do something with them.
A little bit more information would be helpful, especially what exactly you want to achieve, once you have the elements, because then i could also provide more help. Maybe provide a code example?
I try to find an easy solution (I am a totally coding beginner, just use javascript in widgets of a "out of the box" page) for the following problem:
There are multiple attributes visitor can select by click Remove/Show
attribute a (Remove/Show)
attribute b (Remove/Show)
attribute c (Remove/Show)
a.s.o.
based on visitors "selection", I would like to show or hide the list of elements:
element 1 (attribute a and b) - Remove if "a" OR "b" has been selected
element 2 (attribute a) - remove if "a" has been selected
element 3 (attribute a and c) - remove, if "a" OR "c" has been selected
a.s.o.
I am able already to hide elements based on a "selection", but in my solution every element show and hide only based on the unique ID (and so also only on the single selection).
The Javascript I found for that is:
<script type="text/javascript">
//<![CDATA[
function swap(openlink,closelink, linkid, dataid)
{
if( document.getElementById(dataid).style.display == 'none')
{
document.getElementById(dataid).style.display='inline';
document.getElementById(linkid).firstChild.nodeValue=closelink;
} else
{
document.getElementById(dataid).style.display='none';
document.getElementById(linkid).firstChild.nodeValue=openlink;
}
}
//]]>
</script>
And than I could use this HTML Code to Remove/Show the elements:
attribute a Remove
attribute b Remove
attribute c Remove
And my element will be Remove/Show by this:
<div id="showmeA" style="display:inline">Element 1</div>
<div id="showmeB" style="display:inline">Element 2</div>
<div id="showmeB" style="display:inline">Element 3</div>
Is there an easy way to add 2 ids to one "element", so that for example Element 1 could be hidden by id=showmeA AND id=showmeB?
You said the issue yourself: IDs are unique.
This is exactly why you should use something else than id, and class attribute is perfectly fine as it does not have to be unique.
Then, this means that the function will not look for your elements using getElementById() but getElementsByClassName().
Note that this function get elements, this involves that you have to loop through these elements and hide / show the ones targeted.
function swap(openlink, closelink, linkid, dataclass) {
var elements = document.getElementsByClassName(dataclass);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if(element.style.display == 'none') {
element.style.display='inline';
document.getElementById(linkid).firstChild.nodeValue=closelink;
} else {
element.style.display='none';
document.getElementById(linkid).firstChild.nodeValue=openlink;
}
}
}
Do not forget to replace id by class attributes to your HTML, you can put in as much as you want, they simply must be separated by a space:
<div class="showmeA showmeB">Element 1</div>
<div class="showmeB">Element 2</div>
<div class="showmeC">Element 3</div>
Here is an example that you can use to better understand the function and attributes used in your solution, this solves your issue: https://jsfiddle.net/sy2mxscf/
It is also important to inform you that inline Javascript is bad, you should reconsider your code when your Javascript skill will increase.
In order to solve the issue pointed out in the comments, you have to use some kind of counter and increment it when you hide the element, decrement it when you show element of one of his class, and displaying the associate element when this counter is 0.
This is also why you need two differentiated links: the "Remove" to increment, and the "Show" to decrement.
There are several way to implement this solution:
Use an associative array in Javascript
Use a custom attribute on the element
Add and remove specific classes
I chose the last one but this may be not the best one, this is just one of the possibilities.
https://jsfiddle.net/sy2mxscf/2/
The idea is to add or remove a custom "hidemeX" class. If you click on two different "Remove" links targeting the same element, two classes will be added. If you then click on any "Show" link, the associate class will be removed. But there is still a "hidemeX" class remaining until you click on the second link, so the element is not displayed thanks to CSS.
As Delgan says, its better to use class here, and you can use those <a>'s id as their class, so when you use your function swap, you can easily trace back to decide if the elements is selected, so the div should be removed.
Below is how you can separate javascript logic and html structure.
var swap = function(e) {
var close = 'Remove', open = 'Show';
var next = this.text === close ? open : close;
// Set the clicked <a>'s text.
this.text = next;
// Get divs that will affect by this <a>
var affectTarget = this.id;
// Affected div elements
var targets = document.getElementsByClassName(affectTarget);
var i, len = targets.length;
var visible;
var watch, wLen, j;
// For each <div> that will be affect by the clicked <a>, we have to chec :
for (i = 0; i < len; ++i) {
// Get the classes that used as a list to show which <a> will have a effect on it.
watch = targets[i].classList;
wLen = watch.length;
// visibilty is default to inline, if no <a> that it watches is selected, then it'll show
visible = "inline";
for (j = 0; j < wLen; ++j) {
// If any of the <a> it watches is selected, set the visibilty to none.
if (document.getElementById(watch[j]).text === open) {
visible = "none";
break;
}
}
targets[i].style.display = visible;
}
};
// For each switcher, we register a click event for it.
var switchers = document.querySelectorAll("a.showSwitcher");
var i, len = switchers.length;
for (i = 0; i < len; ++i) {
switchers[i].addEventListener('click', swap);
}
attribute a Remove
attribute b Remove
attribute c Remove
<hr/>
<div class="swaplinkA swaplinkB" style="display:inline">Element 1</div>
<div class="swaplinkA"style="display:inline">Element 2</div>
<div class="swaplinkA swaplinkC"style="display:inline">Element 3</div>
I want to duplicate the text value of the active radio buttom before other div. Radios are divided into groups. In each group is always active, only one. Therefore, a new value from each group should always be one, too. I will add a text value, but I cant to make the removal of the previous value of the group.
$('.views-exposed-widget').find('.form-type-radio').on('click', function(){
var a = $(this).closest('.form-type-radio').find('label[class="option"]').text();
$('.views-widget-sort-by').before('<span>'+a+'</span>');
});
My example: http://jsfiddle.net/e59ogp8a/
You could name them (and thus create a mapping between the radio group and the spans) so you can find them easily
$('.views-exposed-widget').on('change', 'input', function () {
var self = $(this),
name = this.name,
text = self.closest('.form-type-radio').find('label[class="option"]').text(),
target = $('.views-widget-sort-by').find('[data-for="'+ name +'"]'); // find the related span
// check if we found a related span, and if not create it
if (target.length == 0){
target = $('<span data-for="'+name+'"></span>').appendTo('.views-widget-sort-by');
}
// set the text of the span
target.text( text );
});
Demo at http://jsfiddle.net/gaby/5nutt42g/1/
You also had a wrong id on the the first radio (it should be edit-tid-1-4 and not edit-tid-1-2)
You have to remove all the prev siblings of your div element.
$('.views-exposed-widget').find('.form-type-radio').on('click', function(){
var a = $(this).closest('.form-type-radio').find('label[class="option"]').text();
$('.views-widget-sort-by').prevAll().remove();
$('.views-widget-sort-by').before('<span>'+a+'</span>');
});
You can use the group name as span's class name to clear the values of the group after group's button clicked.
Take a look here: http://jsfiddle.net/e59ogp8a/3/
$('.views-exposed-widget').find('.form-type-radio').on('click', function(){
var a = $(this).closest('.form-type-radio').find('label[class="option"]').text();
var groupName= $(this).find('.dls-radio').attr("name");
console.log($('.views-widget-sort-by').prev('.'+groupName).text(''));
$('.views-widget-sort-by').before('<span class="'+groupName+'">'+a+'</span>');
});
In my view file i have two div, in div1 there is some buttons, when i click a button in div1 it goes to div2 and in div2 it does same thing, this time it goes to div1.
Now my question is when there is several buttons in div2, how can i take all the button's id in an array. I want to pass this array in a hidden field of another model.
i tried in following way but it does not working.This is my scripting code.
function movebutton(elem){
var teamMember=[];
if( $(elem).parent().attr("id") == "officers_list" ){
$(elem).detach().appendTo('#add_member');
teamMember.push($(elem).attr("id"));
}
else{
$(elem).detach().appendTo('#officers_list');
teamMember.pop($(elem).attr("id"));
}
$("#TeamTeamMember").val(teamMember);
//console.debug('teamMember=>',teamMember);
}
You can use map function. Code below will return an array of ids.
$("#divId input[type='button']").map(function(index,element) { return element.id; });
Here scope of teamMember is local .so whenever you invoke your function it will create new empty array
Make it global
var teamMember=[];
function movebutton(elem){
if( $(elem).parent().attr("id") == "officers_list" ){
$(elem).detach().appendTo('#add_member');
teamMember.push($(elem).attr("id"));
}
else{
$(elem).detach().appendTo('#officers_list');
teamMember.pop($(elem).attr("id"));
}
$("#TeamTeamMember").val(teamMember);
//console.debug('teamMember=>',teamMember);
}
or You could use $.map() function
var teamMember = $("#add_member").find("button").map(function(){
return this.id;
}).get();
Assuming your 2nd div's id is div2 and your buttons marked up with the input tag, the following should create an array containing all buttons' ids that are in the desired div:
var btns = [];
$('#div2 input[type="button"]').each(function() {//if you are using the <button> markup just use $('div2 button').each(..)
btns.push($(this).attr('id'));
});
Hope this helps.
I have two elements, the first one is the default to print on screen
<input id=post-category value="first">
and the other is this, which will only show if some onclick was made and of course the first element must show off
<select id=cat-sel ><option>second</option></select>
UPDATED
I tried this code
el = document.getElementById("post-category");
el.style.visibility = "hidden";
el2 = document.getElementById("cat-sel");
el2.style.visibility = "visible";
but the problem here is, the 2nd element is indented. because it escapes the space for the 1st element. I don't like that, I wanted them to be on the same position
Change to
el = document.getElementById("post-category");
el.style.display = "none";
el2 = document.getElementById("cat-sel");
el2.style.display = "block";
since visible/hidden does not remove the space the element takes up on the page
You need to set display:none on the field you need to hide initially
Assuming a checkbox have
window.onload=function() {
document.getElementById("categoryCheckbox").onclick=function() {
var chk = this.checked;
document.getElementById("post-category").style.display = chk?"none":"block";
document.getElementById("cat-sel").style.display = chk?"block":"none";
}
}
PS: A little more code is needed for the show/hide to survive a reload by the way...
Define CSS for your ID's and fix the position.