abpetkov / powerange

iOS 7 style range slider
http://abpetkov.github.io/powerange/
423 stars 85 forks source link

Chrome & Safari Crash when adding 'step' #8

Open danielravina opened 10 years ago

danielravina commented 10 years ago

My code is:

@$powerrange = @$('.js-range')
new Powerange(@$powerrange[0], { step: 10 })

I console.log all the functions and its crashing on line 1185

 ctor.prototype = Object.create(superCtor.prototype,
      { constructor: {
            value: ctor
          , enumerable: false
          , writable: true
          , configurable: true
        }
    });

Please help! I like this plugin and without step it wont work for me... Thanks!

abpetkov commented 10 years ago

Well if the demo page is not crashing, then something is messed up with your code. I can take a look, but I'm going to need you to provide jsfiddle or something.

startswithaj commented 10 years ago

If you apply Powerange to an element that is inside an element that has never been rendered; when the following code is called (https://github.com/abpetkov/powerange/blob/master/lib/horizontal.js#L30)

if (this.options.step) this.step(this.slider.offsetWidth, this.handle.offsetWidth);

this.slider.offsetWidth will return 0 this.handle.offsetWdith with return 0

Then these 2 zeros are passed to

Powerange.prototype.step = function(sliderSize, handleSize) {
  var dimension = sliderSize - handleSize
    , part = percentage.from(this.checkStep(this.options.step), this.options.max - this.options.min)
    , interval = percentage.of(part, dimension)
    , steps = [];

  for (i = 0; i <= dimension; i += interval) {
    steps.push(i);
  }

  this.steps = steps;

  return this.steps;
};

dimension is then set to 0. interval is then set to (part / 100) * dimension(0) = 0

Then your for loop does; for i = 0; i <= 0(dimension); 0(i) + 0(interval) basically for (i = 0; 0<=0; 0+0) Infinite loop. Browser crashes.

I don't know how you want to approach fixing this. Before you call the step() function you might do

  if (!this.slider.offsetWidth && !this.handle.offsetWidth)
    this.options.step = null
    console.warn("Powerange: step not applied because elm doesn't have width")

The code will run as though step was never provided (this is not a great solution).

One work around if you are calling Powerange against an element that is in a container that is yet to be rendered (ie. like in @danielravina case a backbone view) is to defer the powerange call until after the element has been rendered using setTimeout or equivalent like _.defer.

input = $('<input class="ranger" type="text"></input>')
div = $('<div>').append(input)
$('body').append(div)
// defer the below code until after render.
setTimeout((function(input){
  new Powerange(input, {step: 10})
})(input), 1)