How to pass value in key value pair jquery? - javascript

I want to pass(return) data-filter value and children text , I am able to pass the data-filter value but I am unable to pass the children text. My HTML and JQuery as following:
$(document).ready(function() {
$('.sidebar-filter').on('click', function() {
var filterobj = {};
$(".sidebar-filter").each(function(index, ele) {
var filterval = $(this).children('a').text();
var filterkey = $(this).data('filter');
filterobj[filterkey] = Array.from(document.querySelectorAll('li[data-filter=' + filterkey + '].active')).map(function(el) {
return ele.value;
});
});
console.log(filterobj);
});
});
<ul>
<li class="sidebar-filter " data-filter="category" data-value="1">
Item Name
</li>
</ul>
My return will be like:
category: Array [ undefined ]
I want value inside the array instead of undefined.

Your lis don't have attribute value, actually you want to read attribute data-value, you can achieve your goal by converting return ele.value; to return el.getAttribute('data-value');
$(document).ready(function() {
$('.sidebar-filter').on('click', function() {
var filterobj = {};
$(".sidebar-filter").each(function(index, ele) {
var filterval = $(this).children('a').text();
var filterkey = $(this).data('filter');
filterobj[filterkey] = Array.from(document.querySelectorAll('li[data-filter=' + filterkey + '].active')).map(function(el) {
return el.getAttribute("data-value");
});
});
console.log(filterobj);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<ul>
<li class="sidebar-filter active" data-filter="category" data-value="1">
Item Name
</li>
</ul>

Posting answer, might be of help to someone others too
filterobj[filterkey]= Array.from(document.querySelectorAll
('li[data-filter=' + filterkey+'].active')).map(function(el){
return $(el).data("value")
});

Related

Loop through elements that start with 'req-' in Jquery

I have multiple <ul>-s which has attributes id, data-type and data-value. All id-s have a same prefix.
<ul id='req-*****' data-type='***' data-value='***'>
some <li>-s here
</ul>
. . .
many <ul>-s here
. . .
I have Javascript function where I want to loop through this <ul>-s whose ids starting with 'req' and collect data-type and data-value attribute values like that:
function collect(){
var data = [];
$.each( uls_starting_with_req, function( key, value ) {
data.push({data_type: 'ul_data_type', data_value: 'ul_data_value'});
});
}
So how can I achieve this?
function collect(){
var data = [];
$('ul').each(function(){
var id = $(this).attr('id');
if(id.startsWith('req') ) {
var dataType = $(this).data('type');
var dataValue = $(this).data('value');
data.push({data_type: dataType, data_value: dataValue})
}
})
}
Following is a way to do it:
var data = [];
$("ul[id^='req-']").each(function() {
data.push({ data_type: $(this).data('type'), data_value: $(this).data('value') });
});
The selector selects all the uls which have ID starting with req- and then each loops on them. In each iteration, the value of the data attributes can be fetched using jQuery's data method, which are then pushed to the array data.
Working example:
var data = [];
$("ul[id^='req-']").each(function() {
data.push({
data_type: $(this).data('type'),
data_value: $(this).data('value')
});
});
console.log(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='req-1' data-type='1' data-value='1'>
<li></li>
</ul>
<ul id='req-2' data-type='2' data-value='2'>
<li></li>
</ul>
<ul id='req-3' data-type='3' data-value='3'>
<li></li>
</ul>
using attribute starts with selector:
function collect(){
var data = [];
$('ul[id^="req-"]').each(function(){
data.push({data_type: '+ $(this).data("type") +', data_value: '+ $(this).data("value") +'});
})
}
Use jquery attribute selector
function collect() {
var data = [];
var getUL = $('ul[id^="req-"]');
$.each(getUL, function(key, value) {
data.push({
data_type: $(value).data('type'),
data_value: $(value).data('value')
});
});
console.log(data)
}
collect()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='req-1' data-type='x' data-value='y'></ul>
<ul id='somOtherId' data-type='x2' data-value='y2'></ul>
<ul id='req-3' data-type='x3' data-value='y3'></ul>
Modified brk's answer to use map off of the jQuery object
function collect() {
var getUL = $('ul[id^="req-"]');
var data = getUL.map(function(key, value) {
return {
data_type: $(value).data('type'),
data_value: $(value).data('value')
};
});
console.log(data.get())
}
collect()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='req-1' data-type='x' data-value='y'></ul>
<ul id='somOtherId' data-type='x2' data-value='y2'></ul>
<ul id='req-3' data-type='x3' data-value='y3'></ul>
jQuery is relevant if you have to deal with browsers different implementations/incompatibilities or if what you would like to achieve is quite verbose using vanilla JavaScript.
But if you target recent browsers, you should consider vanilla JavaScript instead since the required code in this case looks pretty the same.
function collect() {
return Array.prototype.slice.call(document.querySelectorAll('ul[id^="req-"]'))
.map(function(x) {
return {data_type: '+ '+x.dataset.type+' +', data_value: '+ '+x.dataset.value+' +'}
});
}
// ES6 version
function collectES6() {
return Array.from(document.querySelectorAll('ul[id^="req-"]'), x => {
return {data_type: `+ ${x.dataset.type} +`, data_value: `+ ${x.dataset.value} +`}
});
}
console.log('Vanilla version (JavaScript 1.6):', collect());
console.log('Es6 version', collectES6());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="req-x" data-type="XX" data-value="xxvalue"></ul>
<ul id="req-y" data-type="YY" data-value="ffvalue"></ul>
<ul id="req-z" data-type="ZZ" data-value="zzvalue"></ul>

Get attribute of all list items and add them to input

I have a list like this:
<ul class="draggable">
<li data-bullet="1"> item 1</li>
<li data-bullet="2"> item 2</li>
<li data-bullet="3"> item 3</li>
</ul>
Using javascript, how do I grab all the list item attributes data-bullet and insert them into the value of an input (separated by a comma):
<input id="insertme" type="hidden" name="bullet" value="">
So the end result will be:
<input id="insertme" type="hidden" name="bullet" value="1,2,3">
I know how to get individual list items but can't get my head around how to get them all and insert them there.
Here you go, A pure javascript solution
Try to use dataset at this context,
var res = "";
[].forEach.bind(document.querySelectorAll(
'.draggable > li[data-bullet]'),function(itm, i){
res += ((i) ? ":" : "") + itm.dataset.bullet;
})();
document.getElementById("insertme").value = res;
DEMO
Or the less complex and a readable version would be,
var elemArray = Array.from(document.querySelectorAll('.draggable > li[data-bullet]')),
res ="";
elemArray.forEach(function(){
res += ((i) ? ":" : "") + itm.dataset.bullet;
});
document.getElementById("insertme").value = res;
As per your new requirement, you can accomplish your task by,
$("button").click(function() {
var parent = $(this).parent();
parent.closest(".draggable").next(":text").val(parent.siblings("li").addBack().map(function(){
return $(this).data("bullet")
}).get().join(":"));
});
DEMO
try
var allBullets = [];
$(".draggable li").each(function(){
allBullets.push($(this).attr("data-bullet"));
});
$("#insertme").val(allBullets.join(","));
If you can use querySelectorAll to find elements and then map it using getAttribute method. For example (ES6 syntax):
const items = document.querySelectorAll('.draggable li');
const result = [...items].map(el => el.getAttribute('data-bullet')).join();
document.getElementById('insertme').value = result;
ES5 analogy:
var items = document.querySelectorAll('.draggable li');
var result = [].slice.call(items).map(function(el) {
return el.getAttribute('data-bullet');
}).join();
document.getElementById('insertme').value = result;

Partial Matches data attribute

I'm using this category filter that exactly matches data attribute product-collection__categoryof the items and the selectors. But I want it a partial or lazy match only. For example, if the selector contains "cats", it will still include items that have "cat","category" etc. I have tried if (categories[i] *= cat) but it's wrong.
Fiddle
HTML
<div class="product-collection">
<ul>
<li class="product-collection__selector
product-collection__selector--active"
data-product-collection__category="">All</li>
<li class="product-collection__selector"
data-product-collection__category="cat1">Category 1</li>
<li class="product-collection__selector"
data-product-collection__category="cat2">Category 2</li>
</ul>
<ul>
<li class="product-collection__item"
data-product-collection__category="cat1">Item 1 [cat 1]</li>
<li class="product-collection__item"
data-product-collection__category="cat2">Item 2 [cat 2]</li>
<li class="product-collection__item"
data-product-collection__category="cat1 cat2">Item 3 [cat 1, cat 2]</li>
</ul>
</div>
Code
$(function() {
$('.product-collection').each(function() {
var $collection = $(this);
var $selectors = $collection.find('.product-collection__selector,.filterselect__selector');
var $items = $collection.find('.product-collection__item');
$selectors.click(function() {
var $selector = $(this);
var cat = $selector.data('product-collection__category');
$selectors.change(function() {
var $selector = $(this);
var cat = $selector.find('option:selected').data('product-collection__category');
$selectors.removeClass('filterselect__selector--active');
$selector.addClass('filterselect__selector--active'); });
if (cat) {
var containsCategory = function(data) {
var categories = data.split(/\s+/);
for (var i = 0; i < categories.length; i++)
if (categories[i] == cat)
return true;
return false;
};
}
else {
$items.fadeIn();
}
});
});
});
I simplified the fiddle so that you could see the selector and test in action - http://jsfiddle.net/cYFLe/64/
$('li').each(function() {
// test the data attribute for partial
if( $(this).is('[data-product-collection__category*="cat"]') ) {
console.log( $(this).text() );
}
});
http://api.jquery.com/is/ is the difference here, it allows the test of the category for truthiness.

Filter LIs with text input - nested LIs not showing?

I am trying to filter a UL for specific LIs with a keyup text input. Problem is, the LIs are nested within a tree, and the filter only sees the top most LI and doesn't appear to be filtering correctly. Typing Pennsylvania should show ONLY Pennsylvania, and nothing above it. Any ideas? Thanks in advance.
http://www.jsfiddle.net/CDAVZ/412
HTML
<input type='text' value='[Enter search term followed by Return]' class='allW treeSearch' />
<ul id="treeview">
<li data-expanded="true"><span class="icon-location-7 md-moon delBlue treeSpace" data-icon=""></span>
<span class="icon-location-7 md-moon white treeSpace" data-icon=""></span>Root
<ul>
<li data-expanded="true"><span class="icon-stack-6 md-moon delLtBlue treeSpace" data-icon=""></span>
<span class="icon-stack-6 md-moon white treeSpace" data-icon=""></span>Gas Model
<ul>
<li data-expanded="true"><span class="glyphicon glyphicon-globe md-moon delGreen treeSpace"></span>
<span class="glyphicon glyphicon-globe md-moon white treeSpace"></span>United States
<ul>
<li data-expanded="true"><span class="icon-pie md-moon delBlue treeSpace" data-icon=""></span>
<span class="icon-pie md-moon white treeSpace" data-icon=""></span>Pennsylvania
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
jQuery
$('.treeSearch').click(function(){
$(this).val('');
});
$('.treeSearch').keyup(function(){
var searchText = $(this).val();
$('#treeview ul').each(function(){
var currentLiText = $(this).text(),
showCurrentLi = currentLiText.indexOf(searchText) !== -1;
$(this).toggle(showCurrentLi);
});
});
if you do not want to change the html you can change .toggle() for .css("visibility")
$('.treeSearch').click(function(){
$(this).val('');
});
$('.treeSearch').keyup(function(){
var searchText = $(this).val();
$('#treeview li').contents().filter(function() {
return this.nodeType == 3;
}).each(function(){
var currentLiText = $(this).text();
if(currentLiText.replace(/\s+/g, '')!=""){
if(currentLiText.indexOf(searchText) !== -1){
$(this).parent("li").css({"visibility": "visible"});
}
else{
$(this).parent("li").css({"visibility": "hidden"});
}
}
});
});
http://jsfiddle.net/HLWMv/1/
this will only show the actual "li"
to remove the if(currentLiText.replace(/\s+/g, '')!=""){ part you need to remove the extra spaces and new lines in your html
UPDATE
case insensitive
$('.treeSearch').click(function(){
$(this).val('');
});
$('.treeSearch').keyup(function(){
var searchText = $(this).val();
$('#treeview li').contents().filter(function() {
return this.nodeType == 3;
}).each(function(){
var currentLiText = $(this).text().toLowerCase();
if(currentLiText.indexOf(searchText.toLowerCase()) !== -1){
$(this).parent("li").css({"visibility": "visible"});
}
else{
$(this).parent("li").css({"visibility": "hidden"});
}
});
});
http://jsfiddle.net/HLWMv/2/
I removed the spaces in the HTML
Note: This make extensive dom manipulations.... please beware about the cost associated with it
From what I can understand, you need to make dom structure changes to achieve this
$('.treeSearch').click(function () {
$(this).val('');
});
RegExp.quote = function (str) {
return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
};
$('#treeview li').each(function () {
var $this = $(this);
var text = $this.contents().map(function () {
return this.nodeType == 3 && $.trim($(this).text()) != '' ? $.trim($(this).text()) : undefined;
}).get().join(' ');
$this.data('parent', $this.parent()).data('text', text);
})
$('.treeSearch').keyup(function () {
var regex = new RegExp(RegExp.quote(this.value), 'i');
var $selected = $('#treeview li').removeClass('selected').hide().filter(function () {
return regex.test($(this).data('text'));
}).addClass('selected').show();
$selected.each(function () {
var $this = $(this),
$parent = $this.parent(),
$ul = $this.data('parent');
var $li = $this;
while ($ul.is(':not(#treeview)') && !$ul.parent().hasClass('selected')) {
$li = $ul.parent();
$ul = $li.parent();
}
$this.appendTo($ul)
})
});

Matching Checkboxes By Value

I have a list of checkboxes, I'm trying to check these based on the value of a textbox.
var codes = $('#textbox1').val().split(','); // this contains [ "Dept1" and "Dept2" ]
var allDeptChecks = $('.Dept-help input:checkbox'); // this contains all of my checkboxes
allDeptChecks.attr('checked', false);
$.each(codes, function() {
var chkDept = allDeptChecks.find("[value='"+this+"']"); // no matter what I try, this selector matches 0 elements
chkDept.attr('checked', true);
});
<li title="Dept 1">
<input type="checkbox" name="chkDept1" value="Dept1">
<span>Dept1</span>
<span>Description Numero Uno</span>
</li>
<li title="Dept 2">
<input type="checkbox" name="chkDept2" value="Dept2">
<span>Dept2</span>
<span>Description Numero Dos</span>
</li>
Shouldn't this work?
EDIT: Here's a JSFiddle
Here you go
$('#lnkGo').click(function () {
var codes = $('#textbox1').val().split(','); // this contains [ "Dept1" and "Dept2" ]
var allDeptChecks = $('input:checkbox'); // this contains all of my checkboxes
allDeptChecks.prop('checked', false);
$.each(codes, function () {
var chkDept = allDeptChecks.filter("input[value='" + this + "']"); // no matter what I try, this selector matches 0 elements
chkDept.prop('checked', true);
});
});
Try this :
$.each(codes, function(i, value) {
$("input[value='"+value+"']").prop('checked', true);
});

Categories

Resources