I am trying to change navigation a tag color when the user clicks on the <a> tag. The JS is working fine, except the first time the user clicks on the <a> tag; only in the second time the a tag color changes.
JavaScript:
function toggleNav(pageId){
activeColor();
var href = 'html/' + pageId + '.html';
window.onload = document.getElementById('main').innerHTML =
loadPage(href);
}
function activeColor(){
var header = document.getElementById("allNav");
var btns = header.getElementsByClassName("notActive");
for (var i = 0; i < btns.length; i++) {
var button1 = btns[i];
button1.addEventListener("click" ,
function() {
var current = document.getElementsByClassName(" active");
console.log(current.length);
for (var i = 0; i < current.length + 1; i++) {
current[0].className = current[0].className.replace("
active", "");
}
var myString = this.id;
var stringLength = myString.length;
var lastChar = myString.charAt(stringLength - 1);
if(lastChar == "2"){
var add = document.getElementById(this.id);
var id2Nmae = add.id.slice(0, -1);
var add2 = document.getElementById(id2Nmae);
add.className += " active";
add2.className += " active";
}
else{
var add = document.getElementById(this.id);
var id2Nmae = add.id + "2";
var add2 = document.getElementById(id2Nmae);
add.className += " active";
add2.className += " active";
}
});
}
}
HTML :
<div id="allNav">
<div class="sidebar" id="mySidebar" style="display:block">
<button id="open" onclick="Toggle()">
<a ><i class="fas fa-bars"></i></a>
</button>
<i class="glyphicon glyphicon-screenshot"></i>
<i class="glyphicon glyphicon-exclamation-sign"></i>
<i class="fas fa-burn"></i>
<i class="fas fa-utensils"></i>
<i class="fa fa-line-chart"></i>
<i class="far fa-comments"></i>
<i class="fas fa-bell"></i>
</div>
I succeeded to solve the problem, It was an issue I made by the DOM path not correct.
In the first time the page loads, the default load was the "goals" id by the next JS code:
var href = 'html/goals.html';
window.onload = document.getElementById('main').innerHTML = loadPage(href);
In this why the "addEventListener" needed to load at the first time and only in the second time the function can run.
I changed the default function to:
toggleNav('goals')
I hope I helped if somebody will experience the same issue.
Thanks for the help.
I ran your script and in the console I got
Uncaught TypeError: Cannot read property 'id' of null
(in chrome dev tools) Have you checked the element view (next to console) to see how the javascript is interacting with the HTML?
from looking at the code, the number "2" is for ids that are selected, however, everything ends with the number 2 and it is never actually removed. Is that intentional?
The loop doesn't seem to like "this.id" as it loses the reference (error above).
have you put in alerts to see where the pointer is in the loop?
Related
This question already has answers here:
Javascript:DIV AppendChild
(2 answers)
Closed 4 years ago.
i have a problem with appendChild. in the code below , i am trying to add multiple button elements to the div with looping , but i get only one button . I know how appendChild works . In developers.mozilla it is said , that if element already exists , it is removed from its parent and is set anew . So this is the reason i cant add multiple amount of same elements (button) to the node .
So here is my question , what is the optimal and best way to make it happen ?
function Slide() {
this.currentStep = 0;
this.time = 2000;
this.images = [];
this.images[0] = 'images/image1.jpg';
this.images[1] = 'images/image2.jpg';
this.images[2] = 'images/image3.jpg';
this.images[3] = 'images/image4.jpg';
this.images[4] = 'images/image5.jpg';
let imagesCount = this.images.length;
let indicatorContainer = document.createElement('div');
indicatorContainer.classList.add('slide-indicator');
let buttonIndicator = document.createElement('button');
buttonIndicator.classList.add('button-indicator');
buttonIndicator.setAttribute('type', 'button');
for (let i = 0; i < imagesCount; i+=1) {
indicatorContainer.appendChild(buttonIndicator);
}
document.querySelector('.slide').appendChild(indicatorContainer);
}
Slide.prototype.carousel = function() { // arrow function-ov chi ashxatum ...uxxel
document.querySelector('.image').src = this.images[this.currentStep];
this.currentStep < this.images.length - 1 ? this.currentStep += 1 : this.currentStep = 0;
setTimeout(this.carousel.bind(imageSlide), this.time);
};
const imageSlide = new Slide();
imageSlide.carousel();
<div class="wrapper">
<div class="slide">
<img class="image" src="" width="1000" height="500" alt="image">
</div>
<div class="controls">
<button class="button prev" type="button">
previous
<span class="arrow arrow-prev"></span>
</button>
<button class="button next" type="button">
next
<span class="arrow arrow-next"></span>
</button>
</div>
</div>
In your approach you're assigning the same buttonIndicator in each loop iteration and not creating any new ones. What you have to to is to create new button in each loop iteration to make it work the way you want.
So this should work:
for (let i = 0; i < imagesCount; i+=1) {
let buttonIndicator = document.createElement('button');
buttonIndicator.classList.add('button-indicator');
buttonIndicator.setAttribute('type', 'button');
indicatorContainer.appendChild(buttonIndicator);
}
Also it makes more sense to use const instead of let as you're not reasigning those variables.
Use cloneNode:
indicatorContainer.appendChild(buttonIndicator.cloneNode());
If I am using JS to create a new window/tweet to share, can I pull in information from my local storage as well?
<li class="fa fa-twitter" onclick="window.open('https://twitter.com/intent/tweet?text=I just score X on this game!', 'newwindow', 'width=300, height=250')"></li>
We currently store a user's score in LocalStorage with a value of score. We even print it on the page. Would there ba away to upload it into the tweet?
So far I've tried using a span, and appending the score, but this breaks the URL.
Any ideas?
You can add that value using concatenation:
<li class="fa fa-twitter" onclick="window.open('https://twitter.com/intent/tweet?text=I just score ' + localStorage['score'] + ' on this game!', 'newwindow', 'width=300, height=250')"></li>
Inline js is terrible :)
Try this
<li class="fa fa-twitter" onclick="onClick"></li>
function onClick(){
var val = localStorage.get('something');
window.open("https://twitter.com/intent/tweet?text=I just score X on this"+val+" game!',
'newwindow',
'width=300,height=250')
}
Yes, can you definitely do this. I wouldn't use inline onclick attribute for this purpose. Simply, add event listener, and you open the window with user score from localStorage, along with your text.
<li class="fa fa-twitter" id="tweet"></li>
<script>
$('#tweet').on('click', function(e){
var score = localStorage.getItem('userScore');
var tweetTxt = 'I just scored ' + score + ' on this game!';
window.open('https://twitter.com/intent/tweet?text='+encodeURIComponent(tweetTxt), 'newwindow', 'width=300, height=250')
});
</script>
Keep things clear and simple.
tweetScore = function() {
var score = localStorage.getItem('score');
var text = 'I just score '+ score + ' on this game!';
/* var options =
{ width: 300; height:200, ... }
*/
var url = 'https://twitter.com/intent/tweet?text='+text;
window.open(url, 'newwindow', 'width=300,height=200');
// or fetch them from options
return 0;
}
<li class="fa fa-twitter" onclick="tweetScore()">
tweet
</li>
Btw, you can also seperate the url forming from tweetScore() function.
urlCreator = function(foo) {
//some operations
//var url = foo+..
return url;
}
then use it's return value in tweetScore()
tweetScore = function() {
var score = localStorage.getItem('score');
var text = 'I just score '+ score + ' on this game!';
/* var options =
{ width: 300; height:200, ... }
*/
var url = createUrl(text);
...
you can also extend it by passing arguments - that will allow you to tweet lots of things, not just scores.
tweetThis(arg1) {
//process arg1
//createUrl
}
Okay, so I am using the dribbble API to GET my works from dribbble
I set up a few VAR's to help with the process;
var dribbble = 'crobertson97';
var limit = '10'; //items per page
var per_page = '&per_page='+limit+''; //url
var accessToken = '12345678910'; //client
var url = 'https://api.dribbble.com/v1/users/'+dribbble+'/shots/?access_token='+accessToken+'&callback=?'+per_page; //url
I want to add a view more button that if clicked will do three things;
the button <a id="readmore" class="btn btn-success white"> View More</a>
Change the text of the button from view more to view less
Change the var limit = 10 to 20
3.Be able to revert --> view less
Add an onclick function to the html:
<a id="readmore" class="btn btn-success white" onclick="buttonClick(this)"> View More</a>
And create the following function in the JS:
function buttonClick(but) {
if(limit==10) {
limit = 20;
but.innerHTML= "View less";
} else {
limit = 10;
but.innerHTML = "View more";
}
}
There's still the display of the content to manage, but you didn't give much information about what you want and how the data is given!
Pretty easy, using modern web API.
readmore.addEventListener('click', readmoreless);
var limit = 10;
function readmoreless(){
if(limit == 10){
readmore.innerHTML = "View Less";
limit = 20;
} else {
readmore.innerHTML = "View More";
limit = 10;
}
}
<a id="readmore" class="btn btn-success white">View More</a>
I have a submit button which I am sharing between 'Create' and 'Update'. I want the following labels depending on my page state:
Create = Submit
Update = Update
These buttons also have an image at the front of them using glyphicon but the image will be the same for both buttons.
To get to my page states (listed above) I have other JavaScript functions which the relevant buttons call.
All my code is below. I am struggling as I am fairly new to JavaScript and I now I can do it by adding using Value but this doesn't work due to my image.
Edit Button HTML
<button type="button"class="btn btn-default" name="RegCashMove_Edit_Button" onclick='RegCashMoveEdit()'>
<span class="glyphicon glyphicon-pencil" title="Edit" style="vertical-align: middle"></span>
</button>
Create Button HTML
<button type="button" class="btn btn-default" name="RegCashMove_Create_Button" onclick='RegCashMoveCreate()'>
<span class="glyphicon glyphicon-plus"></span> Create
</button>
Variable Button HTML
This is the button I want the label to be variable on. At the moment its 'Submit'
<button name="RegularCashMovements_Submit_Button" class="btn btn-default" id="RegularCashMovements_Submit_Button" type="submit">
<span class="glyphicon glyphicon-ok"></span> Submit
</button>
JavaScript function for 'Create' button
function RegCashMoveCreate(txt) {
document.getElementById('selection').value = "Create";
document.getElementById('index').value = "";
document.getElementById('RCMViewState').value = "Initial";
document.getElementById('submitAndCancel').style.display = "block";
document.getElementById('editAndConfirm').style.display = "none";
document.getElementById('yesAndNo').style.display = "none";
document.getElementById('confirmTemplate').style.display = "none";
document.getElementById('createEditDeleteTopLine').style.display = "block";
document.getElementById('RegCashMoveHeading').innerHTML = "<h3>" + txt + "</h3>";
document.getElementById('RegCashMoveFields').style.display = "block";
document.getElementById('RegCashMoveDeleteConfirmation').style.display = "none";
document.getElementById('FromDiv').innerHTML = "<%=fromInnerHtml%>";
document.getElementById('ToDiv').innerHTML = "<%=toInnerHtml%>";
document.getElementById('AmountDiv').innerHTML = "<%=amountInnerHtml%>";
document.getElementById('FrequencyDiv').innerHTML = "<%=frequencyInnerHtml%>";
document.getElementById('FromErrorDiv').innerHTML = "";
document.getElementById('ToErrorDiv').innerHTML = "";
document.getElementById('AmountErrorDiv').innerHTML = "";
document.getElementById('FrequencyErrorDiv').innerHTML = "";
document.getElementById('RegCashMove_From_DropDownList').value = "- - Please select - -";
document.getElementById('RegCashMove_To_DropDownList').value = "- - Please select - -";
document.getElementById('RegCashMove_Amount_TextBox').value = "";
document.getElementById('RegCashMove_Frequency_DropDownList').value = "0";
};
JavaScript function for 'Edit' button
function RegCashMoveEdit(txt, from, to, amount, frequency, index) {
document.getElementById('selection').value = "Edit"
document.getElementById('index').value = index;
document.getElementById('RCMViewState').value = "Initial";
document.getElementById('submitAndCancel').style.display = "block";
document.getElementById('editAndConfirm').style.display = "none";
document.getElementById('yesAndNo').style.display = "none";
document.getElementById('confirmTemplate').style.display = "none";
document.getElementById('createEditDeleteTopLine').style.display = "block";
document.getElementById('RegCashMoveHeading').innerHTML = "<h3>" + txt + "</h3>";
document.getElementById('RegCashMoveFields').style.display = "block";
document.getElementById('RegCashMoveDeleteConfirmation').style.display = "none";
document.getElementById('FromDiv').innerHTML = "<%=fromInnerHtml%>";
document.getElementById('ToDiv').innerHTML = "<%=toInnerHtml%>";
document.getElementById('AmountDiv').innerHTML = "<%=amountInnerHtml%>";
document.getElementById('FrequencyDiv').innerHTML = "<%=frequencyInnerHtml%>";
document.getElementById('FromErrorDiv').innerHTML = "";
document.getElementById('ToErrorDiv').innerHTML = "";
document.getElementById('AmountErrorDiv').innerHTML = "";
document.getElementById('FrequencyErrorDiv').innerHTML = "";
document.getElementById('RegCashMove_From_DropDownList').value = from;
document.getElementById('RegCashMove_To_DropDownList').value = to;
document.getElementById('RegCashMove_Amount_TextBox').value = amount;
document.getElementById('RegCashMove_Frequency_DropDownList').value = frequency;
};
I no I should be able to add a variable in each of my JavaScript function to display the relevant label but my issue is getting it on the button with my image
You can set the textual content of a HTML element with the "textContent" property ("innerText" in IE < 9):
var button = document.getElementById('RegularCashMovements');
button.innerText = button.textContent = 'new text';
The span element inside the button element should not be removed.
If you also want to change the title of the span do it like that:
for (var index = 0; index < button.childNodes.length; index++) {
if (button.childNodes[index].tagName == 'SPAN') {
button.childNodes[index].title = 'new title';
break;
}
}
You need to iterate through all child nodes of the button, instead of taking the first one, because than you will get the text content of the button again.
I hope i understood your problem. I also have to say, that your javascript is very procedural and inperformant because of all the "display: none;" and innerHTML accesses. My tip for you would be to think more objective and put all elements you need to hide in one container element and hide that one.
How do I show one random icon on page load with js? Below is the HTML code I have:
<span>
<i class="fa fa-trash-o" id="icon-one"></i>
<i class="fa fa-frown-o" id="icon-two"></i>
<i class="fa fa-thumbs-o-down" id="icon-three"></i>
</span>
I need to show only one of the three icons.
My HTML would be
<span id = "mySpan"></span>
You can do this using javascript
var myRand = Math.floor(Math.random() * 3) + 1;
var randString = '';
if(myRand == 1)
randString = 'one';
else if(myRand == 2)
randString = 'two';
else if(myRand == 3)
randString = 'three';
var ele = document.createElement("div");
ele.setAttribute("id","icon-"+randString );
document.getElementById("mySpan").appendChild(ele);
Well , this assumes that your ids have the icon and not the classes
<span>
<i class="fa fa-trash-o" style="display: none;" id="icon-one"></i>
<i class="fa fa-frown-o" style="display: none;" id="icon-two"></i>
<i class="fa fa-thumbs-o-down" style="display: none;" id="icon-three"></i>
</span>
var icons = [ 'icon-one', 'icon-two', 'icon-three' ],
icon = icons[Math.floor(Math.random()*icons.length)];
$( '#' + icon ).show();
This should work if you are using jquery.
use this function to get a random no in range(min, max)
function getRandomArbitary (min, max) {
return Math.random() * (max - min) + min;
}
and use appropriately to show the tag hide other wise
such as
js
var r = function getRandomArbitary (1, 3);
var eleCategory = document.getElementById("main_div");
var eleChild = eleCategory.childNodes;
for( i = 0 , i<eleChild.length; i++ ){
if(i==r){
eleChild[ i ].style.display='block';
}
else
{
eleChild[ i ].style.display='none';
}
}
html
<span id="main_div">
<i class="fa fa-trash-o" id="icon-one"></i>
<i class="fa fa-frown-o" id="icon-two"></i>
<i class="fa fa-thumbs-o-down" id="icon-three"></i>
</span>
you can use java script here. So if there are only three icons one , two and three.
use random function to generate a number between one two and three
var x= Math.floor((Math.random()*3)+1);
if (x==1)
{
//fetch the div id = "icon-one" and display
}
else if (x==2)
{
//fetch the div id = "icon-two" and display
}
else
{
//fetch the div id = "icon-three" and display
}
Although this will work way better if you can rename your id's two icon1,icon2 and so on
it will just be this then :
var x= Math.floor((Math.random()*3)+1);
var icon = "icon";
var id = icon.concat(x);
Simple work woth using jQuery.
Working jsFiddle