I am trying to do include 3 images on my page. These images must have the following behavior done: When an unbordered image is clicked, it gets a border on it. When a bordered imaged is clicked, the border gets removed. In other words the border gets toggled on & off every time it is clicked, for that image.
I can get the border on when clicked, but I can not figure out how to remove it again.
This is what I have for JS so far:
ims = document.getElementsByTagName("img");
for( i=0 ; i<ims.length ; i++ ){
ims[i].onclick=function(){
this.style.borderStyle = "solid";
this.style.borderColor = "red";
}
}
You could check the style:
ims[i].onclick=function() {
if (this.style.borderStyle == "solid") {
this.style.borderStyle = "none";
} else {
this.style.borderStyle = "solid";
this.style.borderColor = "red";
}
}
JSFiddle
Here you have a solution based on Doorknob, but with classes, as I recommended on the comment:
var ims = document.getElementsByTagName("img");
for( var i=0 ; i<ims.length ; i++ ){
ims[i].onclick=function() {
if (this.className == "clicked") {
this.className = "";
} else {
this.className = "clicked";
}
};
}
And the css classes:
img {
padding: 5px;
}
img.clicked {
padding: 0;
border: 5px solid red;
}
Here you can see the benefits of using classes.
Here is the jsFiddle.
For further investigation I would recommend to check how to do it if the img tag has multiple classes ;). Ask again if you have any doubts.
Related
I have a relatively simple demo here where I have two embed elements with the same class, and upon page load one is set to display and the other is not. I'm calling a function and setting an interval for every 5 seconds starting on page load which should toggle the display rules for the classes (only one embed element should show at a time and then they should alternate on the timer).
I have border colors on the embed elements for testing, but it seems like neither element is showing on page load once I added the second 'if' statement in the JS
What am I doing wrong
window.onload = function () {
test();
setInterval(function() {
test();
}, 5000);
}
function test(){
console.log('starting');
var all = document.getElementsByClassName('pdfEmbed');
for (var i = 0; i < all.length; i++) {
if(all[i].style.display = "none"){
all[i].style.display = "block";
}
if(all[i].style.display="block"){
all[i].style.display = "none";
}
}
}
<embed class="pdfEmbed" src="#" style="margin-top: 40px;position:absolute; display: block; left: 0; top: 0; border: 1px solid red;" width="100%" height="100%" type="application/pdf">
<embed class="pdfEmbed" src="#" style="margin-top: 40px;position:absolute; border: 1px solid black; display: none; left: 0; top: 0;" width="100%" height="100%" type="application/pdf">
Here's what's happening with the second if:
// set current child display to "block" if it is "none"
if(all[i].style.display = "none"){
all[i].style.display = "block";
}
// the check is always true, since you just set the display to "block"
if(all[i].style.display="block"){
// therefore, for all elements set display to none
all[i].style.display = "none";
}
The fix is easy: Use an else if instead of the second if. In case you only want to have the two display states "none" and "block", an else is enough.
EDIT: I just noticed a second error. You have to use comparison (== or ===) instead of assignment (=) in your if conditions. So this should be working:
if(all[i].style.display == "none") {
all[i].style.display = "block";
} else {
all[i].style.display = "none";
}
var last_index = 0;
function test() {
var e = document.querySelectorAll(".pdfEmbed");
for (var k = 0; k < e.length; k++) {
e[k].style.display = k == last_index ? "block" : "none";
}
last_index++;
if (last_index >= e.length) { last_index = 0; }
}
Been racking my brains trying to figure this out. I've tried adding $( document ).ready(function() { and closing it again around the script but not joy.
It's a simple filter. Supposed to show / hide div elements depending on the button. The script adds 'active' to the button clicked and removes it from the other buttons.
It works exactly as intended on Code Pen. However, when running it locally or on a server, the filter works fine, 'active' is added to the button clicked, but 'active' is not removed from the last button and keeps stacking (ie if I click snowdonia 4 times, the class 'active' is applied 4 times. If I then click tryfan, active is applied correctly but not removed from the previous button)
The code I'm using is below. Any help would be much appreciated. The Javascript is EXACTLY as it appears in my filter.js file
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
var header = document.getElementById("myBtnContainer");
var btns = header.getElementsByClassName("btn-filter");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
if (current.length > 0) {
current[0].className = current[0].className.replace(" active", "");
}
this.className += " active";
});
}
.filterDiv {
display: none;
/* Hidden by default */
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
.btn-filter {
background-color: #fff;
border-radius: 0;
padding-right: 5px;
padding-left: 5px;
padding-top: 4px;
padding-bottom: 4px;
text-transform: uppercase;
font-family: 'Montserrat';
font-size: 14px;
font-weight: 600;
color: #91227e;
border: 2px;
border-style: solid;
border-color: #91227e;
}
.active,
.btn-filter:hover {
background-color: #91227e;
color: #fff;
}
<div id="myBtnContainer">
<button class="btn-filter active" onclick="filterSelection('all')"> Show all</button>
<button class="btn-filter" onclick="filterSelection('snowdon')"> Snowdon</button>
<button class="btn-filter" onclick="filterSelection('tryfan')"> Tryfan</button>
<button class="btn-filter" onclick="filterSelection('glyder')"> Glyder</button>
</div>
Here are the scripts I have linked in the html file:
And here a link to a working version in codepen: https://codepen.io/dan-anderton-the-sasster/pen/vYgWdER
This is not an answer, but more of a suggestion. But with your localhost environment are you also including the necessary files which are being used in the codepen example?
IE: jquery?
I cannot tell from the example you have provided, but a link to the codepen would be useful.
TRY - you may need to tweak slightly to fit your html, as I cannot view this:
var btns = document.getElementsByClassName("btn-filter");
var i;
for (i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
this.classList.toggle("activated");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
Turns out there was a CSS conflict with the active tag between my code and bootstrap. Changing the class to be applied to the current button solved the problem. So changing it from active to active-filter in this case and then styling accordingly.
Thanks everyone for looking at it for me.
I am trying to make my selector so when it gets the class of transform with the tagname with p, it will do some event in my case it is mouse hovering but i am having trouble with it.
I know there are jquery solutions but i am doing it with pure javascript. here is the code below currently
var hoverEvent = document.getElementsByTagName("p").getElementsByClassName("transform");
for (let i = 0; i < hoverEvent .length; i++) {
hoverEvent [i].onmouseover=function() {
this.style.color = "yellow";
// changes paragraph with class of transform to yellow during hover
}
} // end for
for (let i = 0; i < hoverEvent .length; i++) {
hoverEvent [i].onmouseout=function() {
this.style.color = "black";
// changes it back to black
}
}
You can use a CSS selector in querySelectorAll to find all paragraphs with that classname:
var hoverEvent = document.querySelectorAll("p.transform");
var transformPs = document.querySelectorAll("p.transform");
for (let i = 0; i < transformPs .length; i++) {
// on mouse over
transformPs[i].onmouseover = function () {
this.style.color = "yellow";
// changes paragraph with class of transform to yellow during hover
};
// on mouse out
transformPs[i].onmouseout = function () {
this.style.color = "black";
// changes it back to black
};
}
you can use classList to check class of element
var p = document.getElementsByTagName("p");
if (p.classList.contains('transform')){
// do whatever you want to do
}
The vanilla JavaScript equivalent would be using document.querySelectorAll:
function turnYellow (e) { e.target.style.color = 'yellow' }
function turnBlack (e) { e.target.style.color = '' }
document.querySelectorAll('p.transform').forEach(function (p) {
p.addEventListener('mouseover', turnYellow)
p.addEventListener('mouseout', turnBlack)
})
body { background: #ccc; }
<p class="transform">Example Paragraph</p>
However, I think the best approach would be to forego the JavaScript altogether and instead rely on the CSS pseudo-selector :hover:
body { background: #ccc; }
p.transform:hover {
color: yellow;
}
<p class="transform">Example Paragraph</p>
i have a function that i'm working with in javascript to highlight every other row of a given table that is named by the same class ...i am running into a problem, the code works great but it will only detect the first table named with that class...i need it to perform the task for every single table named with the same class.
i've tried a few things but nothing worked...any suggestions?
thanks!
heres what i'm working with
function start(){
var list=document.getElementsByClassName("highlight");
for(i=0; i<list.length; i++){
var element= list[i].getElementsByTagName("tr");
for(i=0; i<element.length; i++)
{
if (i%2 == 0) {
element[i].className = "odd"
}
else{
element[i].className = "even";
}
}
}
}
window.addEventListener("load", start, false);
You need to use a different variable in the inner for statement.
See a working sample here:
http://codepen.io/anon/pen/wsCxG
window.onload = start;
function start(){
var list=document.getElementsByClassName("highlight");
for(i=0; i<list.length; i++)
{
var element= list[i].getElementsByTagName("tr");
for(j=0; j<element.length; j++)
{
if (j%2 == 0) {
element[j].className = "odd"
}
else{
element[j].className = "even";
}
}
}
}
what about pure css3?
tr:nth-child(odd) {
background-color: green;
}
tr:nth-child(even) {
background-color: red;
}
with highlight
.highlight tr:nth-child(odd) {
background-color: green;
}
.highlight tr:nth-child(even) {
background-color: red;
}
example
http://jsfiddle.net/RppAT/
if you want js (shorthand+while--)
function OE(){
var lists=document.getElementsByClassName("highlight"),listsLength=lists.length;
while(listsLength--){
var trs=lists[listsLength].getElementsByTagName("tr"),trsLength=trs.length;
while(trsLength--){
trs[trsLength].className=(trsLength%2==0)?'odd':'even';
}
}
}
window.onload=OE;
I the following code here in which you can play a Wheel of Fortune-like game with one person (more of my test of javascript objects).
My issue is that when the screen is small enough, the lines do not seem to break correctly.
For example:
Where the circle is, I have a "blank" square. The reason why I have a blank square is so that when the screen is big enough, the square serves as a space between the words.
Is there a way in my code to efficiently know if the blank square is at the end of the line and to not show it, and then the window gets resized, to show it accordingly?
The only thought I had was to add a window.onresize event which would measure how big the words are related to how big the playing space is and decide based on that fact, but that seems very inefficient.
This is my code for creating the game board (starts # line 266 in my fiddle):
WheelGame.prototype.startRound = function (round) {
this.round = round;
this.lettersInPuzzle = [];
this.guessedArray = [];
this.puzzleSolved = false;
this.currentPuzzle = this.puzzles[this.round].toUpperCase();
this.currentPuzzleArray = this.currentPuzzle.split("");
var currentPuzzleArray = this.currentPuzzleArray;
var lettersInPuzzle = this.lettersInPuzzle;
var word = document.createElement('div');
displayArea.appendChild(word);
word.className = "word";
for (var i = 0; i < currentPuzzleArray.length; ++i) {
var span = document.createElement('div');
span.className = "wordLetter ";
if (currentPuzzleArray[i] != " ") {
span.className += "letter";
if (!(currentPuzzleArray[i] in lettersInPuzzle.toObject())) {
lettersInPuzzle.push(currentPuzzleArray[i]);
}
word.appendChild(span);
} else {
span.className += "space";
word = document.createElement('div');
displayArea.appendChild(word);
word.className = "word";
word.appendChild(span);
word = document.createElement('div');
displayArea.appendChild(word);
word.className = "word";
}
span.id = "letter" + i;
}
var clear = document.createElement('div');
displayArea.appendChild(clear);
clear.className = "clear";
};
Instead of JavaScript, this sounds more like a job for CSS, which solves this problem all the time when dealing with centered text.
Consider something like this:
CSS
#board {
text-align: center;
border: 1px solid blue;
font-size: 60pt;
}
.word {
display: inline-block;
white-space: nowrap; /* Don't break up words */
margin: 0 50px; /* The space between words */
}
.word span {
display: inline-block;
width: 100px;
border: 1px solid black
}
HTML
<div id="board">
<span class="word"><span>W</span><span>h</span><span>e</span><span>e</span><span>l</span></span>
<span class="word"><span>o</span><span>f</span></span>
<span class="word"><span>F</span><span>o</span><span>r</span><span>t</span><span>u</span><span>n</span><span>e</span></span>
</div>
Here's a fiddle (try resizing the output pane).
Here you go. Uses the element.offsetTop to determine if a .space element is on the same line as its parent.previousSibling.lastChild or parent.nextSibling.firstChild.
Relevant Code
Note: In the fiddle I change the background colors instead of changing display so you can see it work.
// hides and shows spaces if they are at the edge of a line or not.
function showHideSpaces() {
var space,
spaces = document.getElementsByClassName('space');
for (var i = 0, il = spaces.length ; i < il; i++) {
space = spaces[i];
// if still display:none, then offsetTop always 0.
space.style.display = 'inline-block';
if (getTop(nextLetter(space)) != space.offsetTop || getTop(prevLetter(space)) != space.offsetTop) {
space.style.display = 'none';
} else {
space.style.display = 'inline-block';
}
}
}
// navigate to previous letter
function nextLetter(fromLetter) {
if (fromLetter.nextSibling) return fromLetter.nextSibling;
if (fromLetter.parentElement.nextSibling)
return fromLetter.parentElement.nextSibling.firstChild;
return null;
}
// navigate to next letter
function prevLetter(fromLetter) {
if (fromLetter.previousSibling) return fromLetter.previousSibling;
if (fromLetter.parentElement.previousSibling)
return fromLetter.parentElement.previousSibling.lastChild;
return null;
}
// get offsetTop
function getTop(element) {
return (element) ? element.offsetTop : 0;
}
showHideSpaces();
if (window.addEventListener) window.addEventListener('resize', showHideSpaces);
else if (window.attachEvent) window.attachEvent('onresize', showHideSpaces);
jsFiddle