ساخت فیلتر محصولات با جاوا اسکرپیت و کوئری PHP

ساخت فیلتر محصولات با جاوا اسکرپیت و کوئری PHP

فیلتر محصولات PHP و جاوا اسکریپت – در این آموزش از javascript برای ساخت کنترل فرم فیلتر استفاده می کنیم و در پایان اطلاعات فیلتر را به صورت query string در آدرس URL می آوریم و امکان استفاده از این اطلاعات در PHP با سوپر گلوبال GET_$ امکان پذیر می باشد .

دموی فیلتر محصولات


در این آموزش از کتابخانه های جاوا اسکریپت select2 , persian date picker , Ion.RangeSlider و … استفاده می کنیم بنابراین می توانید کل پروژه را از اینجا دانلود کنید .

فایل index.html

<!DOCTYPE html>
<html lang="fa" dir="rtl">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Premium Multipurpose Admin & Dashboard Template">
    <title>فیلتر حرفه ای با query string - رپید کد</title>


    <link href="https://rapidcode.ir/wp-content/themes/rapidcode/static/image/sample/Logo.png" id="favicon.ico"
        rel="shortcut icon" type="ico">
    <link href="assets/css/bootstrap.min.css" id="bootstrap.all.min" rel="stylesheet" type="text/css">
    <link href="assets/css/icons.css" id="icons" rel="stylesheet" type="text/css">
    <link href="assets/css/sweetalert2.min.css" id="sweetalert2" rel="stylesheet" type="text/css">
    <link href="assets/css/select2.min.css" id="select2" rel="stylesheet" type="text/css">
    <link href="assets/css/persian-datepicker.min.css" id="datepicker.jalali" rel="stylesheet" type="text/css">
    <link href="assets/css/persian-datepicker-custom.min.css" id="datepicker.jalali.theme" rel="stylesheet"
        type="text/css">
    <link href="assets/css/ion.rangeSlider.min.css" id="ion.rangeSlider" rel="stylesheet" type="text/css">
    <link href="assets/css/app.css" id="app" rel="stylesheet" type="text/css">
    <link href="assets/custom/main.css" id="main" rel="stylesheet" type="text/css">
</head>

<body data-layout="detached" data-topbar="colored" class="product_list_php">

    <div class="container-fluid">
        <!-- Begin page -->
        <div id="layout-wrapper">

            <header id="page-topbar">
                <div class="navbar-header">
                    <div class="container-fluid">
                        <div class="float-right">

                            <div class="dropdown d-inline-block d-lg-none ml-2">
                                <button type="button" class="btn header-item noti-icon waves-effect"
                                    id="page-header-search-dropdown" data-toggle="dropdown" aria-haspopup="true"
                                    aria-expanded="false">
                                    <i class="mdi mdi-magnify"></i>
                                </button>
                                <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right p-0"
                                    aria-labelledby="page-header-search-dropdown">

                                    <form class="p-3">
                                        <div class="form-group m-0">
                                            <div class="input-group">
                                                <input type="text" class="form-control" placeholder="جستجو ..."
                                                    aria-label="Recipient's username">
                                                <div class="input-group-append">
                                                    <button class="btn btn-primary" type="submit"><i
                                                            class="mdi mdi-magnify"></i></button>
                                                </div>
                                            </div>
                                        </div>
                                    </form>
                                </div>
                            </div>



                            <div class="dropdown d-none d-lg-inline-block ml-1">
                                <button type="button" class="btn header-item noti-icon waves-effect"
                                    data-toggle="fullscreen">
                                    <i class="mdi mdi-fullscreen"></i>
                                </button>
                            </div>

                            <div class="dropdown d-inline-block">
                                <button type="button" class="btn header-item waves-effect"
                                    id="page-header-user-dropdown" data-toggle="dropdown" aria-haspopup="true"
                                    aria-expanded="false">
                                    <img class="rounded-circle header-profile-user"
                                        src="https://secure.gravatar.com/avatar/0c55399c2cb5d0deb2b1c5420ee0d49c?s=256&d=mm&r=g"
                                        alt="Header Avatar">
                                    <span class="d-none d-xl-inline-block ml-1">حسین باقری</span>
                                    <i class="mdi mdi-chevron-down d-none d-xl-inline-block"></i>
                                </button>
                                <div class="dropdown-menu dropdown-menu-right">
                                    <!-- item-->
                                    <a class="dropdown-item" href="#"><i
                                            class="bx bx-user font-size-16 align-middle mr-1"></i> پروفایل</a>
                                    <div class="dropdown-divider"></div>
                                    <a class="dropdown-item text-danger" href="#"><i
                                            class="bx bx-power-off font-size-16 align-middle mr-1 text-danger"></i>
                                        خروج</a>
                                </div>
                            </div>

                        </div>
                        <div>
                            <!-- LOGO -->
                            <div class="navbar-brand-box">
                                <a href="index-2.html" class="logo logo-dark">
                                    <span class="logo-sm">
                                        <img src="https://rapidcode.ir/wp-content/themes/rapidcode/static/image/sample/Logo.png"
                                            alt="" height="20">
                                    </span>
                                    <span class="logo-lg">
                                        <img src="https://rapidcode.ir/wp-content/themes/rapidcode/static/image/sample/Logo.png"
                                            alt="" height="17">
                                    </span>
                                </a>

                                <a href="/" class="logo logo-light">
                                    <span class="logo-sm">
                                        <img src="https://rapidcode.ir/wp-content/themes/rapidcode/static/image/sample/Logo.png"
                                            alt="" height="20">
                                    </span>
                                    <span class="logo-lg">
                                        <img src="https://rapidcode.ir/wp-content/themes/rapidcode/static/image/sample/Logo.png"
                                            alt="" height="55">
                                    </span>
                                </a>
                            </div>

                            <button type="button"
                                class="btn btn-sm px-3 font-size-16 header-item toggle-btn waves-effect"
                                id="vertical-menu-btn">
                                <i class="fa fa-fw fa-bars"></i>
                            </button>

                        </div>

                    </div>
                </div>
            </header>
            <!-- ============================================================== -->
            <!-- Start right Content here -->
            <!-- ============================================================== -->
            <div class="main-content">

                <div class="page-content">

                    <!-- start page title -->
                    <div class="row">
                        <div class="col-12">
                            <div class="page-title-box d-flex align-items-center justify-content-between">
                                <h4 class="page-title mb-0 font-size-18">لیست محصولات</h4>
                            </div>
                        </div>
                    </div>
                    <!-- end page title -->

                    <div class="row">
                        <div class="col-xl-12">

                            <div class="row">

                                <div class="col-md-12">
                                    <div class="card">
                                        <div class="card-body">

                                            <form data-route="index.html" action="" id="filter-form" method="post"
                                                novalidate>

                                                <a href="#block-wrapper-filter" data-toggle="collapse">
                                                    <h4 class="col-12 text-sm-center btn btn-info">فیلتر</h4>
                                                </a>

                                                <div class="collapse" id="block-wrapper-filter"
                                                    data-parent="#filter-form">
                                                    <div class="row" id="filter-wrapper">
                                                        <div class="filter-checklist">

                                                            <div class="select2-wrapper sort-wrapper input-wrapper active"
                                                                data-name="sort">
                                                                <select id="sort-select2" class="select2">
                                                                    <input type="text" id="sort"
                                                                        class="ds-none the-value select2-content-list"
                                                                        value="">
                                                                </select>
                                                            </div>

                                                            <button type="button" id="clear-filter"
                                                                class="btn btn-danger waves-effect waves-light">پاکسازی
                                                                فیلتر</button>

                                                            <div class="btn-group dropright">
                                                                <button type="button"
                                                                    class="btn btn-info waves-effect waves-light dropdown-toggle"
                                                                    data-toggle="dropdown" aria-haspopup="true"
                                                                    aria-expanded="false">
                                                                    <i class="mdi mdi-chevron-right"></i>فیلتر بر اساس
                                                                </button>
                                                                <div class="switch-list dropdown-menu">

                                                                </div>
                                                            </div>

                                                        </div>

                                                    </div>
                                                    <div class="text-sm-right mb-5">
                                                        <button type="submit"
                                                            class="btn btn-lg btn-block btn-success">جستجو</button>
                                                    </div>
                                                </div>

                                            </form>

                                            <table id="datatable-product-list" class="datatable table table-bordered"
                                                data-options='{"columnDefs":[{"orderable":false,"targets":13},{"orderable":false,"targets":1}]}'>
                                                <thead>
                                                    <tr>
                                                        <th data-filter data-input="numberSeperator" data-name="id">شناسه
                                                        </th>
                                                        <th data-name="thumbnail">تصویر</th>
                                                        <th data-filter data-input="text" data-name="title">عنوان</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":500000000,"from":0,"to":499000000,"step":10,"prefix":"<span class=\"d-inline-block\">تومان</span> "}'
                                                            data-name="price">قیمت (تومان)</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":10000000,"from":0,"to":9990000,"step":10,"prefix":"<span class=\"d-inline-block\">فروش</span> "}'
                                                            data-name="sale_count">تعداد فروش</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":10000000,"from":0,"to":9990000,"step":10,"prefix":"<span class=\"d-inline-block\">موجودی</span> "}'
                                                            data-name="entity">موجودی</th>
                                                        <th data-filter data-input="selectMultiple"
                                                            data-values='["<option selected value=\"1\">موجود</option>","<option value=\"0\">ناموجود</option>"]'
                                                            data-name="entity_x_val">وضعیت موجودی</th>
                                                        <th data-filter data-input="selectMultiple"
                                                            data-values='["<option selected value=\"1\">منتشرشده</option>","<option value=\"2\">ناموجود دستی</option>","<option value=\"3\">پیش نویس</option>"]'
                                                            data-name="status_page">وضعیت صفحه</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":10000000,"from":0,"to":9990000,"step":10,"prefix":"<span class=\"d-inline-block\">عدد پرسش</span> "}'
                                                            data-name="comments_questions_count">تعداد پرسش ها</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":10000000,"from":0,"to":9990000,"step":10,"prefix":"<span class=\"d-inline-block\">عدد رتبه</span> "}'
                                                            data-name="comments_rate_count">تعداد رتبه ها</th>
                                                        <th data-filter data-input="numberRange"
                                                            data-options='{"min":0,"max":5,"from":1,"to":4.8,"step":0.1,"prefix":"<span class=\"d-inline-block\">رتبه</span> "}'
                                                            data-name="comments_rate">رتبه</th>
                                                        <th data-filter data-input="dateRange"
                                                            data-options='{"timePicker": {"enabled": false}}'
                                                            data-name="timestamp_created_at">تاریخ انتشار</th>
                                                        <th data-filter data-input="dateRange"
                                                            data-options='{"timePicker": {"enabled": false}}'
                                                            data-name="timestamp_updated_at">تاریخ بروزرسانی</th>
                                                        <th>عملیات</th>
                                                    </tr>
                                                </thead>

                                                <tbody>


                                                    <tr>
                                                        <td data-seperator="true">1336</td>
                                                        <td><img width="70"
                                                                src="https://dkstatics-public.digikala.com/digikala-products/9db64cde85334e3bf4a6571547d339c57867f11f_1634032209.jpg?x-oss-process=image/resize,m_lfit,h_300,w_300/quality,q_80">
                                                        </td>
                                                        <td>گوشی موبایل اپل مدل iPhone 13 A2634 دو سیم‌ کارت ظرفیت 128
                                                            گیگابایت و رم 4 گیگابایت</td>
                                                        <td data-seperator="true">32999000</td>
                                                        <td data-seperator="true">3201</td>
                                                        <td data-seperator="true">0</td>
                                                        <td>
                                                            <div class="badge badge-large badge-pill badge-danger">
                                                                ناموجود</div>
                                                        </td>
                                                        <td>ناموجود پویا</td>
                                                        <td data-seperator="true">6446</td>
                                                        <td data-seperator="true">5542</td>
                                                        <td>4.8</td>
                                                        <td data-value="1651918585" data-date-persianed="true">
                                                            1401-02-17 14:46:25</td>
                                                        <td data-value="1651918590" data-date-persianed="true">
                                                            1401-02-17 14:46:30</td>
                                                        <td>
                                                            <form action="" method="POST">
                                                                <input type="hidden" name="product_id" value="1336">
                                                                <a href="edit"
                                                                    class="btn btn-info waves-effect waves-light table-action-button"
                                                                    id="action_edit">ویرایش</a>
                                                                <input
                                                                    class="btn btn-danger waves-effect waves-light table-action-button"
                                                                    name="action_delete" id="action_delete"
                                                                    type="button" value="حذف">
                                                            </form>
                                                        </td>
                                                    </tr>

                                                    <tr>
                                                        <td data-seperator="true">17</td>
                                                        <td><img width="70"
                                                                src="https://dkstatics-public.digikala.com/digikala-products/6207b3bf015d7fff97e9e04868497ac6a30474a3_1630140408.jpg?x-oss-process=image/resize,m_lfit,h_300,w_300/quality,q_90">
                                                        </td>
                                                        <td>گوشی موبایل سامسونگ مدل Galaxy A12 Nacho SM-A127F/DS</td>
                                                        <td data-seperator="true">3689000</td>
                                                        <td data-seperator="true">200</td>
                                                        <td data-seperator="true">15</td>
                                                        <td>
                                                            <div class="badge badge-large badge-pill badge-success">
                                                                موجود</div>
                                                        </td>
                                                        <td>منتشر شده</td>
                                                        <td data-seperator="true">4</td>
                                                        <td data-seperator="true">5</td>
                                                        <td>4.5</td>
                                                        <td data-value="1651918685" data-date-persianed="true">
                                                            1401-02-17 14:48:05</td>
                                                        <td data-value="1651918690" data-date-persianed="true">
                                                            1401-02-17 14:48:10</td>
                                                        <td>
                                                            <form action="" method="POST">
                                                                <input type="hidden" name="product_id" value="17">
                                                                <a href="edit"
                                                                    class="btn btn-info waves-effect waves-light table-action-button"
                                                                    id="action_edit">ویرایش</a>
                                                                <input
                                                                    class="btn btn-danger waves-effect waves-light table-action-button"
                                                                    name="action_delete" id="action_delete"
                                                                    type="button" value="حذف">
                                                            </form>
                                                        </td>
                                                    </tr>

                                                    <tr>
                                                        <td data-seperator="true">18</td>
                                                        <td><img width="70"
                                                                src="https://dkstatics-public.digikala.com/digikala-products/ac6a9c2f04fc386e2d42b4ffdecef759259d0e83_1645449789.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/quality,q_90">
                                                        </td>
                                                        <td>گوشی موبایل شیائومی مدل Redmi Note 11 دو سیم‌ کارت ظرفیت 128
                                                            گیگابایت و رم 6 گیگابایت</td>
                                                        <td data-seperator="true">5399000</td>
                                                        <td data-seperator="true">131</td>
                                                        <td data-seperator="true">5</td>
                                                        <td>
                                                            <div class="badge badge-large badge-pill badge-success">
                                                                موجود</div>
                                                        </td>
                                                        <td>ناموجود دستی</td>
                                                        <td data-seperator="true">13</td>
                                                        <td data-seperator="true">19</td>
                                                        <td>4.7</td>
                                                        <td data-value="1651918785" data-date-persianed="true">
                                                            1401-02-17 14:49:45</td>
                                                        <td data-value="1651918790" data-date-persianed="true">
                                                            1401-02-17 14:49:50</td>
                                                        <td>
                                                            <form action="" method="POST">
                                                                <input type="hidden" name="product_id" value="18">
                                                                <a href="edit"
                                                                    class="btn btn-info waves-effect waves-light table-action-button"
                                                                    id="action_edit">ویرایش</a>
                                                                <input
                                                                    class="btn btn-danger waves-effect waves-light table-action-button"
                                                                    name="action_delete" id="action_delete"
                                                                    type="button" value="حذف">
                                                            </form>
                                                        </td>
                                                    </tr>


                                                </tbody>

                                            </table>

                                        </div>
                                    </div>

                                </div>

                            </div>

                        </div>

                    </div>
                    <!-- End row -->

                </div>
                <!-- End Page-content -->
                <!-- end main content-->
                <footer class="footer">
                    <div class="container-fluid">
                        <div class="row">
                            <div class="col-sm-6">
                                <div class="text-sm-right d-none d-sm-block">
                                    <script>
                                        document.write(new Date().getFullYear())
                                    </script> © RapidCode.iR
                                </div>
                            </div>
                            <div class="col-sm-6">
                                <div class="text-sm-right d-none d-sm-block">
                                    کتابخانه مجازی برنامه نویسان - رپید کد
                                </div>
                            </div>
                        </div>
                    </div>
                </footer>
            </div>

        </div>
        <!-- END layout-wrapper -->
    </div>
    <!-- end container-fluid -->

    <script id="jquery" src="assets/js/jquery.min.js"></script>
    <script id="bootstrap.bundle.min" src="assets/js/bootstrap.bundle.min.js"></script>
    <script id="app.init" src="assets/custom/app.init.js"></script>
    <script id="sweetalert2" src="assets/js/sweetalert2.min.js"></script>
    <script id="select2" src="assets/js/select2.min.js"></script>
    <script id="select2FaSrc" src="assets/js/i18n/fa.min.js"></script>
    <script id="datepicker.jalali.date" src="assets/js/persian-date.min.js"></script>
    <script id="datepicker.jalali" src="assets/js/persian-datepicker.min.js"></script>
    <script id="ion.rangeSlider" src="assets/js/ion.rangeSlider.min.js"></script>
    <script id="product.list.min" src="assets/custom/product.list.js"></script>

</body>

</html>


استایل main.css

/* ================> page=* */

.ds-none{
    display: none;
}

table {
    width: 100%;
}

.form-group {
    overflow: hidden;
    border: 1px solid #d8d8d8;
    padding: 5px
}

.drag-top {
    position: relative;
    top: -20px;
}

.select2-results__option[aria-selected],
.select2-container--default .select2-results__option[aria-selected=true] {
    background-color: #f1f1f1;
}

/* ================> page=product.list.php */

.table td, .table th{
    padding: 0.45rem;
}

#filter-wrapper{
    box-shadow: 0 0 5px #e5e5e5;
    border-radius: 4px;
    padding: 25px 21px 21px 21px;
    margin-bottom: 25px;
    position: relative;
    min-height: 100px;
}

#filter-wrapper .filter-checklist{
    display: block;
    text-align: left;
    width: 100%;
    position: relative;
    top: -13px;
    left: 0;
}

#filter-wrapper .filter-checklist .select2-wrapper{
    display: inline-block;
}

.input-wrapper{
    border: 1px solid #f0f0f0;
    display: none;
}

.input-wrapper.active{
    display: block;
}

.input-wrapper .navigator{
    width: 35%;
    margin: 15px 5px;
}

.input-wrapper .navigator#from , .input-wrapper #from-label{
    margin-top: 15px;
    float: right;
}

.input-wrapper .navigator#to , .input-wrapper #to-label{
    margin-top: 15px;
    float: left;
}

#query{
    display: inline-block;
    width: 25%;
}

.dataTables_length {
    display: none;
}

.table-action-button[name=action_edit] {
    margin-bottom: 15px;
}

#action_edit {
    margin-bottom: 15px;
}

.badge-large {
    font-size: 14px;
    padding-bottom: 7px;
}




اسکریپت app.init.js برای کنترل فرم و ساخت کوئری استرینگ

$(document).ready(function () {

    /* ================> Functions */

    window.getCurrentQuery = function () {
        const params = new URL(document.location.href).searchParams;
        return params;
    }

    window.onMultipleSelect2Change = function (e, extraParam = null) {
        const thisElement = $(e.target);

        if (extraParam == "queryCheck" && (thisElement.val() == null || thisElement.val() == "")) {
            const firstOption = thisElement.find("option").first();
            if (firstOption.length)
                thisElement.val(firstOption.val()).trigger("change");
        }

        const thisElementParent = thisElement.parent();
        const thisElementContentList = thisElementParent.find('.select2-content-list');
        if (thisElementContentList.length && thisElement.val() != "") {
            thisElementContentList.val(thisElement.val());
            thisElementContentList.trigger("input")
        }

    }

	window.seperateNumber = function (val, preverseZero = false) {

        const value = val.toString().replace(/,/gi, "").replace(/\D/gi, "");

        if (isNaN(Number(value))) return false;

        let seperatedValue = new Intl.NumberFormat('en-US', { style: "decimal" }).format(value);

        if (seperatedValue == 0 && !preverseZero) seperatedValue = '';

        return {
            seperatedValue: seperatedValue,
            value: value
        };
    }

    window.generateSelect2Feature = function (element, options = {}) {
        if (typeof select2 == "undefined") return false;
        const res = element.select2(options);
        return res;
    }

    window.elementSeperator = function (index, element) {
        const currentElement = $(element);

        let val = currentElement.text();
        let finalVal = seperateNumber(val, true);
        currentElement.text(finalVal['seperatedValue'])

        currentElement.attr('data-value', finalVal['value']);
    }

    window.onInputNumberSeperator = function (e) {
        const thisElement = $(e.target);

        const val = seperateNumber(thisElement.val());
        const seperatedValue = val['seperatedValue'] === false ? '' : val['seperatedValue'];

        thisElement.val(seperatedValue);
        thisElement.attr('data-value', val['value']);
        thisElement.trigger('seperatedvalue');
    }

    window.getDataOptionPlugin = function (element, options) {

        const dataOptions = element.attr('data-options') ? JSON.parse(element.attr('data-options')) : {};
        const mOptions = Object.assign({}, options);

        for (const key of Object.keys(dataOptions)) {
            const currentElement = dataOptions[key];
            mOptions[key] = currentElement;
        }

        return mOptions;
    }

    window.generateIonRangeSliderFeature = function (element, options = {}) {
        if (typeof $().ionRangeSlider === "undefined") return false;

        const mOptions = getDataOptionPlugin(element, options);

        const res = element.ionRangeSlider(mOptions);
        return res;
    }

    window.generatePersianDatepickerFeature = function (element, options = {}) {
        if (typeof persianDatepicker === "undefined") return false;

        const mOptions = getDataOptionPlugin(element, options);

        const res = element.persianDatepicker(mOptions);

        element.on('input', res, function (e) {
            const pd = e.data;
            const thisElement = $(e.target)
            const val = thisElement.val();
            if (val) {
                const timestamp = val * 1000;
                pd.setDate(timestamp)
            }
        });


        return res;
    }

    window.syncRangeSliderAndInput = function (data) {

        const thisElement = data.input;
        const thisElementParent = thisElement.parent();

        const fromDOM = thisElementParent.find(".navigator#from");
        const toDOM = thisElementParent.find(".navigator#to");

        if (fromDOM.length && toDOM.length) {


            if ((!fromDOM.attr('data-initial') && !toDOM.attr('data-initial'))) {

                function syncInitialValueToRanger(e) {
                    if (!e.thisElement.data('ionRangeSlider')) {
                        setTimeout(syncInitialValueToRanger, 100, e);
                        return false;
                    }

                    if (e.fromDOM.val() != "" && e.toDOM.val() != "") {
                        e.thisElement.data('ionRangeSlider').update({
                            from: fromDOM.val(),
                            to: toDOM.val()
                        });
                    } else {
                        e.fromDOM.val(e.from);
                        e.toDOM.val(e.to);
                    }


                    e.fromDOM.attr('data-initial', "true");
                    e.toDOM.attr('data-initial', "true");
                }

                setTimeout(syncInitialValueToRanger, 100, {
                    fromDOM: fromDOM,
                    toDOM: toDOM,
                    thisElement: thisElement,
                    from: data.from,
                    to: data.to,
                })


            } else {
                if (typeof data['from'] != "undefined") {
                    fromDOM.val(data.from)
                    fromDOM.trigger("input")
                }

                if (typeof data['to'] != "undefined") {
                    toDOM.val(data.to)
                    toDOM.trigger("input")
                }
            }


            function onInput(e) {
                const thisElement = $(this);
                const thisElementVal = thisElement.val();
                const ion = e.data.ion;

                if (!isNaN(Number(e.data.min)) && !isNaN(Number(e.data.max))) {

                    const options = sweetAlertOptions.info;
                    options.title = "حد مجاز";
                    options.text = "مقدار داده شده از حد مجاز رد شده است";
                    if (!(e.data.min <= thisElementVal)) {
                        Swal.fire(options);
                        thisElement.val(e.data.min);
                        return false;
                    } else if (!(thisElementVal <= e.data.max)) {
                        Swal.fire(options);
                        thisElement.val(e.data.max);
                        return false;
                    }
                }


                if (thisElement.attr('id') == "from")
                    ion.data('ionRangeSlider').update({ from: thisElementVal })
                else if (thisElement.attr('id') == "to") {
                    ion.data('ionRangeSlider').update({ to: thisElementVal })
                }

            }

            fromDOM.off("input", onInput).on("input", {
                ion: thisElement,
                from: data.from,
                to: data.to,
                min: data.min,
                max: data.max
            }, onInput);


            toDOM.off("input", onInput).on("input", {
                ion: thisElement,
                from: data.from,
                to: data.to,
                min: data.min,
                max: data.max
            }, onInput)

        }
    }

    // filter functions
    window.generateFilterInput = function (inputName) {
        const inputList = {
            "text": `<div class="input-wrapper col-4" data-name="x-wrapper"> <center> <div>x-title</div> </center> <input class="form-control mt-2 the-value" type="text" id="x-id"> </div>`,
            "numberSeperator": `<div class="input-wrapper col-4" data-name="x-wrapper"> <center> <div>x-title</div> </center> <input type="text" data-seperator="true" class="form-control mt-2 the-value" id="x-id"></div>`,
            "numberRange": `<div class="input-wrapper multi-value col-4" data-name="x-wrapper"> <center> <div>x-title</div> </center> <input type="text" id="x-id" data-options='x-options' class="ion-ranger"> <label id="from-label" for="from">از</label> <input class="form-control form-control-sm from the-value navigator" type="number" id="from" placeholder="از"> <input class="form-control form-control-sm to the-value navigator" type="number" id="to" placeholder="تا"> <label id="to-label" for="to">تا</label> </div>`,
            "selectMultiple": `<div class="input-wrapper multi-value col-4" data-name="x-wrapper"> <center class="mb-2"> <div>x-title</div> </center> <select class="form-control select2 select2-multiple" multiple data-options='x-options'>x-options-value</select> <input type="text" id="x-id" class="ds-none the-value select2-content-list" value=""> </div>`,
            "dateRange": `<div class="input-wrapper multi-value col-4" data-name="x-wrapper"> <center class="mb-2"> <div>x-title</div> </center> <div class="row"> <div class="col-6"> <label for="from-date">از</label> <input type="text" id="from-date" class="form-control from the-value x-id date-picker-shamsi" data-options='x-options'> </div> <div class="col-6"> <label for="to-date">تا</label> <input type="text" id="to-date" class="form-control to the-value x-id date-picker-shamsi" data-options='x-options'> </div> </div> </div>`,
            "switch": `<div class="custom-control custom-switch mb-2" dir="ltr"> <input type="checkbox" class="custom-control-input active-filter" data-id="x-id" id="for-x-id" x-checked> <label class="custom-control-label" for="for-x-id">x-title</label> </div>`,
            "option": `<option value="x-value" x-selected>x-title</option>`,
        }

        if (!inputList[inputName]) return false;

        return inputList[inputName];
    }

    window.filterInputOnInput = function (e) {
        const thisElement = $(e.target);
        const thisElementParent = thisElement.parents(filterOptions.inputWrapper);
        let key = thisElementParent.attr('data-name');
        let value = '';

        if (!thisElementParent.hasClass("active")) return false;

        if (thisElementParent.find("input.from,input.to").length) {
            let from, to;
            from = thisElementParent.find('input.from').val();
            to = thisElementParent.find('input.to').val();
            value = `${from},${to}`;
        }
        else {
            value = thisElementParent.find(filterOptions.valueInput).attr('data-value') ? thisElementParent.find(filterOptions.valueInput).attr('data-value') : thisElementParent.find(filterOptions.valueInput).val();
        }

        const map = `${key}=${value}`;

        return map;

    }

    window.checkQueryForFilters = function () {

        if (!$(filterOptions.wrapper).length) return false;

        let params = getCurrentQuery();
        params = Array.from(params.entries());

        const iteratedList = [];

        var select2SetValue = function (select2DOM, value) {
            if (select2DOM.hasClass(select2Options.generatedClass)) {
                select2DOM.val(value).trigger('change', "queryCheck");
            }

            else {
                var runUntilGenerateSelect2 = function (obj) {
                    if (!obj.element.hasClass(select2Options.generatedClass)) {
                        setTimeout(runUntilGenerateSelect2, 100, obj);
                        return false;
                    }

                    obj.element.val(obj.value).trigger('change', "queryCheck");

                }

                setTimeout(runUntilGenerateSelect2, 100, {
                    element: select2DOM,
                    value: value
                });
            }
        }

        for (const param of params) {
            const key = param[0];
            const value = param[1];

            if (iteratedList.includes(key)) continue;
            if (value == "" || value == ",") continue;



            const inputWrapper = $(`div[data-name=${key}`);
            const switchWrapper = $(filterOptions.switchWrapper);

            const select2DOM = inputWrapper.find('select.select2');

            if (!inputWrapper.length) continue;

            iteratedList.push(key);

            if (switchWrapper.length) {

                const activeSwitch = switchWrapper.find(`.active-filter[data-id="${key}"]`);

                if (activeSwitch.length) {
                    activeSwitch.prop("checked", true);
                    onSwitchFilter({
                        target: activeSwitch
                    });
                }

            }



            if (value.search(/,/gi) != -1) {
                const multiVal = value.split(",");
                const from = multiVal[0];
                const to = multiVal[1];
                const fromDOM = inputWrapper.find('input.from');
                const toDOM = inputWrapper.find('input.to');


                if (fromDOM.length && toDOM.length) {
                    fromDOM.val(from).trigger('input');
                    toDOM.val(to).trigger('input');
                } else if (select2DOM.length) {

                    select2SetValue(select2DOM, multiVal);

                    const select2ContentList = inputWrapper.find('.select2-content-list');
                    if (select2ContentList.length) {
                        select2ContentList.val(multiVal.join(","));
                    }
                }

            } else {
                inputWrapper.find(filterOptions.valueInput).val(value).trigger('input');

                if (select2DOM.length) {
                    select2SetValue(select2DOM, value);
                }
            }



        }

        if (iteratedList.length) {
            $(filterOptions.blockWrapper).removeClass('collapse').addClass('collapsed show')
        }

    }

    window.generateFilterForm = function (elements, filterWrapper, swtichWrapper, sortWrapper) {

        if (!filterWrapper.length) return false;

        const select2SortDOM = sortWrapper.find('select.select2');

        for (let element of elements) {
            element = $(element);
            const dataset = {
                type: null,
                options: null,
                values: null,
                name: null,
                title: null,
            }

            dataset['type'] = element.attr('data-input');
            dataset['options'] = element.attr('data-options') ? element.attr('data-options') : '';
            dataset['values'] = element.attr('data-values') ? JSON.parse(element.attr('data-values')) : [];
            dataset['name'] = element.attr('data-name');
            dataset['title'] = element.text();

            if (!dataset['type']) return false;

            const template = generateFilterInput(dataset['type']);
            if (!template) return false;


            // switch filter for appended element
            const templateSwitch = generateFilterInput('switch');
            let templateSwitchDynamic = templateSwitch.replace(/x-title/gi, dataset['title']).replace(/x-id/gi, dataset['name']);

            //templateSwitchDynamic = templateSwitchDynamic.replace(/x-checked/gi, 'checked')


            const tempateDynamic = template.replace(/x-wrapper/gi, dataset['name']).replace(/x-title/gi, dataset['title']).replace(/x-id/gi, dataset['name']).replace(/x-options-value/gi, dataset['values'].join("\n")).replace(/x-options/gi, dataset['options'])

            filterWrapper.append(tempateDynamic);
            swtichWrapper.append(templateSwitchDynamic);
        }

        const sortDOM = sortWrapper.find(filterOptions.valueInput);
        if (sortDOM.length) {
            if (sortDOM.val() == "") {
                sortDOM.val(select2SortDOM.val());
            }
        }

        const inputWrapper = filterWrapper.find(filterOptions.inputWrapper)
        const theValue = inputWrapper.find(filterOptions.valueInput);

        theValue.on('input seperatedvalue', function (e) {
            const queryList = [];
            for (let valDOM of theValue) {
                const res = filterInputOnInput({
                    target: valDOM
                });

                if (!res) continue;

                if (!queryList.includes(res))
                    queryList.push(res);
            }

            const query = "?" + queryList.join("&");

            const form = $(filterOptions.form);
            form.attr('action', form.attr('data-route') + query)

        });

    }

    window.onSwitchFilter = function (e) {
        const thisElement = $(e.target);
        const checkStatus = thisElement.prop('checked');

        const inputWrapper = $(filterOptions.inputWrapper + `[data-name=${thisElement.attr('data-id')}]`);
        const select2DOM = $(filterOptions.sortWrapper).find("select.select2");

        const dataset = {
            title: inputWrapper.find("center").text(),
            name: inputWrapper.attr("data-name")
        }

        const templateOption = generateFilterInput('option');

        if (checkStatus) {
            inputWrapper.addClass('active');
            const options = [];
            options.push(templateOption.replace(/x-title/gi, dataset['title'] + ": صعودی").replace(/x-value/gi, dataset['name'] + ":asc"));
            options.push(templateOption.replace(/x-title/gi, dataset['title'] + ": نزولی").replace(/x-value/gi, dataset['name'] + ":desc"));
            select2DOM.append(options.join("\n"));
            select2DOM.trigger("change");
        } else {
            inputWrapper.removeClass('active');
            const options = select2DOM.find(`option[value='${dataset['name'] + ":asc"}'],option[value='${dataset['name'] + ":desc"}']`)
            options.remove();
            select2DOM.trigger("clear");
        }

        const filterWrapper = inputWrapper.parents(filterOptions.wrapper);
        const firstInput = filterWrapper.find(filterOptions.valueInput).first();

        if (firstInput.length) {
            firstInput.trigger("input");
        }

    }

    /* ================> END Functions */


    /* ================> default Options */
    
    window.filterOptions = {
        wrapper: '#filter-wrapper',
        inputWrapper: '.input-wrapper',
        form: '#filter-form',
        switchWrapper: '.filter-checklist .dropright .dropdown-menu',
        sortWrapper: '.select2-wrapper',
        blockWrapper: '#block-wrapper-filter',
        clearFilter: '#clear-filter',
        valueInput: '.the-value'
    }

    window.sweetAlertOptions = {
        question: {
            title: "عنوان",
            text: "توضیح",
            type: "warning",
            showCancelButton: true,
            confirmButtonColor: "#34c38f",
            cancelButtonColor: "#f46a6a",
            confirmButtonText: "بله",
            cancelButtonText: 'انصراف'
        },
        info: {
            title: "عنوان",
            text: 'توضیح',
            type: 'warning',
            confirmButtonColor: '#3b5de7',
            confirmButtonText: 'باشه'
        }

    }

    window.shamsiDatePickerOptions = {
        format: 'X',
        timePicker: {
            enabled: true
        },
        initialValue: false,
        onSelect: function () {
            const thisElement = $(this.model.inputElement);

            if (this.format.toLowerCase() === "x" && !this.default_ts) {
                const timestamp = thisElement.val();
                const now = new persianDate(timestamp * 1000);
                const dateObj = now.startOf('day').ON;
                const date = dateObj.persian;
                let finalTimestamp = 0;
                let dateArray = [];

                if (thisElement.attr("id") == "from-date") {
                    dateArray = [date.year, date.month + 1, date.day, 0, 0, 0, 0];
                } else if (thisElement.attr("id") == "to-date") {
                    dateArray = [date.year, date.month + 1, date.day, 23, 59, 59, 0];
                }

                finalTimestamp = new persianDate(dateArray);
                finalTimestamp = finalTimestamp.unix();

                thisElement.val(finalTimestamp);
            }

            thisElement.trigger('input');

        }
    }

    window.ionRangeSliderOptions = {
        skin: "round",
        type: "double",
        grid: true,
        min: 0,
        max: 1000,
        from: 100,
        to: 990,
        step: 1,
        prettify_separator: ",",
        postfix: '',
        prefix: '',
        onStart: syncRangeSliderAndInput,
        onChange: function () { },
        onFinish: syncRangeSliderAndInput,
        onUpdate: function () { }
    }

    window.select2Options = {
        generatedClass : 'select2-hidden-accessible',
    }

    /* ================> END Options */


    /* ================> INIT */
    
    // generate element filter form
    generateFilterForm($('[data-filter]'), $(filterOptions.wrapper), $(filterOptions.switchWrapper), $(filterOptions.sortWrapper));


    /*

    window.filterOptions = {
        wrapper: '#filter-wrapper',
        inputWrapper: '.input-wrapper',
        form: '#filter-form',
        switchWrapper: '.filter-checklist .dropright .dropdown-menu',
        sortWrapper: '.select2-wrapper',
        blockWrapper: '#block-wrapper-filter',
        clearFilter: '#clear-filter',
        valueInput: '.the-value'
    }
    */


    // generate persian date picker
    $('input.date-picker-shamsi').each(function (index, element) {
        element = $(element);
        generatePersianDatepickerFeature(element, shamsiDatePickerOptions)
    });

    // generate number seperator input tag event
    $('input[data-seperator]').on("input", onInputNumberSeperator);

    // generate number seperator all element
    $('[data-seperator]').each(elementSeperator)

    // set old value filters
    checkQueryForFilters();


    /* ================> END INIT */
});


اسکریپت product.list.js برای آماده سازی کتابخانه ها و افزودن event listener

$(document).ready(function () {

    /* ================> Functions */

    

    function preventSwitchModalOff(e) {
        const thisElement = $(e.target);
        const thisElementParent = thisElement.parent('.dropright');

        if (thisElement.attr('aria-expanded') == "false") {
            setTimeout(function () {
                thisElementParent.removeClass('show');
            }, 10)
        } else {
            thisElementParent.addClass('show');
        }

    }

    function onClickClearFilter(e) {
        const Form = $(filterOptions.form);

        Form.attr("action", Form.attr("data-route"));
        Form.submit();
    }

    /* ================> END Functions */


    /* ================> EVENTS */

    $('.dropright button[data-toggle=dropdown]').on("click", preventSwitchModalOff)

    $(filterOptions.switchWrapper).find('.active-filter').on("change", onSwitchFilter)

    $(filterOptions.clearFilter).on("click", onClickClearFilter);

    /* ================> END EVENTS */

    /* ================> INIT */

    // generate range slider
    $(".ion-ranger").each(function (index, element) {
        element = $(element);
        generateIonRangeSliderFeature(element, ionRangeSliderOptions)
    });


    // enable Select2 All
    $('select.select2').each(function (index, element) {
        element = $(element);
        generateSelect2Feature(element, {}).on('change', onMultipleSelect2Change)
        element.trigger("change");
    });

    /* ================> END INIT */
});


دانلود سورس پروژه فیلتر محصولات

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

contact us