LOADING...

Preview

Pen ID
Unlock Campus Themeforest adv

 

Code

CSS
html, body {
  height: 100%;
}

body {
  font: 16px Arial;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-flow: column;
      flex-flow: column;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
}

.multiRange {
  margin: 3em 0;
  width: 40%;
  min-width: 150px;
}
.multiRange.type1 .multiRange__range {
  color: #EEE;
  -webkit-transition: 50ms;
  transition: 50ms;
}
.multiRange.type1 .multiRange__range:nth-child(2) {
  color: #EC5564;
}
.multiRange.type1 .multiRange__range .multiRange__handle {
  box-shadow: none;
  background: #EC5564;
}
.multiRange.type1 .multiRange__range .multiRange__handle__value {
  background: #EC5564;
  color: white;
}
.multiRange.type1 .multiRange__range .multiRange__handle__value::after {
  border-color: #EC5564 transparent transparent;
}

body.multiRange-grabbing {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.multiRange {
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}
.multiRange__rangeWrap {
  height: 12px;
  background: #E8E8E8;
  border-radius: 3px;
  position: relative;
  z-index: 5;
}
.multiRange__range {
  height: 100%;
  position: absolute;
  right: 0;
  background: currentColor;
}
.multiRange__range:nth-child(1) {
  color: #e5b26c;
}
.multiRange__range:nth-child(2) {
  color: #d1e56c;
}
.multiRange__range:nth-child(3) {
  color: #8ae56c;
}
.multiRange__range:nth-child(4) {
  color: #6ce594;
}
.multiRange__range:nth-child(5) {
  color: #6ce5db;
}
.multiRange__range:first-child > .multiRange__handle {
  display: none;
}
.multiRange__range.grabbed > .handle {
  background: black;
}
.multiRange__range .multiRange__handle {
  width: 2px;
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: -1px;
  cursor: -webkit-grab;
  cursor: grab;
  background: currentColor;
  box-shadow: 1px 0 white, -1px 0 white;
  -webkit-transition: .2s;
  transition: .2s;
}
.multiRange__range .multiRange__handle:active {
  cursor: inherit;
}
.multiRange__range .multiRange__handle__value {
  position: absolute;
  -webkit-transform: translate(-50%, -6px);
          transform: translate(-50%, -6px);
  min-width: 10px;
  background: #333;
  color: white;
  padding: 2px 6px;
  top: -100%;
  left: 0;
  white-space: nowrap;
  font-size: 11px;
  text-align: center;
  border-radius: 4px;
  cursor: default;
}
.multiRange__range .multiRange__handle__value::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -3px;
  border-color: #333 transparent transparent;
  border-style: solid;
  border-width: 3px 4px;
  -webkit-transform: translate(-50%, 50%);
          transform: translate(-50%, 50%);
  color: #333;
  font-size: 15px;
}
.multiRange__ticks {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
      -ms-flex-pack: justify;
          justify-content: space-between;
  height: 6px;
  margin: 2px 0 0 0;
  font: 10px Arial;
  cursor: default;
}
.multiRange__ticks > div {
  height: 100%;
  width: 1px;
  background: #DDD;
  color: #888;
}
.multiRange__ticks > div:nth-child(5n - 4) {
  height: 200%;
}
.multiRange__ticks > div:nth-child(5n - 4)::before {
  display: block;
  content: attr(data-value);
  -webkit-transform: translate(-50%, 100%);
          transform: translate(-50%, 100%);
  text-align: center;
  width: 40px;
}
JS
// (C) Yair Even-Or 2017
// DO NOT COPY 

(function(){  
function extend(o1, o2){
    for( var key in o2 )
        if( o2.hasOwnProperty(key) )
            o1[key] = o2[key];
};
    
this.MultiRange = function MultiRange( placeholderElm, settings ){
    settings = typeof settings == 'object' ? settings : {}; // make sure settings is an 'object'

    this.settings = {
        minRange   : typeof settings.minRange == 'number' ? settings.minRange : 1,
        tickStep   : settings.tickStep || 5,
        step       : typeof settings.step == 'number' ? settings.step : 1,
        scale      : 100,
        min        : settings.min || 0,
        max        : settings.max || 100,
    }
    
    this.delta = this.settings.max - this.settings.min;
    
    // if "ticks" count was defined, re-calculate the "tickStep"
    if( settings.ticks )
        this.settings.tickStep = this.delta / settings.ticks;

    // a list of ranges (ex. [5,20])
    this.ranges = settings.ranges || [
        this.settings.min + this.settings.tickStep, 
        this.settings.max - this.settings.tickStep
    ]

    this.id = Math.random().toString(36).substr(2,9), // almost-random ID (because, fuck it)
    this.DOM = {}; // Store all relevant DOM elements in an Object
    extend(this, new this.EventDispatcher());
    this.build(placeholderElm);
    this.events.binding.call(this);
}

MultiRange.prototype = {
    build : function( placeholderElm ){
        var that = this,
            scopeClasses = placeholderElm.className.indexOf('multiRange') == -1 ? 
                            'multiRange ' + placeholderElm.className : 
                            placeholderElm.className; 

        this.DOM.scope = document.createElement('div');
        this.DOM.scope.className = scopeClasses;
      
        this.DOM.rangeWrap = document.createElement('div');
        this.DOM.rangeWrap.className = 'multiRange__rangeWrap';
        this.DOM.rangeWrap.innerHTML = this.getRangesHTML();

        this.DOM.ticks = document.createElement('div');
        this.DOM.ticks.className = 'multiRange__ticks';
        this.DOM.ticks.innerHTML = this.generateTicks();

        // append to Scope
        this.DOM.scope.appendChild(this.DOM.rangeWrap);
        this.DOM.scope.appendChild(this.DOM.ticks);

        // replace the placeholder component element with the real one
        placeholderElm.parentNode.replaceChild(this.DOM.scope, placeholderElm);
    },

    generateTicks(){
        var steps = (this.delta) / this.settings.tickStep,
            HTML = '',
            value, 
            i;

        for( i = 0; i <= steps; i++ ){
            value =(+this.settings.min) + this.settings.tickStep * i; // calculate tick value
            value = value.toFixed(1).replace('.0', ''); // cleaup
            HTML += '
'; } return HTML; }, getRangesHTML(){ var that = this, rangesHTML = '', ranges; this.ranges.unshift(0) // if( this.ranges[0] > this.settings.min ) // this.ranges.unshift(this.settings.min) if( this.ranges[this.ranges.length - 1] < this.settings.max ) this.ranges.push(this.settings.max); ranges = this.ranges; ranges.forEach(function(range, i){ if( i == ranges.length - 1 ) return; // skip last ltem var leftPos = (range - that.settings.min) / (that.delta) * 100; // protection.. if( leftPos < 0 ) leftPos = 0; // range = ranges[i+1] - range; rangesHTML += '
\
\
'+ range.toFixed(1).replace('.0', '') +'
\
\
'; }) return rangesHTML; }, /** * A constructor for exposing events to the outside */ EventDispatcher : function(){ // Create a DOM EventTarget object var target = document.createTextNode(''); // Pass EventTarget interface calls to DOM EventTarget object this.off = target.removeEventListener.bind(target); this.on = target.addEventListener.bind(target); this.trigger = function(eventName, data){ if( !eventName ) return; var e = new CustomEvent(eventName, {"detail":data}); target.dispatchEvent(e); } }, /** * DOM events listeners binding */ events : { binding : function(){ this.DOM.rangeWrap.addEventListener('mousedown', this.events.callbacks.onMouseDown.bind(this)) //prevent anything from being able to be dragged this.DOM.scope.addEventListener("dragstart", function(e){ return false }); // this.eventDispatcher.on('add', this.settings.callbacks.add) }, callbacks : { onMouseDown : function(e){ var target = e.target; if( !target ) return; if( target.className == 'multiRange__handle__value' ) target = target.parentNode; else if( target.className != 'multiRange__handle' ) return; // set some variables (so percentages could be calculated on mousemove) var _BCR = this.DOM.scope.getBoundingClientRect(); this.offsetLeft = _BCR.left; this.scopeWidth = _BCR.width; this.DOM.currentSlice = target.parentNode; this.DOM.currentSlice.classList.add('grabbed'); this.DOM.currentSliceValue = this.DOM.currentSlice.querySelector('.multiRange__handle__value'); document.body.classList.add('multiRange-grabbing'); // bind temporary events (save "bind" reference so events could later be removed) this.events.onMouseUpFunc = this.events.callbacks.onMouseUp.bind(this); this.events.mousemoveFunc = this.events.callbacks.onMouseMove.bind(this); window.addEventListener('mouseup', this.events.onMouseUpFunc) window.addEventListener('mousemove', this.events.mousemoveFunc) }, onMouseUp : function(e){ this.DOM.currentSlice.classList.remove('grabbed'); window.removeEventListener('mousemove', this.events.mousemoveFunc); window.removeEventListener('mouseup', this.events.onMouseUpFunc); document.body.classList.remove('multiRange-grabbing'); // publish the event var value = parseInt( this.DOM.currentSlice.style.left ); this.trigger('changed', {idx:+this.DOM.currentSlice.dataset.idx, value:value, ranges:this.ranges}) this.DOM.currentSlice = null; }, onMouseMove : function(e){ if( !this.DOM.currentSlice ){ window.removeEventListener('mouseup', this.events.onMouseUpFunc); return; } // do not continue if the mouse was overflowing of the left or the right side of the range if( e.clientX < this.offsetLeft || e.clientX > (this.offsetLeft + this.scopeWidth) ) return; var that = this, value, // the numeric value // minLeftPerc = this.settings.minRange/this.delta*100, // minRightPerc = (this.delta - this.settings.minRange)/this.delta*100, xPosScopeLeft = e.clientX - this.offsetLeft, // the left percentage value leftPrecentage = xPosScopeLeft / this.scopeWidth * 100, prevSliceValue = this.ranges[+this.DOM.currentSlice.dataset.idx - 1], nextSliceValue = this.ranges[+this.DOM.currentSlice.dataset.idx + 1]; value = this.settings.min + (this.delta/100*leftPrecentage); if( this.settings.step ){ // if( value%this.settings.step > 1 ) return; value = Math.round((value) / this.settings.step ) * this.settings.step } // make sure a slice value doesn't go above the next slice value and not below the previous one if( value < prevSliceValue + this.settings.minRange ) value = prevSliceValue + this.settings.minRange; if( value > nextSliceValue - this.settings.minRange ) value = nextSliceValue - this.settings.minRange; // define min and max move points if( value < (this.settings.min + this.settings.minRange) ) value = this.settings.min + this.settings.minRange; if( value > (this.settings.max - this.settings.minRange) ) value = this.settings.max - this.settings.minRange; leftPrecentage = (value - this.settings.min) / this.delta * 100; // update the DOM window.requestAnimationFrame(function(){ if( that.DOM.currentSlice ){ that.DOM.currentSlice.style.left = leftPrecentage + '%'; that.DOM.currentSliceValue.innerHTML = value.toFixed(1).replace('.0', ''); } }) // update "ranged" Array this.ranges[this.DOM.currentSlice.dataset.idx] = +value.toFixed(1); // publish the event this.trigger('change', {idx:+this.DOM.currentSlice.dataset.idx, value:value, ranges:this.ranges}) } } } } })(this); //////// USAGE ////// var multiRange1 = new MultiRange(document.querySelectorAll('.multiRange')[0], { ranges : [15, 44, 77, 88], step : 0 }); var multiRange2 = new MultiRange(document.querySelectorAll('.multiRange')[1], { min : 150, max : 5000, ticks : 80, step : 10, minRange : 50 }); multiRange1.on('changed', onrangeChanged); multiRange2.on('changed', onrangeChanged); function onrangeChanged(e){ console.log( e, e.detail ) }
Term
Wed, 12/06/2017 - 19:44

Related Codes

Pen ID
Pen ID
Pen ID
Square Adv