Javascript "document.getElementById" wildcard loop? - javascript

Can wildcards be used with the Javascript "document.getElementById" line?
I have a Vb.net form with 3 div elements ("page1, page2, page3"). What I'm hoping to accomplish is allowing the user to click a button or hyperlink button that will navigate them to the next div ("page#"). Is there a way to do something like the following & loop through each element that has an ID like "page1", "page2", "page3", etc without hard coding?
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'none')
e.style.display = 'block';
else
e.style.display = 'none';

For what I understand, you are looking for the querySelectorAll function and a for-in loop:
var elements = document.querySelectorAll("[id^='page']");
for(var e in elements){
// do Stuff - each element get's reached by elements[e]
}
for example:
var elements = document.querySelectorAll("[id^='page']");
for(var e in elements){
if(elements[e].style.display == 'none')
elements[e].style.display = 'block';
else
elements[e].style.display = 'none';
}
this will catch all elements with an id starting with the word "page" and toggle their visibility

Short answer: no, this is not possible. As Markai has pointed out, it is possible. I still feel like using a class is more appropriate, as this better captures the semantics.
A bit longer answer: perhaps you can give each element a class="page". Then you can hide all elements with that class and only display the one you're interested in. You can get elements with class 'page' by using document.getElementsByClassName('page') or the more friendly jQuery selector $('.page').

You could loop the elements. Instead of a toggle, hide all elements except the one you want.
function EnableVisibility(elementName, elementId)
{
for(i=1;i<4;i++)
{
if(i == elementId)
document.getElementById(elementName + i).style.display = 'block';
else
document.getElementById(elementName + i).style.display = 'none';
}
}
EnableVisibility("page", 2); // This would hide all pages and display page2
If you don't like the hardcoded 4, you could change the for loop with a while and if getElementById returns a null then exit the loop.
I personally like the class idea from Martijn and instead of changing the style directly you add or remove a class ex: class="page visible" class="page hidden"

Related

How to select an element with specific css value in javascript

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?

How to convert links to text using JQuery?

I try to think up function which can replace links to text. Image inside a tag should be moved to the wrapper, the original a should be removed.
JS:
var selectors = 'a.mark-video;a.sp5;a>img[alt!=""]'
selectors = selectors.split(";").join(", ");
$(selectors).each(function() {
var current = this;
if (this.nodeName == "IMG") {
current = this.parentNode;
if (current.nodeName != "A")
current = this.parentNode;
if (current.nodeName != "A")
return false;
current = $(current);
}
var wrapper = current.parent();
var new_context = $().append(current.html());
current.remove();
wrapper.append(new_context);
}
);
The problem is
1) that the image is not inserted into the wrapper
2) if it would be inserted it would not have correct position.
I am experimenting using webextensions API (Firefox addon) and I injected the code to site:
http://zpravy.idnes.cz/zahranicni.aspx
In the debugger you can see two wrappers with class="art ". I have removed the first link but image is not inserted. The second one has not been removed yet when debugger was paused after first iteraction.
I hope you can find out why the image is not appended and how to append it to the original position of the element a. I need to find out position of the element a first, and then to move the image into to correct position - that is before div.art-info.
Note: please do not change the selectors string. This is the users input from form field.
Edit:
Almost there:
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).html().replaceWith($(this)); // error: html() result does not have replaceWith...
}
Is this what you're looking for?
https://jsfiddle.net/4tmz92to/
var images = $('a > img');
$.each(images, function(key, image) {
$(this).parent().replaceWith(image);
});
First select all the images that you want to remove the link from, then loop through them and simply replace the parent() with the image.
I have finally solved the problem:
$(selectors).each(
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).replaceWith(
$(this).html()
);
}
);
This works similar. Novocaine suggested not to use $(this).html() but this would skip some images so I prefer to use it.

'href' Not Showing Output on Click

Im trying to have a href link expand/display extra text when clicked however when I click it nothing happens.
When I run the html code I can click on the link but it does not show the text for some reason.
Any idea why?
Heres the code:
<html>
click to expand
<div id="divID" style="display: none;">this is expanded</div>
</html>
I'm trying to keep the code as short as possible as the above code will have to be repeated hundreds of times for each link.
Assuming you're using jQuery, you are using the CSS selector incorrectly. Your line should be this:
click to expand
The # in #divID represents any element with an id of divID, whereas just using divID will search for divID tags (something like <divID></divID>)
See here for more documentation on the ID Selector and here's a list of all the CSS selectors you can use, including the Element Selector for you to understand why your previous code didn't work.
You can also combine CSS selectors to narrow your selection in the future, although it's not much necessary with an ID selector:
click to expand
And if you absolutely insist on not using jQuery:
click to expand
or breaking it out into its own function:
<script>
function toggleElementById(id) {
if (document.getElementById(id).style.display == 'none') {
document.getElementById(id).style.display = 'block';
} else {
document.getElementById(id).style.display = 'none';
}
}
</script>
click to expand
Add this to your page:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Then:
$('#divID').toggle();
I see you're using jQuery, right? So I wrote your answer in jQuery..
$('.toggle').click(function () {
var selected = $(this).attr('href');
$('.expandable'+selected).toggle();
});
Check out the jsfiddle
If you're not using jQuery than here is the javascript version (html changed).
var expandable = document.getElementsByClassName("expandable");
for (i = 0; i < expandable.length; ++i) {
expandable[i].setAttribute('style','display: none;');
}
var toggle = document.getElementsByClassName("toggle");
for (i = 0; i < toggle.length; ++i) {
toggle[i].setAttribute('onclick','toggler(this)');
}
function toggler(obj) {
var id = obj.dataset.toggle,
el = document.getElementById(id);
el.style.display = (el.style.display != 'none' ? 'none' : '');
}
Check out the jsfiddle

js - swap image on click

I'm trying to replace one div with another and turn the others off:
JS
function imgToSWF1() {
document.getElementById('movie-con2 movie-con3 movie-con4').style.display = 'none';
document.getElementById('movie-con').style.display = 'block';
}
function imgToSWF2() {
document.getElementById('movie-con movie-con3 movie-con4').style.display = 'none';
document.getElementById('movie-con2').style.display = 'block';
}
function imgToSWF3() {
document.getElementById('movie-con movie-con2 movie-con4').style.display = 'none';
document.getElementById('movie-con3').style.display = 'block';
}
function imgToSWF4() {
document.getElementById('movie-con movie-con2 movie-con3').style.display = 'none';
document.getElementById('movie-con4').style.display = 'block';
}
HTML
<span onmouseover="src=imgToSWF1();"><div class="numbers">01</div></span>
<span onmouseover="src=imgToSWF2();"><div class="numbers">02</div></span>
<span onmouseover="src=imgToSWF3();"><div class="numbers">03</div></span>
<span onmouseover="src=imgToSWF4();"><div class="numbers">04</div></span>
I can't seem to get this to work and I believe that targetting multiple ID's isn't possible like this? Anyway any advice would be smashing - thanks!
You're correct that you cannot supply multiple ids to document.getElementById(). Instead, you can grab them all individually using an array. There are many ways to accomplish what you are trying to do. This is a straightforward method based on iterating through the array of the elements to hide and hiding all of them.
This method expects you to define the array of nodes to hide in each of your functions, and so is non-ideal.
// Example:
function imgToSWF1() {
var nodes = ['movie-con2', 'movie-con3', 'movie-con4'];
// Loop over and hide every node in the array
for (var i=0; i<nodes.length; i++) {
document.getElementById(nodes[i]).style.display = 'none';
}
document.getElementById('movie-con').style.display = 'block';
}
Better:
This can be refactored into one function, however. Make one function which recieves the node you want to show as an argument. Hide the others. The array should contain all nodes that may be hidden in any circumstance, and be defined at a higher scope than the function.
// Array holds all nodes ids
var nodes = ['movie-con', 'movie-con2', 'movie-con3', 'movie-con4'];
// Function receives a node id which will be shown
function imageToSWF(nodeId) {
// Loop over and hide every node in the array
for (var i=0; i<nodes.length; i++) {
document.getElementById(nodes[i]).style.display = 'none';
}
// And unhide/show the one you want, passed as an argument
document.getElementById(nodeId).style.display = 'block';
}
Call as:
<span onmouseover="imageToSWF('movie-con');"><div class="numbers">01</div></span>
<span onmouseover="imageToSWF('movie-con2');"><div class="numbers">02</div></span>
<span onmouseover="imageToSWF('movie-con3');"><div class="numbers">03</div></span>
<span onmouseover="imageToSWF('movie-con4');"><div class="numbers">04</div></span>
You have to target one element at a time with document.getElementById, eg. document.getElementById('movie-con2').style.display='none'; document.getElementById('movie-con3').style.display='none';
etc, etc.
You could also use Jquery siblings selector to show or hide all elements that are siblings within a parent tag.
You definitely can't do that in straight up javascript. The document.getElementById function only returns a single element from the DOM.
Some docs can be had here:
http://www.w3schools.com/jsref/met_doc_getelementbyid.asp
https://developer.mozilla.org/en-US/docs/DOM/document.getElementById
If you were to use a toolkit like jQuery you could do something like:
$('div[id^="movie-con"]').hide(); // hide everything
$('div["movie-con"' + index + "]").show(); // show the one we want
Since you're not using jQuery it's not quite as easy. Something like:
var matches = document.getElementById("containerDiv").getElementsByTagName("img");
for( var i = 0; i < matches.length; i++ )
matches[i].style.display = "none";
document.getElementById('movie-con' + index).style.display = "block";

javascript choose what is going to include element

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.

Categories

Resources