Create Price Range Slider Filter For Product Using jQuery & PHP with MySQL

Create Price Range Slider for Product Using jQuery & PHP with MySQL

Price Range Slider for Product

Go slider is exceptionally helpful to add channel highlight to the information list. Run slider, for the most part, used to channel information by value run. Value extend slider enables the client to channel the record set by choosing value run as opposed to entering the cost physically.

In this instructional exercise, we’ll make a value run slider utilizing jQuery and add channel usefulness to the information list with PHP and MySQL. The value channel is a required element in items posting and range slider is an immaculate decision for value channel. Here we’ll indicate how you can without much of a stretch add a value go slider to the items list utilizing jQuery in PHP and channel items by value run utilizing jQuery, Ajax, PHP, and MySQL.

Live Demo   Download Source Code

dbconfig.php

 

<?php
// Database configuration
$dbHost     = "localhost";
$dbUsername = "root";
$dbPassword = "";
$dbName     = "lisenme";

// Create database connection
$db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);

// Check connection
if ($db->connect_error) {
    die("Connection failed: " . $db->connect_error);
}
?>

index.php

<!DOCTYPE html>
<html lang="en">
<head>
<title>Create Price Range Slider for Product in jQuery & PHP with MySQL by lisenme</title>
<style>
.container{padding: 20px;}
.filter-panel{width:100%;}
.filter-panel p{margin-right: 30px;float: left;}
#productContainer{float: left;width: 100%;}
.list-item{
    float: left;
    width: 15%;
    height: 80px;
    padding: 10px;
    border: 2px solid #cacaca;
    margin: 10px 10px 10px 0px;
}
.list-item h2{margin: 0;}
</style>
<link rel="stylesheet" href="jquery.range.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="jquery.range.js"></script>
<script>
function filterProducts() {
    var price_range = $('.price_range').val();
    $.ajax({
        type: 'POST',
        url: 'getProducts.php',
        data:'price_range='+price_range,
        beforeSend: function () {
            $('.container').css("opacity", ".5");
        },
        success: function (html) {
            $('#productContainer').html(html);
            $('.container').css("opacity", "");
        }
    });
}
</script>
</head>
<body>
<h1>Create Price Range Slider For Product in JQuery & PHP with MySQL</h1>
<div class="container">
    <div class="filter-panel">
        <p><input type="hidden" class="price_range" value="0,500" /></p>
        <input type="button" onclick="filterProducts()" value="FILTER" />
    </div>
    <div id="productContainer">
        <?php
        //Include database configuration file
        include('dbConfig.php');
        
        //get product rows
        $query = $db->query("SELECT * FROM products ORDER BY created DESC");
        
        if($query->num_rows > 0){
                while($row = $query->fetch_assoc()){
            ?>
                <div class="list-item">
                    <h2><?php echo $row["name"]; ?></h2>
                    <h4>Price: <?php echo $row["price"]; ?></h4>
                </div>
        <?php }
        }else{
            echo 'Product(s) not found';
        } ?>
    </div>
</div>

<script>
$('.price_range').jRange({
    from: 0,
    to: 500,
    step: 50,
    format: '%s USD',
    width: 1150,
    showLabels: true,
    isRange : true
});
</script>
</body>
</html>

products.php

<?php
if(isset($_POST['price_range'])){
    
    //Include database configuration file
    include('dbConfig.php');
    
    //set conditions for filter by price range
    $whereSQL = $orderSQL = '';
    $priceRange = $_POST['price_range'];
    if(!empty($priceRange)){
        $priceRangeArr = explode(',', $priceRange);
        $whereSQL = "WHERE price BETWEEN '".$priceRangeArr[0]."' AND '".$priceRangeArr[1]."'";
        $orderSQL = " ORDER BY price ASC ";
    }else{
        $orderSQL = " ORDER BY created DESC ";
    }
    
    //get product rows
    $query = $db->query("SELECT * FROM products $whereSQL $orderSQL");
    
    if($query->num_rows > 0){
        while($row = $query->fetch_assoc()){
    ?>
        <div class="list-item">
            <h2><?php echo $row["name"]; ?></h2>
            <h4>Price: <?php echo $row["price"]; ?></h4>
        </div>
    <?php }
    }else{
        echo 'Product(s) not found';
    }
}
?>

jquery.js

(function($, window, document, undefined) {
	'use strict';

	var jRange = function() {
		return this.init.apply(this, arguments);
	};
	jRange.prototype = {
		defaults: {
			onstatechange: function() {},
      ondragend: function() {},
      onbarclicked: function() {},
			isRange: false,
			showLabels: true,
			showScale: true,
			step: 1,
			format: '%s',
			theme: 'theme-green',
			width: 300,
			disable: false,
			snap: false
		},
		template: '<div class="slider-container">\
			<div class="back-bar">\
                <div class="selected-bar"></div>\
                <div class="pointer low"></div><div class="pointer-label low">123456</div>\
                <div class="pointer high"></div><div class="pointer-label high">456789</div>\
                <div class="clickable-dummy"></div>\
            </div>\
            <div class="scale"></div>\
		</div>',
		init: function(node, options) {
			this.options       = $.extend({}, this.defaults, options);
			this.inputNode     = $(node);
			this.options.value = this.inputNode.val() || (this.options.isRange ? this.options.from + ',' + this.options.from : '' + this.options.from);
			this.domNode       = $(this.template);
			this.domNode.addClass(this.options.theme);
			this.inputNode.after(this.domNode);
			this.domNode.on('change', this.onChange);
			this.pointers      = $('.pointer', this.domNode);
			this.lowPointer    = this.pointers.first();
			this.highPointer   = this.pointers.last();
			this.labels        = $('.pointer-label', this.domNode);
			this.lowLabel      = this.labels.first();
			this.highLabel     = this.labels.last();
			this.scale         = $('.scale', this.domNode);
			this.bar           = $('.selected-bar', this.domNode);
			this.clickableBar  = this.domNode.find('.clickable-dummy');
			this.interval      = this.options.to - this.options.from;
			this.render();
		},
		render: function() {
			// Check if inputNode is visible, and have some width, so that we can set slider width accordingly.
			if (this.inputNode.width() === 0 && !this.options.width) {
				console.log('jRange : no width found, returning');
				return;
			} else {
				this.options.width = this.options.width || this.inputNode.width();
				this.domNode.width(this.options.width);
				this.inputNode.hide();
			}

			if (this.isSingle()) {
				this.lowPointer.hide();
				this.lowLabel.hide();
			}
			if (!this.options.showLabels) {
				this.labels.hide();
			}
			this.attachEvents();
			if (this.options.showScale) {
				this.renderScale();
			}
			this.setValue(this.options.value);
		},
		isSingle: function() {
			if (typeof(this.options.value) === 'number') {
				return true;
			}
			return (this.options.value.indexOf(',') !== -1 || this.options.isRange) ?
				false : true;
		},
		attachEvents: function() {
			this.clickableBar.click($.proxy(this.barClicked, this));
			this.pointers.on('mousedown touchstart', $.proxy(this.onDragStart, this));
			this.pointers.bind('dragstart', function(event) {
				event.preventDefault();
			});
		},
		onDragStart: function(e) {
			if ( this.options.disable || (e.type === 'mousedown' && e.which !== 1)) {
				return;
			}
			e.stopPropagation();
			e.preventDefault();
			var pointer = $(e.target);
			this.pointers.removeClass('last-active');
			pointer.addClass('focused last-active');
			this[(pointer.hasClass('low') ? 'low' : 'high') + 'Label'].addClass('focused');
			$(document).on('mousemove.slider touchmove.slider', $.proxy(this.onDrag, this, pointer));
			$(document).on('mouseup.slider touchend.slider touchcancel.slider', $.proxy(this.onDragEnd, this));
		},
		onDrag: function(pointer, e) {
			e.stopPropagation();
			e.preventDefault();

			if (e.originalEvent.touches && e.originalEvent.touches.length) {
				e = e.originalEvent.touches[0];
			} else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
				e = e.originalEvent.changedTouches[0];
			}

			var position = e.clientX - this.domNode.offset().left;
			this.domNode.trigger('change', [this, pointer, position]);
		},
		onDragEnd: function(e) {
			this.pointers.removeClass('focused')
				.trigger('rangeslideend');
			this.labels.removeClass('focused');
			$(document).off('.slider');
		  this.options.ondragend.call(this, this.options.value);
		},
		barClicked: function(e) {
			if(this.options.disable) return;
			var x = e.pageX - this.clickableBar.offset().left;
			if (this.isSingle())
				this.setPosition(this.pointers.last(), x, true, true);
			else {
				var firstLeft      	= Math.abs(parseFloat(this.pointers.first().css('left'), 10)),
						firstHalfWidth 	= this.pointers.first().width() / 2,
						lastLeft 			 	= Math.abs(parseFloat(this.pointers.last().css('left'), 10)),
						lastHalfWidth  	= this.pointers.first().width() / 2,
						leftSide        = Math.abs(firstLeft - x + firstHalfWidth),
						rightSide       = Math.abs(lastLeft - x + lastHalfWidth),
						pointer;

				if(leftSide == rightSide) {
					pointer = x < firstLeft ? this.pointers.first() : this.pointers.last();
				} else {
					pointer = leftSide < rightSide ? this.pointers.first() : this.pointers.last();
				}
				this.setPosition(pointer, x, true, true);
			}
			this.options.onbarclicked.call(this, this.options.value);
		},
		onChange: function(e, self, pointer, position) {
			var min, max;
			min = 0;
			max = self.domNode.width();

			if (!self.isSingle()) {
				min = pointer.hasClass('high') ? parseFloat(self.lowPointer.css("left")) + (self.lowPointer.width() / 2) : 0;
				max = pointer.hasClass('low') ? parseFloat(self.highPointer.css("left")) + (self.highPointer.width() / 2) : self.domNode.width();
			}

			var value = Math.min(Math.max(position, min), max);
			self.setPosition(pointer, value, true);
		},
		setPosition: function(pointer, position, isPx, animate) {
			var leftPos, rightPos,
				lowPos = parseFloat(this.lowPointer.css("left")),
				highPos = parseFloat(this.highPointer.css("left")) || 0,
				circleWidth = this.highPointer.width() / 2;
			if (!isPx) {
				position = this.prcToPx(position);
			}
			if(this.options.snap){
				var expPos = this.correctPositionForSnap(position);
				if(expPos === -1){
					return;
				}else{
					position = expPos;
				}
			}
			if (pointer[0] === this.highPointer[0]) {
				highPos = Math.round(position - circleWidth);
			} else {
				lowPos = Math.round(position - circleWidth);
			}
			pointer[animate ? 'animate' : 'css']({
				'left': Math.round(position - circleWidth)
			});
			if (this.isSingle()) {
				leftPos = 0;
			} else {
				leftPos = lowPos + circleWidth;
				rightPos = highPos + circleWidth;
			}
			var w = Math.round(highPos + circleWidth - leftPos);
			this.bar[animate ? 'animate' : 'css']({
				'width': Math.abs(w),
				'left': (w>0) ? leftPos : leftPos + w
			});
			this.showPointerValue(pointer, position, animate);
			this.isReadonly();
		},
		correctPositionForSnap: function(position){
			var currentValue = this.positionToValue(position) - this.options.from;
			var diff = this.options.width / (this.interval / this.options.step),
				expectedPosition = (currentValue / this.options.step) * diff;
			if( position <= expectedPosition + diff / 2 && position >= expectedPosition - diff / 2){
				return expectedPosition;
			}else{
				return -1;
			}
		},
		// will be called from outside
		setValue: function(value) {
			var values = value.toString().split(',');
			values[0] = Math.min(Math.max(values[0], this.options.from), this.options.to) + '';
			if (values.length > 1){
				values[1] = Math.min(Math.max(values[1], this.options.from), this.options.to) + '';
			}
			this.options.value = value;
			var prc = this.valuesToPrc(values.length === 2 ? values : [0, values[0]]);
			if (this.isSingle()) {
				this.setPosition(this.highPointer, prc[1]);
			} else {
				this.setPosition(this.lowPointer, prc[0]);
				this.setPosition(this.highPointer, prc[1]);
			}
		},
		renderScale: function() {
			var s = this.options.scale || [this.options.from, this.options.to];
			var prc = Math.round((100 / (s.length - 1)) * 10) / 10;
			var str = '';
			for (var i = 0; i < s.length; i++) {
				str += '<span style="left: ' + i * prc + '%">' + (s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '') + '</span>';
			}
			this.scale.html(str);

			$('ins', this.scale).each(function() {
				$(this).css({
					marginLeft: -$(this).outerWidth() / 2
				});
			});
		},
		getBarWidth: function() {
			var values = this.options.value.split(',');
			if (values.length > 1) {
				return parseFloat(values[1]) - parseFloat(values[0]);
			} else {
				return parseFloat(values[0]);
			}
		},
		showPointerValue: function(pointer, position, animate) {
			var label = $('.pointer-label', this.domNode)[pointer.hasClass('low') ? 'first' : 'last']();
			var text;
			var value = this.positionToValue(position);
			// Is it higer or lower than it should be?

			if ($.isFunction(this.options.format)) {
				var type = this.isSingle() ? undefined : (pointer.hasClass('low') ? 'low' : 'high');
				text = this.options.format(value, type);
			} else {
				text = this.options.format.replace('%s', value);
			}

			var width = label.html(text).width(),
				left = position - width / 2;
			left = Math.min(Math.max(left, 0), this.options.width - width);
			label[animate ? 'animate' : 'css']({
				left: left
			});
			this.setInputValue(pointer, value);
		},
		valuesToPrc: function(values) {
			var lowPrc = ((parseFloat(values[0]) - parseFloat(this.options.from)) * 100 / this.interval),
				highPrc = ((parseFloat(values[1]) - parseFloat(this.options.from)) * 100 / this.interval);
			return [lowPrc, highPrc];
		},
		prcToPx: function(prc) {
			return (this.domNode.width() * prc) / 100;
		},
		isDecimal: function() {
			return ((this.options.value + this.options.from + this.options.to).indexOf(".")===-1) ? false : true;
		},
		positionToValue: function(pos) {
			var value = (pos / this.domNode.width()) * this.interval;
			value = parseFloat(value, 10) + parseFloat(this.options.from, 10);
			if (this.isDecimal()) {
				var final = Math.round(Math.round(value / this.options.step) * this.options.step *100)/100;
				if (final!==0.0) {
					final = '' + final;
					if (final.indexOf(".")===-1) {
						final = final + ".";
					}
					while (final.length - final.indexOf('.')<3) {
						final = final + "0";
					}
				} else {
					final = "0.00";
				}
				return final;
			} else {
				return Math.round(value / this.options.step) * this.options.step;
			}
		},
		setInputValue: function(pointer, v) {
			// if(!isChanged) return;
			if (this.isSingle()) {
				this.options.value = v.toString();
			} else {
				var values = this.options.value.split(',');
				if (pointer.hasClass('low')) {
					this.options.value = v + ',' + values[1];
				} else {
					this.options.value = values[0] + ',' + v;
				}
			}
			if (this.inputNode.val() !== this.options.value) {
				this.inputNode.val(this.options.value)
					.trigger('change');
				this.options.onstatechange.call(this, this.options.value);
			}
		},
		getValue: function() {
			return this.options.value;
		},
		getOptions: function() {
			return this.options;
		},
		getRange: function() {
			return this.options.from + "," + this.options.to;
		},
		isReadonly: function(){
			this.domNode.toggleClass('slider-readonly', this.options.disable);
		},
		disable: function(){
			this.options.disable = true;
			this.isReadonly();
		},
		enable: function(){
			this.options.disable = false;
			this.isReadonly();
		},
		toggleDisable: function(){
			this.options.disable = !this.options.disable;
			this.isReadonly();
		},
		updateRange: function(range, value) {
			var values = range.toString().split(',');
			this.interval = parseInt(values[1]) - parseInt(values[0]);
			if(value){
				this.setValue(value);
			}else{
				this.setValue(this.getValue());
			}
		}
	};

	var pluginName = 'jRange';
	// A really lightweight plugin wrapper around the constructor,
	// preventing against multiple instantiations
	$.fn[pluginName] = function(option) {
		var args = arguments,
			result;

		this.each(function() {
			var $this = $(this),
				data = $.data(this, 'plugin_' + pluginName),
				options = typeof option === 'object' && option;
			if (!data) {
				$this.data('plugin_' + pluginName, (data = new jRange(this, options)));
				$(window).resize(function() {
					data.setValue(data.getValue());
				}); // Update slider position when window is resized to keep it in sync with scale
			}
			// if first argument is a string, call silimarly named function
			// this gives flexibility to call functions of the plugin e.g.
			//   - $('.dial').plugin('destroy');
			//   - $('.dial').plugin('render', $('.new-child'));
			if (typeof option === 'string') {
				result = data[option].apply(data, Array.prototype.slice.call(args, 1));
			}
		});

		// To enable plugin returns values
		return result || this;
	};

})(jQuery, window, document);

style.css

.slider-container {
  width: 300px;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.slider-container .back-bar {
  height: 10px;
  position: relative;
}
.slider-container .back-bar .selected-bar {
  position: absolute;
  height: 100%;
}
.slider-container .back-bar .pointer {
  position: absolute;
  width: 10px;
  height: 10px;
  background-color: red;
  cursor: col-resize;
  opacity: 1;
  z-index: 2;
}
.slider-container .back-bar .pointer.last-active {
  z-index: 3;
}
.slider-container .back-bar .pointer-label {
  position: absolute;
  top: -17px;
  font-size: 8px;
  background: white;
  white-space: nowrap;
  line-height: 1;
}
.slider-container .back-bar .focused {
  z-index: 10;
}
.slider-container .clickable-dummy {
  cursor: pointer;
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 1;
}
.slider-container .scale {
  top: 2px;
  position: relative;
}
.slider-container .scale span {
  position: absolute;
  height: 5px;
  border-left: 1px solid #999;
  font-size: 0;
}
.slider-container .scale ins {
  font-size: 9px;
  text-decoration: none;
  position: absolute;
  left: 0;
  top: 5px;
  color: #999;
  line-height: 1;
}
.slider-container.slider-readonly .clickable-dummy,
.slider-container.slider-readonly .pointer {
  cursor: auto;
}
.theme-green .back-bar {
  height: 5px;
  border-radius: 2px;
  background-color: #eeeeee;
  background-color: #e7e7e7;
  background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#eeeeee), to(#dddddd));
  background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
  background-image: linear-gradient(to bottom, #eeeeee, #dddddd);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffdddddd', GradientType=0);
}
.theme-green .back-bar .selected-bar {
  border-radius: 2px;
  background-color: #a1fad0;
  background-image: -moz-linear-gradient(top, #bdfade, #76fabc);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#bdfade), to(#76fabc));
  background-image: -webkit-linear-gradient(top, #bdfade, #76fabc);
  background-image: -o-linear-gradient(top, #bdfade, #76fabc);
  background-image: linear-gradient(to bottom, #bdfade, #76fabc);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbdfade', endColorstr='#ff76fabc', GradientType=0);
}
.theme-green .back-bar .pointer {
  width: 14px;
  height: 14px;
  top: -5px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  border-radius: 10px;
  border: 1px solid #AAA;
  background-color: #e7e7e7;
  background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#eeeeee), to(#dddddd));
  background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
  background-image: linear-gradient(to bottom, #eeeeee, #dddddd);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffdddddd', GradientType=0);
}
.theme-green .back-bar .pointer-label {
  color: #999;
}
.theme-green .back-bar .focused {
  color: #333;
}
.theme-green .scale span {
  border-left: 1px solid #e5e5e5;
}
.theme-green .scale ins {
  color: #999;
}
.theme-blue .back-bar {
  height: 5px;
  border-radius: 2px;
  background-color: #eeeeee;
  background-color: #e7e7e7;
  background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#eeeeee), to(#dddddd));
  background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
  background-image: linear-gradient(to bottom, #eeeeee, #dddddd);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffdddddd', GradientType=0);
}
.theme-blue .back-bar .selected-bar {
  border-radius: 2px;
  background-color: #92c1f9;
  background-image: -moz-linear-gradient(top, #b1d1f9, #64a8f9);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b1d1f9), to(#64a8f9));
  background-image: -webkit-linear-gradient(top, #b1d1f9, #64a8f9);
  background-image: -o-linear-gradient(top, #b1d1f9, #64a8f9);
  background-image: linear-gradient(to bottom, #b1d1f9, #64a8f9);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffb1d1f9', endColorstr='#ff64a8f9', GradientType=0);
}
.theme-blue .back-bar .pointer {
  width: 14px;
  height: 14px;
  top: -5px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  border-radius: 10px;
  border: 1px solid #AAA;
  background-color: #e7e7e7;
  background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#eeeeee), to(#dddddd));
  background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
  background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
  background-image: linear-gradient(to bottom, #eeeeee, #dddddd);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffdddddd', GradientType=0);
}
.theme-blue .back-bar .pointer-label {
  color: #999;
}
.theme-blue .back-bar .focused {
  color: #333;
}
.theme-blue .scale span {
  border-left: 1px solid #e5e5e5;
}
.theme-blue .scale ins {
  color: #999;
}

 

You May Also Like

About the Author: Ranjith Kumar A

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x