bootstrap-slider icon indicating copy to clipboard operation
bootstrap-slider copied to clipboard

tick labels are not correctly possitioned if slider is used in a modal

Open Bhoft opened this issue 9 years ago • 27 comments

The tick labels are not correctly positioned when the slider is used in a bootstrap modal.

see fiddle: http://jsfiddle.net/h3WDq/662/

slider_problem

Bhoft avatar Jul 02 '15 09:07 Bhoft

This appears to be related (if not a duplicate) of: #140 #358 #381

seiyria avatar Jul 02 '15 12:07 seiyria

this has something "similar" the problem with the tick labels is that when the slider is used on a modal the "calculated" labelSize is 0 and therefore all calculations done with it are also wrong.

The labelSize is wrong because "this.size" is zero.

var labelSize = this.size / (this.options.ticks.length - 1);

The calculation should be done if something is visible. which seems not the case if a modal is used or the slider is added via ajax in a modal.

This problem would be fixed (and all other positioning problems) if all positions/margins etc. are not set in "px" but instead in "%".

Bhoft avatar Jul 02 '15 13:07 Bhoft

Another thing i have seen that on vertical orientation the tick labels are also not working at all (so also in the normal rendering)

As written above this is all because of "px" alignment of the labels.

Also the positioning with fixed ticks_positions isn't working (test with 0%,50% ,100%)

i have updated the fiddle to show these issues http://jsfiddle.net/h3WDq/752/ (updated the fiddle with new src links)

I have already fixed the tick label positioning problem see my latest commit. https://github.com/seiyria/bootstrap-slider/commit/97e11114589d53659c95db6663ecb97736dfd49a

I used the flexbox method mentioned here http://stackoverflow.com/questions/19461521/how-to-center-an-element-horizontally-and-vertically and used css translate to put the labels in the correct position.

Bhoft avatar Jul 03 '15 09:07 Bhoft

@Bhoft, I got around the initial issue with tick label positioning (which also occurs in a Bootstrap nav-tab which is not active on page load) by calling

$("input.slider").bootstrapSlider('refresh');

once the tab has switched. I would think that the same should work for modals.

mat2maa avatar Nov 04 '15 15:11 mat2maa

As you might have seen in a fiddle which uses my fork i fixed this issue some time ago some other way (I don't set the positions like the original version, so i don't have to do a refresh).

I don't know what has changed since that date on the original version because I didn't had time to check and my PRs nether were merged and are now again not automatically merge-able.

But my fiddle tests still seem to work https://github.com/seiyria/bootstrap-slider/issues/341#issuecomment-143150101 so i guess the issue is still valid on current version.

Bhoft avatar Nov 04 '15 16:11 Bhoft

I've the same problem, the issue only happens if the slider is hidden by default and when it appears, the labels are displayed like in first image above, but is not happening if the slider is initially displayed, someone knows what's the issue related to?

ghost avatar Mar 17 '16 12:03 ghost

This might have been fixed by the most recent bug fix. Have you tried the most recent version?

rovolution avatar Mar 17 '16 13:03 rovolution

I'm with 6.1.6, this bug still there, label positions incorrect when slider created in a modal.

I got around just like what @mat2maa said, only difference is, wrapped in a timeout call (sorry, it's in typescript)

let slider = new Slider(id, options) this.Timeout(() => { slider.refresh() })

leondeng avatar Mar 18 '16 04:03 leondeng

This is still an issue in Release v7.0.3. Please add a fix.

johan313 avatar May 03 '16 19:05 johan313

If something is urgent, we'd suggest you to add a well-tested PR. It closes issues a lot faster!

seiyria avatar May 03 '16 19:05 seiyria

Confirmed this issue is still present in 7.0.2:

https://jsfiddle.net/jz7f7vas/

el-timm avatar May 04 '16 22:05 el-timm

Request you to write the code in CSS. How ever the solution would be temporarily

.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{ width: 35 !important; }

if they anyone gets the solution it would be a great help

pgksunilkumar avatar Dec 14 '16 13:12 pgksunilkumar

This still seems to be an issue with 9.7.2:

https://jsfiddle.net/jz7f7vas/ (same example from @el-timm )

As pointed out, it will render fine on the page after clicked / interacted with, and if the page is not refreshed, it will continue to render properly with each subsequent click to open the modal - it's just the initial render that is hosed.

Any known ways around it?

magnumpci avatar Mar 13 '17 23:03 magnumpci

Until someone has the time to fix this, here is a very simple workaround that seems to work:

https://jsfiddle.net/jz7f7vas/7/

var thisModal =$('#myModal');
thisModal.modal('show');
$("#slider").slider("refresh");
thisModal.modal('hide');

(it's kind of stupid, but hey, it works. :P)

skeets23 avatar Mar 29 '17 17:03 skeets23

just have to instantiate the slider BEFORE you call it in your code - for anyone noob like me :)

EugeneRaynerNZ avatar Mar 30 '17 02:03 EugeneRaynerNZ

we would really appreciate a PR to fix this!

rovolution avatar Mar 30 '17 03:03 rovolution

+1 Same issue with v9.8.0

tohagan avatar May 03 '17 23:05 tohagan

I was able to work around this problem by triggering a resize event that causes a redraw: window.dispatchEvent(new Event('resize'));

The refresh command caused other side-effects so this was the easiest workaround.

mmaday avatar Jun 22 '17 15:06 mmaday

I was able to resolve this using the 'relayout' event to force a redraw at the right moment. Since I'm using the data-provide attribute my jQuery command looks as follows: $('input[data-provide="slider"]').slider('relayout');

limoniapps avatar Jul 05 '17 19:07 limoniapps

Currently using an interval approach in my ngx app.

const interval = setInterval(() => this.slider.refresh(), 100);
this.modal.onShown = () => clearInterval(interval);

Or, from a more jQuery approach...

var interval = setInterval(function() {$("#slider").slider("refresh")}, 100);
$('#modal').on('shown.bs.modal', function() {clearInterval});

This is the only way I could get the modal to appear smoothly and not have a timer perpetually running in the background.

This solution does not please me in any way.

michaeljpeake avatar Aug 23 '17 09:08 michaeljpeake

I found a Fix, in my case I use this slider inside an item into bootstrap carousel (#webform-carousel), I put refresh() function into slid.bs.carousel event and this update all style parameters for those labels.

var slider_credit = new Slider("#credit_score", { ticks: [619, 659, 699, 739], ticks_labels: ['Pobre 639 o Menor', 'Justo 640-679', 'Buena 680-719', 'Excelente 720+'], value: 619, step: 40, tooltip: 'hide' });

$('#webform-carousel').on('slid.bs.carousel',function(e){ slider_credit.refresh(); });

xmediasoftware avatar Sep 28 '17 20:09 xmediasoftware

I initially tried this Javascript fix for Bootstrap 4, but it made a subtle flash when initiated:

$('#modal').on('shown.bs.modal', function (e) {
  $("#slider").slider("refresh");
})

However, looking through the fork by @Bhoft, I realized I only needed to commit the following changes:

boostrap-slider.js – line 1259 (included the old code for reference)

if (this.tickLabels[i]) {
this.tickLabels[i].style[styleSize] = labelSize + '%';
this.tickLabels[i].style.position = 'absolute';
if (this.options.ticks_positions[i] !== undefined) {
this.tickLabels[i].style[this.stylePos] = this.options.ticks_positions[i] + '%';
} else {
this.tickLabels[i].style[this.stylePos] = (100 / (this.options.ticks.length-1)) *  i  + '%';
}
// this.tickLabels[i].style[styleSize] = labelSize + "px";
// if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) {
// 	this.tickLabels[i].style.position = 'absolute';
// 	this.tickLabels[i].style[this.stylePos] = percentage + "%";
// 	this.tickLabels[i].style[styleMargin] = -labelSize / 2 + 'px';
// } else if (this.options.orientation === 'vertical') {
// 	if (this.options.rtl) {
// 		this.tickLabels[i].style['marginRight'] = this.sliderElem.offsetWidth + "px";
// 	} else {
// 		this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + "px";
// 	}
// 	this.tickLabelContainer.style[styleMargin] = this.sliderElem.offsetWidth / 2 * -1 + 'px';
// }
}

bootstrap-slider.css (line 154) or custom css file

.slider-tick-label {
    display: -webkit-flexbox;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    justify-content: center;
}

.slider.slider-vertical .slider-tick-label-container .slider-tick-label {
    padding-left: 30px;
}

Since I am only using the vertical slider and not sure how , I won't make a PR (yet).

mathiasmadsen avatar Jan 02 '18 14:01 mathiasmadsen

for me this fixed the issue. I called this when using the next button action method that would render the bootstrap slider in a form.

window.dispatchEvent(new Event('resize'));

vikitripathi avatar May 14 '18 13:05 vikitripathi

I had it in a bootstrap tab, this worked for me:

    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        window.dispatchEvent(new Event('resize'));  
    });

jlautner avatar Sep 06 '18 20:09 jlautner

hmmm...so looks like the solution would be to somehow expose a way to trigger the method listening for the resize event

rovolution avatar Sep 09 '18 08:09 rovolution

Until someone has the time to fix this, here is a very simple workaround that seems to work:

https://jsfiddle.net/jz7f7vas/7/

var thisModal =$('#myModal');
thisModal.modal('show');
$("#slider").slider("refresh");
thisModal.modal('hide');

(it's kind of stupid, but hey, it works. :P)

It is really nice.

bj015852 avatar Apr 16 '19 03:04 bj015852

Hi! I solved this problem by adding this line in the slider statement:

$('.slider').bootstrapSlider({
 ...
 ticks_positions: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
...
})

Defines the positions of the tick values in percentages. The first value should always be 0, the last value should always be 100 percent.

So the numbers don't overlap and each one takes its place.

ghost avatar Feb 21 '20 07:02 ghost