Move elements with jquery based on data attr with appendTo - html

What I need is that, when loading the site, move the li element into the ul element based on the datta attr. I did it, but for some reason, it doesn't work.
<li class="classeul_name" data-nivelpai="BR04ZJCTF000">Nivel 1</li>
<li class="classeul_name" data-nivelpai="BR055XCTF003">Nivel 2</li>
<ul data-geral1="BR04ZJCTF000">
</ul>
<ul data-geral1="BR055XCTF003">
</ul>
jQuery
$(window).on("load", function(){
// Joga o nĂ­vel 2
liName = $('.classeul_name').data('nivelpai');
$('li[data-nivelpai="'+liName+'"]').appendTo($('ul[data-geral1="'+liName+'"]'));
});

Instead on window load event you need to use the dom ready event:
$(function () { .... });
Moreover you need to loop on elements (i.e. .each()) and append() element.
The snippet:
$('.classeul_name').each(function(idx, ele) {
var newPlace = '[data-geral1="' + ele.dataset.nivelpai + '"]';
$(newPlace).append(ele)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="classeul_name" data-nivelpai="BR04ZJCTF000">Nivel 1</li>
<li class="classeul_name" data-nivelpai="BR055XCTF003">Nivel 2</li>
<ul data-geral1="BR04ZJCTF000">
</ul>
<ul data-geral1="BR055XCTF003">
</ul>

Putting li out of ul isn't valid HTML. I think it is better to do this work in server side. However you need to loop through every li and append it to relevant ul.
$(function(){
$('.classeul_name').each(function(){
$(this).appendTo($('ul[data-geral1="'+$(this).data('nivelpai')+'"]'));
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="classeul_name" data-nivelpai="BR04ZJCTF000">Nivel 1</li>
<li class="classeul_name" data-nivelpai="BR055XCTF003">Nivel 2</li>
<ul data-geral1="BR04ZJCTF000">
</ul>
<ul data-geral1="BR055XCTF003">
</ul>
Also you can use .append() instead
$(function(){
$('ul[data-geral1]').append(function(){
return $('li[data-nivelpai="'+$(this).data('geral1')+'"]')
})
})

Related

Cant expand second level of menu

Im a jquery noob and I cant figure out how to get the next level expanding in a clickable accordion like menu.
Here is the fiddle:
https://jsfiddle.net/hinterseer/gaxm6uqo/29/
Html
<div class="navbar-collapse">
<ul class="nav">
<li class="subMenu">Archive <span class="caret toggle">+</span>
<ul class="subMenu-link">
<li>Test 1</li>
<li>Test 2</li>
</ul>
</li>
<li class="subMenu"> Archive 2 <span class="caret toggle">+</span>
<ul class="subMenu-link">
<li class="subMenu">Archive 3 <span class="caret toggle">+</span>
<ul class="subMenu-link">
<li>Test 3</li>
<li>Test 4</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
css
.subMenu-link {
display: none;
}
.subMenu {
list-style: none;
}
jQyery
(function($) {
$("li.subMenu").unbind().click(function () {
var slideDown = $(this).find(".toggle").text() == "+" ? false : true;
$(".subMenu-link").slideUp();
$(".toggle").text('+');
if (!slideDown) {
$(this).find('.subMenu-link').slideDown();
$(this).find('.toggle').text('-');
}
});
})(jQuery);
I've refactored things a bit further to enable toggling of each list item and their children independently. I've listed the changes below:
change the listener to $(".toggle").on('click', function() {...
change slideDown to const and modify selector $(this).find(".caret:first")...
use .siblings() for slide up/down functionality, $(this).siblings(".subMenu-link").slideUp()
restructure HTML to wrap li text in its own span so that the text triggers the toggle instead of the whole element (and its children)
add cursor: pointer to .toggle for visual cue to user indicating click
Saw this and thought I'd give things a shot even if it was more than asked.
(function($) {
$(".toggle").on('click', function() {
const slideDown = $(this).find(".caret:first").text() == "+" ? false : true;
$(this).siblings(".subMenu-link").slideUp();
$(this).find(".caret").text('+');
if (!slideDown) {
$(this).siblings('.subMenu-link').slideDown();
$(this).find('.caret').text('-');
}
});
})(jQuery);
.subMenu-link {
display: none;
}
.subMenu {
list-style: none;
}
.toggle {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navbar-collapse">
<ul class="nav">
<li class="subMenu"><span class="toggle">Archive <span class="caret">+</span></span>
<ul class="subMenu-link">
<li>Test 1</li>
<li>Test 2</li>
</ul>
</li>
<li class="subMenu"><span class="toggle">Archive 2 <span class="caret">+</span></span>
<ul class="subMenu-link">
<li class="subMenu"><span class="toggle">Archive 3 <span class="caret">+</span></span>
<ul class="subMenu-link">
<li>Test 3</li>
<li>Test 4</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Just add :first in this line:
var slideDown = $(this).find(".toggle:first").text() == "+" ? false : true;

How can I add value of data attribute in another div?

I have a div like this:
<div class="configurator-item">
<ul>
<li class="banner-list-img" data-price="122"></li>
</ul>
</div>
Inside this div I have added another div using jQuery:
Here's the jQuery:
jQuery('li.banner-list-img').prepend(jQuery('<div class="show-price"> </div>'));
After I run this jQuery a div is added:
<div class="configurator-item">
<ul>
<li class="banner-list-img" data-price="122">
<div class="show-price"> </div>
</li>
</ul>
</div>
Now I'm trying to get the value of data-price attribute to show inside the div(with class show-price with this jQuery:
jQuery('.banner-list-img').each(function() {
var itemprice = jQuery(this).text();
jQuery('.show-price').html(itemprice);
})
But this is not working. It should show something like this:
<div class="configurator-item">
<ul>
<li class="banner-list-img" data-price="122">
<div class="show-price"> 122 </div>
</li>
</ul>
</div>
How can I do like this.
You could use jQuery.data() to get the data attribute and .find() to only update the element with show-price class which is descendant:
jQuery('li.banner-list-img[data-price]').prepend(jQuery('<div class="show-price"> </div>'));
jQuery('.banner-list-img[data-price]').each(function() {
jQuery(this).find('.show-price').html(jQuery(this).data('price'));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="configurator-item">
<ul>
<li class="banner-list-img" data-price="122"></li>
<li class="banner-list-img" data-price="123"></li>
<li class="banner-list-img" data-price="124"></li>
<li class="banner-list-img"></li>
</ul>
</div>
And this could be improved doing the prepend with the data value all in one go:
jQuery('.banner-list-img[data-price]').each(function() {
jQuery(this).prepend(jQuery('<div class="show-price">' + jQuery(this).data('price') + '</div>'));
})
.banner-list-img[data-price="0"] .show-price {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="configurator-item">
<ul>
<li class="banner-list-img" data-price="122"></li>
<li class="banner-list-img" data-price="123"></li>
<li class="banner-list-img" data-price="124"></li>
<li class="banner-list-img"></li>
<li class="banner-list-img" data-price="0"></li>
</ul>
</div>
You can use simply this code
$(".button").click(function(){
alert("Value: " + $(".show-price").val());
});
You this in click event is referring to button only.
So you have to do something like this
jQuery('.button').click(function() {
var itemprice = jQuery('.banner-list-img').attr('data-price');
jQuery('.show-price').html(itemprice);
})
Above code only works for one li element. If there are multiple li elements you should use this code
jQuery('.button').click(function() {
jQuery('.banner-list-img').each(function() {
var itemprice = jQuery(this).attr('data-price');
jQuery(this).children('.show-price').html(itemprice);
})
})
After updating question
jQuery('.banner-list-img').each(function() {
var itemprice = jQuery(this).attr('data-price');
jQuery(this).children('.show-price').html(itemprice);
})
Or more better way for your example
jQuery('.banner-list-img').each(function() {
jQuery(this).prepend('<div class="show-price">' + jQuery(this).attr('data-price') + '</div>');
})
Here we are adding HTML when prepending div inside li

CSS Nested lists items and alternate background

I am searching for a way to have list items have alternating background colors. When there is a nested list the items keep alternating but the child is indented without having the background color of the parent flow down to its nested children.
It is not possible to apply classes. Also the amount of items is variable. Preferably it should work for an infinite amount of nested lists. But if that is not possible a cap on 3 depths (as in picture) should be enough. If it is easier to do by using divs instead of li and ul, that is also possible for me. I prefer pure HTML/CSS.
Because all my experiments did no good I can only supply a JSFiddle with the nested lists.
https://jsfiddle.net/qmdwpzt8/1/
<ul>
<li>Item 1
<ul>
<li>Item 1-1</li>
<li>Item 1-2
<ul>
<li>Item 1-2-1</li>
<li>Item 1-2-2</li>
</ul>
</li>
<li>Item 1-3</li>
</ul>
</li>
<li>Item 2
<ul>
<li>Item 2-1
<ul>
<li>Item 2-1-1</li>
</ul>
</li>
</ul>
</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Here is one potential solution: https://jsfiddle.net/qmdwpzt8/3/
Not sure if all your requirements will be met by it, but I updated your list with div's:
<ul>
<li><div>Item 1</div>
<ul>
<li><div>Item 1-1</div></li>
<li><div>Item 1-2</div>
<ul>
<li><div>Item 1-2-1</div></li>
<li><div>Item 1-2-2</div></li>
</ul>
</li>
<li><div>Item 1-3</div></li>
</ul>
</li>
<li><div>Item 2</div>
<ul>
<li><div>Item 2-1</div>
<ul>
<li><div>Item 2-1-1</div></li>
</ul>
</li>
</ul>
</li>
<li><div>Item 3</div></li>
<li><div>Item 4</div></li>
</ul>
And then add background colors with jQuery:
$( document ).ready(function() {
var b = true;
$( "div" ).each(function( index ) {
b = !b;
if (b) {
$(this).css("background-color", "#ff0000");
} else {
$(this).css("background-color", "#00ff00");
}
});
});
This does depend on jQuery/Javascript.

having 2 different styles for ui-state-default and ui-selected

at the moment, i am using the selectable JQUERY function
<style>
#selectable .ui-selecting { background: #FECA40; }
#selectable .ui-selected { background: #F39814; color: white; }
</style>
<ol id="selectable">
<li class="ui-widget-content">Item 1</li>
<li class="ui-widget-content">Item 2</li>
<li class="ui-widget-content">Item 3</li>
<li class="ui-widget-content">Item 4</li>
<li class="ui-widget-content">Item 5</li>
<li class="ui-widget-content">Item 6</li>
<li class="ui-widget-content">Item 7</li>
</ol>
but for some reason, when i select an element, the color will not change to bright orange but revert to the default gray of ui-state-default like below:
But if I go to the Chrome debugger and uncheck the background in ui-state-default in the style section, it works perfectly.
Is it because of this snippet:
var nodes = document.getElementById('selectable').getElementsByClassName('ui-widget-content');
if (nodes.length > 0)
{
nodes[0].innerHTML = getSymbol();
nodes[0].setAttribute("class", "ui-state-default");
}
How do i go around this problem, such that when i click on the element of interest, the color will change like i specified in the <style> tag.
With jQuery, this is quite simple.
$('.ui-widget-content') will select all of your LI elements. (alternately you could use $('#selectable li'))
$('.ui-widget-content').click(function() {
$(.'ui-widget-content').removeClass('.ui-state-default'); <-- this clears previous selections
$(this).addClass('.ui-state-default'); <-- this adds the class to the clicked item
})

Select inner HTML item in CSS

How can I use CSS selectors to apply a style only to the inner item in a list. Example:
HTML fragment:
<ul class="list">
<li>Item 1</li>
<li>
<ul class="list">
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>
<ul class="list">
<li>Subitem 1.1</li>
</ul>
</li>
</ul>
</li>
</ul>
CSS fragment:
ul.list {
border: 1px solid red;
}
What I need is to have a border only arround the "Subitem 1.1" string. The list is generated and it's not possible to add an extra class or id and as the list has no fixed depth it's not an option to specify an "ul > ul > ul.list" or similar selector.
I believe you cannot do this with only CSS if it is not possible to use an Id or unique class. In this case I think jQuery is the way to go:
$("li").children().eq( $("li").children().length - 1 ).
css('border', '1px solid red');
The idea is to use eq() to pinpoint the deepest child.
Hope this helps
it's not an option to specify an "ul > ul > ul.list" or similar selector.
Why not? This, or adding a class, is the solution.
You've basically specified a requirement to identify an element, then rejected all the approaches that you could use to do so.
<html>
<head>
<style type="text/css">
li.list {
border: 1px solid red;
}
</style>
</head>
<body>
<ul >
<li>Item 1</li>
<li>
<ul >
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>
<ul >
<li class="list">Subitem 1.1</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
</html>
I Hope This ma help you..
JoseSantos is correct in that it can't be done with pure CSS. Here's how I'd do it in jQuery:
$("ul").each(function(){
if ($(this).find("ul").length == 0)
$(this).addClass("list");
});