Is it possible to change a certain on hover over another certain item.
For example:
<li>
test
</li>
JS
var list = document.getElementById('li');
var link = document.getElementById('a');
list.onmouseover = function() {
link.style.color = "#8080ff";
}
If i hover over the li item I want the text inside the a tag to change, but this code is not working.
I cant use css or jquery library.
http://jsfiddle.net/Nt8Pq/40/
Your code looks for elements with ids and you have not ids. You would need to select them by the tag name and loop over the collection. And than you would need to find the anchor that is inside of the collection.
var menu = document.getElementById("menu");
var lis = menu.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
var li = lis[i];
li.addEventListener("mouseover", function() {
this.getElementsByTagName("a")[0].style.color = "#8080ff";
});
li.addEventListener("mouseout", function() {
this.getElementsByTagName("a")[0].style.color = "#000000";
});
}
<ul id="menu">
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
</ul>
In the end this is a lot of code to implement
ul li:hover a {
color : "#8080ff";
}
SO you could just inject a CSS rule if you are not able to actually add styles to the page...
var sheet = window.document.styleSheets[0];
sheet.insertRule('#menu li:hover a { color: #8080ff; }', sheet.cssRules.length);
<ul id="menu">
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
</ul>
This can be done with some simple HTML event attributes and JavaScript.
<li>
test
</li>
HTML Event Attributes
If you want to do it with JS, here is the answer. But like said before, you shouldn't do it this way:
<li id="list">
<a id="link" href="#">test</a>
</li>
var list = document.getElementById('list');
var link = document.getElementById('link');
http://jsfiddle.net/Nt8Pq/45/
Assuming you can not modify the CSS or the source of the web page, and you are stuck only with a single javascript file in which you wish to modify some features of a web page, then this approach will work:
One caveat is you have to use of an index in document.getElementsByTagName('li') which returns an array. If you always need the first element for example, you can hard code this index as zero. Otherwise, you need to iterate over the collection looking for the one you wish to change.
Finally, you can modify the style of the firstChildElement after you find the list item you want.
var li = document.getElementsByTagName('li')[0];
li.onmouseover = function() {
li.firstElementChild.style.color = "#F00"; // red
}
li.onmouseout = function() {
li.firstElementChild.style.color = "#000"; // black
};
<li>
Mouse over me.
</li>
var nodesArray = document.getElementById('myID').getElementsByTagName('a');
for (var i = 0; i < nodesArray.length; i++) {
nodesArray[i].style.color = 'red';
}
May be you will find your solution in this link:-https://ubuntuforums.org/showthread.php?t=1692280
Related
I have two filters , "Bidder" and "Seller". "Bidder" is the active filter.
It is working fine when I clicked on the filters, it is showing their corresponding elements.
The only problem is when the page loads, it is displaying the elements of both the "Bidder" and "Seller" filter. However, I want it to display the corresponding elements of my active filter only when the page loads.
I have tried to use display: none; to hide it but it does not work.
let indicator = document.querySelector('.indicator').children;
let main = document.querySelector('.info').children;
for (let i = 0; i < indicator.length; i++) {
indicator[i].onclick = function() {
for (let x = 0; x < indicator.length; x++) {
indicator[x].classList.remove('active');
}
this.classList.add('active');
const displayItems = this.getAttribute('data-filter');
for (let z = 0; z < main.length; z++) {
main[z].style.transform = 'scale(0)';
setTimeout(() => {
main[z].style.display = 'none';
}, 0);
if ((main[z].getAttribute('data-category') == displayItems)) {
main[z].style.transform = 'scale(1)';
setTimeout(() => {
main[z].style.display = 'block';
}, 0);
}
}
}
}
<ul class="indicator">
<li data-filter="bidder" class="active">Bidder</a>
</li>
<li data-filter="seller">Seller</a>
</li>
</ul>
<ul class=" info">
<li data-category="bidder"><a>abc</a></li>
<li data-category="seller"><a>efg</a></li>
</ul>
First of all, your HTML is invalid. I'd plug it into a validator and make sure to open and close all of those tags.
Secondly, .style = ... is often an antipattern, as it seems to be here. Hardcoding CSS into JS is as difficult to maintain as hardcoding JS (or CSS) into HTML. Prefer creating CSS classes, then adding and removing them with .toggle and .classList. Ideally, classes are the declarative lingua franca/glue between the three worlds of structure, behavior and style.
You can indeed use display: none to hide things as you mention, but I don't see any CSS code provided and your JS only runs on click, so there's nothing that would affect visibility on load.
There are at least two options: you can add these visibility classes statically to the HTML or you can assign them from JS after the DOM loads. Which is "better" depends on your use case.
Absent any other contextual information, I'd suggest adding the classes to the static HTML. If you handle it in JS and display the static HTML by default, your user might see the not-yet-hidden elements momentarily then disappear once the JS runs.
As a consequence, if you do use JS, you'd probably want to hide the whole wrapper by default and only show it to the user after your JS has properly assigned the necessary visibility classes using a loop and classList.add().
If you're going that far, you might even generate all of the elements with the correct visibility properties dynamically with JS, depending on where your data is coming from.
Here's a suggestion that shows the usage of classes in HTML that can be added/removed by JS, and have the necessary CSS styling to hide/show by default.
const indicatorEls =
[...document.querySelectorAll(".indicator li")]
;
const infoEls = [...document.querySelectorAll(".info li")];
for (const el of indicatorEls) {
el.addEventListener("click", () => {
for (const el of indicatorEls) {
el.classList.remove("active");
}
el.classList.add("active");
const filterTarget = el.getAttribute("data-filter");
for (const el of infoEls) {
el.classList.remove("info-item-active");
if (el.getAttribute("data-category") === filterTarget) {
el.classList.add("info-item-active");
}
}
});
}
.info-item {
display: none;
}
.info-item-active {
display: block;
}
.active {
background: red;
}
<ul class="indicator">
<li data-filter="bidder" class="active">Bidder</li>
<li data-filter="seller">Seller</li>
</ul>
<ul class="info">
<li
data-category="bidder"
class="info-item info-item-active"
>
a
</li>
<li data-category="seller" class="info-item">
b
</li>
<li data-category="seller" class="info-item">
c
</li>
<li
data-category="bidder"
class="info-item info-item-active"
>
d
</li>
<li data-category="seller" class="info-item">
e
</li>
</ul>
it is fairly simple.
I want to make a current class and put it on a link that is currently active
like this : <li class="li current"><a>Link1</a></li>
but before that, the JS should get all of element with class="li", loop through it and remove the class=" current" if any.
after looping end, then add class=" current" to the element which triggers the event.
for example if user clicks on link3 then JS should remove the class=" current" on link1 and then add class=" current" on link3
it would look like this : <li class="li current"><a>link3</a></li>
it looks like I cannot use getElementsByClassName() for event listener. what should I do to make an event listener then?
the HTML
document.addEventListener("DOMContentLoaded",function(){
var et = document.getElementsByClassName("li");
for(i=0; i <et.length; i++){
et[i].addEventListener("click",function(){
funclink(event);
});
};
});
function funclink(event){
//first get all element with class "li" and remove class " current"
//then add class " current" to the element which triggers the event
var slink = document.getElementsByClassName("li");
for(i =0; i < slink.length; i++){
slink[i].className = slink[i].className.replace(" current","");
}
event.currentTarget.className += " current";
}
.current {
color : orange;
}
<ul id="navmenu">
<li class="li current">Home</li>
<li class="li">Call Service
<li class="li"><a class="a-left" href="#">Rental</a></li>
<li class="li"><a class="a-left" href="#">Sales</a></li>
</li>
</ul>
As commented before, you will have to loop over elements to add eventListener. document.getElementsByClassName will return a NodeList.
Also, if you are only calling your function with event param, you can just pass function ref instead.
Also, instead again fetching all lis, just fetch those lis that has class current. This will reduce number of iterations.
You should use classList instead of className. It has many helpful methods like add, remove and toggle.
Edit 1
As you need to retain the selected li even after refresh, you will have to use client storage or query param to tell your JS about the selected element.
For security reasons, SO does not provide access to localStorage, so you will have to copy code and debug on local files.
document.addEventListener("DOMContentLoaded", function() {
var lis = document.getElementsByClassName("li")
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", funclink.bind(lis[i], i));
}
initializeUI();
});
function funclink(index, event) {
var lis = document.querySelectorAll('.li.current');
for(var i = 0; i< lis.length; i++){
lis[i].classList.remove('current');
}
this.classList.add('current');
setIndex(index)
}
function initializeUI(){
var lis = document.querySelectorAll('.li');
var index = parseInt(locatStorage.getItem('liIndex'));
lis[index || 0].classList.add("current");
}
function setIndex(index){
localStorage.setItem("liIndex", index);
}
function blockAnchors(){
var as = document.querySelectorAll('a');
for(var i = 0; i< as.length; i++){
as[i].onclick = function(){
return false
}
}
}
blockAnchors();
.current{
background: #ddd;
}
<ul id="navmenu">
<li class="li">Home</li>
<li class="li">Call Service
<li class="li"><a class="a-left" href="?module=rental">Rental</a></li>
<li class="li"><a class="a-left" href="?module=sales">Sales</a></li>
</li>
</ul>
Note: I have added a blockAnchors to stop navigation on a's click. This is just for demonstration.
Array of elements doesn't have to initialized two times.
Using li class is a useless. Modern browsers (IE8+) can use querySelector() (querySelectorAll()) (similiar functionality to the jQuery selector).
When document is ready we get array of links in #navmenu, we add listeners to them.
funclink function removes all classes from links and then sets class "current" to the element, that has triggered that function.
var slink; //prepare global scope var that will be filled with link elems
document.addEventListener("DOMContentLoaded", function() {//wait for document to be loaded
slink = document.querySelectorAll("#navmenu li");//fill global var with array of link elems
for (i = 0; i < slink.length; i++) {//add click listener to all link elems
slink[i].addEventListener("click", function() {
funclink(event);
});
}
});
function funclink(event) {
for (i = 0; i < slink.length; i++)slink[i].className = ""; //remove all current classes
event.currentTarget.className = "current"; //add current class to the element that triggered fnc
}
a {
color: blue;
}
.current,
.current a {
color: red;
}
<ul id="navmenu">
<li class="current">Home</li>
<li>Call Service
<li><a class="a-left" href="#?module=rental">Rental</a></li>
<li><a class="a-left" href="#?module=sales">Sales</a></li>
</li>
</ul>
<div id="product_parts">
<ul id="product_list">
<li class="active" data-maxlength="200" > <img src="images/ts/1.jpg" /> </li>
<li data-maxlength="200" > <img src="images/ts/2.jpg" /> </li>
<li data-maxlength="60" > <img src="images/ts/3.jpg" /> </li>
<li data-maxlength="60" > <img src="images/ts/1.jpg" /> </li>
</ul>
</div>
Here is an unordered list. i have a function that runs when the img tag of a list is clicked.Now i want this myfunction() to run for every img list item.
This is my funnction
$('#product_parts li>img').click(function(){
$('#product_parts li').removeClass('active');
$(this).parents('li').addClass('active');
var selected_canvas_image = $(this).attr('src');
var obj = 'main_layer_'+($(this).parents('li').index() + 1) ;
add_canvas(false,selected_canvas_image,'','all',obj);
})
This was the solution i tried
var lis = document.getElementById("product_list").getElementsByTagName('li').find('li);
for(i=0;i<lis.length();i++)
{
lis[i].click();
}
Unfortunately it doesnt work
In your Vanilla JavaScript, there is several problems.
One, you have a syntax error: for(i=0;i<lis.length();i++)
length isn't a function, but you are using it as one. It should be lis.length instead:
for (i = 0; i < lis.length; i++) {
lis[i].click();
}
Two, you are triggering a click event on #product_list li, not the img:
var lis = document.getElementById("product_list").getElementsByTagName('li');
You should select the img instead of the li:
var lis = document.getElementById("product_list").getElementsByTagName('img');
If you are fine with losing a little bit of browser support, you can use querySelectorAll():
var lis = document.querySelectorAll("#product_list li>img");
Your code should now look like:
var lis = document.querySelectorAll("#product_list li>img");
for (i = 0; i < lis.length; i++) {
lis[i].click();
}
However
You are already using jQuery in you project, so you might as well use it's functions:
$("#product_list li>img").click()
Much shorter, much easier.
Since you use Jquery already here is a simple solution
$( "#product_parts li>img" ).each( function( index, element ){
$(element).click();
});
Just iterate over each of the image in list and click them.
Here is a working JS Fiddle.
https://jsfiddle.net/g838s4zd/2/
I'm trying to display the full list that have the same id that matches with the select option. But I can't figure out how to get the id from the attribute by using the name to be able to filter it.
The html example:
<select id='groopy' onchange='see();'>
<option>default</option>
<option>lista1</option>
<option>list1</option>
</select>
<ul id='grupo'>
<li id='list1' name="lista">Playground (Rangbhoomi)</li>
<li id='default' name="lista">Empire Made Me</li>
<li id='default' name="lista">Transmission</li>
<li id='lista1' name="lista">Hostel Room 131</li>
<li id='default' name="lista">A Disobedient Girl</li>
<li id='default' name="lista">Travels in the Land of Kubilai Khan</li>
<li id='list1' name="lista">The Indian Mutiny</li>
<li id='lista1' name="lista">Beauty and Sadness</li>
<li id='default' name="lista">The Collaborator</li>
<li id='list1' name="lista">I, Lalla</li>
<li id='default' name="lista">No Full Stops in India</li>
<li id='lista1' name="lista">For Lust of Knowing</li>
<li id='default' name="lista">On the Road to Kandahar</li>
</ul>
And the script I'm trying:
<script>
function see(){
var listita = document.getElementById('groopy').options[document.getElementById('groopy').selectedIndex].value;
var items = document.getElementsByName("lista");
var items_id = document.getElementsByName("lista").getAttribute('id');
if(listita==items_id){
for(var i = 0; i < items.length; i++)
{
document.getElementById("description").innerHTML = items[i].outerHTML;
}
}
}
onload= see();
</script>
By the way, the select and the ul are generated dynamically so I don't actually now the id's that could be provided. I'm trying a little different approach here .
When I manage to make the select filter work, the for stop working. WHY? I'm going crazy with this. Please help!!
Firstly you are having multiple elements with same id's which is wrong.. Cause getElementbyId will only fetch the first element encountered by it.
Replace then with class instead
Next you are overwriting the HTML for every iteration, so you will always have the last item appended to it.
Instead store that in a variable and append it after the for loop.
you need to bind your element with a change event, otherwise your call only works once when the page loads for the first time.
Try this
// Cache the selector as you are using it multiple times
var dropdown = document.getElementById('groopy');
function see() {
// set the selected option
var listita = dropdown.options[dropdown.selectedIndex].value
items = document.getElementsByClassName(listita);
html = '';
// For each item with class name, iterate over it and store in a string
for (var i = 0; i < items.length; i++) {
if (items[i].className == listita) {
console.log((items[i].outerHTML));
html += items[i].outerHTML
}
}
// set the html after the for loop
document.getElementById("description").innerHTML = html;
}
onload = see();
// attach the change event handler
dropdown.addEventListener('change', see);
Check Fiddle
try changing the id's to class in the li tags and use this function...
function see(){
var selectedVal = document.getElementById('groopy').options[document.getElementById('groopy').selectedIndex]. value;
var items = document.getElementsByClassName(selectedVal);
var html = '';
for(var i = 0; i < elements.length; i++)
{
html += items[i].outerHTML;
}
document.getElementById("description").innerHTML = html;
}
onload= see();
Step1 - Change id to class
Step2 - Traverse DOM elements with jQuery class selector. In this way replace document.getElementId('id) with $('.className')
I have a function that generates a unordered list of links and I want to use javascript to select the last 2 links so that I can align them to the right.
so in the following example I would need to select the li parent of link4 and link5, then add a class so i can style it
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
<li>link5</li>
</ul>
In the end it should be something like this:
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li class="align_right">link4</li>
<li class="align_right">link5</li>
</ul>
Couldn't you generate class="align_right" for the last 2 links when you build the list?
By the way, if you want to do this by javascript, you could do:
//get the sidebarmenu element
var sidebar = document.getElementById('sidebarmenu');
//getting the ul inside the wrapper
var ul = sidebar.getElementsByTagName("ul")[0];
//getting al the li childs
var li = ul.getElementsByTagName("li");
var totLi = li.length;
if(totLi >= 2){ //setting class to last 2
li[totLi-1].className = "align_right";
li[totLi-2].className = "align_right";
}
Edit: updated for your particular needs
Running example:
http://www.jsfiddle.net/steweb/m4v2J/
In Jquery:
$('ul li:last-child').prev('li').andSelf().addClass("align_right");
This best be done in the function generating those items, if you insist on client side script afterwards, here it is:
var oList = document.getElementById("myList");
var arrItems = oList.getElementsByTagName("li");
if (arrItems.length >= 2) {
arrItems[arrItems.length - 2].className = "align_right";
arrItems[arrItems.length - 1].className = "align_right";
}
For this to work, add ID to the <ul> tag and use it,