Passing text to a javascript function - javascript

I'm just starting in on javascript and working on a problem that our instructor gave us. We have an html site with four buttons, each of the buttons has a color, and when you hit the button it changes the background/text color. Sample HTML and javascript below.
HTML
<div id="wrapper">
<ul id="switcher">
<li id="grayButton"></li>
<li id="whiteButton"></li>
<li id="blueButton"></li>
<li id="yellowButton"></li>
</ul>
</div>
CSS
document.getElementById("yellowButton").onclick = turnYellow;
function turnYellow (){
document.getElementById("wrapper").style.backgroundColor = "yellow";
document.getElementById("wrapper").style.color = "orange";
}
I got that to work fine, but I was trying to refactor so that my function was more generic:
document.getElementById("grayButton").onclick = changeColor("gray", "white");
function changeColor(backColor, frontColor) {
document.getElementById("wrapper").style.backgroundColor = backColor;
document.getElementById("wrapper").style.color = frontColor;
}
and I can't figure out why that doesn't work. Any thoughts?

You need to call your function in an anonymous function, adding the parameters () caused the function to be invoked immediately:
document.getElementById("grayButton").onclick = function() {
changeColor("gray", "white");
}

"element.onlick" event requires a function object (callable/callback) not a return value. Thus it should be:
document.getElementById("grayButton").onclick = function(){
changeColor("gray", "white");
}
Also, HTML5 data attributes seems like a great idea:
<html>
<body>
<div id="wrapper">
<ul id="switcher">
<li data-bg-color="red" data-color="white" onclick="changeColor(this)">
red/white
</li>
<li data-bg-color="gray" data-color="black" onclick="changeColor(this)">
gray/black
</li>
</ul>
</div>
<script>
function changeColor(el) {
var wrapper = document.getElementById("wrapper");
wrapper.style.color = el.getAttribute('data-color');
wrapper.style.backgroundColor = el.getAttribute('data-bg-color');
}
</script>
</body>
</html>
HTML5 Data Attributes

This is my solution My example
HTML
<body onload="start()">
<div id="wrapper">
<ul>
<li data-params="yellow,orange">Hit me</li>
<li data-params="green,darkgreen">Hit me</li>
<li data-params="aqua,blue">Hit me</li>
<li data-params="chocolate,brow">Hit me</li>
</ul>
</div>
</body>
JavaScript
function start(){
//Get necesary elements
var list = document.getElementsByTagName("li");
//Adding event
for(var i in list){
list[i].addEventListener("click", changeStyle);
}
}
function changeStyle(){
var params = this.dataset.params.split(","),
wrapper = document.getElementById("wrapper");
wrapper.style.backgroundColor = params[0];
wrapper.style.color = params[1];
}

You simply called the function changeColor and assigned its return value which is undefined to the event handler.
I am pretty sure it even worked and changed the text color and background color for that element but not like what you expected i.e. synchronously vs asynchronously.
You just need to leave a reference to the event handler like this changeColor without the parentheses like what you did in the first example and the event handler would take care of everything for you when the event occurs/fires and it detects it.

Related

Replicate CSS :focus selector for multiple elements using javascript

I have this website: https://www.australianathleticscalendar.com.au/
I want to make it so you can have selected an 'Events' filter and 'State' filter at once (I.e. 100m and QLD at once), and the bubbles in each filter will have styling (I.e. like :focus). With each filter, select one category. When you change categories within a filter, the previous one selected must also be unstyled (I.e. can't select 100m and 200m at once. Moving from 100m to 200m would remove styling from 100m and add it to 200m).
The problem is with css is that you can only :focus one element at a time.
How can I achieve this using javascript?
I've pulled the relevant code into a codepen here.
This is the functions which draw the two filters:
function drawCategories() {
var template = Handlebars.compile(document.getElementById("menu-template").innerHTML);
console.log('draw ', this.products);
document.getElementById('menu-container').innerHTML = template(this.events);
}
function drawStates() {
var template = Handlebars.compile(document.getElementById("menu-template-2").innerHTML);
console.log('draw ', this.products);
document.getElementById('menu-container-states').innerHTML = template(this.states);
}
function showCategory(event) {
this.title = event;
drawProducts();
}
function showState(state) {
this.titleStates = state;
drawProducts();
}
And this is the HTML for the two filters:
<!-- Events filter -->
<div class="container">
<script id="menu-template" type="text/x-handlebars-template">
<ul class="navbar-nav">
{{#each this as |event|}}
<li class="nav-item"></li>
<a class="nav-link" href="#" onclick="showCategory('{{event.name}}');">{{event.name}}</a>
{{/each}}
<a class="navbar-brand hover-color" href="#" onclick="showAllEvents();">All Events</a>
</ul>
<ul class="navbar-nav ml-auto"></ul>
<li class="nav-item">
</li>
</ul>
</div>
</script>
</div>
<!-- States filter -->
<div class="container">
<script id="menu-template-2" type="text/x-handlebars-template">
<ul class="navbar-nav">
{{#each this as |state|}}
<li class="nav-item"></li>
<a class="nav-link nav-link-states" href="#" onclick="showState('{{state.name}}');">{{state.name}}</a>
{{/each}}
<a class="navbar-brand hover-color-states" href="#" onclick="showAllStates();">All States</a>
</ul>
<ul class="navbar-nav ml-auto"></ul>
<li class="nav-item">
</li>
</ul>
</div>
</script>
</div>
As often there are many ways to achieve this. I think the easiest might be to add an extra argument to the calls made in the click handlers -- passing this -- so the handler knows exactly which DOM element needs to get styling:
<a onclick="showCategory(this, '{{event.name}}');">
<a onclick="showAllEvents(this);">
<a onclick="showState(this, '{{state.name}}');">
<a onclick="showAllStates(this);">
Then in your code define a function that will apply a CSS class to a given DOM element, but also makes sure that it will be the only element having that class. Then use this utility function in the click handlers, which must now also take that extra argument:
// Utility function that ensures only one element has the given CSS class:
function selectElem(elem, className) {
let prevSelected = document.querySelector("." + className);
if (prevSelected) prevSelected.classList.remove(className);
elem.classList.add(className);
}
function showCategory(elem, event) { // <-- extra parameter, here and below...
selectElem(elem, "selectedEvent"); // <-- add this call, here and below...
this.title = event;
drawProducts();
}
function showAllEvents(elem) {
selectElem(elem, "selectedEvent");
this.title = "All Events";
drawProducts();
}
function showState(elem, state) {
selectElem(elem, "selectedState"); // <-- different style here and below
this.titleStates = state;
drawProducts();
}
function showAllStates(elem) {
selectElem(elem, "selectedState");
this.titleStates = "All States";
drawProducts();
}
Now it is up to you to define the style of two new CSS classes: selectedEvent and selectedState. You can give them the same definition with a comma:
.selectedState, .selectedEvent {
# Your styling ...
}

How Get Name Class With Javascript?

Hi everyone i need get name class menu li for load this page
html
<body>
<div class="menu">
<ul>
<li class="page2" id="page2">PAGE TOW</li>
<li class="page3" id="page3">PAGE THREE</li>
</ul>
</div>
<div class="load"></div>
</body>
js
$(document).on('click','.menu li',function(){
var Get_Name_Class = //Get Name Class
if(/* var Get_Name_Class*/).hasClass("page2")) {
$(".load").load('page2.php');
}
else if(/* var Get_Name_Class*/).hasClass("page3")) {
$(".load").load('page3.php');
}
});
how can i this ( get id or class not difference )
Use this to refer the clicked element inside the handler callback.
$(document).on('click','.menu li',function(){
// cache the reference
var $this = $(this);
// check using the cached element
if($this.hasClass("page2")) {
$(".load").load('page2.php');
}
else if($this.hasClass("page3")) {
$(".load").load('page3.php');
}
});
You can do it using jQuery. If it is class you can do:
$(".className")
if it is id you can do:
$("#idName")
if it is just html element you can do:
$("elementName")
Pass this.className with ".php" concatenated to .load()
$(document).on('click','.menu li',function() {
$(".load").load(this.className + ".php")
});
$(document).on('click','.menu li',function(){
// cache the reference
var $this = $(this);
// check using the cached element
if($this.hasClass("page2")) {
$(".load").load('page2.php');
}
else if($this.hasClass("page3")) {
$(".load").load('page3.php');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="menu">
<ul>
<li class="page2" id="page2">PAGE TOW</li>
<li class="page3" id="page3">PAGE THREE</li>
</ul>
</div>
<div class="load"></div>
</body>
use "#" symbol for id so your code becomes
("#idname")
or u can use "this" which points to the present class u are working on
Don't use classnames. One day you'll add an extra class to those elements and your site will stop working and you'll be left wondering why - or in the worst case it'll slip unnoticed.
Say you have one or even more buttons for page2 triggering - than it's the perfect place to use the data-* attribute!
$(document).on('click', '[data-load]', function() {
var page = $(this).data("load");
console.log(page); // Just to test
$(".load").load(page +'.php');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a data-load="page2">PAGE TWO :) me too</a>
<div class="menu">
<ul>
<li data-load="page2">PAGE TOW</li>
<li data-load="page3">PAGE THREE</li>
</ul>
</div>
<div class="load"></div>

I Want to know how to change the style of an partcular <li> in a particular <ul> by javascript

I want to know how to change the style of an particular <li> in a particular <ul> by JavaScript
My code goes something like this
<ul id="menu">
<li id="number1">1</li>
<li id="number2">2</li>
</ul>
Now let's say I want to change the background color of the li#number1 of the ul#menu using JavaScript.
This is your solution in plain JavaScript:
var el = document.querySelector('#number1');
el.addEventListener('click', function(e) {
el.style.backgroundColor = 'blue';
});
Here is a solution using javascript and button.
<script>
function doSth(){
var nodes = document.getElementById("menu").getElementsByTagName("li");
for(var i=0; i<nodes.length; i++) {
if (nodes[i].id == 'number2') {
nodes[i].style.background = "blue";
}
}
}
</script>
<ul id="menu">
<li id="number1">1</li>
<li id="number2">2</li></ul>
<input type="button" onClick="doSth();" value="Click here"/>

Console function not defined error?

I do not understand why my function isn't working and why I keep getting a "test is not defined error" when I try to run it.
I want the page to scroll down to the appropriate section, when the user clicks the right menu item.
<ul class="timelineNav">
<li class="navItem">
<button type="button" onclick='test("1")'>
Event1
</button>
</li>
<li class="navItem"><a class="navItem" href="url">Event2</a></li>
<li class="navItem"><a class="navItem" href="url">Event3</a></li>
<li class="navItem"><a class="navItem" href="url">Event4</a></li>
<li class="navItem"><a class="navItem" href="url">Event5</a></li>
</ul>
<article id="post1">
some text
</article>
<article id="post2">
some text
</article>
<article id="post3">
some text
</article>
Javascript function:
function test(postLocation){
var post = $('#post'+postLocation).offset();
$(window).scrollTop(post.top);
};
I originally wanted to make the list item itself start the function, but I guess it has to be a button?
You don't show where the function test() is defined, but if it is inside a document-ready handler (or any other function), it is not in the global scope, so it cannot be called from an onclick attribute.
Either:
(1) Stop using an onclick attribute and bind a click event handler to the elements.
(2) Move the definition of the function outside the document-ready handler.
(3) Defined the function like this:
window.test = function(postLocation) {
var post = $('#post'+postLocation).offset();
$(window).scrollTop(post.top);
};
Also, you do not have to use a button. You should be able to make it so the function executes by a click on a list item.
I suggest the following:
HTML:
<ul class="timelineNav">
<li>Event 1</li>
<li>Event 2</li>
<li>Event 3</li>
<li>Event 4</li>
</ul>
<article id="post1">
some text
</article>
<article id="post2">
some other text
</article>
JQuery:
$('.timelineNav').children('li').children('a').click(function(event) {
event.preventDefault();
var $article = $($(this).attr('href'));
$(window).scrollTop($article.offset().top);
});
JSFiddle DEMO
Although the <a> elements are not needed, they do cause the mouse pointer to change.
Updated HTML
Added the id to the button for better jquery selection
<ul class="timelineNav">
<li class="navItem">
<button type="button" id="clickbutton">Event1</button>
</li>
...
JS
Attach event to your button, remove inline event click
$(function () {
$('.navItem').on('click', '#clickbutton', function () {
var location = 1; //define or fetch your location here
var post = $('#post' + location).offset();
alert(post);
$(window).scrollTop(post.top);
});
});
Demo

switching two ids with ajax callback

I was kindly helped by Jonathan over here simple javascript question-linking button state to image swap?
The problem is that this makes the "active" class the same class for both list items.
Each list item needs to toggle its own active and its own inactive class (each is a button with its own css styling and background image).
Can you please help me modify the script so that I can do that?
Here is Jonathans provided code:
<li class="transcript">
<a id="transcriptionhorbutton" class="inactive"
href="javascript:void()"
onclick="getDataReturnText('/lessons/transcriptions/ajaxcalls/L1horizontal.txt', callback);make_active(this);"></a>
</li>
<li class="transcript">
<a id="transcriptionvertbutton" class="inactive"
href="javascript:void()"
onclick="getDataReturnText('/lessons/transcriptions/ajaxcalls/L1vertical.txt', callback);make_active(this);"></a>
</li>
<script>
var buttons = [ document.getElementById("transcriptionvertbutton"),
document.getElementById("transcriptionhorbutton")];
function make_active(el) {
deactivate_buttons();
el.setAttribute("class","active");
}
function deactivate_buttons() {
buttons[0].setAttribute("class","inactive");
buttons[1].setAttribute("class","inactive");
}
</script>
I understand that the problem is here:
function make_active(el) {
deactivate_buttons();
el.setAttribute("class","active");
}
but I don't know enough to separate that into two different classes.
Just add an extra parameter to the function:
function make_active(el, classname) {
deactivate_buttons();
el.setAttribute("class",classname);
}
Then change your calls just a bit. Here is the completed code. Note I changed all calls of setAttribute to .className instead. This was just so you don't run into any trouble with IE6:
<li class="transcript">
<a id="transcriptionhorbutton" class="inactive"
href="javascript:void()"
onclick="getDataReturnText('/lessons/transcriptions/ajaxcalls/L1horizontal.txt', callback);make_active(this,'active_class_1');"></a>
</li>
<li class="transcript">
<a id="transcriptionvertbutton" class="inactive"
href="javascript:void()"
onclick="getDataReturnText('/lessons/transcriptions/ajaxcalls/L1vertical.txt', callback);make_active(this,'active_class_2');"></a>
</li>
<script>
var buttons = [ document.getElementById("transcriptionvertbutton"),
document.getElementById("transcriptionhorbutton")];
function make_active(el, classname) {
deactivate_buttons();
el.className = classname;
}
function deactivate_buttons() {
buttons[0].className = "inactive_class_1";
buttons[1].className = "inactive_class_2";
}
</script>

Categories

Resources