jquery append where trigger is bigger then - javascript

I'm trying to append child to listing but what I want to do is to append it in the place ordering by data-price.
my template:
<ul>
<li data-price="18"></li>
<li data-price="27"></li>
<li data-price="28"></li>
<li data-price="31"></li>
<li data-price="99"></li>
<li data-price="101"></li>
<li data-price="191"></li>
</ul>
my js what I've tried so far:
var template = '<li data-price="100"></li>';
$('ul').find('li').filter(function() {
return $(this).attr("data-price") > 99;
}).after(template);
so if the price is 100 it should be appended by price ordering and in this case where price is greater then 99 but less then 101, but i dont have any working solution for that.

I'm not sure if this is the best way to do it and if it'll always work, but it works for your question. Try it out
var template = '<li data-price="100">100</li>';
var checkPrice = $(template).attr("data-price");
var appendBefore = $('ul li').filter(function(){
return parseInt($(this).attr("data-price")) > checkPrice-1;
})[0];
console.log(appendBefore);
$(appendBefore).before(template);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-price="18">18</li>
<li data-price="27">27</li>
<li data-price="28">28</li>
<li data-price="31">31</li>
<li data-price="99">99</li>
<li data-price="101">101</li>
<li data-price="191">191</li>
</ul>

check if that is what you need:
https://jsfiddle.net/3er0da9c/
var template = '<li data-price="100"></li>';
var itemValue = parseInt($(template).attr('data-price')); //Getting value that we should compare
var value, smaller = 0, smallerItem; //We will need those variables to know where to place our "template"
smallerItem = $('ul > li:first-of-type'); //Set the smaller item in our list to be the first one. Change that if your list wont be always asc sorted
$('ul > li').each(function(){ //run through the given list
value = parseInt($(this).attr('data-price'));
if ((itemValue == value) || ( itemValue > value )){ //if the actual item is equal, put our item right after it. If the item is smaller then our number, we save it and keep running
smaller = value;
smallerItem = $(this);
}
});
if (smaller != 0) //This will happens when we have at least one item smaller then our number
smallerItem.after(template);
else
smallerItem.before(template); //else, we add our number at top

Related

How to createElement of list/images in separate rows?

So below I have the HTML code that is part of my draggable/droppable:
Drag from here:
<ul id="sortable1" class="dropBox connectedSortable">
<li class="ui-state-default">Word 1</li>
<li class="ui-state-default">Word 2</li>
<li class="ui-state-default">Word 3</li>
<li class="ui-state-default">Word 4</li>
</ul>
Drop a word onto each iamge: <br>
<ul class = "row">
<li id="drop1" class="dropZones images"><img src="image1.jpg"></li>
<li id="drop2" class="dropZones images"><img src="image2.jpg"></li>
</ul>
<ul class = "row">
<li id="drop_zone3" class="dropZones images"><img src="image3.jpg"></li>
<li id="drop_zone4" class="dropZones images"><img src="image4.jpg"></li>
</ul>
</div>
I am trying to create this using document.createElement() etc. But am having difficulty doing this efficiently.
The purpose of the rows (in above code) are for formatting (using bootstrap4), since there are 6 pictures total in my array, and I want 2 rows of 3.
Below, I have an array that holds all the images' src's. This array is passed into the function. I'm able to create one row/ul, with all of the li's/images inside. But I want to be able to create what I have above, with as little hard coding as possible and as efficiently as possible.
I have:
function createType3(arr)
{
var count = 0;
var length = arr.length;
var list = document.createElement("ul");
list.classList.add("row");
for (var i = 0; i < length; i++)
{
//create list and associated ids and classes
var listPiece=document.createElement("li");
listPiece.classList.add("dropZones","images","list-inline");
listPiece.setAttribute("id","dropZone");
//create image tags and append
var imageSRC = document.createElement("IMG");
imageSRC.setAttribute("src",arr[i]);
listPiece.appendChild(imageSRC);
list.appendChild(listPiece);
}
return list;
}
I'm having trouble doing this, thank you.
You could create a document fragment and add list elements to it. Create a new list whenever i % 3 is zero. Make that 3 an argument so that you can use the function also for lists of any other number of entries:
function createType(arr, groupSize = 3) {
var lists = document.createDocumentFragment(),
list;
for (var i = 0; i < arr.length; i++) {
if (i % groupSize === 0) {
list = document.createElement("ul");
list.classList.add("row");
lists.appendChild(list);
}
//create list and associated ids and classes
var listPiece = document.createElement("li");
listPiece.classList.add("dropZones","images","list-inline");
listPiece.setAttribute("id","dropZone");
//create image tags and append
var imageSRC = document.createElement("IMG");
imageSRC.setAttribute("src", arr[i]);
listPiece.appendChild(imageSRC);
list.appendChild(listPiece);
}
return lists;
}
You could call it like this:
var frag = createType(["img1.png","img2.png","img3.png","img4.png"], 3);
document.body.appendChild(frag); // add it somewhere in your HTML page

How to loop through an array and find matches with the values in the array

I have 2 sets of arrays which their value is grabbed by data-attribute(data-product-name), 1 is the whole list of available item, another 1 is selected item, for selected item they are attached to a country.
<!-- the item list -->
<div class="whole_list">
<ul>
<li data-product-name="a">item A<button>ATTACH</button></li>
<li data-product-name="b">item B<button>ATTACH</button></li>
<li data-product-name="c">item C<button>ATTACH</button></li>
<li data-product-name="d">item D<button>ATTACH</button></li>
<li data-product-name="e">item E<button>ATTACH</button></li>
</ul>
</div>
<!-- selected item block -->
<div class="selected_item_container">
<ul class="selected_items">
<li data-product-name="a">item A</li>
<li data-product-name="b">item B</li>
<li data-product-name="e">item E</li>
</ul>
<button class="edit_country">EDIT</button>
</div>
$('.edit_country').on('click', function () {
// to grab text/string from .whole_list data-product-name
var productName = []; // product name
$('.whole_list li').each(function (index) {
productName .push($(this).data('product-name'));
});
// to grab text/string from .selected_item_container data-product-name
var selProductName = []; // selected product name
$('.selected_item_container').find('[data-product-name]').each(function () {
selProductName .push($(this).data('product-name'));
});
// if the string/text matches, change the button text
$('.whole_list li').each(function (index) {
if ($(this).data('product-name') === arrProductName[index]) {
$(this).find('button').text('DETACH');
} else {
$(this).find('button').text('ATTACH');
}
});
});
Ideally is when user click on edit_country button, the .whole_list already have those selected item button changed to DETACH text. I tried, but the problem is, it only change the item A & item B button, item E button no changes.
I think it got to do with the indexing mismatch. I'm not sure, please advise, thanks.
Demo site
Use .indexOf to find if a value exists in an array.
Like this:
arrProductName.indexOf( $(this).data('product-name') ) != -1
Because, using $(this).data('product-name') === arrProductName[index]...
If your array is like:
var arrProductName = ["a","c","d"];
a will be found at index 0,
b will not be found,
c wil NOT be found at index 2... It is d,
d wil NOT be found at index 3... It is undefined,
e will not be found.
See it in CodePen.
Try the code below
$('.edit_country').on('click', function() {
// to grab text/string from .whole_list data-product-name
var productName = []; // product name
$('.whole_list li').each(function(index) {
productName.push($(this).data('product-name'));
});
// to grab text/string from .selected_item_container data-product-name
var selProductName = []; // selected product name
$('.selected_item_container').find('[data-product-name]').each(function() {
selProductName.push($(this).data('product-name'));
});
$(selProductName).each(function(index) {
$('.whole_list li[data-product-name=' + selProductName[index] + ']').find('button').text('DETACH');
});
});

jQuery filter to select first two and then next two

I have the following list:
<li class="list one" data-number="2"></li>
<li class="list one" data-number="2"></li>
<li class="list two" data-number="3"></li>
<li class="list two" data-number="7"></li>
And I need to pass each value from data-number attribute to a variable based on the list class.
I have these functions for that:
var list_one = 0;
var list_two = 0;
$(".one").each(function (i, val) {
var number = $(this).data('number')
list_one = list_one + parseInt(number); // Gives 4
});
$(".two").each(function (i, val) {
var number = $(this).data('number')
list_two = list_two + parseInt(number); // Gives 10
});
But as the list grows, this becomes a long and messy code. What's the best way to get the values from the first two li, and then the two next, etc and pass the sum to the variable?
The list will always have this structure, so I don't need to concider that the number of lis with each class will vary.
You can obtain an object of summed values:
var result = {};
$('.list').each(function(idx, ele) {
var key = ele.classList.toString().replace(/ /g, '_');
result[key] = (+result[key] || 0) + +ele.dataset["number"];
});
console.log(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="list one" data-number="2">one</li>
<li class="list one" data-number="2">one</li>
<li class="list two" data-number="3">two</li>
<li class="list two" data-number="7">tow</li>
</ul>
I believe this will work, it saves a sum of every two numbers. So if you have 20 elements, listValues will have a length of 10
var listValues = [];
$('li.list').each(function(i, val){
if (i % 2 == 0) {
listValues[] = parseInt($(this).data('number'));
} else {
listValues[listValues.length - 1] += parseInt($(this).data('number'));
}
});

jQuery find data attributes with one datakey and multiple values

I want to retrive all the objects with one datakey and multiple values, for QuickSand:
<ul>
<li data-company="Microsoft">Steve</li>
<li data-company="Google">Jobs</li>
<li data-company ="Facebook">Michael</li>
<li data-company ="Google">Richard</li>
<li data-company ="Facebook">Tim</li>
</ul>
How can i retreve all the li items with data-company Microsoft and Google (these two values are in a array) like this:
var itemes = $('ul').find('li[data-comapany={"Microsoft","Google"}]');
Thank you.
you could create an array of the required companies, and check for each li if the data is contained in that array:
var companies = ["Microsoft", "Google"];
$(function() {
var items = $('ul li').filter(function() {
return $.inArray($(this).data("company"), companies) > -1;
});
items.css({
"position": "relative",
"margin-left": "25px"
});
console.log(items);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-company="Microsoft">Steve</li>
<li data-company="Google">Jobs</li>
<li data-company="Facebook">Michael</li>
<li data-company="Google">Richard</li>
<li data-company="Facebook">Tim</li>
</ul>
You could filter it:
var itemes = $('ul').find('li').filter(function(){
return $(this).data('company').match(/Microsoft|Google/);
});
-DEMO-
To handle case for LI without any data-company set, you should use:
var itemes = $('ul').find('li').filter(function(){
var data = $(this).data('company');
return data ? data.match(/Microsoft|Google/) : null;
});
You can also combine selectors:
var items = $("[data-company*='Microsoft'], [data-company*='Google']");
jsFiddle
You could do it like this:
var companies = ['Google', 'Microsoft', 'Waffle House'];
companies.forEach(function(company, index) {
companies[index] = "li[data-company='" + company + "']";
});
$('ul').find(companies.join(',')).css('background', 'red');

js select hours for each day of the week

I am allowing a user to select hours for each day of the week through the use of lists. Visually the lists are just boxes with 1am, 2am, 3am, etc inside them and when clicked are highlighted to show they are 'selected'. To do this I add a class of 'hour-selected' to the li item.
I also need to keep track of what hours the user has clicked for each day (those with class 'hour-selected'. I know this logic works as I have used this code before, but only for one day. In this example, I need to show all days on the same page.
With a few changes to my original code I came up with this, but I feel there must be some optimization I could do to prevent the repeating js used to push selected hours in for each day, but I am out of ideas and thoughts to do this...
html : (this would repeat for each day of the week with id different for day)
<ol id="hour-select-mon" class="clearfix">
<li class="">12am</li>
<li class="">1am</li>
<li class="">2am</li>
<li class="">3am</li>
<li class="">4am</li>
<li class="">5am</li>
<li class="">6am</li>
<li class="">7am</li>
<li class="">8am</li>
<li class="">9am</li>
<li class="">10am</li>
<li class="">11am</li>
<li class="">12pm</li>
<li class="">1pm</li>
<li class="">2pm</li>
<li class="">3pm</li>
<li class="">4pm</li>
<li class="">5pm</li>
<li class="">6pm</li>
<li class="">7pm</li>
<li class="">8pm</li>
<li class="">9pm</li>
<li class="">10pm</li>
<li class="">11pm</li>
</ol>
JS :
$('#hour-select-mon li, #hour-select-tue li, #hour-select-wed li, #hour-select-thu li, #hour-select-fri li, #hour-select-sat li, #hour-select-sun li').on('click', function() {
$(this).toggleClass('hour-selected');
});
// get selected hours in array
var monHours = var tueHours = var wedHours = var thuHours = var friHours = var satHours = var sunHours = [];
$('#hour-select-mon .hour-selected').each(function(k,v) {
monHours.push($(v).text());
});
$('#hour-select-tue .hour-selected').each(function(k,v) {
tueHours.push($(v).text());
});
$('#hour-select-wed .hour-selected').each(function(k,v) {
wedHours.push($(v).text());
});
$('#hour-select-thu .hour-selected').each(function(k,v) {
thuHours.push($(v).text());
});
$('#hour-select-fri .hour-selected').each(function(k,v) {
friHours.push($(v).text());
});
$('#hour-select-sat .hour-selected').each(function(k,v) {
satHours.push($(v).text());
});
$('#hour-select-sun .hour-selected').each(function(k,v) {
sunHours.push($(v).text());
});
Or if you want to collect all selected items at once you may use a code similar to this:
var selected = {};
$('.hour-selected').each(function(k,v) {
var day = $(v).parent().attr('id').substr(-3, 3);
selected[day] = selected[day] || [];
selected[day].push($(v).text());
});
Try this
var selectedHours = {};
$('ol > li').on('click', function() {
var li = $(this);
li.toggleClass('hour-selected');
var parentId = $(this).parent().attr("id");
selectedHours[parentId] ? selectedHours[parentId].push(li.text()) : selectedHours[parentId] = [li.text()]
});
selectedHours will have the following structure
{
"hour-select-mon" : ["4pm", "6pm"],
"hour-select-tue" : ["9am"],
...
}

Categories

Resources