How to avoid overlay using InstantSearch.js rangeSlider? - algolia

I'm using InstantSearch.js (via algolia) to make a price rangeslider. It's ok and it works well with one exception: the prices overlap when they are too close.
We can see it on several examples, even on the site of the doc:
Doc algolia
I use it for vehicle prices so we don't see anything when don looks for vehicles with prices not far apart
I would simply like to leave the 2 rheostat-tooltip fixed but I can't find a way to do it. (the prices don't move, but the cursors do)
You can see my problem here :
As #cmgchess suggested in comment I post a link where there is an example : example instantSearch and where you can easily see the overlapping.
thanks for any time and help :)
HTML
<li class="u-bt-thin-translucid">
<button class="my-grid mod-space-between mod-middle my-text mod-ff-lead-bold-2 mod-fs-sm2 mod-uppercase u-pt-sm u-pb-sm u-c-neutral-dark-2 u-bc-neutral-light-max u-w-100 u-b-none"
my-toggle="dd-filtrer-par-prix-mensualite"
my-toggle-options="force_dismiss"
u-pr-xxs="sm,md">
<span class="mod-on icon-chevron-up u-fs-lg"></span>
<span class="mod-off icon-chevron-down u-fs-lg"></span>
</button>
<div class="u-pb-sm" my-toggle-name="dd-filtrer-par-prix-mensualite">
<div class="my-text mod-uppercase">Prix</div>
<div id="price-range" class="u-pl-sm u-pr-md u-mb-md"></div>
<div class="my-text mod-uppercase">Mensualité (€/mois)</div>
<div id="monthly-price-range" class="u-pl-sm u-pr-md"></div>
</div>
</li>
JS
// Filtre prix
if (document.querySelector('#price-range') !== null) {
algoliaBmc.search.addWidgets([
instantsearch.widgets.rangeSlider({
container: '#price-range',
attribute: 'price',
precision: 0,
step: isGoa ? 10 : 1000,
pips: false,
tooltips: true
})
]);
}

Related

how do I rendering multiple components using xstreamjs

Suppose, I want to render 3 buttons which are mapped from Array
export const homePage = soruces => {
const array$ = xs.fromArray([1,2,3])
return {
DOM: array$.map(e => {
return <button id={e}>click</button>
})
};
};
but I only get the lastest button which has id of 3
<div id="app">
<button id="3">click</button>
</div>
how do i get all the buttons rendered like this using xstream or rxjs
<div id="app">
<button id="1">click</button>
<button id="2">click</button>
<button id="3">click</button>
</div>
That depends a bit on what you want to achieve. The code you have there basically says: "I get three pieces of data, each at some arbitrary point of time" (because fromArray basically takes the data from the array one by one and puts it into the stream.
If you now what to collect the data over time, you can add fold((buttons, newButton) => buttons.concat(newButton), []).
If however you just happen to have three poeces of data, that always should be three buttons, do not use fromArray but the normal Array.map. You can then use xs.of to emit the three buttons at once (compared to one by one in the first part)

Meteor templates. How can I not render a HTML element based on an {{#if}}?

I have a collection that stores phone numbers for companies.
If a company has a phone number, draw those phone numbers.
If a company has no phone number, don't draw any.
Currently it half works. It will not draw the phone numbers if no numbers are in the collection, but it still draws the < h4 >Phone< /h4 > heading and I don't want it to.
Here's the code:
<template name="orgPage">
<h2>Organisation Name: {{name}}</h2>
<h3>Contact Details</h3>
<ul>
{{#if phone}}
<h4>Phone</h4>
{{#each phone}}
<li>{{number}} ({{type}})</li>
{{/each}}
{{else}}
<p>No contact numbers</p>
{{/if}}
</ul>
</template>
and
Template.orgPage.helpers({
'phone': function() {
return organisationsPhoneNumbers.find({ orgId: currentOrgId })
}
});
How can I get it to NOT draw the < h4 >Phone< /h4 > if there is no data returned from the collection?
short answer
Keep all of your original code and replace {{#if phone}} with {{#if phone.count}}
long answer
Spacebars has a really cool path evaluation feature, which is best explained with an example.
Imagine you have a post document in your current context. Each post is modeled to have a fetchAuthor helper, which returns a user document. Let's suppose you need the lower cased version of the author's last name. In JavaScript you could write something like:
post.fetchAuthor().profile.firstName.toLowerCase()
Now if we need that value in a template we can write:
{{post.fetchAuthor.profile.firstName.toLowerCase}}
As spacebars evaluates each identifier in the path, it checks to see if it's a function - if it is, it invokes it. Note this only works if the called functions take no arguments.
Circling back to our original example, the phone helper returns a cursor, which has a count function. We can write {{#if phone.count}} and spacebars will figure out that we mean phone.count() because count is a function.
I faced this problem early on, here's a simple approach where you return an object from the helper that includes the count:
js:
Template.orgPage.helpers({
'phone': function() {
var cursor = organisationsPhoneNumbers.find({ orgId: currentOrgId });
return { count: cursor.count(), items: cursor };
}
})
html:
{{#if phone.count}}
<h4>Phone</h4>
{{#each phone.items}}
<li>{{number}} ({{type}})</li>
{{/each}}
{{/if}}
There is a fairly standard pattern for this kind of scenarios that avoids re-running the same helper multiple times:
<template name="orgPage">
<h2>Organisation Name: {{name}}</h2>
<h3>Contact Details</h3>
{{#with phone}}
{{#if count}}
<h4>Phone</h4>
<ul>
{{#each .}}
<li>{{number}} ({{type}})</li>
{{/each}}
</ul>
{{else}}
<p>No contact numbers</p>
{{/if}}
{{/with}}
</template>
The with block sets the scope for its content to the result of thephone helper, which is a cursor.
It then checks if the count() helper/method is truth-y. If so, it uses an each iterator tor render the list of items, else - the message indicating no numbers is displayed.
Note that there is an each...else clause that works if you don't need anything outside the each block.

complex jquery/css selector

I need a selector for this code:
<div class="panel-heading BWHeadingForSection">
<a style="text-decoration:none" href="#faq-cat-1-sub-2" data-parent="#accordion-cat-2" data-toggle="collapse" tabindex="90">
<i class="fa fa-truck fa-lg"></i>
UPS Deutschland
<span class="pull-right">
<i class="glyphicon glyphicon-plus"></i>
</span>
</a>
</div>
And I tried that:
$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]').on("click", function(){
count++;
if(count%2==0){
$("#faq-cat-1-sub-"+globalcarriernumber).slideToggle();
//why doesn't this selector work?
//if ( $(this+">span i").hasClass('plus') ) {
// $(this+">span i").removeClass('plus').addClass('minus');
// }
//this selector work's, at least it enters the if -block
if ( $('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i').hasClass('plus') ) {
$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i').removeClass('glyphicon glyphicon-plus').addClass('glyphicon glyphicon-minus');
}
}else{
$("#faq-cat-1-sub-"+globalcarriernumber).hide();
}
});
The relevant line is "$(this+">span i")" and/or "$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i')" , which needs some adjustment. I have to replace that "plus"("") with "minus".
If I use the FireBug debugger I get for "$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i')" ,it goes into that if-block, but the symbol is still the same. And if I use "$(this+">span i")" I get(when I hove over it) : "a#faq-cat-1-sub-2",but it's not entering the if-block.
Thanks...
First of all you are mixing types here. The function $(...) accepts either an object (a DOM node or a jQuery object) or a selector string but not a concatenation of both.
So better try $(this).find('span i').
As far as I can see in your code snippet, the element you will find then, has the css classes 'glyphicon' and 'glyphicon-plus', but no class 'plus'. So you probably won't be able to remove that. Maybe you want to remove 'glyphicon-plus' and add 'glyphicon-minus'?

JQuery UI Slider Without Numbers

I am trying to build a rating form and want to use the JQuery UI increment slider except I don't want the value to be numbers, I'd like it to say something like "great" or "bad"
I'm great with HTML & CSS not so much with JavaScript or JQuery. I am taking a class in NYC next month to help me become more fluent in these languages. In the mean time any and all help is appreciated. I tried to hack other scripts I have found but keep running into problems. I ran into this script which is close to what I want, except the increments show #s.
I feel as if this code can be easily modified to do what I want.
http://jsfiddle.net/dmcgrew/EquTn/3/
<html>
<div class="kpa_rate kpa_rate1">
<label for="kpa1_rating_value">Parking:</label>
<div id="1" class="slider"></div>
<input type="text" class="kpa1_rating_value" name="kpa1_rating" value="0" />
</div>
<div class="kpa_rate kpa_rate2">
<label for="kpa2_rating_value">Entrance:</label>
<div id="2" class="slider"></div>
<input type="text" class="kpa2_rating_value" name="kpa2_rating" value="0" />
</div>
</html>
JavaScript
<script>
$(function() {
$( ".slider" ).slider({
range: "max",
min: 0,
max: 5,
value: $("input", this).val(),
slide: function( event, ui ) {
//get the id of this slider
var id = $(this).attr("id");
//select the input box that has the same id as the slider within it and set it's value to the current slider value.
$("span[class*=" + id + "]").text(ui.value);
$("input[class*=" + id + "]").val(ui.value);
}
});
});
</script>
Did you want different words ("great, good, neutral, etc") for each value, or just good/bad at the ends?
If you want diff words for each of the 5 values, then like j08691 said, make an array that has the words you want at the indexes you want.
After this, replace the ui.value in .val(ui.value) with the array of value (Arr[ui.value]).
(I'm not sure you actually need the "span" part, but I don't do jquery, so I'm not sure).
$(function() {
var Array = ["die","very bad", "bad", "neutral","good","great"];
$( ".slider" )...etc
...
$("input[class*=" + id + "]").val(Array[ui.value]);
This worked for me.
I did a bit of tinkering, and I think I've found a way to superficially solve your problem. Since the number inputted as the first value doesn't affect the slider button/thing, I'd say just put the first word that the slider should indicate (in my case, "die").
//value does not equal a number here
In the next bit of code, just change input to Array[input], and you should be all set!
min: 0,
max: 5,
value: $("Array[input]"
I hope this works well enough for you.

Dojo events: getting it to work with dynamically added DOM elements

I have a method of a class as follows:
add_file: function(name, id, is_new){
// HTML: <div class="icon mime zip">name.zip <a>x</a></div>
var components = name.split('.');
var extension = components[components.length-1];
this.container.innerHTML += "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>";
// Add event to a tag
dojo.connect(dojo.byId('remove-'+id), 'onclick', function(ev){
// here i am
});
},
All is working well, until I run this method more than once. The first time the event is registered correctly, and clicking the 'x' will run the "here i am" function. However, once I add more than one node (and yes, the ID is different), the event is registered to the last node, but removed from any previous ones.
In affect I have this:
<div id="field[photos]-filelist">
<div id="file1" class="icon mime jpg">file1.jpg <a id="remove-file1" href="#remove">x</a></div>
<div id="file2" class="icon mime jpg">file2.jpg <a id="remove-file2" href="#remove">x</a></div>
</div>
...and the remove link only works for the last node (remove-file2 in this case).
The problem is you are using the innerHTML +=
That is going to take the existing html, convert it to plain markup, and then completely create new nodes from the markup. In the process, all of the nodes with events get replaced with nodes that look exactly the same but are not connected to anything.
The correct way to do this is to use dojo.place(newNodeOrHTML, refNode, positionString)
var myNewHTML = "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>"
//This won't work as is breaks all the connections between nodes and events
this.container.innerHTML += myNewHTML;
//This will work because it uses proper dom manipulation techniques
dojo.place(myNewHTML, this.container, 'last');