Skip to content

Commit d190fd0

Browse files
committed
Refactor and performance changes
1 parent f848d59 commit d190fd0

File tree

1 file changed

+171
-25
lines changed

1 file changed

+171
-25
lines changed

rzslider.js

Lines changed: 171 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,42 @@
1111

1212
angular.module('rzModule', [])
1313

14-
.factory('Slider', ['$timeout', '$document', function($timeout, $document)
14+
.value('throttle',
15+
// Taken from underscore project
16+
function throttle(func, wait, options) {
17+
var getTime = (Date.now || function() {
18+
return new Date().getTime();
19+
});
20+
var context, args, result;
21+
var timeout = null;
22+
var previous = 0;
23+
options || (options = {});
24+
var later = function() {
25+
previous = options.leading === false ? 0 : getTime();
26+
timeout = null;
27+
result = func.apply(context, args);
28+
context = args = null;
29+
};
30+
return function() {
31+
var now = getTime();
32+
if (!previous && options.leading === false) previous = now;
33+
var remaining = wait - (now - previous);
34+
context = this;
35+
args = arguments;
36+
if (remaining <= 0) {
37+
clearTimeout(timeout);
38+
timeout = null;
39+
previous = now;
40+
result = func.apply(context, args);
41+
context = args = null;
42+
} else if (!timeout && options.trailing !== false) {
43+
timeout = setTimeout(later, remaining);
44+
}
45+
return result;
46+
}
47+
})
48+
49+
.factory('Slider', ['$timeout', '$document', 'throttle', function($timeout, $document, throttle)
1550
{
1651
/**
1752
* Slider
@@ -107,6 +142,20 @@ angular.module('rzModule', [])
107142
*/
108143
this.maxValue = 0;
109144

145+
/**
146+
* High value handle offset in percentages
147+
*
148+
* @type {number}
149+
*/
150+
this.highValOffsetPerc = 0;
151+
152+
/**
153+
* Low value handle offset in percentages
154+
*
155+
* @type {number}
156+
*/
157+
this.lowValOffsetPerc = 0;
158+
110159
/**
111160
* The delta between min and max value
112161
*
@@ -189,8 +238,8 @@ angular.module('rzModule', [])
189238

190239
$timeout(function()
191240
{
192-
self.setPointers();
193-
self.adjustLabels();
241+
self.updateHandles('both');
242+
self.adjustLabels('timeout');
194243
self.bindToInputEvents();
195244
});
196245

@@ -200,17 +249,17 @@ angular.module('rzModule', [])
200249
// Watch for changes to the model
201250
this.scope.$watch(this.refLow, function()
202251
{
203-
self.setPointers();
204-
self.adjustLabels();
252+
self.updateHandles('low');
253+
self.adjustLabels('refLow');
205254
});
206255

207256
if(this.range)
208257
{
209258
// We have to watch it only for range slider
210259
this.scope.$watch(this.refHigh, function()
211260
{
212-
self.setPointers();
213-
self.adjustLabels();
261+
self.updateHandles('high');
262+
self.adjustLabels('refHigh');
214263
});
215264
}
216265

@@ -220,8 +269,8 @@ angular.module('rzModule', [])
220269
this.scope.$watch('rzSliderFloor', function()
221270
{
222271
self.setMinAndMax();
223-
self.setPointers();
224-
self.adjustLabels();
272+
self.updateHandles('both');
273+
self.adjustLabels('floor');
225274
});
226275
}
227276

@@ -231,8 +280,8 @@ angular.module('rzModule', [])
231280
this.scope.$watch('rzSliderCeil', function()
232281
{
233282
self.setMinAndMax();
234-
self.setPointers();
235-
self.adjustLabels();
283+
self.updateHandles('both');
284+
self.adjustLabels('ceil');
236285
});
237286
}
238287
},
@@ -308,6 +357,7 @@ angular.module('rzModule', [])
308357
this.minOffset = 0;
309358
this.maxOffset = this.barWidth - pointerWidth;
310359
this.offsetRange = this.maxOffset - this.minOffset;
360+
this.setLeft(this.ceilBub, this.barWidth - this.offsetWidth(this.ceilBub));
311361
},
312362

313363
/**
@@ -317,26 +367,25 @@ angular.module('rzModule', [])
317367
*/
318368
setPointers: function()
319369
{
320-
var newHighValue, newLowValue, minPtrOL, maxPtrOL, selBarOL, selBarWidth;
370+
var minPtrOL, maxPtrOL, selBarOL, selBarWidth;
321371

322-
this.setLeft(this.ceilBub, this.barWidth - this.offsetWidth(this.ceilBub));
323-
newLowValue = this.percentValue(this.scope[this.refLow]);
372+
this.lowValOffsetPerc = this.percentValue(this.scope[this.refLow]);
324373
// Set low value slider handle position
325-
minPtrOL = this.setLeft(this.minPtr, this.percentToOffset(newLowValue));
374+
minPtrOL = this.setLeft(this.minPtr, this.percentToOffset(this.lowValOffsetPerc));
326375
// Set low value label position
327376
this.setLeft(this.lowBub, minPtrOL - this.halfOffsetWidth(this.lowBub) + this.ptrHalfWidth);
328377

329378
if (this.range)
330379
{
331-
newHighValue = this.percentValue(this.scope[this.refHigh]);
380+
this.highValOffsetPerc = this.percentValue(this.scope[this.refHigh]);
332381
// Set high value slider handle position
333-
maxPtrOL = this.setLeft(this.maxPtr, this.percentToOffset(newHighValue));
382+
maxPtrOL = this.setLeft(this.maxPtr, this.percentToOffset(this.highValOffsetPerc));
334383
// Set high value slider handle label position
335384
this.setLeft(this.highBub, maxPtrOL - (this.halfOffsetWidth(this.highBub)) + this.ptrHalfWidth);
336385

337386
// Set selection bar position
338387
selBarOL = this.setLeft(this.selBar, minPtrOL + this.ptrHalfWidth);
339-
selBarWidth = this.percentToOffset(newHighValue - newLowValue);
388+
selBarWidth = this.percentToOffset(this.highValOffsetPerc - this.lowValOffsetPerc);
340389
this.selBar.css({width: selBarWidth + 'px'});
341390

342391
// Set combined label position
@@ -348,13 +397,94 @@ angular.module('rzModule', [])
348397
}
349398
},
350399

400+
/**
401+
* Update slider handles and label positions
402+
*
403+
* @param {string} which
404+
*/
405+
updateHandles: function(which)
406+
{
407+
if(which === 'low')
408+
{
409+
this.updateLowHandle();
410+
if(this.range) { this.updateSelectionBar(); }
411+
return;
412+
}
413+
414+
if(which === 'high')
415+
{
416+
this.updateHighHandle();
417+
if(this.range) { this.updateSelectionBar(); }
418+
return;
419+
}
420+
421+
// Update both
422+
this.updateLowHandle();
423+
this.updateHighHandle();
424+
this.updateSelectionBar();
425+
},
426+
427+
/**
428+
* Update low slider handle position and label
429+
*
430+
* @returns {undefined}
431+
*/
432+
updateLowHandle: function()
433+
{
434+
var minPtrOL;
435+
436+
this.lowValOffsetPerc = this.percentValue(this.scope[this.refLow]);
437+
// Set low value slider handle position
438+
minPtrOL = this.setLeft(this.minPtr, this.percentToOffset(this.lowValOffsetPerc));
439+
440+
// Set low value label position
441+
this.setLeft(this.lowBub, minPtrOL - this.halfOffsetWidth(this.lowBub) + this.ptrHalfWidth);
442+
},
443+
444+
/**
445+
* Update high slider handle position and label
446+
*
447+
* @returns {undefined}
448+
*/
449+
updateHighHandle: function()
450+
{
451+
var maxPtrOL;
452+
453+
this.highValOffsetPerc = this.percentValue(this.scope[this.refHigh]);
454+
// Set high value slider handle position
455+
maxPtrOL = this.setLeft(this.maxPtr, this.percentToOffset(this.highValOffsetPerc));
456+
// Set high value slider handle label position
457+
this.setLeft(this.highBub, maxPtrOL - (this.halfOffsetWidth(this.highBub)) + this.ptrHalfWidth);
458+
},
459+
460+
/**
461+
* Update slider selection bar, combined label and range label
462+
*/
463+
updateSelectionBar: function()
464+
{
465+
var selBarOL, selBarWidth;
466+
467+
// Set selection bar position
468+
selBarOL = this.setLeft(this.selBar, this.percentToOffset(this.lowValOffsetPerc) + this.ptrHalfWidth);
469+
selBarWidth = this.percentToOffset(this.highValOffsetPerc - this.lowValOffsetPerc);
470+
this.selBar.css({width: selBarWidth + 'px'});
471+
472+
// Set combined label position
473+
this.setLeft(this.cmbBub, selBarOL + selBarWidth / 2 - this.halfOffsetWidth(this.cmbBub) + 1);
474+
475+
// Set range label position
476+
this.setLeft(this.selBub, selBarOL + selBarWidth / 2 - this.halfOffsetWidth(this.selBub) + 1);
477+
this.scope.rzSliderDiff = this.roundStep(this.scope[this.refHigh] - this.scope[this.refLow]);
478+
},
479+
351480
/**
352481
* Adjust label positions and visibility
353482
*
354483
* @returns {undefined}
355484
*/
356485
adjustLabels: function ()
357486
{
487+
// console.log('al', this.scope.$id + ' ' + arguments[0]);
358488
var bubToAdjust = this.highBub;
359489

360490
this.fitToBar(this.lowBub);
@@ -593,34 +723,49 @@ angular.module('rzModule', [])
593723
*/
594724
onStart: function (pointer, ref, event)
595725
{
726+
var which;
727+
596728
if(this.tracking !== '') { return }
597729

598730
this.tracking = ref;
599731

732+
switch (ref)
733+
{
734+
case 'rzSliderModel':
735+
case 'rzSliderLow':
736+
which = 'low';
737+
break;
738+
739+
case 'rzSliderHigh':
740+
which = 'high';
741+
break;
742+
}
743+
600744
pointer.addClass('active');
601745

602746
event.stopPropagation();
603747
event.preventDefault();
604748

605749
if(event.touches)
606750
{
607-
$document.on('touchmove', angular.bind(this, this.onMove));
751+
$document.on('touchmove', angular.bind(this, this.onMove, which));
608752
$document.on('touchend', angular.bind(this, this.onEnd, pointer));
609753
}
610754
else
611755
{
612-
$document.on('mousemove', angular.bind(this, this.onMove));
756+
$document.on('mousemove', angular.bind(this, this.onMove, which));
613757
$document.on('mouseup', angular.bind(this, this.onEnd, pointer));
614758
}
615759
},
616760

617761
/**
618762
* onMove event handler
619763
*
620-
* @param {Event} event The event
764+
* @param {string} ref
765+
* @param {Event} event The event
621766
* @returns {undefined}
622767
*/
623-
onMove: function (event)
768+
onMove: function (ref, event)
624769
{
625770
var eventX = event.clientX || event.touches[0].clientX,
626771
newOffset, newPercent, newValue;
@@ -648,8 +793,8 @@ angular.module('rzModule', [])
648793
}
649794

650795
this.scope[this.tracking] = this.roundStep(newValue);
651-
this.setPointers();
652-
this.adjustLabels();
796+
this.updateHandles(ref);
797+
this.adjustLabels('onMove');
653798
this.scope.$apply();
654799
},
655800

@@ -677,9 +822,10 @@ angular.module('rzModule', [])
677822

678823
this.tracking = '';
679824
}
680-
681825
};
682826

827+
Slider.prototype.adjustLabels = throttle(Slider.prototype.adjustLabels, 350);
828+
683829
return Slider;
684830
}])
685831

0 commit comments

Comments
 (0)