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

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 ...

Related

Handlebars lookup to make an href

I am trying to make a mod on an existing app. All I want to do is create an href that contains a url, but using the handlebars lookup function. When I try it just returns a blank value.
Here is my function:
var cardLink = function generateCardLink() {
var url = `"url/container-scan-reports/${vendor}/${product}/${image}"`
return url;
}
//...
res.render('vendor', {
title: 'Vendor Images',
images: images,
tags: tags,
cardLink: cardLink
});
I am then trying to pass in href this way on the top div of template.
<div class="row row-cards-pf ">
{{#each images}}
<div href={{lookup ../cardLink #index }} class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<div class="card-pf card-pf-view card-pf-view-select card-pf-view-single-select">
<div class="card-pf-body">
<div class="card-pf-top-element">
<span class="pficon-image card-pf-icon-circle"></span>
</div>
<h2 class="card-pf-title text-center">
{{ this }}
</h2>
<div class="card-pf-items text-center">
<div class="card-pf-item">
{{{ lookup ../tags #index}}}
</div>
</div>
<!-- <p class="card-pf-info text-center"><strong>Most recent image</strong> {{ lookup ../mostRecentImages #index}}</p> -->
</div>
<div class="card-pf-view-checkbox">
<input type="checkbox">
</div>
</div>
</div><!-- /col -->
{{/each}}
Can anyone help me?
You don't need lookup in this case. I think you want to display the url, so #index is not the right reference. Try it this way:
<div href={{../cardLink}} class="col-xs-12 col-sm-6 col-md-4 col-lg-4">

Ionic + AngularJS: ng-repeat filter not working on grid layout but works in list

I am currently learning building apps with ionic v1 and angular.
Here's the scenario, I'm trying to make a grid of cards and was able to do it by following the tutorial on this link.
I was able to populate the grid with cards using json data. However, I also need to add a search box in order to filter the results. I used angularJS ng-repeat filter on the view but it is not filtering it correctly.
here's my code:
angular.module('starter')
.factory('Disasters', function() {
var disasters= [{
id: 0,
name: 'Earthquake',
face: 'img/earthquake/thumbs.PNG',
}, {
id: 1,
name: 'Flash Floods',
face: 'img/flood/thumbs.png',
}, {
id: 2,
name: 'Typhoon',
face: 'img/typhoon/thumbs.png',
}, {
id: 3,
name: 'Avalanche',
face: 'img/avalanche/thumbs.png',
}];
return {
all: function() {
return disasters;
},
remove: function(disaster) {
disasters.splice(disasters.indexOf(disaster), 1);
},
get: function(disasterID) {
for (var i = 0; i < disasters.length; i++) {
if (disasters[i].id === parseInt(disasterID)) {
return disasters[i];
}
}
return null;
}
};
})
.controller('DisasterCtrl', function($scope,$state,$ionicSideMenuDelegate,Chats,Facts){
$scope.disasters = Disasters.all();
})
and here's the code for my view
<ion-content>
<input type="text" ng-model="search">
<div ng-repeat="disaster in disasters | filter: search" ng-if="$index % 2 === 0">
<div class="row">
<div class="col col-50 no-padding" ng-if="$index < disasters.length">
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disasters[$index].slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disasters[$index].id}})">
<p class="bold uppercase font12">{{disasters[$index].name}}</p>
</div>
</div>
</div>
<div class="col col-50 no-padding" ng-if="$index < disasters.length">
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disasters[$index + 1].slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disasters[$index + 1].id}})">
<p class="bold uppercase font12">{{disasters[$index + 1].name}}</p>
</div>
</div>
</div>
</div>
</div>
</ion-content>
when I type something on the search text box it always shows the first two object in the JSON data.
If I change the view into a list the filter works, however it is required to apply the grid styling on the view.
Thanks!
Pluker link of the code : plnk code link
The problem with your grid layouting is that you are using the ng-repeat in a row instead of the columns so when the search item is among a particular it returns the full row because thats where your item is located. so i created a code to help you sort it in plnk where i used the ng-repeat in a column instead of the row and added a style to the row to make it break which is this
class="row" style="flex-wrap: wrap;"
Input: <input type="text" ng-model="search.name" style="border:1px solid #ccc">
<br>
<div class="row" style="flex-wrap: wrap;" >
<div class="col col-50 no-padding" ng-repeat="disaster in disasters | filter: search" >
{{$index}}
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disaster.slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disaster.id}})">
<p class="bold uppercase font12">{{disaster.name}}</p>
</div>
</div>
</div>
</div>
That should work for you as needed. here is the demo running demo
reference from this answer

Javascript in html tags to avoid repetition

I am a newbie to JavaScript and I need to use it with bootstrap for my own web page. My question is now how can I make a loop so that pictures names (stored as an array) can emerge in the right places of the HTML code so I do not have to copy the blocks of code for each picture.
For example :
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="02.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="03.jpg">
</div>
</div>
As we can see here the only different text is the src.How can I store the names (paths) in an array and make a loop that changes the src property?
Thank you!
Try this demo: http://jsbin.com/pinoxeqapi/1/edit?html,output
I think that's what you're looking for.
CODE
$(function () {
var images = ["01.jpg", "01.jpg", "02.jpg", "03.jpg"];
$.each(images, function (index, element) {
var imgContainer = "<div class='row'><div class='col-md-3 col-xs-6 portfolio-item><img class='img-responsive' src='" + element + "'></div></div>";
$("body").append(imgContainer);
});
});
First Include JQuery (If not)
<script>
var srcArray = ['01.jpg', '02.jpg', '03.jpg', '04.jpg'];
$(document).ready(function () {
for (var i = 0; i < srcArray.length; i++) {
$('div.row img.img-responsive').eq(i).attr("src", srcArray[i]);
}
});
</script>
I would recommend using one of the templating frameworks described in some of the other answers. If you're interested to see how to implement this in pure JS:
var temp = document.querySelector('#portfolio-item-template');
['01.jpg', '02.jpg', '03.jpg', '04.jpg'].forEach(function(src) {
temp.content.querySelector(".img-responsive").src = src;
var newImg = document.importNode(temp.content, true);
document.querySelector('#insertion-point').appendChild(newImg);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="portfolio-item-template">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive">
</div>
</div>
</template>
<div id="insertion-point">
</div>
You can use a template stored in the HTML and then generate the actual elements using an array of the image sources. Something like John Resig's micro-templates can achieve this.
<script type="text/template" id="img-tmpl">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item>
<img class="img-responsive" src="<%= src %>">
</div>
</div>
</script>

Get children under a parent using jQuery

$(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>

jquery .sortable() on <div> store and retrieve

I am trying to use sortable() on divs and it's working fine, but I couldn't store the sorted divs and retrieve them for the user in the database.
here is my code:
<div class="row">
<div class="col-sm-3 col-xs-6 widget-container-col">
<div class="widget-box widget-color-blue" id="1">
<div class="widget-header">
<h4 class="widget-title">Japanese Yen</h4>
</div>
<div class="widget-body">
<div class="center bold bigger-300"><i class="fa fa-lg fa-jpy smaller-90 up-5"></i> {{ round($currencyWidget['price'], 2) }}</div>
<div class="center">as of {{ $currencyWidget['date'] }}</div>
</div>
</div>
</div>
<div class="col-sm-3 col-xs-6 widget-container-col">
<div class="widget-box widget-color-blue" id="2">
<div class="widget-header">
<h4 class="widget-title">Another Widget</h4>
</div>
<div class="widget-body">
<div class="center bold bigger-300">Test Widget</div>
</div>
</div>
</div>
<div class="col-sm-3 col-xs-6 widget-container-col">
</div>
<div class="col-sm-3 col-xs-6 widget-container-col">
</div>
and Here is my jquery code:
$('.widget-container-col').sortable({
connectWith: '.widget-container-col',
items: '> .widget-box',
opacity: 0.8,
revert: true,
forceHelperSize: true,
placeholder: 'widget-placeholder',
forcePlaceholderSize: true,
tolerance: 'pointer',
start: function(event, ui){
ui.item.parent().css({'min-height': ui.item.height()})
},
update: function(event, ui) {
var data = $(this).sortable('serialize');
ui.item.parent({'min-height':''})
}
});
Any suggestions?
Thank you,
You can fetch the 'id' , 'index' map of sortable by iterating through all the items in sortable ,
$.map($(".widget-container-col > .widget-box "), function(element) {
return element.id + ' = ' + $(element).index();
});
Which will return you data in following form ,
["2 = 0", "1 = 1"]
See an example here
As for this ,
Also, once I save the data to the database, how would I load the page
after retrieving the data from the DB sorted the same way the user
stored it.
You should maintain the data in sorted order while fetching from database.

Categories

Resources