├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── release-drafter.yml └── workflows │ ├── ci.yml │ ├── publish.yml │ └── release-drafter.yml ├── .gitignore ├── AUTHORS ├── INSTALL ├── LICENSE ├── MANIFEST.in ├── README.rst ├── demoproject ├── __init__.py ├── compat.py ├── filter │ ├── __init__.py │ ├── fixtures │ │ └── test_data.json │ ├── forms.py │ ├── models.py │ ├── static │ │ ├── css │ │ │ └── bootstrap-switch.css │ │ └── js │ │ │ └── bootstrap-switch.min.js │ ├── templates │ │ └── user │ │ │ └── user_list.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── manage.py ├── settings.py ├── templates │ └── home.html ├── tests.py ├── urls.py └── wsgi.py ├── django_genericfilters ├── __init__.py ├── fields.py ├── forms.py ├── models.py ├── static │ ├── css │ │ ├── filters_list.css │ │ └── genericfilters.css │ └── js │ │ └── genericfilters.js ├── templates │ ├── genericfilters │ │ ├── filter_list.html │ │ ├── order_by_list.html │ │ └── query_filter.html │ └── snippets │ │ └── pagination.html ├── templatetags │ ├── __init__.py │ ├── paginator.py │ ├── updateurl.py │ └── utils.py ├── tests │ ├── __init__.py │ ├── test_fields.py │ ├── test_forms.py │ ├── test_templatetags.py │ └── test_views.py └── views.py ├── docker-compose.yml ├── docs ├── Makefile ├── about │ ├── authors.txt │ ├── changelog.txt │ ├── index.txt │ └── license.txt ├── api │ ├── filtered_form.txt │ ├── filtered_list_view.txt │ └── index.txt ├── conf.py ├── dev.txt ├── index.txt └── install.txt ├── pyproject.toml ├── requirements.txt ├── setup.cfg ├── setup.py └── tox.ini /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @peopledoc/python-community 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Closes # 2 | 3 | 4 | ### Successful PR Checklist: 5 | - [ ] Tests 6 | - [ ] (not applicable?) 7 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | template: | 2 | $CHANGES 3 | 4 | ## Kudos: 5 | 6 | $CONTRIBUTORS 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - 'master' 8 | tags: 9 | - '*' 10 | 11 | jobs: 12 | build: 13 | 14 | # When testing new Python or Django versions, one should use the 15 | # filterwarnings definition of setup.cfg to turn deprecation warnings 16 | # into errors. 17 | strategy: 18 | matrix: 19 | include: 20 | 21 | - name: Python 3.7 / Django 3.2 22 | python_version: "3.7" 23 | tox_env: py37-django32 24 | 25 | - name: Python 3.8 / Django 3.2 26 | python_version: "3.8" 27 | tox_env: py38-django32 28 | 29 | - name: Python 3.9 / Django 2.2 30 | python_version: "3.9" 31 | tox_env: py39-django22 32 | 33 | - name: Python 3.9 / Django 3.0 34 | python_version: "3.9" 35 | tox_env: py39-django30 36 | 37 | - name: Python 3.9 / Django 3.1 38 | python_version: "3.9" 39 | tox_env: py39-django31 40 | 41 | - name: Python 3.9 / Django 3.2 42 | python_version: "3.9" 43 | tox_env: py39-django32 44 | 45 | - name: Python 3.9 / Django 4.0 46 | python_version: "3.9" 47 | tox_env: py39-django40 48 | 49 | - name: Python 3.10 / Django 3.2 50 | python_version: "3.10" 51 | tox_env: py310-django32 52 | 53 | - name: Lint 54 | python_version: "3.10" 55 | tox_env: lint 56 | 57 | 58 | name: "${{ matrix.name }}" 59 | runs-on: ubuntu-latest 60 | 61 | services: 62 | postgres: 63 | image: postgres 64 | # Set health checks to wait until postgres has started 65 | env: 66 | POSTGRES_PASSWORD: postgres 67 | options: >- 68 | --health-cmd pg_isready 69 | --health-interval 10s 70 | --health-timeout 5s 71 | ports: 72 | - 5432:5432 73 | 74 | steps: 75 | - uses: actions/checkout@v2 76 | 77 | - name: Set up Python 78 | id: setup-python 79 | uses: actions/setup-python@v2 80 | with: 81 | python-version: ${{ matrix.python_version }} 82 | 83 | - name: Pip cache 84 | uses: actions/cache@v2 85 | with: 86 | path: | 87 | ~/.cache/ 88 | key: ${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('setup.py') }} 89 | 90 | - name: Install Tox 91 | run: pip install tox 92 | 93 | - name: Run ${{ matrix.name }} 94 | run: tox -e ${{ matrix.tox_env }} 95 | env: 96 | PGHOST: localhost 97 | PGUSER: postgres 98 | PGPASSWORD: postgres 99 | 100 | report-status: 101 | name: success 102 | runs-on: ubuntu-latest 103 | needs: build 104 | steps: 105 | 106 | - name: Report success 107 | run: echo 'Success !' 108 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | deploy: 10 | name: Publish package to PyPI 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Set up Python 16 | id: setup-python 17 | uses: actions/setup-python@v2 18 | with: 19 | python-version: ${{ matrix.python_version }} 20 | 21 | - name: Install 22 | run: pip install build 23 | 24 | - name: Wait for tests to succeed 25 | uses: fountainhead/action-wait-for-check@v1.0.0 26 | id: wait-for-ci 27 | with: 28 | token: ${{ secrets.GITHUB_TOKEN }} 29 | checkName: success 30 | 31 | - name: Exit if CI did not succeed 32 | if: steps.wait-for-ci.outputs.conclusion != 'success' 33 | run: exit 1 34 | 35 | - name: Build package 36 | run: python -m build 37 | 38 | - name: Publish a Python distribution to PyPI 39 | uses: pypa/gh-action-pypi-publish@release/v1 40 | with: 41 | user: __token__ 42 | password: "${{ secrets.PYPI_TOKEN }}" 43 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | update_release_draft: 10 | runs-on: ubuntu-latest 11 | steps: 12 | # Drafts the next Release notes as Pull Requests are merged into "master" 13 | - uses: release-drafter/release-drafter@v5 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .coverage 3 | .DS_Store 4 | .mypy_cache 5 | .pytest_cache 6 | .tox 7 | .venv 8 | *.egg-info 9 | *.pyc 10 | build 11 | dist 12 | docs/_build 13 | htmlcov 14 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | ###################### 2 | Authors & contributors 3 | ###################### 4 | 5 | Maintainer: Rémy Hubscher 6 | 7 | Original code by `Novapost `_ team: 8 | 9 | * Benoît Bryon 10 | * Rémy Hubscher 11 | * Natal Ngétal 12 | * Yohann Gabory -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | ############ 2 | Installation 3 | ############ 4 | 5 | This project is open-source, published under BSD license. 6 | See :doc:`/about/license` for details. 7 | 8 | If you want to install a development environment, you should go to :doc:`/dev` 9 | documentation. 10 | 11 | Install the package with your favorite Python installer. As an example, with 12 | pip: 13 | 14 | .. code-block:: sh 15 | 16 | pip install django-generic-filters 17 | 18 | Don't forget to register your application in your Django 19 | ``INSTALLED_APPS`` setting. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ####### 2 | License 3 | ####### 4 | 5 | Copyright (c) 2013, Novapost SAS. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of django-generic-filters nor the names of its contributors 19 | may be used to endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include django_genericfilters * 2 | global-exclude *.pyc .*.swp *~ 3 | include *.txt 4 | include AUTHORS CHANGELOG INSTALL LICENSE README.rst VERSION 5 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ###################### 2 | django-generic-filters 3 | ###################### 4 | 5 | `django-generic-filters` is a toolkit to filter results of Django's 6 | ``ListView``, using forms. 7 | 8 | Main use cases are obviously search forms and filtered lists. 9 | 10 | As a developer, given you have a ``ListView``, in order to let the user 11 | filter the results: 12 | 13 | * use a form to easily render the filters as HTML; 14 | * the user typically sends the filters via GET; 15 | * validate the user's input using a Django form; 16 | * filter the Django view's queryset using form's cleaned data. 17 | 18 | .. image:: https://secure.travis-ci.org/peopledoc/django-generic-filters.png?branch=master 19 | :alt: Build Status 20 | :target: https://secure.travis-ci.org/peopledoc/django-generic-filters 21 | 22 | 23 | ******* 24 | Example 25 | ******* 26 | 27 | **views.py** 28 | 29 | .. code-block:: python 30 | 31 | from django_genericfilters.views import FilteredListView 32 | 33 | 34 | class UserListView(FilteredListView): 35 | # ListView options. FilteredListView inherits from ListView. 36 | model = User 37 | template_name = 'user/user_list.html' 38 | paginate_by = 10 39 | context_object_name = 'users' 40 | 41 | # FormMixin options. FilteredListView inherits from FormMixin. 42 | form_class = UserListForm 43 | 44 | # FilteredListView options. 45 | search_fields = ['first_name', 'last_name', 'username', 'email'] 46 | filter_fields = ['is_active', 'is_staff', 'is_superuser'] 47 | default_order = 'last_name' 48 | 49 | def form_valid(self, form): 50 | """Return the queryset when form has been submitted.""" 51 | queryset = super(UserListView, self).form_valid(form) 52 | 53 | # Handle specific fields of the custom ListForm 54 | # Others are automatically handled by FilteredListView. 55 | 56 | if form.cleaned_data['is_active'] == 'yes': 57 | queryset = queryset.filter(is_active=True) 58 | elif form.cleaned_data['is_active'] == 'no': 59 | queryset = queryset.filter(is_active=False) 60 | 61 | if form.cleaned_data['is_staff'] == 'yes': 62 | queryset = queryset.filter(is_staff=True) 63 | elif form.cleaned_data['is_staff'] == 'no': 64 | queryset = queryset.filter(is_staff=False) 65 | 66 | if form.cleaned_data['is_superuser'] == 'yes': 67 | queryset = queryset.filter(is_superuser=True) 68 | elif form.cleaned_data['is_superuser'] == 'no': 69 | queryset = queryset.filter(is_superuser=False) 70 | 71 | return queryset 72 | 73 | 74 | **forms.py** 75 | 76 | .. code-block:: python 77 | 78 | from django import forms 79 | from django.utils.translation import gettext_lazy as _ 80 | from django_genericfilters import forms as gf 81 | 82 | 83 | class UserListForm(gf.QueryFormMixin, gf.OrderFormMixin, gf.FilteredForm): 84 | is_active = gf.ChoiceField(label=_('Status'), 85 | choices=(('yes', _('Active')), 86 | ('no', _('Unactive')))) 87 | 88 | is_staff = gf.ChoiceField(label=_('Staff')) 89 | 90 | is_superuser = gf.ChoiceField(label=_('Superuser')) 91 | 92 | def get_order_by_choices(self): 93 | return [('date_joined', _(u'date joined')), 94 | ('last_login', _(u'last login')), 95 | ('last_name', _(u'Name'))] 96 | 97 | 98 | ***** 99 | Forms 100 | ***** 101 | 102 | Several form mixins are provided to cover frequent use cases: 103 | 104 | * ``OrderFormMixin`` with order_by and order_reverse fields. 105 | * ``QueryFormMixin`` for little full-text search using icontains. 106 | 107 | See "mixin" documentation for details. 108 | 109 | ********** 110 | Ressources 111 | ********** 112 | 113 | * Documentation: https://django-generic-filters.readthedocs.io 114 | * PyPI page: http://pypi.python.org/pypi/django-generic-filters 115 | * Code repository: https://github.com/peopledoc/django-generic-filters 116 | * Bugtracker: https://github.com/peopledoc/django-generic-filters/issues 117 | -------------------------------------------------------------------------------- /demoproject/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peopledoc/django-generic-filters/11b07972174a250b6867c6ae56c45ad5c31693fc/demoproject/__init__.py -------------------------------------------------------------------------------- /demoproject/compat.py: -------------------------------------------------------------------------------- 1 | try: 2 | from django.urls import reverse # noqa 3 | except ImportError: 4 | from django.core.urlresolvers import reverse # noqa 5 | -------------------------------------------------------------------------------- /demoproject/filter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peopledoc/django-generic-filters/11b07972174a250b6867c6ae56c45ad5c31693fc/demoproject/filter/__init__.py -------------------------------------------------------------------------------- /demoproject/filter/fixtures/test_data.json: -------------------------------------------------------------------------------- 1 | [{"pk": 1, "model": "auth.user", "fields": {"username": "admin", "first_name": "Antoine", "last_name": "SMITH", "is_active": true, "is_superuser": true, "is_staff": true, "last_login": "2013-09-02T07:31:50.863", "groups": [], "user_permissions": [], "password": "pbkdf2_sha256$10000$yYbejhAvkPpm$7ujg/lmvFoNrMmOnX86uM7f80VejlnIDwcRZzxTOYkI=", "email": "antoine.smith@example.com", "date_joined": "2013-09-02T07:31:50.863"}}, {"pk": 3, "model": "auth.user", "fields": {"username": "johndoe", "first_name": "John", "last_name": "DOE", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2013-09-02T08:23:41.894", "groups": [], "user_permissions": [], "password": "", "email": "john.doe@tutu.com", "date_joined": "2013-09-02T08:23:41.894"}}, {"pk": 4, "model": "auth.user", "fields": {"username": "phildupont", "first_name": "Phil", "last_name": "DUPONT", "is_active": false, "is_superuser": false, "is_staff": false, "last_login": "2013-09-02T08:25:35.673", "groups": [], "user_permissions": [], "password": "", "email": "phil.dupont@tutu.com", "date_joined": "2013-09-02T08:25:35.673"}}, {"pk": 5, "model": "auth.user", "fields": {"username": "chucknorris", "first_name": "Chuck", "last_name": "NORRIS", "is_active": true, "is_superuser": false, "is_staff": true, "last_login": "2013-09-02T08:26:27.551", "groups": [], "user_permissions": [], "password": "", "email": "chuck.norris@tutu.com", "date_joined": "2013-09-02T08:26:27.551"}}] 2 | -------------------------------------------------------------------------------- /demoproject/filter/forms.py: -------------------------------------------------------------------------------- 1 | from django.utils.translation import gettext_lazy as _ 2 | 3 | from django_genericfilters import forms as gf 4 | 5 | 6 | class UserListForm(gf.FilteredForm): 7 | is_active = gf.ChoiceField( 8 | label=_("Status"), choices=(("yes", _("Active")), ("no", _("Unactive"))) 9 | ) 10 | 11 | is_staff = gf.ChoiceField(label=_("Staff")) 12 | 13 | is_superuser = gf.ChoiceField(label=_("Superuser")) 14 | 15 | def get_order_by_choices(self): 16 | return [ 17 | ("date_joined", _("date joined")), 18 | ("last_login", _("last login")), 19 | ("last_name", _("Name")), 20 | ] 21 | -------------------------------------------------------------------------------- /demoproject/filter/models.py: -------------------------------------------------------------------------------- 1 | # Create your models here. 2 | -------------------------------------------------------------------------------- /demoproject/filter/static/css/bootstrap-switch.css: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrapSwitch v1.8 by Larentis Mattia @SpiritualGuru 3 | * http://www.larentis.eu/ 4 | * 5 | * Enhanced for radiobuttons by Stein, Peter @BdMdesigN 6 | * http://www.bdmdesign.org/ 7 | * 8 | * Project site: 9 | * http://www.larentis.eu/switch/ 10 | * ============================================================ 11 | * Licensed under the Apache License, Version 2.0 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * ============================================================ */ 14 | .has-switch { 15 | display: inline-block; 16 | cursor: pointer; 17 | -webkit-border-radius: 5px; 18 | -moz-border-radius: 5px; 19 | border-radius: 5px; 20 | border: 1px solid; 21 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 22 | position: relative; 23 | text-align: left; 24 | overflow: hidden; 25 | line-height: 8px; 26 | -webkit-user-select: none; 27 | -moz-user-select: none; 28 | -ms-user-select: none; 29 | -o-user-select: none; 30 | user-select: none; 31 | vertical-align: middle; 32 | min-width: 100px; 33 | } 34 | .has-switch.switch-mini { 35 | min-width: 72px; 36 | } 37 | .has-switch.switch-mini i.switch-mini-icons { 38 | height: 1.20em; 39 | line-height: 9px; 40 | vertical-align: text-top; 41 | text-align: center; 42 | transform: scale(0.6); 43 | margin-top: -1px; 44 | margin-bottom: -1px; 45 | } 46 | .has-switch.switch-small { 47 | min-width: 80px; 48 | } 49 | .has-switch.switch-large { 50 | min-width: 120px; 51 | } 52 | .has-switch.deactivate { 53 | opacity: 0.5; 54 | filter: alpha(opacity=50); 55 | cursor: default !important; 56 | } 57 | .has-switch.deactivate label, 58 | .has-switch.deactivate span { 59 | cursor: default !important; 60 | } 61 | .has-switch > div { 62 | display: inline-block; 63 | width: 150%; 64 | position: relative; 65 | top: 0; 66 | } 67 | .has-switch > div.switch-animate { 68 | -webkit-transition: left 0.5s; 69 | -moz-transition: left 0.5s; 70 | -o-transition: left 0.5s; 71 | transition: left 0.5s; 72 | } 73 | .has-switch > div.switch-off { 74 | left: -50%; 75 | } 76 | .has-switch > div.switch-on { 77 | left: 0%; 78 | } 79 | .has-switch input[type=radio], 80 | .has-switch input[type=checkbox] { 81 | display: none; 82 | } 83 | .has-switch span, 84 | .has-switch label { 85 | -webkit-box-sizing: border-box; 86 | -moz-box-sizing: border-box; 87 | box-sizing: border-box; 88 | cursor: pointer; 89 | position: relative; 90 | display: inline-block; 91 | height: 100%; 92 | padding-bottom: 4px; 93 | padding-top: 4px; 94 | font-size: 14px; 95 | line-height: 20px; 96 | } 97 | .has-switch span.switch-mini, 98 | .has-switch label.switch-mini { 99 | padding-bottom: 4px; 100 | padding-top: 4px; 101 | font-size: 10px; 102 | line-height: 9px; 103 | } 104 | .has-switch span.switch-small, 105 | .has-switch label.switch-small { 106 | padding-bottom: 3px; 107 | padding-top: 3px; 108 | font-size: 12px; 109 | line-height: 18px; 110 | } 111 | .has-switch span.switch-large, 112 | .has-switch label.switch-large { 113 | padding-bottom: 9px; 114 | padding-top: 9px; 115 | font-size: 16px; 116 | line-height: normal; 117 | } 118 | .has-switch label { 119 | text-align: center; 120 | margin-top: -1px; 121 | margin-bottom: -1px; 122 | z-index: 100; 123 | width: 34%; 124 | border-left: 1px solid #cccccc; 125 | border-right: 1px solid #cccccc; 126 | color: #333333; 127 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 128 | background-color: #f5f5f5; 129 | background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); 130 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); 131 | background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); 132 | background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); 133 | background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); 134 | background-repeat: repeat-x; 135 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); 136 | border-color: #e6e6e6 #e6e6e6 #bfbfbf; 137 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 138 | *background-color: #e6e6e6; 139 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 140 | 141 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 142 | } 143 | .has-switch label:hover, 144 | .has-switch label:focus, 145 | .has-switch label:active, 146 | .has-switch label.active, 147 | .has-switch label.disabled, 148 | .has-switch label[disabled] { 149 | color: #333333; 150 | background-color: #e6e6e6; 151 | *background-color: #d9d9d9; 152 | } 153 | .has-switch label:active, 154 | .has-switch label.active { 155 | background-color: #cccccc \9; 156 | } 157 | .has-switch label i { 158 | color: #000; 159 | text-shadow: 0 1px 0 #fff; 160 | line-height: 18px; 161 | pointer-events: none; 162 | } 163 | .has-switch span { 164 | text-align: center; 165 | z-index: 1; 166 | width: 33%; 167 | } 168 | .has-switch span.switch-left { 169 | -webkit-border-top-left-radius: 4px; 170 | -moz-border-radius-topleft: 4px; 171 | border-top-left-radius: 4px; 172 | -webkit-border-bottom-left-radius: 4px; 173 | -moz-border-radius-bottomleft: 4px; 174 | border-bottom-left-radius: 4px; 175 | } 176 | .has-switch span.switch-right { 177 | color: #333333; 178 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 179 | background-color: #f0f0f0; 180 | background-image: -moz-linear-gradient(top, #e6e6e6, #ffffff); 181 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#ffffff)); 182 | background-image: -webkit-linear-gradient(top, #e6e6e6, #ffffff); 183 | background-image: -o-linear-gradient(top, #e6e6e6, #ffffff); 184 | background-image: linear-gradient(to bottom, #e6e6e6, #ffffff); 185 | background-repeat: repeat-x; 186 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffffffff', GradientType=0); 187 | border-color: #ffffff #ffffff #d9d9d9; 188 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 189 | *background-color: #ffffff; 190 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 191 | 192 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 193 | } 194 | .has-switch span.switch-right:hover, 195 | .has-switch span.switch-right:focus, 196 | .has-switch span.switch-right:active, 197 | .has-switch span.switch-right.active, 198 | .has-switch span.switch-right.disabled, 199 | .has-switch span.switch-right[disabled] { 200 | color: #333333; 201 | background-color: #ffffff; 202 | *background-color: #f2f2f2; 203 | } 204 | .has-switch span.switch-right:active, 205 | .has-switch span.switch-right.active { 206 | background-color: #e6e6e6 \9; 207 | } 208 | .has-switch span.switch-primary, 209 | .has-switch span.switch-left { 210 | color: #ffffff; 211 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 212 | background-color: #005fcc; 213 | background-image: -moz-linear-gradient(top, #0044cc, #0088cc); 214 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0044cc), to(#0088cc)); 215 | background-image: -webkit-linear-gradient(top, #0044cc, #0088cc); 216 | background-image: -o-linear-gradient(top, #0044cc, #0088cc); 217 | background-image: linear-gradient(to bottom, #0044cc, #0088cc); 218 | background-repeat: repeat-x; 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0044cc', endColorstr='#ff0088cc', GradientType=0); 220 | border-color: #0088cc #0088cc #005580; 221 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 222 | *background-color: #0088cc; 223 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 224 | 225 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 226 | } 227 | .has-switch span.switch-primary:hover, 228 | .has-switch span.switch-left:hover, 229 | .has-switch span.switch-primary:focus, 230 | .has-switch span.switch-left:focus, 231 | .has-switch span.switch-primary:active, 232 | .has-switch span.switch-left:active, 233 | .has-switch span.switch-primary.active, 234 | .has-switch span.switch-left.active, 235 | .has-switch span.switch-primary.disabled, 236 | .has-switch span.switch-left.disabled, 237 | .has-switch span.switch-primary[disabled], 238 | .has-switch span.switch-left[disabled] { 239 | color: #ffffff; 240 | background-color: #0088cc; 241 | *background-color: #0077b3; 242 | } 243 | .has-switch span.switch-primary:active, 244 | .has-switch span.switch-left:active, 245 | .has-switch span.switch-primary.active, 246 | .has-switch span.switch-left.active { 247 | background-color: #006699 \9; 248 | } 249 | .has-switch span.switch-info { 250 | color: #ffffff; 251 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 252 | background-color: #41a7c5; 253 | background-image: -moz-linear-gradient(top, #2f96b4, #5bc0de); 254 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#2f96b4), to(#5bc0de)); 255 | background-image: -webkit-linear-gradient(top, #2f96b4, #5bc0de); 256 | background-image: -o-linear-gradient(top, #2f96b4, #5bc0de); 257 | background-image: linear-gradient(to bottom, #2f96b4, #5bc0de); 258 | background-repeat: repeat-x; 259 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2f96b4', endColorstr='#ff5bc0de', GradientType=0); 260 | border-color: #5bc0de #5bc0de #28a1c5; 261 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 262 | *background-color: #5bc0de; 263 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 264 | 265 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 266 | } 267 | .has-switch span.switch-info:hover, 268 | .has-switch span.switch-info:focus, 269 | .has-switch span.switch-info:active, 270 | .has-switch span.switch-info.active, 271 | .has-switch span.switch-info.disabled, 272 | .has-switch span.switch-info[disabled] { 273 | color: #ffffff; 274 | background-color: #5bc0de; 275 | *background-color: #46b8da; 276 | } 277 | .has-switch span.switch-info:active, 278 | .has-switch span.switch-info.active { 279 | background-color: #31b0d5 \9; 280 | } 281 | .has-switch span.switch-success { 282 | color: #ffffff; 283 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 284 | background-color: #58b058; 285 | background-image: -moz-linear-gradient(top, #51a351, #62c462); 286 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#51a351), to(#62c462)); 287 | background-image: -webkit-linear-gradient(top, #51a351, #62c462); 288 | background-image: -o-linear-gradient(top, #51a351, #62c462); 289 | background-image: linear-gradient(to bottom, #51a351, #62c462); 290 | background-repeat: repeat-x; 291 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff51a351', endColorstr='#ff62c462', GradientType=0); 292 | border-color: #62c462 #62c462 #3b9e3b; 293 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 294 | *background-color: #62c462; 295 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 296 | 297 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 298 | } 299 | .has-switch span.switch-success:hover, 300 | .has-switch span.switch-success:focus, 301 | .has-switch span.switch-success:active, 302 | .has-switch span.switch-success.active, 303 | .has-switch span.switch-success.disabled, 304 | .has-switch span.switch-success[disabled] { 305 | color: #ffffff; 306 | background-color: #62c462; 307 | *background-color: #4fbd4f; 308 | } 309 | .has-switch span.switch-success:active, 310 | .has-switch span.switch-success.active { 311 | background-color: #42b142 \9; 312 | } 313 | .has-switch span.switch-warning { 314 | color: #ffffff; 315 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 316 | background-color: #f9a123; 317 | background-image: -moz-linear-gradient(top, #f89406, #fbb450); 318 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f89406), to(#fbb450)); 319 | background-image: -webkit-linear-gradient(top, #f89406, #fbb450); 320 | background-image: -o-linear-gradient(top, #f89406, #fbb450); 321 | background-image: linear-gradient(to bottom, #f89406, #fbb450); 322 | background-repeat: repeat-x; 323 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff89406', endColorstr='#fffbb450', GradientType=0); 324 | border-color: #fbb450 #fbb450 #f89406; 325 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 326 | *background-color: #fbb450; 327 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 328 | 329 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 330 | } 331 | .has-switch span.switch-warning:hover, 332 | .has-switch span.switch-warning:focus, 333 | .has-switch span.switch-warning:active, 334 | .has-switch span.switch-warning.active, 335 | .has-switch span.switch-warning.disabled, 336 | .has-switch span.switch-warning[disabled] { 337 | color: #ffffff; 338 | background-color: #fbb450; 339 | *background-color: #faa937; 340 | } 341 | .has-switch span.switch-warning:active, 342 | .has-switch span.switch-warning.active { 343 | background-color: #fa9f1e \9; 344 | } 345 | .has-switch span.switch-danger { 346 | color: #ffffff; 347 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 348 | background-color: #d14641; 349 | background-image: -moz-linear-gradient(top, #bd362f, #ee5f5b); 350 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#bd362f), to(#ee5f5b)); 351 | background-image: -webkit-linear-gradient(top, #bd362f, #ee5f5b); 352 | background-image: -o-linear-gradient(top, #bd362f, #ee5f5b); 353 | background-image: linear-gradient(to bottom, #bd362f, #ee5f5b); 354 | background-repeat: repeat-x; 355 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbd362f', endColorstr='#ffee5f5b', GradientType=0); 356 | border-color: #ee5f5b #ee5f5b #e51d18; 357 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 358 | *background-color: #ee5f5b; 359 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 360 | 361 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 362 | } 363 | .has-switch span.switch-danger:hover, 364 | .has-switch span.switch-danger:focus, 365 | .has-switch span.switch-danger:active, 366 | .has-switch span.switch-danger.active, 367 | .has-switch span.switch-danger.disabled, 368 | .has-switch span.switch-danger[disabled] { 369 | color: #ffffff; 370 | background-color: #ee5f5b; 371 | *background-color: #ec4844; 372 | } 373 | .has-switch span.switch-danger:active, 374 | .has-switch span.switch-danger.active { 375 | background-color: #e9322d \9; 376 | } 377 | .has-switch span.switch-default { 378 | color: #333333; 379 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 380 | background-color: #f0f0f0; 381 | background-image: -moz-linear-gradient(top, #e6e6e6, #ffffff); 382 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#ffffff)); 383 | background-image: -webkit-linear-gradient(top, #e6e6e6, #ffffff); 384 | background-image: -o-linear-gradient(top, #e6e6e6, #ffffff); 385 | background-image: linear-gradient(to bottom, #e6e6e6, #ffffff); 386 | background-repeat: repeat-x; 387 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffffffff', GradientType=0); 388 | border-color: #ffffff #ffffff #d9d9d9; 389 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 390 | *background-color: #ffffff; 391 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */ 392 | 393 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 394 | } 395 | .has-switch span.switch-default:hover, 396 | .has-switch span.switch-default:focus, 397 | .has-switch span.switch-default:active, 398 | .has-switch span.switch-default.active, 399 | .has-switch span.switch-default.disabled, 400 | .has-switch span.switch-default[disabled] { 401 | color: #333333; 402 | background-color: #ffffff; 403 | *background-color: #f2f2f2; 404 | } 405 | .has-switch span.switch-default:active, 406 | .has-switch span.switch-default.active { 407 | background-color: #e6e6e6 \9; 408 | } 409 | -------------------------------------------------------------------------------- /demoproject/filter/static/js/bootstrap-switch.min.js: -------------------------------------------------------------------------------- 1 | /*! ============================================================ 2 | * bootstrapSwitch v1.8 by Larentis Mattia @SpiritualGuru 3 | * http://www.larentis.eu/ 4 | * 5 | * Enhanced for radiobuttons by Stein, Peter @BdMdesigN 6 | * http://www.bdmdesign.org/ 7 | * 8 | * Project site: 9 | * http://www.larentis.eu/switch/ 10 | * ============================================================ 11 | * Licensed under the Apache License, Version 2.0 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * ============================================================ */ 14 | !function($){"use strict";$.fn['bootstrapSwitch']=function(method){var inputSelector='input[type!="hidden"]';var methods={init:function(){return this.each(function(){var $element=$(this),$div,$switchLeft,$switchRight,$label,$form=$element.closest('form'),myClasses="",classes=$element.attr('class'),color,moving,onLabel="ON",offLabel="OFF",icon=false,textLabel=false;$.each(['switch-mini','switch-small','switch-large'],function(i,el){if(classes.indexOf(el)>=0)myClasses=el});$element.addClass('has-switch');if($element.data('on')!==undefined)color="switch-"+$element.data('on');if($element.data('on-label')!==undefined)onLabel=$element.data('on-label');if($element.data('off-label')!==undefined)offLabel=$element.data('off-label');if($element.data('label-icon')!==undefined)icon=$element.data('label-icon');if($element.data('text-label')!==undefined)textLabel=$element.data('text-label');$switchLeft=$('').addClass("switch-left").addClass(myClasses).addClass(color).html(onLabel);color='';if($element.data('off')!==undefined)color="switch-"+$element.data('off');$switchRight=$('').addClass("switch-right").addClass(myClasses).addClass(color).html(offLabel);$label=$('