<commit_before>function ScrubberView() {
  this.makeAccessors();
  this.createDOM();
  this.attachListeners();
  this.onValueChanged = function () {};
}

ScrubberView.prototype.makeAccessors = function () {
  var value = 0;
  var min = 0;
  var max = 1;

  this.value = function (_value) {
    if (_value === undefined) return value;
    if (value === _value) return this;
    value = _value;
    this.redraw();
    this.onValueChanged(_value);
    return this;
  };

  this.min = function (_min) {
    if (_min === undefined) return min;
    if (min === _min) return this;
    min = _min;
    this.redraw();
    return this;
  };

  this.max = function (_max) {
    if (_max === undefined) return max;
    if (max === _max) return this;
    max = _max;
    this.redraw();
    return this;
  };
};

ScrubberView.prototype.createDOM = function () {
  this.elt = document.createElement('div');
  this.track = document.createElement('div');
  this.thumb = document.createElement('div');

  this.elt.className = 'scrubber';
  this.track.className = 'track';
  this.thumb.className = 'thumb';

  this.elt.appendChild(this.track);
  this.elt.appendChild(this.thumb);
};

ScrubberView.prototype.redraw = function () {
  var frac = (this.value() - this.min())/(this.max() - this.min());
  this.thumb.style.left = frac*100 + '%';
};

ScrubberView.prototype.attachListeners = function ()  {
  var self = this;
  var mousedown = false;
  var cachedLeft;
  var cachedWidth;

  var start = function () {
    mousedown = true;
    cachedLeft = self.elt.offsetLeft;
    cachedWidth = self.elt.offsetWidth;
  };

  var stop = function () {
    mousedown = false;
    cachedLeft = undefined;
    cachedWidth = undefined;
  };

  var setValueFromPageX = function (pageX) {
    var frac = Math.min(1, Math.max((pageX - cachedLeft)/cachedWidth, 0));
    self.value((1-frac)*self.min() + frac*self.max());
  };

  this.elt.addEventListener('mousedown', start);
  this.elt.addEventListener('touchstart', start);

  document.addEventListener('mousemove', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.pageX);
  });

  document.addEventListener('touchmove', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.changedTouches[0].pageX);
  });

  this.elt.addEventListener('mouseup', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.pageX);
  });

  this.elt.addEventListener('touchend', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.changedTouches[0].pageX);
  });

  document.addEventListener('mouseup', stop);
  document.addEventListener('touchend', stop);
};
<commit_msg>Add ability to set step value; set drag opacity<commit_after>function ScrubberView() {
  this.makeAccessors();
  this.createDOM();
  this.attachListeners();
  this.onValueChanged = function () {};
}

ScrubberView.prototype.makeAccessors = function () {
  var value = 0;
  var min = 0;
  var max = 1;
	var step = 0;

  this.value = function (_value) {
    if (_value === undefined) return value;
    if (value === _value) return this;

		if (step > 0) {
			var remainder = (_value - min) % step;
			value = _value - remainder;
			if (Math.abs(remainder) * 2 >= step) {
				value += (remainder > 0) ? step : (-step);
			}
		} else {
			value = _value;
		}

    this.redraw();
    this.onValueChanged(value);
    return this;
  };

  this.min = function (_min) {
    if (_min === undefined) return min;
    if (min === _min) return this;
    min = _min;
    this.redraw();
    return this;
  };

  this.max = function (_max) {
    if (_max === undefined) return max;
    if (max === _max) return this;
    max = _max;
    this.redraw();
    return this;
  };

	this.step = function (_step) {
		if (_step === undefined) return step;
		if (step === _step) return this;
		step = _step;
		this.redraw();
		return this;
	};


};

ScrubberView.prototype.createDOM = function () {
  this.elt = document.createElement('div');
  this.track = document.createElement('div');
  this.thumb = document.createElement('div');

  this.elt.className = 'scrubber';
  this.track.className = 'track';
  this.thumb.className = 'thumb';

  this.elt.appendChild(this.track);
  this.elt.appendChild(this.thumb);
};

ScrubberView.prototype.redraw = function () {
  var frac = (this.value() - this.min())/(this.max() - this.min());
  this.thumb.style.left = frac*100 + '%';
};

ScrubberView.prototype.attachListeners = function ()  {
  var self = this;
  var mousedown = false;
  var cachedLeft;
  var cachedWidth;

  var start = function () {
    mousedown = true;
    cachedLeft = self.elt.offsetLeft;
    cachedWidth = self.elt.offsetWidth;
		self.thumb.style.opacity = 1;
		self.thumb.style.borderWidth = 0;
  };

  var stop = function () {
    mousedown = false;
    cachedLeft = undefined;
    cachedWidth = undefined;
		self.thumb.style.opacity = 0.7;
		self.thumb.style.borderWidth = '8px';
  };

  var setValueFromPageX = function (pageX) {
    var frac = Math.min(1, Math.max((pageX - cachedLeft)/cachedWidth, 0));
    self.value((1-frac)*self.min() + frac*self.max());
  };

  this.elt.addEventListener('mousedown', start);
  this.elt.addEventListener('touchstart', start);

  document.addEventListener('mousemove', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.pageX);
  });

  document.addEventListener('touchmove', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.changedTouches[0].pageX);
  });

  this.elt.addEventListener('mouseup', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.pageX);
  });

  this.elt.addEventListener('touchend', function (evt) {
    if (!mousedown) return;
    evt.preventDefault();
    setValueFromPageX(evt.changedTouches[0].pageX);
  });

  document.addEventListener('mouseup', stop);
  document.addEventListener('touchend', stop);
};

{'fraction_non_alphanumeric': 0.1574242675053799, 'fraction_numerical': 0.005131600728356232, 'mean_word_length': 3.4755555555555557, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6831801', 'n_tokens_mistral': 2065, 'n_tokens_neox': 2008, 'n_words': 418}