I am trying to change display property of my div using js but it is not showing any change.
In Js code if statements are not becoming true though in css all the properties are set properly.
Please help I am a novice and not understanding the issue. Below is the code I am trying
My HTML Code:
<!DOCTYPE html>
<html>
<head>
<script src="main.js" type="text/JavaScript"></script>
</head>
<body>
<nav id="nav">
<ul class="main_nav">
<li id="About_me">About Me</li>
<li id="home1">Home</li>
</ul>
</nav>
<div id="About">
<p>Hello</p>
</div>
<div id="home">
<p>hi</p>
</div>
</body>
My JS code:
function About_Me_Sel()
{
var Id;
Id =document.getElementById("About");
if(Id.style.display == "block")
{
Id.style.display = "none";
}
}
function Home_Sel()
{
var Id;
Id= document.getElementById("home");
if(Id.style.display == "none")
{Id.style.display = "block";
}
else
alert("hello");
}
That won't work the first time around. The style property is not connected to your stylesheet, so JavaScript doesn't know what rule's you've set there. The style property reflects a style attribute that gets written into your element's tag. (You can hard-code one into your HTML if you want.) So the value is always null until you set it.
Before
<div id="About">
After
<div id="About" style="display: block">
Try reversing the conditional
if (Id.style.display != "block")
{
Id.style.display = "block";
}
else
{
Id.style.display = "none";
}
I used Ajax to load in other content into my div, and i got the content from other php files. this way
function changecontent(name){
var htmlUrl = name;
$.ajax({
url: htmlUrl,
dataType: 'html',
success: function(data) {
console.log("Current page is: " + htmlUrl);
$("#maincontent").fadeOut(function() {
$(this).html(data).fadeIn("fast");
});
}
});
}
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="main.js" type="text/JavaScript"></script>
</head>
<body>
<nav id="nav">
<ul class="main_nav">
<li id="About_me">About Me</li>
<li id="home">Home</li>
</ul>
</nav>
<div id="maincontent">
<p>Hello</p>
</div>
<div id="home">
<p>hi</p>
</div>
</body>
eks: about_me.php
<a>I'awesome</a>
You have a number of errors in your code; I'll try to go through them one-by-one to clarify those problems and offer solutions that should, hopefully, lead to better understanding (and practice) in future.
First, an id "...assigns a name to an element. This name must be unique in a document."1. Note the 'must,' which means that a document with a duplicated id (more than one element sharing the same id value makes the document invalid, and causes problems with JavaScript, since it will only ever look for one element with a given id, and recover from invalid documents with unpredictable results).
That being the case I've amended the ids of the div elements by, effectively, adding the Content string, and amended the ids of the li elements to be single word and lower-case so that they can be predictably made to reference each other. This gives the following HTML:
<nav id="nav">
<ul class="main_nav">
<li id="about">About Me</li>
<li id="home">Home</li>
</ul>
</nav>
<div id="aboutContent">
<p>Hello</p>
</div>
<div id="homeContent">
<p>hi</p>
</div>
JS Fiddle (this still doesn't work as you'd intend, because the other problems still exist; it's merely to show the corrected/amended HTML).
Now, the JavaScript.
The reason it can't work, as noted by #Jeffman in his answer is because element.style references only the in-line styles of an element (those set with the style attribute), not the styles set with either a stylesheet or in the head of the document. This means you're comparing an undefined variable with a string, which will always be false.
You're also using two functions to do the same thing, which is wasteful and unnecessary. This is the second reason I've modified the ids of the various elements. A modified (single) function to do what you want to do:
function sel(e, self) {
// e is the click event,
// self is the 'this' DOM node
var id = self.parentNode.id,
toggle = document.getElementById(id + 'Content'),
display = toggle.style.display;
toggle.style.display = display == 'block' ? 'none' : 'block';
}
The above requires the following HTML for the a elements:
About Me
JS Fiddle demo.
Now, this still requires obtrusive JavaScript (using in-line event-handling within the HTML itself, which requires updates every time you may want to add further event-handling or change the function to call upon those events). Therefore I'd suggest moving to a more unobtrusive version, such as:
function sel(e, self) {
// e is the click event,
// self is the 'this' DOM node
var id = self.parentNode.id,
toggle = document.getElementById(id + 'Content'),
display = toggle.style.display;
toggle.style.display = display == 'block' ? 'none' : 'block';
}
var links = document.getElementById('nav').getElementsByTagName('a');
for (var i = 0, len = links.length; i < len; i++) {
links[i].onclick = function (e){
sel(e, this);
};
}
JS Fiddle demo.
Now, while this works, this still requires assigning event-handlers to multiple elements (despite being more easily done using a loop within JavaScript itself).
The easier way is to delegate the event-handling to the parent element, and assess, in the function itself, where the event originated. Which would give the following JavaScript:
function sel(e) {
// e is the click event,
// self is the 'this' DOM node
var self = e.target,
id = self.parentNode.id,
toggle = document.getElementById(id + 'Content'),
display = toggle.style.display;
toggle.style.display = display == 'block' ? 'none' : 'block';
}
var nav = document.getElementById('nav');
nav.addEventListener('click', sel);
JS Fiddle demo.
Notes:
http://www.w3.org/TR/html401/struct/global.html#h-7.5.2.
References:
addEventListener().
document.getElementById().
getElementsByTagName().
Node.parentNode.
Related
I have a script that gets data from a Google Sheet and displays it as a webpage - using JS and Tabletop.js.
There are multiple entries in the Sheet thus multiple entries in the webpage. To organise the Data I have a hide/show button. When the button is clicked on the first entry it works. However when the any of the other buttons are clicked it hides or shows the first entries data, not its own!
How do I hide/show each individual entries data? Below is the code I am working with!
I am new to JavaScript - Thanks in advance!
P.S - I struggled writing the Title to the questions!
<link href="../common/cats-copy.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<style>
#add-info {
display: none
}
</style>
<body>
<div class="container">
<h1>Resturants</h1>
<div id="content"></div>
<script id="cat-template" type="text/x-handlebars-template">
<div class="entry">
<h5>{{establishment_name}}</h5>
<h6>Area: {{area}}</h6>
<h6>Cuisine: {{cuisine}}</h6>
<button id="btn" class="button-primary" onclick="myFunction()">Hide</button>
<div id="add-info">
<h6>Address: {{address}}</h6>
<h6>Google Maps: {{google_maps_location}}</h6>
<h6>Opening Times: {{opening_times}}</h6>
<h6>Rating: {{rating}}</h6>
<h6>Added By: {{added_by}}</h6>
<h6>Date Added: {{date_added}}</h6>
</div>
</div>
</script>
</div>
<!-- Don't need jQuery for Tabletop, but using it for this example -->
<script type="text/javascript" src="handlebars.js"></script>
<script type="text/javascript" src="../../src/tabletop.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
var public_spreadsheet_url = 'https://docs.google.com/spreadsheets/d/1h5zYzEcBIA5zUDc9j4BTs8AcJj-21-ykzq6238CnkWc/edit?usp=sharing';
$(document).ready( function() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
parseNumbers: true } );
});
function showInfo(data, tabletop) {
var source = $("#cat-template").html();
var template = Handlebars.compile(source);
$.each( tabletop.sheets("food").all(), function(i, food) {
var html = template(food);
$("#content").append(html);
});
}
</script>
<script>
function myFunction() {
var x = document.getElementById("add-info");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
</body>
</html>
Are all the entries on your page filled from the given template, meaning they are divs with the class entry? If so, I think your issue is the following: Your entry div has a child div with the id="add-info". And when you click the button, your handler function (myFunction()) tries to get a reference to that div via document.getElementById("add-info"); Now, if you have multiple such entries on a page, you will have multiple divs with id="add-info". But the id attribute of an element must be unique in your whole document. See the description of id or that of getElementById().
So the root cause of your problem is that the same id is used multiple times in the document when it shouldn't be. You get the behavior you're seeing because getElementById() just happens to be returning a reference to the first element it finds on the page, regardless of which button you click. But I believe you're in undefined behavior territory at that point.
One way to solve the problem is to somehow give myFunction() information about which button was clicked, while making each div you'd like to manipulate unique so they can be found easier. For instance, you can use the order of the restaurant on your page as its "index", and use that as the id of the div you'd like to hide/show. And you can also pass this index as an argument when you call your click handler:
...
<button id="btn" class="button-primary" onclick="myFunction('{{index}}')">Hide</button>
<div id="{{index}}">
<!-- The rest of the code here... -->
...
... add the index into your template context, so Handlebars can fill in the {{index}} placeholder:
...
$.each( tabletop.sheets("food").all(), function(i, food) {
food.index = i // Give your context its 'index'
var html = template(food);
$("#content").append(html);
});
...
... and then alter your function slightly to use the given argument instead of always looking for the div with id="add-info":
function myFunction(indexToToggle) {
var x = document.getElementById(indexToToggle);
// rest of the code is same
With this approach, I expect your DOM to end up with divs that have ids that are just numbers ("3", "4", etc.) and your click handler should get called with those as arguments as well.
Also note that your <button> element has id="btn". If you repeat that template on your page, you will have multiple <button>s with the same id. If you start trying to get references to your buttons via id you will have similar issues with them too since the ids won't be unique.
I get two error messages when trying to load the page with the code below. The error messages are:
"Uncaught TypeError: Cannot set property 'href' of null at HTMLAnchorElement.col.(anonymous function).onclick (http://www.jimbrink.org/:363:17)"
"Uncaught ReferenceError: bindEvents is not defined at (index):375"
I'm trying to create a link that, when clicked, would switch to another css file (with different fonts).
(BONUS QUESTION: Is there a way for the link to toggle between the two stylesheets?)
I've taken this from another StackOverflow question, but I can't seem to get the code to work my situation.
Here's the link:
<li>JB's Fav Font</li>
Here's the js function from the bottom of the page:
<!-- cssswitcher js -->
<script type='text/javascript'>
window.onload = function bindEvents(){
var css=document.getElementById('style');
var col=document.querySelectorAll('a.changeStyle');
/* iterate through collection and assign listener */
for( var n in col )if( col[n].nodeType==1 ) col[n].onclick=function(e){
e.preventDefault();/* prevent jumping to top of page etc */
var el=typeof(e.target)!='undefined' ? e.target : e.srcElement;
/* assign style attributes */
css.href=el.dataset.style;
css.rel=el.dataset.rel;
css.type=el.dataset.type;
/* store reference to style selected in localstorage */
localStorage.setItem( 'style', el.dataset.style );
};
/* if there is a reference to the user's css choice in storage, assign it */
if( localStorage.getItem( 'style' )!=null ) css.href=localStorage.getItem( 'style' );
}
document.addEventListener( 'DOMContentLoaded', bindEvents, false );
</script>
First, start by defining the original style like this:
HTML:
<link id="style" rel="stylesheet" type="text/css" href="style.css" />
Notice the id=style that we'll use to find the element. That might fix your first error.
For the second one, you have to decide whether to use document.addEventListener( 'DOMContentLoaded', bindEvents, false ); or window.onload because they're different functions. This might help you window.onload vs. body.onload vs. document.onready.
So, now we can do some Javascript:
HTML (the links):
<li><button onclick='setStyle("css/style.comicsans.css")'>JB's Fav Font</button></li>
<li><button onclick='setStyle("css/style.other.css")'>Other Font</button></li>
First, notice that I'm only using a parameter to call setStyle function on click, and btw it's better to work with <button>, this way we get a cleaner result.
Javascript:
var cssStyle = document.getElementById('style');
window.onload = function(){
if(localStorage && localStorage.getItem("style"))
cssStyle.href = localStorage.getItem("style");
};
function setStyle(newStyle){
cssStyle.href = newStyle;
if(localStorage)
localStorage.setItem("style", newStyle);
};
BONUS:
But if you are only be using two styles, then try to simplify, and do a shorthand method to do this:
HTML:
<li><button onclick='toggleStyle()'>Toggle</button></li>
<!-- cssswitcher js -->
<script type='text/javascript'>
var cssStyle = document.getElementById('style');
var listStyles = ["css/style.comicsans.css", "css/style.other.css"];
window.onload = function(){
if(localStorage && localStorage.getItem("style"))
cssStyle.href = localStorage.getItem("style");
};
function toggleStyle(){
var previousStyle = cssStyle.href;
if(previousStyle.endsWith(listStyles[0]))
newStyle = listStyles[1];
else
newStyle = listStyles[0];
cssStyle.href = newStyle;
if(localStorage)
localStorage.setItem("style", newStyle);
};
</script>
I did this in one of my projects using JQuery, I hope this will help you :
HTML :
<ul id="projectList">
<li class="project">Lorem Lorem</li>
<li class="project viewed">Lorem Lorem</li>
<li class="project viewed selected">Lorem Lorem</li>
<li class="project viewed selected">Lorem Lorem</li>
<li class="project viewed">Lorem Lorem</li>
</ul>
JavaScript with Dynamic CSS Code :
var data = {
"projectColors": {
"viewedColor": "#fffc20",
"selectedColor": "#ff7920"
}
};
var style = $(document.createElement("style")).attr("type", "text/css");
style.append("#projectList .project.viewed {color: " + data.projectColors.viewedColor + ";}");
style.append("#projectList .project.selected {color: " + data.projectColors.selectedColor + ";}");
style.appendTo("head");
JSFiddle :
https://jsfiddle.net/nikdtu/9gberp5o/
I want to remove class of div id from other page anchor link.
firstPage.html
<div class="question show" id="a1">
Sample 1
</div>
<div class="question" id="a2">
Sample 2
</div>
list.html
$(function () {
$("a").click(function () {
$("#a2").addClass('question show');
});
});
</script>
</head>
<body>
Link 1
Link 2
</body>
I want to add class addClass('question show') to that div id which is clicked.
I tried here with Link1 for id=a1
But I'm failed to set class ('question show') help me to correct my code
Please check code here
http://plnkr.co/edit/fzdfjdrRbcWmir5wHcJW?p=preview
I'm taking a different approach. I'll not add the function to list.html. Let the page firstPage.html be called with the value. We will capture the anchor from firstPage.html.
Also, since your all divs have the class 'question'; I'm ignoring that class and targeting only 'show' class.
So, load this function with your firstPage.html:
$(document).ready(function(){
var call = $(location).attr('href').split('#');
var ancr = $.trim(call[1]);
if(ancr === undefined || ancr == ''){
// Anchor not set, do nothing
} else {
if (!$('#'+ancr).hasClass('show')) {
$('#'+ancr).addClass('show');
}
}
});
I also assume you don't have multiple divs with same ID (which generally should not be).
I hope this will do what you need.
I appreciate all the suggestions I've gotten so far-thank you!
I'll try to describe a bit better what I'm trying to do:
I want to switch a CSS class on the active (clicked on) tab item on a item (to make a highlight effect while its related content is showing).
The JS Fiddle http://jsfiddle.net/4YX5R/9/ from Vlad Nicula comes close to what I'm trying to achieve, however I can't get it to work in my code.
The tabs are linked to content which is shown on the page when the tab is clicked. This part is working fine. I just want to change the CSS style on the ContentLink items when its content is being shown.
I'd also like to keep the content for ContentLink1 visible when the page loads, as it is now in the code, and for ContentLink1 to have the CSS .infoTabActive class when the page loads. When the ContentLink tab is not clicked, it should have the .infoTab class.
This is what I have so far:
HTML:
<article class="grid-70 infoContainer">
<a class="infoTab" id="aTab" href="javascript:show('a')">ContentLink1</a>
<a class="infoTab" id="bTab" href="javascript:show('b')">ContentLink2</a>
<a class="infoTab" id="cTab" href="javascript:show('c')">ContentLink3</a>
<div id="a">
<p> Inhalt 1111111.</p></div>
<div id="b">
<p>Inhalt 222222222
</p></div>
<div id="c">
<p>Inhalt 33333333
<7p></div>
</article>
Javascript:
window.onload = function () {
document.getElementById("a").style.display = "block";
}
function show(i) {
document.getElementById('a').style.display ="none";
document.getElementById('b').style.display ="none";
document.getElementById('c').style.display ="none";
document.getElementById(i).style.display ="block";
}
basic CSS for tab styles I want to apply:
.infoTab {
text-decoration:none;
color:red;
}
.infoTabActive {
text-decoration:none;
color:yellow;
}
Any pointers would be appreciated!
You can switch the classes simply bu using class property on DOM element.
To replace the existing class use
document.getElementById("Element").className = "ClassName";
Similarly to add a new class to exisiting classes use
document.getElementById("Element").className += "ClassName";
Change show function to be like this:
function show(i) {
document.getElementById('a').style.display ="none";
document.getElementById('a').className ="";
document.getElementById('b').style.display ="none";
document.getElementById('b').className ="";
document.getElementById('c').style.display ="none";
document.getElementById('c').className ="";
document.getElementById(i).style.display ="block";
document.getElementById(i).className ="selected";
}
I changed a little bit your code to make it suits your needs.
First, change the onload part in the Fiddle, by no wrap.
Then, you need to hide each elements at start like this :
window.onload = function () {
var list = document.getElementsByClassName("hide");
for (var i = 0; i < list.length; i++) {
list[i].style.display = "none";
}
}
I added an hide class to achieve it. Your show function works well then.
I would do it like this:
add a class called .show which sets the element to display block.
then toggle the classname.
Here's a JSFiddle
And here's an example:
HTML
<article class="grid-70 infoContainer">
<a class="infoTab" id="aTab" href="javascript:show('a')">Werbetexte</a>
<a class="infoTab" id="bTab" href="javascript:show('b')">Lektorate</a>
<a class="infoTab" id="cTab" href="javascript:show('c')">Übersetzung</a>
<div class="box" id="a">
<div class="col1"> <p>Inhalt 1111111.</p></div>
</div>
<div class="box" id="b">
Inhalt 222222222
</div>
<div class="box" id="c">
Inhalt 33333333
</div>
</article>
JavaScript
window.onload = function () {
show('a');
}
function show(elm) {
// get a list of all the boxes with class name box
var shown = document.getElementsByClassName('box');
// loop through the boxes
for( var i=0; i<shown.length; i++ )
{
// set the classname to box (removing the 'show')
shown[i].className = 'box';
}
// change the classname to box show for the element that was clicked
document.getElementById( elm ).className = 'box show';
}
CSS
.box {
display:none;
}
.box.show {
display:block;
}
Simplest way I could think of is this : http://jsfiddle.net/4YX5R/9/
Basically you don't want to listen to each element. If you do that you will have issues with new tabs. If you listen to the parent element like in my example you can add new tabs without having to write any more javascript code.
<a class="infoTab" data-target='a' id="aTab">Werbetexte</a>
Each tab button has a data-target attribute that will describe the div to show as the tab content. Hiding and showing content will be done via css, not style - which is a recommended best practice -.
tabs.addEventListener("click", function ( ev ) {
var childTarget = ev.originalTarget || ev.toElement;
...
}
When a tab is clicked, we check to see which element was clicked from the event listener on the parent, and then get the data-target from it. We use this as a id selector to show the new tab. We also need a reference to the old tab that was active, so we can hide it.
The logic is not that complicated, and with this you can have any number of tabs. I would recommend jQuery for this, since the event delegation might not work in all browsers with the current code.
I hope this helps :)
I'm trying to implement multiple scrollbars with the plugin Tinyscrollabr.js
http://baijs.nl/tinyscrollbar/
To implement the scrollbars, i use a function scrollify like in this article :
http://www.eccesignum.org/blog/making-tinyscrollbarjs-easier-to-implement
HTML :
<ul id="myList">
<li id="scrollbar1" class="col">
<h2>Title 01</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
<li id="scrollbar2 class="col">
<h2>Title 02</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
<li id="scrollbar3 class="col">
<h2>Title 03</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
</ul>
Javascript :
function scrollify(element,options) { // '#element', {list:of,key:values}
var opt = options || {}
$(element).children().wrapAll('<div class="viewport"><div class="overview"></div></div>');
$(element).prepend('<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>');
$(element).tinyscrollbar(options);}
$scrollbar1 = $('#scrollbar1 .scrollBox') ;
$scrollbar2 = $('#scrollbar2 .scrollBox');
$scrollbar3 = $('#scrollbar3 .scrollBox');
$scrollbar4 = $('#scrollbar4 .scrollBox');
$(function() {
scrollify($scrollbar1);
scrollify($scrollbar2);
scrollify($scrollbar3);
scrollify($scrollbar4);
})
I would to make this more simple.
For example, i would to be able to make this :
$(function() {
scrollify('.scrollBox');
})
But tinyscrollbar need an id. With a class, it's load the first scrollbar and not the others. Firebug return this error message "f.obj[0] is undefined"
Sorry if my question is stupid, but how can I do for applying tinyscrollbar to a list of elements with a class ?
And then, after some actions how to update all this scrollbars with the function $allScrollbars.tinyscrollbar_update();
Thanks for help, I'm just beginning with javascript and i'm trying to learn.
I would count the number of elements with the class:
var scrollCount = $(".scrollbox").size();
Then use an iterating loop to call each of your IDs:
for (i=0; i<5; i++) {
scrollify($('#scrollbar' + i));
}
Also I would recommend using DIVs instead of the list setup you have, use the example from the link you shared as a starting point :)
Thanks KneeSkrap3r for your answer. It's a good solution to make this but i'm trying to do something in the case i' don't know the numbers of element to scroll.
I think I've found with something like this (it's a part from the first jquery plugin i'm trying to do ) where $el is all elemnts with the class"scrollbox".
$el.each(function(index)
{
var $scrolls = $(this);
function scrollify(element,options)
{ // '#element', {list:of,key:values}
var opt = options || {}
$(element).children().wrapAll('<div class="viewport"><div class="overview"></div></div>');
$(element).prepend('<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>');
$(element).tinyscrollbar(options);
}
scrollify($scrolls);
// Update heights
$(window).resize(function()
{ $scrolls.tinyscrollbar_update('relative');
});
})
Like this, it's seems to work but i don't know if i'm using good practice of javascript.
For the Html markup, I told the li elements for div, it's better for the semantic.
Thanks for tips ;-)