Click on li with specific "rel" : Pure javascript, no jquery - javascript

I have to do a fully JavaScript (jQuery forbidden) script. I only can use the 'click()' function.
I have to simulate a click on a "li" which has a random attribute for a sneakers website.
For showing you :
The user click on a "mega menu" which display (on the click) the different sizes.
The user choose his size in that menu
I show you the "code" of the html big menu. On this article, "LZAE31" is the ID product.
<ul class="theUlClass" style="display:none">
<li class="theLiClass" rel="LZAE31:40">EU 40</li>
<li class="theLiClass" rel="LZAE31:41">EU 41</li>
<li class="theLiClass" rel="LZAE31:42">EU 42</li>
<li class="theLiClass" rel="LZAE31:43">EU 43</li>
</ul>
Imagine that the user has already buy something on the website, and his size is 42 EU.
The script is 90% ok (the part that the user has already buy something), but now i need to "simulate" a click.
For exemple, the end of the script works and it is :
document.getElementsByClassName("addtocart")[0].click();
So I really need you, to understand how can i click on the "rel="RANDOM:42" in the li.TheLiClass for exemple...

Try with:
First select element:
With Selector:
document.querySelector("[rel='LZAE31:40']")
// try like: console.log(document.querySelector("[rel='LZAE31:40']"));
Or with this function :
function specificRel( rel )
{
var items = document.getElementsByTagName('li');
for (var i=0; i<items.length; i++) {
if (items[i].getAttribute("rel") == rel) {
return items[i];
}
}
}
// try like: console.log(specificRel("LZAE31:40"));
And two, click :
With selector:
document.querySelector("[rel='LZAE31:40']").click();
Or with the function:
specificRel("LZAE31:40").click();

It's a tad bit unclear what you're asking, but I'll give it a shot. To get the LI element with rel=LZAE31:43 is trivial.
for( var a= document.getElementsByTagName('li'),i= 0; i < a.length; ++i )
if( a[i].getAttribute('rel') == 'LZAE31:43' )
break;

Related

Closing one element when opening another within the same loop using Javascript

first time on here so i'll try my best to explain what I'm asking.
So I have 3 list items with the same class name. I've put them in a looping function so that when you click on one it will display a sub set of list items for that specific list item. I also have them inside an if statement that adds a new class name to the specific list item that was clicked. It allows opening and closing of the sub list items when you click the corresponding parent element.
My question is; how can I use this same principle of checking for the additional class name, when the user clicks any of the list items. In other words, I am trying to code it in a way that will allow me to close any of the open sub list items when the user clicks a new list item.
This is what I came up with but it doesn't know what button[i] is when I include it within the "click" function. What I was trying to do with this code is to take whatever list item was clicked, and then check the previous and next iterations of the class name "button" to see if any of the contain also contain the class name "clicked.
HTML
<div class="main">
<ul>
<li>One
<ul>
<li>One-1</li>
<li>One-2</li>
</ul>
</li>
<li>Two
<ul>
<li>Two-1</li>
<li>Two-2</li>
</ul>
</li>
<li>Three
<ul>
<li>Three-1</li>
<li>Three-2</li>
</ul>
</li>
</ul>
</div>
CSS
.main ul ul {
display: none;
}
.main ul ul li {
display: block;
}
Javascript
var button = document.getElementsByClassName("button");
for (i = 0; i < button.length; i++) {
button[i].addEventListener("click", function() {
var prevItem = button[i - 1];
var nextItem = button[i + 1];
if (prevItem.className !== "button") {
prevItem.className = "button";
prevItem.nextElementSibling.style.display = "none";
}
if (nextItem.className !== "button") {
nextItem.className = "button";
nextItem.nextElementSibling.style.display = "none";
}
if (this.className === "button") {
this.className += " clicked";
this.nextElementSibling.style.display = "block";
}
});
}
I am wanting to make this code usable no matter how many list items you add. So checking exactly button[0] button[1] and button[2] wasn't really an option, but I can see how button[i + 1] might not check every list item after it but rather just the next one. I tried adding another loop but ran into similar issues. anyway that's why I'm here. Thanks for any help in advance.
Since I am not sure whether I understood your question correctly, I quickly rephrase it in my own words.
Question: "I have an arbitrary number of list elements, of which each contains a button and a nested list. The button is always visible, the nested list is hidden by default. When the user clicks on a button, the corresponding nested list should be shown. At the same time, all other shown nested lists should be hidden again. How can I achieve this?"
The original HTML looks fine:
<div class="main">
<ul>
<li>One
<ul>
<li>One-1</li>
<li>One-2</li>
</ul>
</li>
<li>Two
<ul>
<li>Two-1</li>
<li>Two-2</li>
</ul>
</li>
<li>Three
<ul>
<li>Three-1</li>
<li>Three-2</li>
</ul>
</li>
</ul>
</div>
The CSS I did not fully understand, but I suggest the following:
.main ul ul {
display: none;
}
.main li.is-active ul {
display: block;
}
.main ul ul li {
display: block;
}
By adding the "is-active" class to an LI element, it is shown. This way, the CSS controls the visibility.
For the JavaScript part, I suggest this:
const buttonElements = Array.from(document.querySelectorAll('.button'));
buttonElements.forEach(buttonElement => {
buttonElement.addEventListener('click', () => {
const activeElements = Array.from(document.querySelectorAll('.is-active'));
activeElements.forEach(activeElement => {
activeElement.classList.remove('is-active');
});
buttonElement.parentElement.classList.add('is-active');
});
});
This solution assumes you can use newer versions of JavaScript/ECMAScript. Overall, it makes use of const and arrow functions.
First, we get all elements with the class "button" by using document.querySelectorAll(). Since the result is a NodeList and no array, we convert it using Array.from(). Afterwards, we loop through the array by using Array.prototpye.forEach(). We add an event listener for the "click" event. When a button is clicked, we search for all elements with the "is-active" class and for each one remove it. Finally, we add the "is-active" class to the parent element of the clicked button using Node.prototype.parentElement().
Here is another solution that works in older browsers:
var buttonElements = document.getElementsByClassName('button');
for (var i = 0; i < buttonElements.length; i++) {
buttonElements[i].addEventListener('click', function(event) {
var activeListElements = document.getElementsByClassName('is-active');
for (var i = 0; i < activeListElements.length; i++) {
activeListElements[i].setAttribute('class', '');
}
event.target.parentNode.setAttribute('class', 'is-active');
});
}
This is pretty much the same as the other approach but works with older versions of JavaScript.
Generally, the idea is to focus on an arbitrary sum of elements instead of an array with a specific length. In natural language something like: "Give me all buttons. For every button, add an event listener. When a button is clicked, give me all active list elements and remove their active status. Then, mark the list item above the button as active".
Hope this helps

Change style/class with javascript on keydown

I'm trying to change the style of an element using javascript on a keydown event. I've already done it with mouse clicks like this :
#mpc ul li:active {
background:#844;
And these are the original properties of the element im trying to change:
<div id="mpc">
<div id="wrapper">
<ul>
<li id="kickDrum_p1">1<p>Kick</p></li>
<li id="snareDrum_p2">2<p>Snare</p></li>
<li id="closedHiHat_p3">3<p>ClosHat</p></li>
<li id="openHiHat_p4">4<p>Open HiHat</p></li>
</ul>
</div>
</div>
This is the original css.
#mpc ul li {
background:#999;
}
I'm really new to css/html and javascript and haven't started learning jquery so I prefer doing it all by javascript and css.
The idea is to assign a different key to every list item and when that key is pressed on the page, the list item's background changes, just like I've done the click event. The difference with the click event is I've made it so it doesn't follow the id's since you manually select the list item you want and then it changes it's style.
With key input however I need to specify which list item exactly I'm targeting.
So I think I need to create a new css class with the properties of the background I want the element to change to and using javascript to tell that when I press the 'H' key for example it should change the element's style to that and when I let go of the key to reverse it back to normal. If that makes sense. I do not know how to ahcieve that.
EDIT:
This is how I tried to do it:
var keypress = document.getElementById("kickDrum_p1")[0]
document.addEventListener("keydown", function (e) {
if(e.keyCode == 69) {
var key = e.keyCode
var color = keypress.getElementByClassName("color")
if(color.length !=0 ){
cur = color[0]
cur.className = " "
}
cur.className="color"
}
});
And in the styles I have this:
#mpc ul li.color {
background:#844;
}
<P ID="MyID" CLASS="Testclass">Test</P>
<SCRIPT>
Add here jQuery
$("*").keypress(function(event){
if(event.which==107 || event.which==75){
$("#MyID").attr("class", "newclass");
}
}
</SCRIPT>
BTW: 107 and 57 are the K and the k in the ASCII table.

Jquery to copy first link to second ul and then change class of first link

Short question:
http://jsfiddle.net/wF4FH/2/
What I want is for Page1 to be right above Page2 and Page10 above Page 20 before I change the classes. This should work for any number of elements.
The code provided gives an "Uncaught TypeError: Object # has no method 'append' ".
Long question:
I'm having problem finding the correct way to insert an li element based on the first link. The problem is I cant use id's on my markup so I have to "walk through" each class and check for names. I might just make this a lot more complicated than it is because my first two solutions didn't work the way I thought they would.
html
<ul class="nav">
<li class="active">
Start
</li>
<li class="has-child">
page1
<ul class="">
<li>
page2
</li>
</ul>
</li>
<li class="has-child">
page10
<ul class="">
<li>
page20
</li>
<li>
page30
</li>
</ul>
</li>
javascript
//Copy first link to child ul li
var pageLinks = $("li.has-child > a:first-child");
if (pageLinks != null) {
//var dropdownMenus = $("li.dropdown > a:first-child");
for (var i = 0; i < pageLinks.length; i++) {
for (var x = 0; x < pageLinks.length; x++) {
if (pageLinks[i].innerHTML === pageLinks[x].innerHTML) {
pageLinks[x].childNodes.append(pageLinks[i]);
}
}
}
}
//Change css classes
$("li.has-child").attr('class', 'dropdown');
$(".dropdown ul").addClass("dropdown-menu");
$(".dropdown a").attr("href", "#").addClass("dropdown-toggle").attr('data-toggle', 'dropdown');
strong text
What I want is for Page1 to be right above Page2 and Page10 above Page 20 before I change the classes. This should work for any number of elements.
When they are copied to the inner ul I change the top level menu item to a different class to work as a clickable dropdown men item.
The code provided gives an "Uncaught TypeError: Object # has no method 'append' ".
It is the navigation of a cms I cant change the markup on.
try this:
$links = $('li.has-child').children('a:first-child');
if($links.length > 0){
$links.each(function(i,link){
$(link).next().prepend($('<li></li>').append($(link)))
})
}
http://jsfiddle.net/wF4FH/6/
You need .clone() method to copy elements..
UPDATED
$links = $('li.has-child').children('a:first-child');
if($links.length > 0){
$links.each(function(i,link){
$(link).next().prepend($('<li></li>').append($(link).clone()))
})
}
http://jsfiddle.net/wF4FH/7/
When you have a jQuery object and you access it by numeric index, you're left with an HTML element. So $('body')[0] == document.body. This means that when you access pageLinks[x], you're really getting a raw element. This means that you want pageLinks[x].appendChild(pageLinks[i]);, not pageLinks[x].childNodes.append(pageLinks[i]);

Retaining state of navigation problems

Hi I am trying to retain the state of a navigation accros multiple pages pages.I have managed to get the indexes of each element I want to retain , the problem is setting them.For some reason only some of the elements seem to be set.
I have debugged the code and it seems as if only one element gets taken into consideration sometimes.I can not figure out what am I doing wrong here.Here is my code:
<ul id="ProductNav">
<li>
<h2>#category.Key.ToUpper()</h2>
<ul>
<li>
<img src="#Url.Content("~/Content/Images/arrow.gif")" class="arrow"/>
#Html.ActionLink(subcategory,"Index" , "Products" , new { subcat = subcategory} , null)
</li>
</ul>
</li>
</ul>
......
var menuState = JSON.parse(sessionStorage["navigation"]);
for (var i = 0; i < menuState.length; i++) {
var menuIndex = menuState[i].eq;
$("ul#ProductNav li").eq(menuIndex).children("ul").css("display", "block");
}
menuState will we an object containing an array of indexes
From what I understand so far the problem begins here:
$("ul#ProductNav li").eq(menuIndex).children("ul").css("display", "block");

remove class from current group

The easiest way to see the problem is checking the code here: http://www.studioimbrue.com/beta
What I need to do is once a thumbnail is clicked, to removed the "selected" class from all other thumbnails that are in this same or without removing them from the other galleries on the page. Right now, I have everything working except the class removal. Someone helped me in another question but wasn't quite specific enough (my javascript skills aren't all that great!) I'm using jQuery. Thanks for the help.
Well in that case, I'm not sure why this doesn't work properly:
$(document).ready(function(){
var activeOpacity = 1.0,
inactiveOpacity = 0.6,
fadeTime = 100,
clickedClass = "selected",
thumbs = ".thumbscontainer ul li img";
$(thumbs).fadeTo(1, inactiveOpacity);
$(thumbs).hover(
function(){
$(this).fadeTo(fadeTime, activeOpacity);
},
function(){
// Only fade out if the user hasn't clicked the thumb
if(!$(this).hasClass(clickedClass)) {
$(this).fadeTo(fadeTime, inactiveOpacity);
}
});
$(thumbs).click(function() {
// Remove selected class from any elements other than this
var previous = $(thumbs+'.'+clickedClass).eq();
var clicked = $(this);
if(clicked !== previous) {
previous.removeClass(clickedClass);
}
clicked.addClass(clickedClass).fadeTo(fadeTime, activeOpacity);
});
});
I see you're using jQuery (and have edited your question accordingly).
With jQuery, it's really easy to get a list of matching elements using CSS syntax:
var list = $('#parentId > .selected');
That gets a list of the direct children of the element with the ID "parentId" that have the class "selected". You can then do things with them, such as:
list.removeClass("selected");
Then add "selected" to the element you want to select.
Edit I think this should do it:
$(thumbs).click(function() {
// Remove selected class from any elements other than this
var clicked, previous;
clicked = $(this);
if (!clicked.hasClass(clickedClass)) {
previous = $(thumbs+'.'+clickedClass);
previous.removeClass(clickedClass).fadeTo(fadeTime, inactiveOpacity);
clicked.addClass(clickedClass).fadeTo(fadeTime, activeOpacity);
}
});
I'm assuming there that the "selected" class isn't necessary for the fade effect to look right.
Note how the above will completely ignore the click if the clicked element already has the class. If you don't want that, remove the hasClass check and add .not(clicked) to the end of the previous = $(thumbs+'.'+clickedClass) line, but I don't know what your fade in would do at that point if you've already done it once.
I'm not getting the hover stuff; I thought you wanted this to happen on click, not hover.
You should take a look at
jQuery.removeClass()
So the point would be to first iterate trough all the images and unset the classname and than set the class on the active one.
Use .closest('.jcarousel-clip') to get the parent div,
then find all the thumbnails and use .removeClass('selected').
Hi Andy it isn't clear your question, but I am going to try to help you.
I am trying to help, and my skills on javascript arent that good either, plus I am not sure if I undertood the question right, please, dont vote me down.
function focusme(){
document.getElementById("focusme").focus();
}
function changeToCurrent(obj){
var menucont = document.getElementById('menu');
var arrLink = menucont.getElementsByTagName('a');
for (var i = 0 ; i < arrLink.length; i++){
arrLink[i].className='';
}
obj.className = "current";
}
<div class="menu" id="menu" >
<a href='' id='focusme' onclick='changeToCurrent(this)'>link1</a>
<a href='' onclick='changeToCurrent(this)'>Once Only link2</a>
<a href='' onclick='changeToCurrent(this)'>link3</a>
<a href='' onclick='changeToCurrent(this)'>link4</a>
<a href='' onclick='changeToCurrent(this)'>link5</
link6
</div>
Hope it helps.

Categories

Resources