More efficient way to change styles using Javascript? - javascript

I have an about section, where I've split it up into multiple sections loaded by JavaScript for easier reading. I'd like the side navigation for this to have a different background color if it is both hovered over and if it is the one selected, and ALSO to have a border right with a unique color for each option. I have it working with no problems, but I'm just wondering if there is a more efficient way to do this than the way I currently am.
In a nutshell, the HTML:
<nav>
<p id="bout" onclick="bout()">About Us</p>
<p id="mish" onclick="mish()">Our Mission</p>
<p id="team" onclick="team()">The Team</p>
<p id="how" onclick="how()">How It Works</p>
<p id="poli" onclick="poli()">Policies</p>
</nav>
<div class="actual">
<div id="about">
<h2>About Us</h2>
<p>We are a conglomerate of hoodlums.</p>
</div>
</div><!-- end actual -->
And the JS:
function bout() {
document.getElementById("about").innerHTML= '<h2>About Us</h2><p>We are a conglomerate of hoodlums.</p>';
document.getElementById("bout").style.borderRight='3px solid red';
document.getElementById("mish").style.borderRight='none';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='ghostwhite';
document.getElementById("mish").style.backgroundColor='bisque';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
function mish() {
document.getElementById("about").innerHTML = '<h2>Mission</h2><p>Our mission is to rid the world of dust bunnies.</p>';
document.getElementById("bout").style.borderRight='none';
document.getElementById("mish").style.borderRight='3px solid orange';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='bisque';
document.getElementById("mish").style.backgroundColor='ghostwhite';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
As you can see, it's quite cumbersome to have to explicitly turn off an on each style when clicked. The main key though is to have each border-right be a different color.
Here is a jsfiddle with the whole thing, but for some reason it's not actually acknowledging the JS: http://jsfiddle.net/4CrhD/
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?

The best way would be to use CSS. Add remove a class on a parent element and have the CSS apply the right rules.
body.mish #bout{
border-right : 3px solid red,
}
body.bout #bout{
border-right : 3px solid blue,
}

Yes. You need to divide between html and styling. Use CSS!
Then you can change styles e.g. with jQuery.css():
$('#mish').css({
'border-right': '3px solid orange',
'background-color':'ghostwhite'
});
Of course you can define styles in a class. A class describes the styling definition for all elements using a class.
nav > p {
border-right: none;
background-color: bisque;
}
.active {
border-right: 3px solid red;
background-color: ghostwhite;
}
If a button is clicked you can dynamically add and remove a classes with:
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
});
Because code duplication is bad (and I don't like to set the full innerHTML), you can create a dynamic page like:
pages = {
'bout': {
'id': 'about',
'headline': 'About Us',
'body': 'We are a conglomerate of hoodlums.'
}
}
Extend the above code to
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
if (pages[$(this).attr('id')]) {
var page = pages[$(this).attr('id')];
$('.actual').first().empty();
var container = $('<div>', { 'id': page.id });
container.append($('<h2>', { 'html': page.headline }));
container.append($('<p>', { 'html': page.body }));
$('.actual').first().append(container);
}
});
Have look at this jsfiddle for a working example
Addressing your "random" question
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?
If you want to have links pointing to this page you can parse the window.location.hash object and link with links like page.html#mish.
To set default a "page" we extend our pages object to provide such a information: http://jsfiddle.net/Eu36g/6/

Define your classes in the CSS : bout, mish, about, poli ... For each one put the CSS you want. After that, in the javascript, you just have to change the class of the element (add class or change class, or whatever) and the new CSS will apply
example
document.getElementById("bout").className = "otherclass"

Related

Remembering color-choice through Jquery (localStorage)

I have created a very simple and basic Jquery script that changes the class for textboxes on my site in order for them to have a different colored background when a button is clicked. I then attempted (with the help of a Jquery-for-dummies-book) to set it up so that the color choice is remembered locally.
I must however be a greater "dummy" than expected because I have not been able to make this work.When I upload the script to the server and test it on the site, I can change the color, but if I close then window and then go to my website again, the color is back to default. It is NOT remembered/stored.
Is it possible the problem stems from the fact that my textboxes use the class "row" to set the background color, and you can not change a class to a different class, but must use a proper element or ID? Or should the order of the script-parts perhaps be different?
Any and all insight is appreciated on my learning-journey.
External script
$(document).ready(function(){
if (localStorage.getItem("farvevalg")=="farve") { $(".row").addClass("farve");
}
if ($(".row").hasClass("farve")) {
localStorage.setItem("farvevalg", "farve");
} else {localStorage.removeItem("farvevalg")}
$('#farvevalg').click(function(){
$(".row").toggleClass('farve');
}); }
My HTML
/*The default color of all textboxes on a page*/
.row {background-color: #e7e7e7;}
/*The color that it changes into when button is clicked*/
.farve {background-color: pink;}
/*The button that must be clicked to change color*/
#farvevalg {
margin-top: 6%;
padding: 5px;
}
Your attempt is correct but add/remove localStorage you are doing at the wrong place. You should do it inside that button click.
WORKING FIDDLE
Snippet won't work because of the CORS issue. It's for code view only.
$(document).ready(function () {
if (localStorage.getItem("farvevalg") == "farve") {
$(".row").addClass("farve");
}
$('#farvevalg').click(function () {
$(".row").toggleClass('farve');
if ($(".row").hasClass("farve")) {
localStorage.setItem("farvevalg", "farve");
} else {
localStorage.removeItem("farvevalg")
}
});
});
/*The default color of all textboxes on a page*/
.row {background-color: #e7e7e7;}
/*The color that it changes into when button is clicked*/
.farve {background-color: pink;}
/*The button that must be clicked to change color*/
#farvevalg {
margin-top: 6%;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<div class="row">
Test
</div>
<button id="farvevalg">
Change
</button>
some changes in login, not tested but should work
$(document).ready(function(){
if (localStorage.getItem("farvevalg")=="farve") {
$(".row").addClass("farve");
}
$('#farvevalg').click(function(){
//only here we add/remove setting
var wasFarveColor = $(".row").hasClass("farve")
$(".row").toggleClass('farve');
if(wasFarveColor)
localStorage.removeItem("farvevalg")
else
localStorage.setItem("farvevalg", "farve")
});
})
what you are doing is, at the start of your application, check it there is a saved item 'farvevalg' with value 'farve'. If that is the case, then you add the class 'farve' to all elements with class 'row'.
After this you check if there is a row element with class 'farve' and, if that is the case' you set the item in storage, otherwise you delete it. As you can see it doesn't make sense for this bit of code to be here as it won't have any effect. You should instead move this if/else block inside of the click callback ( after $(".row").toggleClass('farve'); )

Formatting text in CSS based on output text

I am using Awesome Tables (which I will refer to as AT) to take data from a Google Sheets document and present the data in a format I can embed into a website. I have used a HTML template in the sheets to display the data in the AT form, which utilises inline CSS formatting. The template is only for the table output and as such, only the <body> element exists for that table - i.e. I have no access to <head> section, etc.
I have a piece of data (${"Status"}) pulled in from Google Sheets that can insert one of three text outputs: Active, Delivered or Cancelled. This is called to the output by:
<div style="display:inline-block;color:rgb(87, 87, 87);font-size: 14px;padding: 10px 10px 10px 0;flex-shrink: 0;margin-right: auto;text-transform: capitalize;">
<p><b>Name:</b> ${"Name"}</p>
<p><b>Start Date:</b> ${"Start Date"}</p>
<p><b>Completed Date:</b> ${"Completed Date"}</p>
<p><b>Status:</b> ${"Status"}</p>
</div>
I would like to color format the output text of ${"Status"} so that "Active" = orange, "Cancelled" = red and "Delivered" = green but not 100% sure how to do this. I have read that I probably need to use some sort of JavaScript to achieve this, but to be honest, do not know where to start.
Any help appreciated.
So, following on from the response received, here is my first attempt of writing JavaScript after a bit of online research. Am I heading along the right track?
var jobStatus = "${"Status"}";
if (jobStatus = "Delivered") {
document.getElementById("status").style.color = "green";
} else if (jobStatus = "Active") {
document.getElementById("status").style.color = "orange";
} else {
document.getElementById("status").style.color = "red";
}
If you can edit the html template, I would suggest to use css classes to apply the colors. Therefore just apply the value also as the css class and create a bit of css to format your text (or what ever) how you want it:
<div style="display:inline-block;color:rgb(87, 87, 87);font-size: 14px;padding: 10px 10px 10px 0;flex-shrink: 0;margin-right: auto;text-transform: capitalize;">
<p><b>Name:</b> ${"Name"}</p>
<p><b>Start Date:</b> ${"Start Date"}</p>
<p><b>Completed Date:</b> ${"Completed Date"}</p>
<p class="${"Status"}"><b>Status:</b> ${"Status"}</p>
</div>
The css is static. You can put it in the header section of your document (I understood, you do not have dynamic access to that, is that assumption correct?). Otherwise some js to append it to the body would work as well.
.Active {
color: orange;
}
.Cancelled {
color: red;
}
.Delivered {
color: green;
}

Can't hide other elements while clicking on another

I'm trying to make a toggle which works, but every element I click on creates a stack of these showed elements. Instead I'm trying to hide everything and display only element that I clicked on. Now I can only hide it when I click on the same element twice, which is not what I want. I want to click on one and hide previous ones that were showing.
.totalpoll-choice-image-2 is a bunch of images that always has to be shown. They are what the user clicks on to display hidden description under each image. That description shows up when I click on .totalpoll-choice-image-2. There are 5 images with that class. The next image I click on, I want to hide the previous description box.
My code:
jQuery(document).ready(function() {
var element = document.getElementsByClassName("totalpoll-choice-image-2");
var elements = Array.prototype.slice.call(Array.from( element ) );
console.log(elements);
jQuery(element).each(function(item) {
jQuery(this).unbind('click').click(function(e) {
e.stopPropagation();
var id = jQuery(this).attr("data-id");
console.log(this);
//jQuery("#" + id).css({"display": 'block !important'});
//document.getElementById(id).style.setProperty( 'display', 'block', 'important' );
var descriptionContainer = document.getElementById(id);
var thiss = jQuery(this);
console.log(thiss);
console.log(jQuery(descriptionContainer).not(thiss).hide());
jQuery(descriptionContainer).toggleClass("show");
});
})
})
You can attach event handlers to a group of DOM elements at once with jQuery. So in this case, mixing vanilla JS with jQuery isn't doing you any favors - though it is possible.
I threw together this little example of what it sounds like you're going for.
The script itself is very simple (shown below). The classes and IDs are different, but the idea should be the same:
// Assign click handlers to all items at once
$('.img').click(function(e){
// Turn off all the texts
$('.stuff').hide();
// Show the one you want
$('#' + $(e.target).data('id')).show();
})
https://codepen.io/meltingchocolate/pen/NyzKMp
You may also note that I extracted the ID from the data-id attribute using the .data() method, and attached the event listener with the .click() method. This is the typical way to apply event handlers across a group of jQuery objects.
From what I understood based on your comments you want to show only description of image that has been clicked.
Here is my solution
$('.container').on('click', 'img', function() {
$(this).closest('.container').find('.image-description').addClass('hidden');
$(this).siblings('p').removeClass('hidden');
});
https://jsfiddle.net/rtsj6r41/
Also please mind your jquery version, because unbind() is deprecated since 3.0
You can use event delegation so that you only add your event handler once to the parent of your images. This is usually the best method for keeping work the browser has to do down. Adding and removing classes is a clean method for show and hide, because you can see what is happening by looking at your html along with other benefits like being easily able to check if an item is visible with .hasClass().
jsfiddle: https://jsfiddle.net/0yL5zuab/17/
EXAMPLE HTML
< div class="main" >
<div class="image-parent">
<div class="image">
</div>
<div class="image-descr">
Some text. Some text. Some text.
</div>
</div>
<div class="image-parent">
<div class="image">
</div>
<div class="image-descr">
Some text. Some text. Some text.
</div>
</div>
<div class="image-parent">
<div class="image">
</div>
<div class="image-descr">
Some text. Some text. Some text.
</div>
</div>
<div class="clear">
</div>
</div>
EXAMPLE CSS
.image-parent{
height: 100px;
width: 200px;
float: left;
margin: 5px;
}
.image-parent .image{
background: blue;
height: 50%;
width: 100%;
}
.image-descr{
display: none;
height: 50%;
width: 100%;
}
.show-descr{
display: block;
}
.clear{
clear: both;
}
EXAMPLE JQUERY
$(".main").on("click", ".image-parent", ShowDescription);
function ShowDescription(e) {
var $parent = $(e.target).parent(".image-parent");
var $desc = $parent.find(".image-descr");
$(".image-descr").removeClass("show-descr");
$desc.addClass("show-descr");
}

Jquery will not select button after class has been toggled

I have some jquery that will, when a button is clicked, switch a class from a button to a different class (i.e. on click switch class from #testButton from .first to .second with an image toggle to show it works). The first click works well and it toggles the image, but the second click does not do anything. It seems as if it is not recognizing the new class. Here is a fiddle.
https://jsfiddle.net/myfb44yu/
This is the problematic javascript.
$(document).ready(function(){
$('.first').click(function(){
alert('works');
$('#testButton').toggleClass('first', 'second');
});
$('.second').click(function(){
alert("works");
$('#testButton').toggleClass('second', 'first');
});
});
The interesting thing is that it works when I use an alert() to check but not when I try to change an img src.
Your main issue here is a syntax error in regards to your .toggleClass, but seeing as others have addressed that, I'd like to point out that you should consider re-thinking how you apply your listeners - just as good habit moving forward.
An overview of jQuery Event Bindings
Think of the elements on your page as items in a store. You're an employee, and your manager says "Go put a red tag on anything in the toys department", and so you do. The next day, he puts 10 new toys in the toy department, and says to you "Why don't all the toys have red tags on them?" He then moves one of the toys to the clothing section and asks you, "Why does this item have a red tag on it?" It's simple. You put the red tags on anything in the toys department when he told you to do it - things got moved around afterwards.
The toys in this example would be your .first and .second elements.
This is how jQuery event bindings work - they only apply to elements that satisfied the selector at the time the event was initialized.
So, if you do $('.myClass').click();, then put .myClass on five buttons - none of those buttons will call this function, as they didn't have listeners put on them.
Similarly, if you put a listener on an element using class, but then remove the class from that element, it will maintain the bound event.
The Solution
$(document).on("click", ".first", function() { } );
This is known as event delegation.
In continuing with my analogy from before, this would be the equivalent of skipping tagging the items altogether, and instead just deciding whether or not they're a toy when the customer brings them to the cash register.
Instead of putting the listener on specific elements, we've put it on the entire page. By using ".first" as the second parameter (which takes a selector), the function will only be executed if the element has class first.
Hope this helps.
EDIT: As I was typing, JHecht left a good answer that points out the same issue I outlined above.
N number of elements can have the same class name ,so that's the reason if your trying to search it as $('.classname') returns an array ,so that's the reason your code is not working.class selector
Id is unique,each element should have a single id . In your code button has two id's and for the same button your trying to toggle first and second,you need not have two separate events for first and second
instead you can write as following
check this snippet
$(document).ready(function() {
var firstElements = $('.first')
var first = firstElements[0];
var secondElements = $('.second');
var second = secondElements[0]
$("#testButton").click(function() {
alert('works');
$(this).toggleClass('first').toggleClass('second');
});
});
.first {
color: red;
}
.second {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="img/images.jpeg" alt="" id="testImage">
<div id="testDiv">
<button type="button" id='testButton' class='first'>Hi</button>
</div>
Hope it helps
Ho about this solution. Hope it helps!
$(document).ready(function(){
$("#testButton").click(function(){
if($(this).prop("class") === "first"){
alert('first');
$(this).removeClass("first").addClass("second");
}
else if($(this).prop("class") === "second"){
alert("second");
$(this).removeClass("second").addClass("first");
}
});
});
.first{
color: red;
}
.second{
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<img src="img/images.jpeg" alt="" id="testImage">
<div id="testDiv">
<button type="button" id='testButton' class='first'>Hi</button>
</div>
I hope that what I am about to say makes more sense than I feel it does.
Your issue is that when you assign the click events, there is not currently an element that has a class of .second.
Also, your code is wrong. toggleClass accepts a few arguments, the first is a string of classes, the second is an optional parameter to check whether or not to toggle the classes on or off.
A way to accomplish what you want without changing a whole lot of code is event delegation, shown below.
$(function() {
$(document).on('click', '.btn-first,.btn-second', function() {
//here we are adding the click event on the document object, and telling it that we only want to delegate this event to an object that matches the classes of .btn-first or .btn-second.
//Note: to those saying "why not just do it on the .btn class an avoid having to do this", it is so he can see what delegation looks like. But you are correct, with this markup it would be better to simply add the click event on the .btn class.
$(this).toggleClass('btn-first btn-second');
});
});
.btn {
padding: 4px 8px;
border-radius: 3px;
border: 1px solid grey;
}
.btn-first {
background-color: green;
border-color: green;
}
.btn-second {
background-color: orange;
border-color: orange
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="img/images.jpeg" alt="" id="testImage">
<div id="testDiv">
<button type="button" id='testButton' class='btn btn-first'>Hi</button>
</div>
A combination of javascript, CSS and HTML to toggle the class of #testButton when any element of class "first" or "second" is clicked, including the test button itself. The posted code was changed to supply JQuery's .toggleClass method with a space separated list of class names. Click "run snippet" to test the effect.
$(document).ready(function(){
$('.first').click(function(){
$('#testButton').toggleClass('first second');
});
$('.second').click(function(){
$('#testButton').toggleClass('first second');
});
});
.first { border: thick outset green;}
.second { border: thick inset red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="first">This paragraph has first class</p>
<p class="second">This paragraph has second class</p>
<button type="button" id="testButton" class="first">this button starts out first class</div>
The script can then be simplified by combining multiple class names in a single selector, leaving just:
$(document).ready(function(){
$('.first, .second').click(function(){
$('#testButton').toggleClass('first second');
});
});
Make a neutral class that the buttons both share (.btn).
Then add one of the state classes to each button (.first or .second).
Delegate the click event to the neutral class only ($('.btn').on('click',...).
Then toggle both state classes on this ($(this).toggleClass('first second');)
The images change by CSS, each button has 2 images which alternate between display:none/block according to the button's state class.
There is an example with the images outside of buttons and another example that doesn't toggle classes around.
SNIPPET
$('.btn').on('click', function() {
$(this).toggleClass('first second');
});
/* OR */
$('.alt').on('click', function() {
$('.img').toggle();
});
.first > .one {
display: block;
}
.first > .two {
display: none;
}
.second > .one {
display: none;
}
.second > .two {
display: block;
}
.first + .one {
display: block;
}
.first + .one + .two {
display: none;
}
.second + .one {
display: none;
}
.second + .one + .two {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Use jQuery with CSS</p>
<button class='btn first'>
<img src='http://placehold.it/50x50/000/fff?text=1' class='one'>
<img src='http://placehold.it/50x50/fff/000?text=2' class='two'>
</button>
<button class='btn second'>
<img src='http://placehold.it/50x50/0e0/960?text=1' class='one'>
<img src='http://placehold.it/50x50/fff/000?text=2' class='two'>
</button>
<br/>
<br/>
<button class='btn first'>Toggle</button>
<img src='http://placehold.it/50x50/fc0/00f?text=1' class='one'>
<img src='http://placehold.it/50x50/00f/fc0?text=2' class='two'>
<button class='btn second'>Toggle</button>
<img src='http://placehold.it/50x50/fc0/00f?text=1' class='one'>
<img src='http://placehold.it/50x50/00f/fc0?text=2' class='two'>
<p>Or use only jQuery no CSS</p>
<img src='http://placehold.it/50x50/0e0/930?text=1' class='img'>
<img src='http://placehold.it/50x50/930/0e0?text=2' class='img' style='display:none'>
<button class='alt' style='display:block;'>Toggle</button>

Change CSS Link Property onClick with Javascript/JQuery?

So for example i have two links:
<a onClick="doColorChange()">Link 1</a>
<a onClick="doColorChange()">Link 2</a>
I want it so that when I click Link 1, Link 1 changes to color blue to represent selected, Link 2 stays black. When the user clicks Link 2, then Link 2 changes color to blue and Link 1 changes color back to white.
I currently have a default CSS property for links:
a:link {
color: #green;
}
I am unsure of the best way to handle the "doColorChange()" function. Is it best to create two CSS classes for the two colors, then have doColorChange switch them? Or is it better to give the two links an id and somehow set color properties there? How do I accomplish this?
JQUERY:
$(function() {
var links = $('a.link').click(function() {
links.removeClass('active');
$(this).addClass('active');
});
});
HTML MARKUP:
Link 1
Link 2
I suggest adding a class to the links, that way it's easier.
CSS:
a.link.active { color:blue; }
Added a Live Version (fiddle): http://jsfiddle.net/gHb9F/
HTML
Link 1
Link 2
Script (using jQuery)
$(document).ready(function(){
$('a').click(function(){
$('a').css('color', 'black');
$(this).css('color', 'blue');
});
});
CSS
a:link { color: black; }
a:visited { color: black; }
Fiddle here
Note: The color change will be applied to all anchors current on your page. If you want to limit it to a select few, then put them in a class and add that class to the selector.
Edit:
If you plan on doing anything other than simple color swap, then classes are definitely the way to go (just substitute the .css calls for .addClass and .removeClass with your custom class names.
Try this code. I found it simple to use.
<script type="text/javascript">
var currentLink = null;
function changeLinkColor(link){
if(currentLink!=null){
currentLink.style.color = link.style.color; //You may put any color you want
}
link.style.color = 'blue';
currentLink = link;
}
</script>
<a onClick="changeLinkColor(this)">Link 1</a>
<a onClick="changeLinkColor(this)">Link 2</a>
var doColorChange=function(){ this.style.color="blue";}
Your default CSS colour for links should be:
a:link {
color: #0f0; /* or
color: green;
color: rgb(0,255,0);
}
Otherwise, using jQuery, you can achieve this with:
$('a').click(
function(){
$('.selectedLink').removeClass('selectedLink');
$(this).addClass('selectedLink');
return false
});
Coupled with the CSS:
.selectedLink {
color: #00f;
}
JS Fiddle demo.
Make 2 different classes in css and then swap classes on the links when you click on your link.
CSS
a.link{
color : green;
}
a.selected{
color : black;
}
Javascript
jQuery(a).click(function()
{
jQuery('a.selected').addClass('link');
jQuery('a.selected').removeClass('selected');
jQuery(this).removeClass('link');
jQuery(this).addClass('selected');
});
giving the elements css classes would be a better option. You could do it by using the className property on the object. in doCOlorChange you could write this.className ="newclassName";

Categories