Get children under a parent using jQuery - javascript

$(document).ready(function() {
$.ajax({
type: "POST",
url: 'some/url',
data: {
'name':'myname'
},
success: function (result) {
var result = ["student", "test"];
var length = result.length;
for (var i = 0; i < length; i++) {
var datastores = result;
$('#data_stores').append(
"<div class='col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore' id=" + datastores[i] + "> </div>");
}
}
})
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
$('<pre>').appendTo('body').text(JSON.stringify(ids));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data_stores">
</div>
<div id="data_stores">
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="students">
//Some other codes here
</div>
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="teachers">
//Some other codes here
</div>
</div>
This is a block of code in my HTML. The inner divs under data_stores are created using jquery. The IDs of the children div were result of an AJAX request and assigned on success.
The problem is, I need the ID values of the children divs to use for another AJAX call.
I ran the following:
console.log($("#data_stores"));
Output I got is the same above.
But for,
console.log($("#data_stores").find('.datastore'));
[prevObject: m.fn.init[1], context: document, selector: "#data_stores
.datstore"]
But, when accessing the child it says the element is undefined.
I need to do both AJAX calls on
$(document).ready(function() {
})

Using children like this works:
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
$('<pre>').appendTo('body').text(JSON.stringify(ids));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data_stores">
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="students">
//Some other codes here
</div>
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="teachers">
//Some other codes here
</div>
</div>

Related

Algolia - Refactor code for multiple indices search with autocomplete.js

I'm looking to bridge multiple indices leveraging autocomplete.js. I found this tutorial very helpful. My issue is what happens when I have a lot more that two indices to search?
Currently in our project we'll have over 30 different indices that will need to be searched. Obviously, simply copy 'n paste code over-and-over again is horrible thing to do, but I can't figure out any other way to make this work then just doing that.
Is there another way of doing things that would normalize my code?
Here is an example of it. Just imagine that there are another 28 indices in this example. You can see that it's out of control quickly.
A working JSFiddle can be found here
var client = algoliasearch('9G2RUKPPGE', '8860a74c330efaf0119818fcdd800126');
var SPR = client.initIndex('dev-SPR');
var SWG_SPR = client.initIndex('dev-SWG_SPR');
//initialize autocomplete on search input (ID selector must match)
$('#aa-search-input').autocomplete({ hint: false }, [
{
source: $.fn.autocomplete.sources.hits(SPR, {
hitsPerPage: 15
}),
displayKey: 'name',
//hash of templates used when rendering dataset
templates: {
//'suggestion' templating function used to render a single suggestion
suggestion: function(suggestion) {
const markup = `
<div class="row">
<div class="col-xs-1 col-sm-1 col-md-1 nopadding">
<img src="${suggestion.image}" alt="" class="algolia-thumb">
</div>
<div class="col-xs-11 col-sm-11 col-md-11">
<div class="row">
<div class="col-xs-6 col-sm-8 col-md-8">
<span>${suggestion._highlightResult.code.value}</span>
</div>
<div class="col-xs-6 col-sm-4 col-md-4">
<span>Available Qty: ${suggestion.quantityAvailable.toLocaleString()}</span>
</div>
</div>
<div class="row hidden-xs">
<div class="col">
<span>${suggestion.description}</span>
</div>
</div>
</div>
</div>`;
return '<div class="algolia-result">' + markup + '</div>';
},
empty: function(options) {
return '<div class="algolia-result"><span>No results were found with your current selection.</span></div>';
},
}
},
{
source: $.fn.autocomplete.sources.hits(SWG_SPR, {
hitsPerPage: 15
}),
displayKey: 'name',
//hash of templates used when rendering dataset
templates: {
//'suggestion' templating function used to render a single suggestion
suggestion: function(suggestion) {
const markup = `
<div class="row">
<div class="col-xs-1 col-sm-1 col-md-1 nopadding">
<img src="${suggestion.image}" alt="" class="algolia-thumb">
</div>
<div class="col-xs-11 col-sm-11 col-md-11">
<div class="row">
<div class="col-xs-6 col-sm-8 col-md-8">
<span>${suggestion._highlightResult.code.value}</span>
</div>
<div class="col-xs-6 col-sm-4 col-md-4">
<span>Available Qty: ${suggestion.quantityAvailable.toLocaleString()}</span>
</div>
</div>
<div class="row hidden-xs">
<div class="col">
<span>${suggestion.description}</span>
</div>
</div>
</div>
</div>`;
return '<div class="algolia-result">' + markup + '</div>';
},
empty: function(options) {
return '<div class="algolia-result"><span>No results were found with your current selection.</span></div>';
},
}
}
]).on('autocomplete:selected', function(event, suggestion, dataset) {
window.location.href = window.location.origin + '/' + suggestion.url
});
This line:
$('#aa-search-input').autocomplete({ hint: false }, [] ...
last parameter is an array. Why can't you have a function which given array of the client indexes would do all these client.initIndex('dev-SPR') and then generate an array with all of the objects you have to deal with now?
Call that function with ['dev-SPR','dev-SWG_SPR' ...]
So you end up with:
`$('#aa-search-input').autocomplete({ hint: false }, myNewFn(['dev-SPR','dev-SWG_SPR']))`
Unless something else is different in those objects other than the client indexes ...

Sort elements based on specific classname

I'm trying to order the div based on the col-md-x. First col-md-4 and then col-md-8. I tried the sort function of jQuery in this variant:
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className > b.className;
}
$('.container').append(divElement);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row different col-md-8 left">col-md-8</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 left">col-md-4</div>
<div class="row different col-md-8 left">col-md-8</div>
However this is not sorting on my .col-md-x class but is he sorting on all classes (I think). How could I sort specific on the class col-md-x? I tried also .pop() and .split(), but this is not working in combination with the jQuery .sort() function.
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className.match(/col-md-(\d)/)[1] - b.className.match(/col-md-(\d)/)[1];
}
$('.container').append(divElement);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<dic class="container">
<div class="row different col-md-8 left">1</div>
<div class="row different col-md-4 right">2</div>
<div class="row different col-md-4 right">3</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">5</div>
</div>
You may want to write a function that will return the needed class name by it beginning col-md-
$(function() {
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return getColMdClassName(a) > getColMdClassName(b);
}
$('.container').append(divElement);
});
function getColMdClassName(obj) {
return $.grep(obj.className.split(" "), function(v, i){
return v.indexOf('col-md-') === 0;
}).join();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<div class="row different col-md-8 left">8</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">8</div>
</div>
You are comparing text in sort function but need to compare integers. see below function
$(function(){
var divElement = $('.container').find('.row').sort(sortMe);
$('.container').append(divElement);
});
function sortMe(a, b) {
var aInt = getInteger(a.className);
var bInt = getInteger(b.className);
return aInt > bInt;
}
function getInteger(classNameList)
{
var int = 0;
var classList = classNameList.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
if (classList[i].indexOf('col-md')!=-1) {
int = parseInt(classList[i].replace('col-md-',''));
}
}
return int;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row different col-md-8 left">8</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">8</div>
</div>
Pure js variant:
var divs = document.getElementById('divs');
var map = arr => fn => Array.prototype.map.call(arr, fn);
var getN = str => str.substr(str.indexOf('col-md-'), 8).substr(-1);
var res = map(divs.children)(x => x).sort((a, b) => getN(a.className) - getN(b.className));
res.forEach((el, i) => divs.replaceChild(el, divs.childNodes[i]))
<div id="divs">
<div class="row different col-md-8 left">col-md-8</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 left">col-md-4</div>
<div class="row different col-md-8 left">col-md-8</div>
</div>
The accepted answer is not working for me on Chrome, please check this old fiddle.
But we can enhance the answer:
HTML (no changes)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<dic class="container">
<div class="row different col-md-8 left">1</div>
<div class="row different col-md-4 right">2</div>
<div class="row different col-md-4 right">3</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">5</div>
</div>
JavaScript (small changes):
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className.match(/col-md-(\d)/)[1] - b.className.match(/col-md-(\d)/)[1];
}
$('.container').append(divElement);
The new fiddle is here.

Converting HTML element to Int returning NaN Javascript

I am attempting to make a player health counter, however I am still getting NaN returned.. Help
Here is my HTML
<!--player 1 hp-->
<div class="row">
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
And my JavaScript
function healthCountUp1(){
var player1HP = parseInt(document.getElementById("play1HP").value);
var add = player1HP + 1;
document.getElementById("play1HP").innerHTML = player1HP;
}
You need innerHTML and not value. This is happening because the h2 element has not an attribute called value. So when you read the value of the h2 you get undefined and when you pass undefined to the parseInt you get NaN.
var player1HP = parseInt(document.getElementById("play1HP").innerHTML);
h2 element doesn't have value property, so parseInt will return NaN. You need to use innerHTML or textContent to get value. Also you need to update with variable add.
function healthCountUp1() {
var player1HP = parseInt(document.getElementById("play1HP").innerHTML);
var add = player1HP + 1;
document.getElementById("play1HP").innerHTML = add;
}
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
function healthCountUp1() {
var player1HP = parseInt(document.getElementById("play1HP").textContent);
var add = player1HP + 1;
document.getElementById("play1HP").textContent = add;
}
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
you had better make variable to store health value in:
<div class="row">
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
javascript:
var health = 0;
function healthCountUp1(){
health++;
document.getElementById("play1HP").innerHTML = health;
}

array_chunk in Javascript, after Appending a big chunk using ForLoop

(In edit part at the bottom, I have included my code that I got closest)
Explanation:
I have an ajax post, which fetches data from controller. On success, I have a for loop for each post:
success: function(data) {
var posts = data['data'];
var postsCount = data['per_page'];
var frag = document.createDocumentFragment();
for(i=0; i < postsCount; i++){
frag.appendChild(postElem(posts));
}
document.getElementById('content').appendChild(frag);
}
I also have another function function postElement() which creates eachPost div, appends the child divs into eachPost and returns it
function postElem(posts){
var eachPost = document.createElement('div');
eachPost.className = "col-md-4 eachPost";
//and a big chunk of code that finally appends into `eachPost`.
return eachPost;
}
This works perfectly until here
The structure I got working in html, and also want to achieve in javascript looks like this:
<div id="content">
#foreach (array_chunk($posts->all(), 3) as $row)
<div class="row eachRow">
#foreach($row as $post)
<div class="col-md-3 eachPost">
<!-- rest of the code -->
After some research, I figured out I can achieve array_chunk like this:
var n,j,tempArray,chunk = 3;
for (n=0,j=posts.length; n<j; n+=chunk) {
tempArray = posts.slice(n,n+chunk);
// my other `for`.
}
However, whatever I tried, I couldn't figure out how I can achieve what I achieved in html. I couldn't import eachRow bit in javascript. What is the way of doing it? Is it because of the document.createDocumentFragment() bit?
Edit: What I tried, that fails what I want to achieve:
success: function(data) {
var posts = data['data'];
var postsCount = data['per_page'];
var frag = document.createDocumentFragment();
var eachRow = document.createDocumentFragment();
var n,j,tempArray,chunk = 3;
for (n=0,j=posts.length; n<j; n+=chunk) {
tempArray = posts.slice(n,n+chunk);
for(i=0; i < tempArray.length; i++){
frag.appendChild(postElem(tempArray));
}
var eachRow = document.createElement('div');
eachRow.className = "row eachRow";
eachRow.appendChild(frag);
}
document.getElementById('content').appendChild(eachRow);
}
In this part, it appends the stuff in frag. It creates a div. (See bottom for the view:source)
This creates a post inside each row, and it's like a straight line of posts, instead of 3 posts in 1 row.
What I want to achieve
<div class="row eachRow">
<div class="eachPost>_</div>
<div class="eachPost>_</div>
<div class="eachPost>_</div>
</div>
<div class="row eachRow">
<div class="eachPost>_</div>
<div class="eachPost>_</div>
<div class="eachPost>_</div>
</div>
The code at the top is producing:
<div class="row eachRow">_</div>
<div class="row eachRow">_</div>
<!-- for each bit -->
<div class="eachPost>_</div>
<div class="eachPost>_</div>
<div class="eachPost>_</div>
Code in edit part is producing:
<div class="row eachRow">
<div class="eachPost>_</div>
</div>
<div class="row eachRow">
<div class="eachPost>_</div>
</div>
<div class="row eachRow">
<div class="eachPost>_</div>
</div>

Javascript/Jquery: issue with append in cycle

I get Flickr gallery via API/Json. My issue with my code is that the gallery that I fetch has ~ 30 picture, but this snippet:
$.each(data.album.content,function (index,content)
{
album_container.append(column);
[...]
}
Appends only one <div> to the container, and not 30, but appends in right way 30 a/img to this unique column. I cannot figure why and how solve it.
Thank you for your help!
var album_container = $('div#album');
function callGetAjax(url)
{
return $.get(url,{});
}
function getAlbum(feed_url)
{
callGetAjax(absolute_path+'/feed/'+feed_url)
.success(function(data)
{
})
.error(function(xhr, statusText)
{//console.log(statusText);
})
.done(function(data)
{
var loaded = 0;
album_title = data.album.album_title;
$('h1#gallery-title').html(album_title);
var column = $('<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2"></div>');
$.each(data.album.content,function (index,content)
{
album_container.append(column);
$('<a/>')
.append($('<img class="img-responsive">').prop('src', content.photo))
.prop('href', content.target)
.prop('title', content.title)
.attr('data-gallery', '')
.appendTo(column)
.colorbox({rel:'gallery', speed:0, maxWidth:'95%', maxHeight:'95%'});
});
});
}
Current HTML result:
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2">
<img src="..." />
<img src="..." />
<img src="..." />
[...]
</div>
HTML that I need:
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2">
<img src="..." />
</div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2">
<img src="..." />
</div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2">
<img src="..." />
</div>
[...]
Remember that .append() will move the HTML node around the DOM tree when the node already exists in your document. In your case, you have declared:
var column = $('<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2"></div>')
…outside of your $.each() loop, therefore causing it to be repeatedly moved around inside album_container, instead of being cloned as you have expected. Therefore, what you would do is to declare it within your loop, such that the instance is not outside the scope of your loop:
var album_container = $('div#album');
function callGetAjax(url)
{
return $.get(url,{});
}
function getAlbum(feed_url)
{
callGetAjax(absolute_path+'/feed/'+feed_url)
.success(function(data)
{
})
.error(function(xhr, statusText)
{//console.log(statusText);
})
.done(function(data)
{
var loaded = 0;
album_title = data.album.album_title;
$('h1#gallery-title').html(album_title);
$.each(data.album.content,function (index,content)
{
// Creates a new column for every image element
var column = $('<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2"></div>'),
item = $('<a/>')
.append($('<img class="img-responsive">').attr('src', content.photo))
.attr('href', content.target)
.attr('title', content.title)
.attr('data-gallery', '')
.appendTo(column)
.colorbox({rel:'gallery', speed:0, maxWidth:'95%', maxHeight:'95%'});
// Append column instance to the album container
album_container.append(column);
});
});
}
If you're also looking for a review of your code, may I suggest you transition away from the jqXHR.success() and jqXHR.error() methods? They have been deprecated in favour of the jqXHR.done() and jqXHR.fail() methods. Using promises, we have a backbone that looks like this:
var album_container = $('div#album');
function callGetAjax(url)
{
return $.get(url,{});
}
function getAlbum(feed_url)
{
// Store returned promise from $.get() in a variable
var ajaxCall = callGetAjax(absolute_path+'/feed/'+feed_url);
// Now we listen to the promise
ajaxCall
.done(function(data) {
var loaded = 0;
album_title = data.album.album_title;
$('h1#gallery-title').html(album_title);
$.each(data.album.content,function (index,content)
{
var column = $('<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2"></div>'),
item = $('<a/>')
.append($('<img class="img-responsive">').attr('src', content.photo))
.attr({
'href': content.target,
'title': content.title,
'data-gallery': ''
})
.appendTo(column)
.colorbox({rel:'gallery', speed:0, maxWidth:'95%', maxHeight:'95%'});
album_container.append(column);
});
})
.fail(function(xhr, statusText) {
// Log error
// console.log(statusText);
});
}

Categories

Resources