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
Related
What I am trying to do is to log results using "this" like an array so that the number 0 logs in the console.log whenever I click the first list item, without pre-defined variables and only using one function.
<ul class="menuList">
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Chicken Cordon Bleu</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Chicken Stir Fry</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Chicken Thighs</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Fish Fillet</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Lasagna</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Pizza</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Salmon</a></li>
<li><a class="menuImage" onclick="openMenuItemAll();"><button>›</button>Spaghetti</a></li>
</ul>
<script type="text/javascript">
function openMenuItemAll(){
var menuImage = document.querySelectorAll(".menuImage");
console.log(this.menuImage);
}
</script>
I'm getting undefined in the console.log when I am trying to get the array number based on the position of the menu item
The value of this depends on how the function is called.
Event handler functions will have this equal to the element to which the event handler is bound.
So onclick="this /* is the element */"
Functions called with no context (e.g. if you call openMenuItemAll();) have this equal to undefined (unless you fail to trigger Strict Mode, in which case it will be window).
Aside: <a> is for links. Don't use it if you aren't linking anywhere. It is forbidden to put a <button> inside a link!
First, fix your markup:
<ul class="menuList">
<li><button>›</button>Chicken Cordon Bleu</li>
Note that the link is removed, and I didn't transfer the class because you can infer it from the class on the list itself.
Then select all the buttons:
const buttons = document.querySelector(".menuList button");
Then loop over the buttons and bind your openMenuItemAll function as the event handler.
Array.from(buttons).forEach(
button => button.addEventListener("click", openMenuItemAll)
);
You need to pass this in your function: onclick="openMenuItemAll(this);
Then you can get the index of the target from the array.
That being said, the onclick event will happen anytime that you click anywhere in the <li> element. If you only want the event to fire when clicking on the button, you need to put the event inside the button. Since the button is a child of the li, then you need to pass this.parentElement to pass the <li> to the function.
Also, since the anchor tag is not really being used for it's purpose, you can remove that entirely.
In the snippet below, I also remove the bullets in the list since the buttons really replace the need for having them.
function openMenuItemAll(target) {
const menuImage = document.querySelectorAll(".menuImage");
const index = Array.prototype.indexOf.call(menuImage, target)
console.log(index);
}
.menuImage{
list-style:none;
}
<ul class="menuList">
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Chicken Cordon Bleu
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Chicken Stir Fry
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Chicken Thighs
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Fish Fillet
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Lasagna
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Pizza
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Salmon
</li>
<li class="menuImage">
<button onclick="openMenuItemAll(this.parentElement);">›</button> Spaghetti
</li>
</ul>
Quentin has your answer, but also consider event delegation to make the code more extensible:
window.onload = function() {
document.querySelector('ul').addEventListener('click', showIndex, false);
}
function showIndex (evt) {
let tgt = evt.target;
let btns = this.querySelectorAll('button');
for (let i=0, iLen=btns.length; i<iLen; i++) {
if (btns[i] == tgt) {
console.log('Button ' + i);
return i;
}
}
return null;
}
<ul>
<li><button>›</button>
<li><button>›</button>
<li><button>›</button>
</ul>
You might also consider using an OL (ordered list) in which case the LI elements will have a value attribute that is their position in the list.
But I think even better is to put an attribute on each button to link to their purpose so that order doesn't matter at all so you have:
<button data-menuItem="123">›</button>Chicken Cordon Bleu
Then you can link the reference "123" to whatever (and you can still get the index if you really want).
Html
<ul>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
My app got a list of things then after 5secs. it will automatically go to the next li.
but that is not the problem. the problem is with the click function I want to know the data-id of the li.
According to the OP's comments
Remove the onclick attribute.
Bind the click event using jQuery.
Use closest('li') to get the parent of your links.
function clickFunction(e) {
e.preventDefault(); // This is to prevent the execution of your links!
console.log($(this).closest('li').data('id'));
}
$('a').click(clickFunction);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-id="1">
1
</li>
<li data-id="2">
2
</li>
<li data-id="3">
3
</li>
<li data-id="4">
4
</li>
<li data-id="5">
5
</li>
</ul>
(1) Remove onclick attribute.
(2) Attach a .click handler to all your links
$(function () {
// attach an onclick event handler to your links
$('li a[data-id]').click(function (e) {
// prevent the link from going anywhere
e.preventDefault();
// get the parent li
var li = $(this).closest('li');
// get next li's link data id
console.log(li.next('li').find('a').data('id'));
});
});
so I'm using bootstrap form wizard and my navigation buttons look like this:
<ul class="pager wizard">
<li class="previous">
Prev
</li>
<li class="next">
Next
</li>
</ul>
When I reach the final step the next button become disabled, I want it to be replaced by submit button instead.
Aboud Jouda i assume based on some logic you will know you reached the final step. First add a class to your next a tag. Then execute the below function executeThisOnFinalStep() to change the hyperlink text, remove next class and add final class. Based on this, different onClick function will be executed.
<li class="next">
Next
</li>
function executeThisOnFinalStep() {
$(".pager.wizard.next.atag").html("Submit");
$(".pager.wizard.next.atag").addClass("final");
$(".pager.wizard.next.atag").removeClass("next");
}
//Your onClick Functions.
$(".pager.wizard.next.atag").onClick(){
//write your next logic here
}
$(".pager.wizard.final.atag").onClick(){
//write your submit logic here
}
you try this code:
<ul class="pager wizard">
<li class="previous">
Prev
</li>
<li class="next">
Next
</li>
</ul>
javascript code with jquery:
var finalSteps = 3
var steps = 3;
if (steps == finalSteps) {
$('.next').remove();
$('.pager.wizard').append('<li>submit</li>')
}
I'm trying to make multiple dropdown menu's on my website and I am using this jQuery for this:
$(function() {
var pull = $('#pull');
menu = $('#nav');
menuHeight = menu.height();
$(pull).on('click', function(e) {
e.preventDefault();
menu.slideToggle();
});
});
Here's the html part:
<nav class="container">
<a href="#" id="pull" style="display:block;">
<h3>Menu</h3>
</a>
<ul id="nav" style="display:none;">
<li>Pizza</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
It works wonderful if I only have one drop down menu but as soon as I add another one, only one of them (doesn't matter if it's two, three or more then) is actually dropping down.
I gave every Menu it's own ID and copied the code every time and replaced the ID's but this doesn't work.
Already looked into this (using the same function of different events ) or this (Jquery - use the same function for multiple requests) and other threads but i can't figure out how to apply this on my code...
Here's my Jsfiddle on what I'm trying to do: https://jsfiddle.net/thwdyccr/2/
Use classes instead of ids, and then you can make the same code work for all cases (fiddle):
$(function () {
var pull = $('.pull');
$(pull).on('click', function (e) {
e.preventDefault();
var menu = $(this).next();
menu.slideToggle();
});
});
<nav class="container"> <a href="#" class="pull" style="display:block;">
<h3>Menu1</h3>
</a>
<ul class="nav" style="display:none;">
<li>Pizza
</li>
<li>Pasta
</li>
<li>Burger
</li>
<li>Specials
</li>
<li>Drinks
</li>
</ul>
</nav>
<nav class="container"> <a href="#" class="pull" style="display:block;">
<h3>Menu2</h3>
</a>
<ul class="nav" style="display:none;">
<li>Pizza
</li>
<li>Pasta
</li>
<li>Burger
</li>
<li>Specials
</li>
<li>Drinks
</li>
</ul>
</nav>
Try this:
https://jsfiddle.net/thwdyccr/5/
Rather than using IDs - consider using a class instead - this'll save you lots of duplication in your code (as essentially it's all doing the same thing).
You can specify the target selector (e.g. the element you want to show) by traversing your structure with .parent() .children() or .find()
If you're wondering why I am storing $(this) in var element - it is because the browser has to figure out what $(this) is each time you use it - so it's good practice to store it in a variable.
HTML
<nav class="container">
<a href="#" class="pull" style="display:block;">
<h3>Menu1</h3>
</a>
<ul class="nav" style="display:none;">
<li>Bear</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
<nav class="container">
<a href="#" class="pull" style="display:block;">
<h3>Menu2</h3>
</a>
<ul class="nav" style="display:none;">
<li>Fish</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
JS
$(function() {
$(".pull").click(function(e) {
e.preventDefault();
var element = $(this);
element.parent('nav.container').children("ul.nav").slideToggle();
});
});
You shouldn't use id's for pull. Here's an updated fiddle https://jsfiddle.net/thwdyccr/2/.
Try utilizing Attribute Starts With Selector [name^="value"] [id^=pull] , e.target.parentElement.nextElementSibling to select next ul to call .slideToggle() on
$(function() {
var pull = $("[id^=pull]")
, menu = $("[id^=nav]")
, menuHeight = menu.height();
pull.on("click", function(e) {
e.preventDefault();
$(e.target.parentElement.nextElementSibling).slideToggle();
});
});
jsfiddle https://jsfiddle.net/wpvok7gy/1/
I want add class to clicked li and delete other li class
<ul>
<li onclick="s()"><span>خانه</span></li>
<li onclick="s()"><span>سفارش</span></li>
<li onclick="s()" class="selected"><span>آپلود</span></li>
<li onclick="s()"><span>درباره ما</span></li>
<li onclick="s()"><span>تنظیمات</span></li>
</ul>
I can do it with jquery but now i want do this with javascript?
Don't use inline click handlers. Instead, attach a handler from JavaScript.
<ul id="myUL"> <!-- This is just for example, to make it easier to select -->
<li><span>خانه</span></li>
<li><span>سفارش</span></li>
<li class="selected"><span>آپلود</span></li>
<li><span>درباره ما</span></li>
<li><span>تنظیمات</span></li>
</ul>
Then, in JavaScript:
var myUL = document.querySelector('#myUL');
// Attach one event listener on the parent, instead of one for each element.
// It's more performant and will work with dynamically added entries!
myUL.addEventListener('click', function(event) {
// Here, event.target is the actual event clicked.
// Remove class from selected one.
document.querySelector('#myUL .selected').classList.remove('selected');
// And add it to the current one
event.target.classList.add('selected');
});
Working Example
This is a quick fix and this way is not recommended. But in your case, you need to use this way:
function s (which) {
document.querySelectorAll(".clicked")[0].classList.remove("selected");
which.classList.add("selected");
}
And change the call this way:
<ul>
<li onclick="s(this)"><span>خانه</span></li>
<li onclick="s(this)"><span>سفارش</span></li>
<li onclick="s(this)" class="selected"><span>آپلود</span></li>
<li onclick="s(this)"><span>درباره ما</span></li>
<li onclick="s(this)"><span>تنظیمات</span></li>
</ul>
The right way is to use eventListeners and bind the events to an ID.
var list = document.querySelector('#menu');
list.addEventListener('click', function(event) {
list.querySelector('.selected').classList.remove('selected');
event.target.classList.add('selected');
});
And add the ID to the <ul>:
<ul id="menu">
<li>خانه</li>
<li>سفارش</li>
<li class="selected">آپلود</li>
<li>درباره ما</li>
<li>تنظیمات</li>
</ul>