Nested click event to change element styling - javascript

I'm trying to perform some style changes to list elements. This is what i'm trying to do... I have two lists, one is shopping items, the other is a list that helps manage the shopping items (set priority by changing background color of shopping list item). What i want to do is first click on a shopping item then click on one of the manage items to set some styling. I have something up and running, but it needs some work. One issue is if i go to manage (style) a second item on the list with a different priority, it applies the styling that all items the have been previously styled.
Do the following to see what i mean. Click on Bread, then click on high priority to change the background color of bread to read. Now click on Chips and then click on medium priority to change the background color to black. You'll now see that bread has now changed to black. Not good.
I'm sure the code is bloated, and could probably use some if/else logic instead of using nesting and completely separate function for each styling event. Sorry, posted by another newbie.
here is a fiddle
<div class="the-lst">
<h4>YOUR LIST - Click one of these items first</h4>
<ul id="sortable2" class="connectedSortable">
<li>Bread</li>
<li>Chips</li>
<li>Cookies</li>
</ul>
</div>
<div class="lst-manage">
<h4>MANAGE LIST - Then click one of these items to set priority</h4>
<ul>
<li id="hp">High Priority</li>
<li id="mp">Medium Priority</li>
<li id="lp">Low Priority</li>
<li id="done">Done</li>
<li id="remove">Remove</li>
</ul>
</div>
$(document).ready(function() {
$(".the-lst").on("click", "li", function(event) {
var lst = $(this).closest('li');
$('.lst-manage').on("click", "#hp",function(event) {
lst.css({'background-color': 'red'});
});
});
$(".the-lst").on("click", "li", function(event) {
var lst = $(this).closest('li');
$('.lst-manage').on("click", "#mp",function(event) {
lst.css({'background-color': 'black'});
});
});
$(".the-lst").on("click", "li", function(event) {
var lst = $(this).closest('li');
$('.lst-manage').on("click", "#lp",function(event) {
lst.css({'background-color': 'green'});
});
});
});

I'd reduce it to:
$('#sortable2 li').click(function () {
$('#sortable2 li').removeClass('selected');
$(this).addClass('selected');
})
$('.lst-manage li').click(function () {
if (this.id == "hp") $("#sortable2 li.selected").css('background', 'red')
if (this.id == "mp") $("#sortable2 li.selected").css('background', 'black')
if (this.id == "lp") $("#sortable2 li.selected").css('background', 'green')
})
jsFiddle example

Related

Using a comparison table. Mobile responsive problem when more than one table added?

The comparison table I am using is here:
https://codepen.io/adrianjacob/pen/KdVLXY
When I duplicate the tables and the viewer goes mobile responsive; the buttons are only working for the first table.
Is there any classes or such I can add to the JavaScript and HTML so I can make each group of buttons specific to their table?
Button code:
<ul>
<li class="bg-purple">
<button>Self-Employed</button>
</li>
<li class="bg-blue">
<button>Simple Start</button>
</li>
<li class="bg-blue active">
<button>Essentials</button>
</li>
<li class="bg-blue">
<button>Plus</button>
</li>
JavaScript code:
// DIRTY Responsive pricing table JS
$( "ul" ).on( "click", "li", function() {
var pos = $(this).index()+2;
$("tr").find('td:not(:eq(0))').hide();
$('td:nth-child('+pos+')').css('display','table-cell');
$("tr").find('th:not(:eq(0))').hide();
$('li').removeClass('active');
$(this).addClass('active');
});
// Initialize the media query
var mediaQuery = window.matchMedia('(min-width: 640px)');
// Add a listen event
mediaQuery.addListener(doSomething);
// Function to do something with the media query
function doSomething(mediaQuery) {
if (mediaQuery.matches) {
$('.sep').attr('colspan',5);
} else {
$('.sep').attr('colspan',2);
}
}
// On load
doSomething(mediaQuery);
I'd really appreciate any help, thanks for your time.
The problem is that your jQuery targets are currently too generic, so when you have multiples, it only finds content from the first one and puts it in both. What your script does is update both tables.
I've forked the Codepen, added a second table, and tweaked a couple of values on our comparison table, so you should see different things in each (and each set of tabs acts separately)
https://codepen.io/CapnHammered/pen/QzBbqN
Key part you're missing is some form of parent selector - in this case, we've used an article tag to wrap our table:
$( "ul" ).on("click", "li", function() {
var pos = $(this).index()+2;
$parent = $(this).closest('article');
$parent.find("tr").find('td:not(:eq(0))').hide();
$parent.find('td:nth-child('+pos+')').css('display','table-cell');
$parent.find("tr").find('th:not(:eq(0))').hide();
$parent.find('li').removeClass('active');
$(this).addClass('active');
});
Try this:
$("ul").on("click", "li", function(e) {
var $clicked = $(e.currentTarget); // This will give you the clicked <li>
var $ul = $clicked.parent();
var $table = $ul.next(); // Only works if the table immediately follows the <ul>
var pos = $clicked.index() + 2;
$table.find("tr").find("td:not(:eq(0))").hide();
$table.find("td:nth-child(" + pos + ")").css("display", "table-cell");
$table.find("tr").find("th:not(:eq(0))").hide();
$clicked.siblings().removeClass("active");
$clicked.addClass("active");
});
Basically, when you click a <li> you should search the next table and show/hide the information only on that table. Before you were selecting all <tr> elements so it would affect all tables in the page.
EDIT: after re-reading your question this sentence left me confused:
When I duplicate the tables and the viewer goes mobile responsive; the buttons are only working for the first table.
When I try to duplicate the tables in your codepen the buttons work for both tables, not sure if I'm understanding your problem.

Checking list item hover states to trigger an action - jQuery

I have 4 images in an unordered list. Ideally I want to be able to load all the list items into an array and do a check to see which one is currently hovered.
I know using the jQuery is() function I can check which is in an :hover state. How would I apply this check to all items within that list array?
<ul class="image-list">
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
</ul>
Thanks for any help.
DIM3NSION
Use the mouseover() function:
// Add mouseover event to all your image-items
$('.image-list > .image-item').mouseover(function() {
// $(this) is your hovered image-item object
alert($(this).find('img').attr('src'));
});
Working jsfiddle
Demo: http://jsfiddle.net/GCu2D/758/
JS:
$(function () {
var li = $("ul li"); //get all li. All li are stored in an array.
$(document).on("mouseover", "ul li.image-item", function (e) {
var ele = $(this); //get currently hovered li.
var item = li.index(ele); //get the index of the currently hovered li in that array
console.log(item); //this logs the index. Using this index, do whatever you want with that item.
});
});

Changing the background color of a link after being clicked

I'd like to ask how to change the background color of each link (the rectangular shape surrounding it) to one different color after a link is clicked, and the other links still remain in its original background color.
Each link corresponds to one div placed in the same html file (that I didn't include here).
The point is to let the viewers know which link they are at. By the way, if it is okay I'm looking for the fastest code possible ^_^ (pure css, javascript or jQuery). Appreciate all suggestions!
the highlight only applied to the current link only! (the others will have the normal colors)
<div id="Navigation">
<div id="nav_link">
<ul id="MenuBar" class="MenuBarHorizontal">
<li><a class="MenuBarItemSubmenu" href="javascript:showonlyone('Index_frame');" >Home</a>
<ul>
<li><a href="javascript:showonlyone('Specification_frame');" >Specification</a></li>
<li><a href="javascript:showonlyone('Images_frame');" >Images</a></li>
<li>Video</li>
<li>Contact</li>
</ul>
</li>
<li><a href="javascript:showonlyone('Specification_frame');" >Specification</a></li>
<li><a href="javascript:showonlyone('Images_frame');" >Images</a></li>
<li>Video</li>
<li>Contact</li>
</ul>
</div>
<!--End of nav_link-->
</div>
<!-- End of Navigation-->
function showonlyone(thechosenone) {
$('.newboxes').each(function(index) {
if ($(this).attr("id") == thechosenone) {
$(this).show(1000).fadeIn(500);
}
else {
$(this).hide(1500).fadeOut(500);
}
});
}
EDITED
Guys, there is this one thing that I'm still stuck at even though I spent time on it a lot, I added some more JavaScript links the same with the above in the page with the idea that these new links will be functional just like the former. That is being clicked on ==> the highlight will appear only on these Navigation links. I tried to modify the function from jjurm like this
$(function(){
$("#MenuBar a,#colOne a").bind("click", function(){
var names=$(this).attr('name');
$("#MenuBar a").removeClass("clicked");
$("#MenuBar a[name='names']").addClass("clicked");
});
});
It didn't work and neither did the old ones that used to work
In a similar question to yours I once found out that only changes in text color are allowed some properties can be changed if you use a:visited pseudo-class (UPD: and background-color is one of them). But since your links are javascript links, the :visited selector will not work, hence you cannot do it as a pure CSS solution. You will have to use some kind of javascript. If jQuery is ok, you can try this:
$('a').on('click', function(){$(this).css("background-color","yellow");});
Perhaps you can change the "showonlyone" function? Then you could add the background changing code to it.
You can do this by simple css code:
#MenuBar a:visited {
background: yellow;
}
Edit:
As far as this doesn't work with javascript links (but I haven't tried it), there is other solution with jQuery and CSS.
jQuery code:
$(function(){
$("#MenuBar a").bind("click", function(){
$(this).addClass("clicked");
});
});
CSS:
#MenuBar a.clicked {
background: yellow;
}
Edit2:
Ok, if you want to keep highlighted only last clicked element, it's enough to add this simple line to javascript code:
$(function(){
$("#MenuBar a").bind("click", function(){
$("#MenuBar a").removeClass("clicked"); // Remove all highlights
$(this).addClass("clicked"); // Add the class only for actually clicked element
});
});
Edit3:
If you want to have more links that point to same location and to highlight all of them if one is clicked, follow this:
$(function(){
// Assume that your 'a' elements are in #MenuBar and #colOne
$("#MenuBar a, #colOne a").bind("click", function(){
// Remove all highlights
$("#MenuBar a, #colOne a").removeClass("clicked");
// Store the name attribute
var name = $(this).attr("name");
// Find all elements with given name and highlight them
$("#MenuBar a[name='"+name+"'], #colOne a[name='"+name+"']").addClass("clicked");
});
});
You can add an active class to the clicked anchor. Using live NodeList should work really fast as you also need to unselect previously selected item:
var a = document.getElementById('Navigation').getElementsByClassName('active');
$('#Navigation').on('click', 'a', function() {
if (a[0]) a[0].className = '';
this.className = 'active';
});
http://jsfiddle.net/vBUCJ/
Note: getElementsByClassName is IE9+ if you need to support older versions use jQuery:
var $a = $('#Navigation a');
$('#Navigation').on('click', 'a', function() {
$a.removeClass('active');
$(this).addClass('active');
});
http://jsfiddle.net/vBUCJ/1/
$('#MenuBar').on('click', 'a', function() {
$(this).css('background-color', '#bada55');
});
or if you need unique colors you can use the data-attribute.
$('#MenuBar').on('click', 'a', function() {
var $elem = $(this);
$elem.css('background-color', $elem.data('color'));
});
I'd recommended adding classes instead and using css to define styles.
$('#MenuBar').on('click', 'a', function() {
$(this).addClass('clicked-menu-link');
});
edit:
To remove the other clicks use:
$('#MenuBar').on('click', 'a', function() {
var fancyClass = 'clicked-menu-link';
$('#MenuBar a').removeClass(fancyClass).filter(this).addClass(fancyClass);
});

jQuery UI Sortable on Click

I have the jQuery UI sorting functionality working fine, but I would also like to add in a basic click action to cause the draggable items to change <ul>. I have the <div class="click_area"> disabled from dragging. What I would like is in the first <ul> if the click_area is clicked then the sortable <li> would move to the second <ul> just as if I had dragged it over. Same deal if the click_area is clicked in the second <ul> it will be moved to the first <ul>. I have created a JS Fiddle for testing: http://jsfiddle.net/helpinspireme/wMnsa/
Any suggestions would be greatly appreciated. Thanks.
$("#unassigned_list, #recipients_list").sortable({
connectWith: ".connected_sortable",
items: "li",
handle: ".draggable_area",
stop: function(event, ui) {
updateLi(ui.item);
}
}).disableSelection().on("click", ".click_area", function() {
// First figure out which list the clicked element is NOT in...
var otherUL = $("#unassigned_list, #recipients_list").not($(this).closest("ul"));
var li = $(this).closest("li");
// Move the li to the other list. prependTo() can also be used instead of appendTo().
li.detach().appendTo(otherUL);
// Finally, switch the class on the li, and change the arrow's direction.
updateLi(li);
});
function updateLi(li) {
var clickArea = li.find(".click_area");
if (li.closest("ul").is("#recipients_list")) {
li.removeClass("ui-state-default").addClass("ui-state-highlight");
clickArea.html('←');
} else {
li.removeClass("ui-state-highlight").addClass("ui-state-default");
clickArea.html('→');
}
}
​
Here is a starting place for you,
.on('click', '.click_area', function(){
$(this).parent().appendTo($("#unassigned, recipients").not($(this).closest("ul")));
})
The trick being that the click handler is on the parent container not the individual children, so when they are moved you don't need to keep managing their handlers.
All you need to do is update the stylings.
jsFiddle

how to addClass and removeClass in an anchor

What I want is when I click an anchor it will add a class.
My markup:
<ul>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
Say If I clicked the class="promo-call" it will add class active-call and when I clicked promo-text, it will add class active-text.
Just to be clear on what's on my mind:
E.g:
When clicked promo-call
When clicked promo-text
When clicked promo-data
And so on...
Also when an anchor is active the rest must be inactive, will return to their original class.
I have this code right now:
Just a trial and error. For now I'm just playing the two anchor: class: promo-call & promo-text. What's odd is I have to click twice the button for the background image to show.
jQuery(document).delegate(".promo-call","click",function(e){
jQuery(".promo-text").removeClass("active-text");
jQuery(".promo-call").addClass("active-call");
});
jQuery(document).delegate(".promo-text","click",function(e){
jQuery(".promo-text").addClass("active-text");
jQuery(".promo-call").removeClass("active-call");
});
FYI: I'm using Jquery-Mobile.
try this:
var promobtt = $('a[class^="promo"]');
promobtt.on('click', function(evt) {
evt.preventDefault();
promobtt.removeClass('active-text active-data active-call ...');
$(this).addClass(this.className.replace(/^promo/, "active"));
});
Note that here promobtt.removeClass('active-text active-data active-call ...'); you have to list all active classes you need to use.
Otherwise you should provide one unique "active" class (e.g. active) instead of <n> different active classes: if you're doing this only for a matter of styling you could style you links anyway with one class doing like so.
.promo-text { ... }
.promo-text.active { ... }
.promo-data { ... }
.promo-data.active { ... }
and so on. This would simplify both css code and javascript code because following this way you would only need a toggleClass('.active') applied to all links.
$('a[class^="promo"]').on('click', function() {
$.each('a[class^="promo"]', function() {
$(this).attr('class','');
});
var currentClass = $(this).attr('class');
if(currentClass)
{
var startClass = string.split('-');
if(startClass.length > 1)
{
$(this).toggleClass('active-' + startClass[1]);
}
}
});
Note that this will only work for single-classed elements as in your example.
With .toggleClass("promo-call") you can get this result

Categories

Resources