JS / jQuery - Extend Var in each()-function - javascript

I have two lists in this format:
<ul id="filters" class="option-set button-group" data-filter-group="kategorie">
<li>
Corporate Design
</li>
<li>
Webdesign
</li>
</ul>
In Javascript there is a click-function which addes or removes the class "isotopeactive" to the link-element:
$('#filters a').click(function(){
var $this = $(this);
if ( $this.hasClass('isotopeactive') ) {
$this.removeClass('isotopeactive');
}else{
$this.addClass('isotopeactive');
}
The problem is to get all the data-filter - data from all elements that are "isotopeactive" into one variable. My first try was this, but it does not work..
var filterValue = '';
var i = 0;
$( ".isotopeactive" ).each(function() {
filterValue += $this.attr('data-filter');
i++;
});
In the end i want to get something like this:
filterValue => ".corporatedesign .webdesign"
Any suggestions? Thanks! :)

I'd suggest:
var data = $('.isotopeactive').map(function(){
return this.dataset.filter;
}).get();
For those, older, browsers that don't implement dataset:
var data = $('.isotopeactive').map(function(){
return this.getAttribute('data-filter');
}).get();
Or:
var data = $('.isotopeactive').map(function(){
return $(this).data('filter');
}).get();
This will return an array of values to the data variable.
References:
JavaScript:
Element.getAttribute().
HTMLElement.dataset.
jQuery:
data().
get().
map().

Related

Find the index of an element in an array created by toArray in JS/JQuery

I have a bunch of spans of class = "change" and each has a unique id. I created an array of those spans using:
var changesArray = $('.change').toArray()
I want to be able to get the index of the span in the array when I click on it. I tried:
$('.change').click(function(){
var thisChange = $(this).attr('id');
var thisChangeIndex = $.inArray(thisChange,changesArray);
});
But all I get is -1 for every .change I click on.
I'm a bit of a newbie with this type of code. Help?
The toArray method says
Retrieve all the elements contained in the jQuery set, as an array.
You are looking for a particular id in the array - that will never work.
If you want the index of the item you can use .index()
$('.change').click(function(){
var thisChangeIndex = $('.change').index(this);
console.log(thisChangeIndex);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span class="change">change1</span>
<span class="change">change2</span>
<span class="change">change3</span>
<span class="change">change4</span>
</div>
<div>
<span class="change">change5</span>
<span class="change">change6</span>
<span class="change">change7</span>
<span class="change">change8</span>
</div>
You should keep a plain array of the unique ID's only:
var changesArrayIds = $('.change').toArray().map(function(x) { return x.id; });
Then this line should work fine:
var thisChangeIndex = $.inArray(thisChange, changesArrayIds);
If you insist on using .toArray that works http://codepen.io/8odoros/pen/JKWxqz
var changesArray = $('.change').toArray();
$('.change').click(function(){
var thisChange = $(this).attr('id');
var thisChangeIndex = -1;
$.each( changesArray, function( i, val ) {
if( thisChange==val.id) thisChangeIndex= i;
});
console.log(thisChangeIndex);
});
When you call toArray, you get an array of all the DOM nodes, not the jquery objects. You can search on this instead of $(this):
var changesArray = $('.change').click(function(){
var thisChangeIndex = $.inArray(this,changesArray);
}).toArray();

Convert list of HTML element into Javascript list of object

I'm trying to convert something like this HTML snippet:
<ul>
<li><span>Frank</span><img src="pic.jpg"></li>
<li><span>Steve</span><img src="pic2.jpg"></li>
</ul>
into a JavaScript objects that contain the name and the image's url. How can I do that?
Use map() method
var res = $('ul li').map(function() { // select all li and iterate
// return as required format of array elemnt
return {
name: $('span', this).text(), // get text in span
src: $('img', this).attr('src') // get src attribute
}
}).get(); // get array from jquery object
console.log(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
UPDATE : If you want to generate an object which has key as span text and value as src attribute then use each() method and iterate over elements and generate object.
var res = {};
$('ul li').each(function() { // select all li and iterate
res[$('span', this).text().trim()] = $('img', this).attr('src');
})
console.log(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
var objs = document.querySelectorAll('.to-js-obj li');
var objs_arr = [];
if (objs) {
for (var i = 0; i < objs.length; i++) {
var name = objs[i].querySelector('span').innerText;
var url = objs[i].querySelector('img').src;
objs_arr.push({
name: name,
src: url
});
}
console.log(JSON.stringify(objs_arr));
}
<ul class="to-js-obj">
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
Using jQuery
var $list = $('ul'), // get the list (ideally, add an ID)
$listItems = $list.find('li'); // find list items
if( $listItems.length > 0 ) { // if list items exist
var images = []; // create empty array to store objects
$.each( $listItems, function( index ) { // loop through the list items
var $item = $( $listItems[index] ); // save item as jQuery element
var name = $item.find('span').text(); // Get name from span
var imageSrc = $item.find('img').attr('src'); // Get img src
images[index] = {}; // Create new object in array
images[index].name = name; // Add name
images[index].imageSrc = imageSrc; // Add source
});
}
Returns
[Object {
imageSrc: "pic.jpg",
name: "Frank"
}, Object {
imageSrc: "pic2.jpg",
name: "Steve"
}]
You can use this:
var image_pairs = [];
$("ul li").each(function() {
image_pairs.push({
name: $(this).find("span").text(),
url: $(this).find("img").attr("src")
});
});
console.log(image_pairs);
<ul>
<li><span>Frank</span><img src="pic.jpg"></li>
<li><span>Steve</span><img src="pic2.jpg"></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

data-plugin-options filter is not working

I'm using this JessicaWhite free webtemplate (http://www.html5xcss3.com/2014/02/jessicawhite-responsive-html5-theme.html). I'm trying to set a filter in my image portfolio in order to show images of defined filter by default and not all images.
I've tried many things (data-plugin-options='{"filter": ".category01")'), but no luck.
HTML:
<ul id="filters" class="option-set" data-option-key="filter" data-plugin-options='{"filter": ".category01"}'>
<li>All</li>
<li>Category01</li>
<li>Category02</li>
</ul>
I have also tried to switch ' for " within the data-plugin-options, but no luck.
Here is the JS for "option-set":
/* SORTING */
$(function(){
var $container = $('.projects');
$container.isotope({
itemSelector : '.element'
});
var $optionSets = $('#options .option-set'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('.option-set');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
// parse 'false' as false boolean
value = value === 'false' ? false : value;
options[ key ] = value;
if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {
// changes in layout modes need extra logic
changeLayoutMode( $this, options )
} else {
// otherwise, apply new options
$container.isotope( options );
}
return false;
});
});
Per the below comments, try the following:
Remove the 'data-category' attribute from your portfolio items, it's not being used.
Change your 'filter buttons' markup to the following -
<ul id="filters">
<li><a class="filter-button" href="#filter" data-filter="*" class="btn btn-mini">All</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category01" class="btn btn-mini selected">Category01</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category02" class="btn btn-mini">Category02</a></li>
</ul>
Comment out the entire "sorting" JS function and replace with this -
var $projects = $('.projects').isotope({
filter: '.category 01'
});
$('.filter-button').on( 'click', function() {
var filteredVal = $(this).attr('data-filter');
$projects.isotope({ filter: filteredVal });
$('.filter-button.selected').removeClass('selected');
$(this).addClass('selected');
});

How could I get the text and href value in HTML and then set them to values & labels in autocompelte of JQuery UI

Currently I get this
JS
$(function() {
$("#nav-list123").fadeOut();
$('input').autocomplete({
source: function(req, response) {
var re = $.ui.autocomplete.escapeRegex(req.term);
var matcher = new RegExp( "^" + re, "i" );
var sources = $('.search').select ('li');
response($.grep(sources.text(), function(item){return matcher.test(item.label); }) );
},
select: function(event, ui) {
$('#state_id').val(ui.item.label);
$('#abbrev').val(ui.item.value);
}
});});
within this html
<div><form class="form-search"><input id="autocomplete" type="text"/></form>
<div id="nav-list123">
<ul class="search">
<li> Kitchen Visions</li>
<li> Full Name</li>
<li> Job B</li>
</ul>
</div>
I want to get the elements attributes in the <li>, i tried using .text() or .html() to get text, but I do not know how to convert these attributes to label and value in autocomplete function from JQuery UI to get the match elements.
Could anyone help me? Thanks
You should store the value & href of ul li into an javascript array on page load
& pass this array in autocomplete source
var arr = new Array();
$('ul > li').each(function(){
var temp_obj = {
label:$(this).children('a').attr('href'),
value:$(this).children('a').text().trim()
}
arr.push(temp_obj);
});
//Pass this array in autocomplete source
$('input').autocomplete({
focus: function( event, ui ) {
$( "#your_id" ).val( ui.item.value );
return false;
},
source: arr
});

What is the best way in jQuery to wrap elements based on its data attribute?

Given the following structure:
<ul>
<li data-conference="Conference1" >Spain</li>
<li data-conference="Conference1" >France</li>
<li data-conference="Conference1" >Germany</li>
<li data-conference="Conference1" >Italy</li>
<li data-conference="Conference2" >Austria</li>
<li data-conference="Conference2" >Poland</li>
<li data-conference="Conference3" >Russia</li>
<li data-conference="Conference3" >USA</li>
<li data-conference="Conference3" >China</li>
</ul>
what is the best way (with jQuery), considering performance, to rearrange this into this:
<ul>
<li>Spain</li>
<li>France</li>
<li>Germany</li>
<li>Italy</li>
</ul>
<ul>
<li>Austria</li>
<li>Poland</li>
</ul>
<ul>
<li>Russia</li>
<li>USA</li>
<li>China</li>
</ul>
Thanks!
I think the overall question (group elements by attribute) is good, you just should have put more effort into trying to solve it yourself.
Anyways, grouping elements by an attribute is quite simple. You can create an attribute value -> [element, ...] map, which can be done with an object:
var groups = {};
$('li[data-city]').each(function() {
var attr = $(this).attr('data-city'),
group = groups[attr];
if(!group) {
group = groups[attr] = [];
}
group.push(this);
});
Now you have a collection of lists of DOM elements. You can iterate over the collection and create the HTML lists accordingly.
For example:
for(var group in groups) {
var $list = $('<ul />');
$list.append(groups[group]);
// now append $list somewhere
}
Have a look at Working with Objects [MDN] to get more information about how to process objects.
It's also trivial to do this without jQuery, as long as you have references to the elements, for example as a NodeList. Instead of using .each you can then use a "normal" for loop to iterate that list.
Unless you have a insane amount of cities in those lists I wouldn't worry about performance. The only performance consideration I would take is to avoid repaint / reflows by minimizing writing to the DOM. I think code clarity is much more important in this use case.
That being said I'd implement this with something like this - http://jsfiddle.net/XWufy/.
Here you go:
(function () {
var $list = $( '#list' );
var lists = {};
var $newLists = $();
$list.children().each( function () {
var city = $( this ).data( 'city' );
if ( !lists[ city ] ) lists[ city ] = [];
lists[ city ].push( this );
});
$.each( lists, function ( city, items ) {
var $newList = $( '<ul />' ).append( items );
$newLists = $newLists.add( $newList );
});
$list.replaceWith( $newLists );
}());
Live demo: http://jsfiddle.net/rjt9W/6/
Btw, the code assumes that the list has an ID of "list". Replace the selector in this line
var $list = $( ... );
so that it properly selects your UL element.
Use the data attribute as an object property to sort them, then loop over them to construct the new html. this should get you started:
var list = {};
// for each item
list[item.data('city')] = item.text();
// for each property of list
var ul = $('<ul>');
// for each listItem in current list
var li = $('<li>').text(listItem);
ul.append(li);
try this:
<ul id="first"></ul>// you can create the ul tags by using JavaScript
$("li").each(function(){
data = $(this).attr("data");
if (data == "Conference1") {
txt = $(this).text();
$("<li>" + txt + "</li>").appendTo("ul#first");
}
})
Try this:
var list = [];
var $div = $('#my_container_div');
$('li[data-city]').each(function() {
var $this = $(this), data = $this.attr('data-city');
list[ data ] = list[ data ] || [];
list[ data ].push( $this.text() );
});
for(var data in list) {
var $ul = $div.append('<ul/>');
for(var li in list[data]) {
$ul.append('<li>' + list[data][li] + '</li>');
}
}

Categories