├── .coveragerc ├── .flake8 ├── .github ├── dependabot.yml └── workflows │ ├── run_pre_commit.yml │ └── run_tox.yml ├── .gitignore ├── .isort.cfg ├── .pre-commit-config.yaml ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── docs ├── Makefile └── source │ ├── _ext │ └── djangodocs.py │ ├── changelog.rst │ ├── conf.py │ ├── configuration.rst │ ├── index.rst │ ├── installation.rst │ ├── intro.rst │ ├── quickstart.rst │ ├── reference.rst │ ├── sampleproject.rst │ └── usage.rst ├── easy_select2 ├── __init__.py ├── forms.py ├── static │ └── easy_select2 │ │ ├── css │ │ └── easy_select2.css │ │ ├── js │ │ ├── easy_select2.js │ │ └── init.js │ │ └── vendor │ │ ├── jquery │ │ ├── COPYING │ │ ├── jquery-3.5.1.min.js │ │ └── jquery-3.5.1.min.map │ │ └── select2-4.0.13 │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── css │ │ ├── select2.css │ │ └── select2.min.css │ │ └── js │ │ ├── i18n │ │ ├── af.js │ │ ├── ar.js │ │ ├── az.js │ │ ├── bg.js │ │ ├── bn.js │ │ ├── bs.js │ │ ├── ca.js │ │ ├── cs.js │ │ ├── da.js │ │ ├── de.js │ │ ├── dsb.js │ │ ├── el.js │ │ ├── en.js │ │ ├── es.js │ │ ├── et.js │ │ ├── eu.js │ │ ├── fa.js │ │ ├── fi.js │ │ ├── fr.js │ │ ├── gl.js │ │ ├── he.js │ │ ├── hi.js │ │ ├── hr.js │ │ ├── hsb.js │ │ ├── hu.js │ │ ├── hy.js │ │ ├── id.js │ │ ├── is.js │ │ ├── it.js │ │ ├── ja.js │ │ ├── ka.js │ │ ├── km.js │ │ ├── ko.js │ │ ├── lt.js │ │ ├── lv.js │ │ ├── mk.js │ │ ├── ms.js │ │ ├── nb.js │ │ ├── ne.js │ │ ├── nl.js │ │ ├── pl.js │ │ ├── ps.js │ │ ├── pt-BR.js │ │ ├── pt.js │ │ ├── ro.js │ │ ├── ru.js │ │ ├── sk.js │ │ ├── sl.js │ │ ├── sq.js │ │ ├── sr-Cyrl.js │ │ ├── sr.js │ │ ├── sv.js │ │ ├── th.js │ │ ├── tk.js │ │ ├── tr.js │ │ ├── uk.js │ │ ├── vi.js │ │ ├── zh-CN.js │ │ └── zh-TW.js │ │ ├── select2.full.js │ │ ├── select2.full.min.js │ │ ├── select2.js │ │ └── select2.min.js ├── utils.py └── widgets.py ├── sampleproject ├── README.rst ├── bootstrap.sh ├── demoapp │ ├── __init__.py │ ├── admin.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ └── demoapp │ │ │ ├── note_form.html │ │ │ └── note_list.html │ ├── urls.py │ └── views.py ├── manage.py ├── requirements.txt └── sampleproject │ ├── __init__.py │ ├── local_settings.py │ ├── settings.py │ ├── static │ ├── css │ │ └── .gitkeep │ ├── img │ │ └── .gitkeep │ └── js │ │ └── .gitkeep │ ├── templates │ └── .gitkeep │ ├── urls.py │ └── wsgi.py ├── screenshots ├── select2_multiple.png └── select2_single.png ├── setup.py ├── tests ├── __init__.py ├── test_forms.py ├── test_utils.py └── test_widgets.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = tests/* 3 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | commit-message: 6 | include: "scope" 7 | prefix: "Actions" 8 | directory: "/" 9 | labels: 10 | - "enhancement" 11 | schedule: 12 | interval: "weekly" 13 | -------------------------------------------------------------------------------- /.github/workflows/run_pre_commit.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Sebastian Pipping 2 | # Licensed under the MIT license 3 | 4 | name: Run pre-commit on all files 5 | 6 | on: 7 | pull_request: 8 | push: 9 | schedule: 10 | - cron: '0 16 * * 5' # Every Friday at 16:00 11 | 12 | jobs: 13 | run_pre_commit: 14 | name: Run pre-commit on all files 15 | runs-on: ubuntu-24.04 16 | steps: 17 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 18 | 19 | - name: Set up Python 3.10 20 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 21 | with: 22 | python-version: '3.10' 23 | 24 | - name: Install pre-commit 25 | run: |- 26 | pip install \ 27 | --disable-pip-version-check \ 28 | --user \ 29 | --no-warn-script-location \ 30 | pre-commit 31 | echo "PATH=${HOME}/.local/bin:${PATH}" >> "${GITHUB_ENV}" 32 | 33 | - name: Install pre-commit hooks 34 | run: |- 35 | pre-commit install --install-hooks 36 | 37 | - name: Run pre-commit on all files 38 | run: |- 39 | pre-commit run --all-files 40 | -------------------------------------------------------------------------------- /.github/workflows/run_tox.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 Sebastian Pipping 2 | # Licensed under the MIT license 3 | 4 | name: Run tox 5 | 6 | on: 7 | pull_request: 8 | push: 9 | schedule: 10 | - cron: '0 16 * * 5' # Every Friday at 16:00 11 | 12 | jobs: 13 | run_tox: 14 | name: Run tox 15 | runs-on: ubuntu-24.04 16 | strategy: 17 | matrix: 18 | python-version: 19 | - 3.9 # oldest supported version 20 | - '3.10' # includes tox env about code coverage 21 | 22 | steps: 23 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | 25 | - name: Set up Python ${{ matrix.python-version }} 26 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 27 | with: 28 | python-version: ${{ matrix.python-version }} 29 | 30 | - name: Install tox 31 | run: |- 32 | pip install \ 33 | --disable-pip-version-check \ 34 | --user \ 35 | --no-warn-script-location \ 36 | tox 37 | echo "PATH=${HOME}/.local/bin:${PATH}" >> "${GITHUB_ENV}" 38 | 39 | - name: Run tox (environments matching Python ${{ matrix.python-version }}) 40 | run: |- 41 | set -x 42 | python_version_without_dot="$(sed 's,\.,,' <<< "${{ matrix.python-version }}")" 43 | function join_by { local IFS="$1"; shift; echo "$*"; } 44 | tox_envs=( $(tox --listenvs | fgrep "py${python_version_without_dot}-") ) 45 | tox -e "$(join_by ',' "${tox_envs[@]}")" 46 | env: 47 | COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | dist 3 | build 4 | *.egg-info 5 | 6 | *.log 7 | *.pid 8 | 9 | /sampleproject/bin 10 | /sampleproject/lib 11 | /sampleproject/share 12 | /sampleproject/env 13 | /sampleproject/*.sqlite3 14 | 15 | /docs/build 16 | 17 | .tox 18 | .coverage 19 | .cache 20 | .idea 21 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | line_length = 120 3 | multi_line_output = 2 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2022 Sebastian Pipping 2 | # Licensed under the MIT license 3 | 4 | repos: 5 | - repo: https://github.com/pre-commit/pre-commit-hooks 6 | rev: v4.4.0 7 | hooks: 8 | - id: check-yaml 9 | - id: check-merge-conflict 10 | - id: end-of-file-fixer 11 | exclude: '^easy_select2/static/easy_select2/vendor/' 12 | - id: trailing-whitespace 13 | 14 | - repo: https://github.com/PyCQA/flake8 15 | rev: 6.0.0 16 | hooks: 17 | - id: flake8 18 | args: ['--show-source'] 19 | exclude: '^(docs/source/|sampleproject/demoapp/migrations/)' 20 | 21 | - repo: https://github.com/pycqa/isort 22 | rev: 5.12.0 23 | hooks: 24 | - id: isort 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 asyncee 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | recursive-include easy_select2/static * 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | This is django application that brings select2 widget to select inputs 2 | in admin. 3 | 4 | --------------- 5 | 6 | |python| |pypi| |github-actions| |coveralls| |license| 7 | 8 | 9 | Project aims to support Python 3.9+ and Django 2.2+. 10 | 11 | For **Django < 2.0** version support or **python-2.x** compatibility, please use version **1.3.4** which is 12 | the last version to support **python-2.x** compatibility. 13 | 14 | For **Django 2.0/2.1** version support or **Python 3.5/3.6** compatibility, please use version **1.5.7** which is 15 | the last version to support **Django 2.0/2.1** and **Python 3.5/3.6** compatibility. 16 | 17 | This django library is just a lightweight wrapper on `Select2` library 18 | and provides easy-to-use basic select2 functionality in a django project. 19 | If you need feature-rich solution, i recommend you to look at the latest 20 | django-select2_ library, which have ajax loading support. 21 | 22 | If anyone really wants this functionality in django-easy-select2, 23 | please feel free to contribute. 24 | 25 | .. _django-select2: https://github.com/applegrew/django-select2 26 | 27 | Currently project is not in active development state and 28 | is maintained by community. Pull requests are welcomed! 29 | 30 | 31 | Upgrade notes 32 | ------------- 33 | For details please read changelog_. 34 | 35 | 36 | How it looks 37 | ------------ 38 | 39 | Select one of existing values with single-valued choice field 40 | (ForeignKeyField, for example): 41 | 42 | .. image:: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_single.png 43 | :target: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_single.png 44 | 45 | Easily select 1 or more "categories" for your project, you can also 46 | add a new one in the normal, Django-Admin manner by using the 47 | green + button with multiple-valued choice field (ManyToManyField): 48 | 49 | .. image:: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_multiple.png 50 | :target: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_multiple.png 51 | 52 | 53 | Quickstart 54 | ---------- 55 | 56 | In your admin.py: 57 | 58 | .. code-block:: python 59 | 60 | from django.contrib import admin 61 | from easy_select2 import select2_modelform 62 | from polls.models import Poll 63 | 64 | PollForm = select2_modelform(Poll, attrs={'width': '250px'}) 65 | 66 | class PollAdmin(admin.ModelAdmin): 67 | form = PollForm 68 | 69 | 70 | Thats all. All your choice widgets are select2 widgets 250px wide. 71 | 72 | 73 | Documentation 74 | ------------- 75 | You can read more in the documentation_. 76 | 77 | .. _documentation: http://django-easy-select2.readthedocs.org 78 | 79 | .. _changelog: http://django-easy-select2.readthedocs.org/en/latest/changelog.html 80 | 81 | .. |pypi| image:: https://img.shields.io/pypi/v/django-easy-select2.svg?style=flat-square 82 | :target: https://pypi.python.org/pypi/django-easy-select2 83 | :alt: pypi 84 | 85 | .. |github-actions| image:: https://github.com/asyncee/django-easy-select2/actions/workflows/run_tox.yml/badge.svg 86 | :target: https://github.com/asyncee/django-easy-select2/actions/workflows/run_tox.yml 87 | :alt: GitHub Action "Run tox" 88 | 89 | .. |coveralls| image:: https://img.shields.io/coveralls/asyncee/django-easy-select2.svg?style=flat-square 90 | :target: https://coveralls.io/r/asyncee/django-easy-select2 91 | :alt: coverage 92 | 93 | .. |license| image:: https://img.shields.io/github/license/asyncee/django-easy-select2.svg?style=flat-square 94 | :target: https://github.com/asyncee/django-easy-select2/blob/master/LICENSE.txt 95 | :alt: MIT License 96 | 97 | .. |python| image:: https://img.shields.io/badge/python-3.x-blue.svg?style=flat-square 98 | :target: https://pypi.python.org/pypi/django-easy-select2 99 | :alt: Python 3.x 100 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Easy-select2.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Easy-select2.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Easy-select2" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Easy-select2" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /docs/source/_ext/djangodocs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sphinx plugins for Django documentation. 3 | """ 4 | import json 5 | import os 6 | import re 7 | 8 | from docutils import nodes 9 | from docutils.parsers.rst import Directive, directives 10 | from docutils.statemachine import ViewList 11 | from sphinx import addnodes 12 | from sphinx.builders.html import StandaloneHTMLBuilder 13 | from sphinx.directives import CodeBlock 14 | from sphinx.domains.std import Cmdoption 15 | from sphinx.util.console import bold 16 | from sphinx.util.nodes import set_source_info 17 | from sphinx.writers.html import HTMLTranslator 18 | 19 | # RE for option descriptions without a '--' prefix 20 | simple_option_desc_re = re.compile( 21 | r'([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)') 22 | 23 | 24 | def setup(app): 25 | app.add_crossref_type( 26 | directivename="setting", 27 | rolename="setting", 28 | indextemplate="pair: %s; setting", 29 | ) 30 | app.add_crossref_type( 31 | directivename="templatetag", 32 | rolename="ttag", 33 | indextemplate="pair: %s; template tag" 34 | ) 35 | app.add_crossref_type( 36 | directivename="templatefilter", 37 | rolename="tfilter", 38 | indextemplate="pair: %s; template filter" 39 | ) 40 | app.add_crossref_type( 41 | directivename="fieldlookup", 42 | rolename="lookup", 43 | indextemplate="pair: %s; field lookup type", 44 | ) 45 | app.add_description_unit( 46 | directivename="django-admin", 47 | rolename="djadmin", 48 | indextemplate="pair: %s; django-admin command", 49 | parse_node=parse_django_admin_node, 50 | ) 51 | app.add_directive('django-admin-option', Cmdoption) 52 | app.add_config_value('django_next_version', '0.0', True) 53 | app.add_directive('versionadded', VersionDirective) 54 | app.add_directive('versionchanged', VersionDirective) 55 | app.add_builder(DjangoStandaloneHTMLBuilder) 56 | 57 | # register the snippet directive 58 | app.add_directive('snippet', SnippetWithFilename) 59 | # register a node for snippet directive so that the xml parser 60 | # knows how to handle the enter/exit parsing event 61 | app.add_node(snippet_with_filename, 62 | html=(visit_snippet, depart_snippet_literal), 63 | latex=(visit_snippet_latex, depart_snippet_latex), 64 | man=(visit_snippet_literal, depart_snippet_literal), 65 | text=(visit_snippet_literal, depart_snippet_literal), 66 | texinfo=(visit_snippet_literal, depart_snippet_literal)) 67 | app.set_translator('djangohtml', DjangoHTMLTranslator) 68 | app.set_translator('json', DjangoHTMLTranslator) 69 | app.add_node( 70 | ConsoleNode, 71 | html=(visit_console_html, None), 72 | latex=(visit_console_dummy, depart_console_dummy), 73 | man=(visit_console_dummy, depart_console_dummy), 74 | text=(visit_console_dummy, depart_console_dummy), 75 | texinfo=(visit_console_dummy, depart_console_dummy), 76 | ) 77 | app.add_directive('console', ConsoleDirective) 78 | app.connect('html-page-context', html_page_context_hook) 79 | return {'parallel_read_safe': True} 80 | 81 | 82 | class snippet_with_filename(nodes.literal_block): 83 | """ 84 | Subclass the literal_block to override the visit/depart event handlers 85 | """ 86 | pass 87 | 88 | 89 | def visit_snippet_literal(self, node): 90 | """ 91 | default literal block handler 92 | """ 93 | self.visit_literal_block(node) 94 | 95 | 96 | def depart_snippet_literal(self, node): 97 | """ 98 | default literal block handler 99 | """ 100 | self.depart_literal_block(node) 101 | 102 | 103 | def visit_snippet(self, node): 104 | """ 105 | HTML document generator visit handler 106 | """ 107 | lang = self.highlightlang 108 | linenos = node.rawsource.count('\n') >= self.highlightlinenothreshold - 1 109 | fname = node['filename'] 110 | highlight_args = node.get('highlight_args', {}) 111 | if 'language' in node: 112 | # code-block directives 113 | lang = node['language'] 114 | highlight_args['force'] = True 115 | if 'linenos' in node: 116 | linenos = node['linenos'] 117 | 118 | def warner(msg): 119 | self.builder.warn(msg, (self.builder.current_docname, node.line)) 120 | 121 | highlighted = self.highlighter.highlight_block(node.rawsource, lang, 122 | warn=warner, 123 | linenos=linenos, 124 | **highlight_args) 125 | starttag = self.starttag(node, 'div', suffix='', 126 | CLASS='highlight-%s snippet' % lang) 127 | self.body.append(starttag) 128 | self.body.append('
%s
\n''' % (fname,)) 129 | self.body.append(highlighted) 130 | self.body.append('\n') 131 | raise nodes.SkipNode 132 | 133 | 134 | def visit_snippet_latex(self, node): 135 | """ 136 | Latex document generator visit handler 137 | """ 138 | code = node.rawsource.rstrip('\n') 139 | 140 | lang = self.hlsettingstack[-1][0] 141 | linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1 142 | fname = node['filename'] 143 | highlight_args = node.get('highlight_args', {}) 144 | if 'language' in node: 145 | # code-block directives 146 | lang = node['language'] 147 | highlight_args['force'] = True 148 | if 'linenos' in node: 149 | linenos = node['linenos'] 150 | 151 | def warner(msg): 152 | self.builder.warn(msg, (self.curfilestack[-1], node.line)) 153 | 154 | hlcode = self.highlighter.highlight_block(code, lang, warn=warner, 155 | linenos=linenos, 156 | **highlight_args) 157 | 158 | self.body.append( 159 | '\n{\\colorbox[rgb]{0.9,0.9,0.9}' 160 | '{\\makebox[\\textwidth][l]' 161 | '{\\small\\texttt{%s}}}}\n' % ( 162 | # Some filenames have '_', which is special in latex. 163 | fname.replace('_', r'\_'), 164 | ) 165 | ) 166 | 167 | if self.table: 168 | hlcode = hlcode.replace('\\begin{Verbatim}', 169 | '\\begin{OriginalVerbatim}') 170 | self.table.has_problematic = True 171 | self.table.has_verbatim = True 172 | 173 | hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim} 174 | hlcode = hlcode.rstrip() + '\n' 175 | self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' % 176 | (self.table and 'Original' or '')) 177 | 178 | # Prevent rawsource from appearing in output a second time. 179 | raise nodes.SkipNode 180 | 181 | 182 | def depart_snippet_latex(self, node): 183 | """ 184 | Latex document generator depart handler. 185 | """ 186 | pass 187 | 188 | 189 | class SnippetWithFilename(Directive): 190 | """ 191 | The 'snippet' directive that allows to add the filename (optional) 192 | of a code snippet in the document. This is modeled after CodeBlock. 193 | """ 194 | has_content = True 195 | optional_arguments = 1 196 | option_spec = {'filename': directives.unchanged_required} 197 | 198 | def run(self): 199 | code = '\n'.join(self.content) 200 | 201 | literal = snippet_with_filename(code, code) 202 | if self.arguments: 203 | literal['language'] = self.arguments[0] 204 | literal['filename'] = self.options['filename'] 205 | set_source_info(self, literal) 206 | return [literal] 207 | 208 | 209 | class VersionDirective(Directive): 210 | has_content = True 211 | required_arguments = 1 212 | optional_arguments = 1 213 | final_argument_whitespace = True 214 | option_spec = {} 215 | 216 | def run(self): 217 | if len(self.arguments) > 1: 218 | msg = """Only one argument accepted for directive '{directive_name}::'. 219 | Comments should be provided as content, 220 | not as an extra argument.""".format(directive_name=self.name) 221 | raise self.error(msg) 222 | 223 | env = self.state.document.settings.env 224 | ret = [] 225 | node = addnodes.versionmodified() 226 | ret.append(node) 227 | 228 | if self.arguments[0] == env.config.django_next_version: 229 | node['version'] = "Development version" 230 | else: 231 | node['version'] = self.arguments[0] 232 | 233 | node['type'] = self.name 234 | if self.content: 235 | self.state.nested_parse(self.content, self.content_offset, node) 236 | env.note_versionchange(node['type'], node['version'], node, self.lineno) 237 | return ret 238 | 239 | 240 | class DjangoHTMLTranslator(HTMLTranslator): 241 | """ 242 | Django-specific reST to HTML tweaks. 243 | """ 244 | 245 | # Don't use border=1, which docutils does by default. 246 | def visit_table(self, node): 247 | self.context.append(self.compact_p) 248 | self.compact_p = True 249 | self._table_row_index = 0 # Needed by Sphinx 250 | self.body.append(self.starttag(node, 'table', CLASS='docutils')) 251 | 252 | def depart_table(self, node): 253 | self.compact_p = self.context.pop() 254 | self.body.append('\n') 255 | 256 | def visit_desc_parameterlist(self, node): 257 | self.body.append('(') # by default sphinx puts around the "(" 258 | self.first_param = 1 259 | self.optional_param_level = 0 260 | self.param_separator = node.child_text_separator 261 | self.required_params_left = sum(isinstance(c, addnodes.desc_parameter) for c in node.children) 262 | 263 | def depart_desc_parameterlist(self, node): 264 | self.body.append(')') 265 | 266 | # 267 | # Turn the "new in version" stuff (versionadded/versionchanged) into a 268 | # better callout -- the Sphinx default is just a little span, 269 | # which is a bit less obvious that I'd like. 270 | # 271 | # FIXME: these messages are all hardcoded in English. We need to change 272 | # that to accommodate other language docs, but I can't work out how to make 273 | # that work. 274 | # 275 | version_text = { 276 | 'versionchanged': 'Changed in Django %s', 277 | 'versionadded': 'New in Django %s', 278 | } 279 | 280 | def visit_versionmodified(self, node): 281 | self.body.append( 282 | self.starttag(node, 'div', CLASS=node['type']) 283 | ) 284 | version_text = self.version_text.get(node['type']) 285 | if version_text: 286 | title = "%s%s" % ( 287 | version_text % node['version'], 288 | ":" if node else "." 289 | ) 290 | self.body.append('%s ' % title) 291 | 292 | def depart_versionmodified(self, node): 293 | self.body.append("\n") 294 | 295 | # Give each section a unique ID -- nice for custom CSS hooks 296 | def visit_section(self, node): 297 | old_ids = node.get('ids', []) 298 | node['ids'] = ['s-' + i for i in old_ids] 299 | node['ids'].extend(old_ids) 300 | super().visit_section(node) 301 | node['ids'] = old_ids 302 | 303 | 304 | def parse_django_admin_node(env, sig, signode): 305 | command = sig.split(' ')[0] 306 | env.ref_context['std:program'] = command 307 | title = "django-admin %s" % sig 308 | signode += addnodes.desc_name(title, title) 309 | return command 310 | 311 | 312 | class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder): 313 | """ 314 | Subclass to add some extra things we need. 315 | """ 316 | 317 | name = 'djangohtml' 318 | 319 | def finish(self): 320 | super().finish() 321 | self.info(bold("writing templatebuiltins.js...")) 322 | xrefs = self.env.domaindata["std"]["objects"] 323 | templatebuiltins = { 324 | "ttags": [ 325 | n for ((t, n), (k, a)) in xrefs.items() 326 | if t == "templatetag" and k == "ref/templates/builtins" 327 | ], 328 | "tfilters": [ 329 | n for ((t, n), (k, a)) in xrefs.items() 330 | if t == "templatefilter" and k == "ref/templates/builtins" 331 | ], 332 | } 333 | outfilename = os.path.join(self.outdir, "templatebuiltins.js") 334 | with open(outfilename, 'w') as fp: 335 | fp.write('var django_template_builtins = ') 336 | json.dump(templatebuiltins, fp) 337 | fp.write(';\n') 338 | 339 | 340 | class ConsoleNode(nodes.literal_block): 341 | """ 342 | Custom node to override the visit/depart event handlers at registration 343 | time. Wrap a literal_block object and defer to it. 344 | """ 345 | def __init__(self, litblk_obj): 346 | self.wrapped = litblk_obj 347 | 348 | def __getattr__(self, attr): 349 | if attr == 'wrapped': 350 | return self.__dict__.wrapped 351 | return getattr(self.wrapped, attr) 352 | 353 | 354 | def visit_console_dummy(self, node): 355 | """Defer to the corresponding parent's handler.""" 356 | self.visit_literal_block(node) 357 | 358 | 359 | def depart_console_dummy(self, node): 360 | """Defer to the corresponding parent's handler.""" 361 | self.depart_literal_block(node) 362 | 363 | 364 | def visit_console_html(self, node): 365 | """Generate HTML for the console directive.""" 366 | if self.builder.name in ('djangohtml', 'json') and node['win_console_text']: 367 | # Put a mark on the document object signaling the fact the directive 368 | # has been used on it. 369 | self.document._console_directive_used_flag = True 370 | uid = node['uid'] 371 | self.body.append('''\ 372 |
373 | 374 | 375 | 376 | 377 |
\n''' % {'id': uid}) 378 | try: 379 | self.visit_literal_block(node) 380 | except nodes.SkipNode: 381 | pass 382 | self.body.append('
\n') 383 | 384 | self.body.append('
\n' % {'id': uid}) 385 | win_text = node['win_console_text'] 386 | highlight_args = {'force': True} 387 | if 'linenos' in node: 388 | linenos = node['linenos'] 389 | else: 390 | linenos = win_text.count('\n') >= self.highlightlinenothreshold - 1 391 | 392 | def warner(msg): 393 | self.builder.warn(msg, (self.builder.current_docname, node.line)) 394 | 395 | highlighted = self.highlighter.highlight_block( 396 | win_text, 'doscon', warn=warner, linenos=linenos, **highlight_args 397 | ) 398 | self.body.append(highlighted) 399 | self.body.append('
\n') 400 | self.body.append('
\n') 401 | raise nodes.SkipNode 402 | else: 403 | self.visit_literal_block(node) 404 | 405 | 406 | class ConsoleDirective(CodeBlock): 407 | """ 408 | A reStructuredText directive which renders a two-tab code block in which 409 | the second tab shows a Windows command line equivalent of the usual 410 | Unix-oriented examples. 411 | """ 412 | required_arguments = 0 413 | # The 'doscon' Pygments formatter needs a prompt like this. '>' alone 414 | # won't do it because then it simply paints the whole command line as a 415 | # grey comment with no highlighting at all. 416 | WIN_PROMPT = r'...\> ' 417 | 418 | def run(self): 419 | 420 | def args_to_win(cmdline): 421 | changed = False 422 | out = [] 423 | for token in cmdline.split(): 424 | if token[:2] == './': 425 | token = token[2:] 426 | changed = True 427 | elif token[:2] == '~/': 428 | token = '%HOMEPATH%\\' + token[2:] 429 | changed = True 430 | elif token == 'make': 431 | token = 'make.bat' 432 | changed = True 433 | if '://' not in token and 'git' not in cmdline: 434 | out.append(token.replace('/', '\\')) 435 | changed = True 436 | else: 437 | out.append(token) 438 | if changed: 439 | return ' '.join(out) 440 | return cmdline 441 | 442 | def cmdline_to_win(line): 443 | if line.startswith('# '): 444 | return 'REM ' + args_to_win(line[2:]) 445 | if line.startswith('$ # '): 446 | return 'REM ' + args_to_win(line[4:]) 447 | if line.startswith('$ ./manage.py'): 448 | return 'manage.py ' + args_to_win(line[13:]) 449 | if line.startswith('$ manage.py'): 450 | return 'manage.py ' + args_to_win(line[11:]) 451 | if line.startswith('$ ./runtests.py'): 452 | return 'runtests.py ' + args_to_win(line[15:]) 453 | if line.startswith('$ ./'): 454 | return args_to_win(line[4:]) 455 | if line.startswith('$ python'): 456 | return 'py ' + args_to_win(line[8:]) 457 | if line.startswith('$ '): 458 | return args_to_win(line[2:]) 459 | return None 460 | 461 | def code_block_to_win(content): 462 | bchanged = False 463 | lines = [] 464 | for line in content: 465 | modline = cmdline_to_win(line) 466 | if modline is None: 467 | lines.append(line) 468 | else: 469 | lines.append(self.WIN_PROMPT + modline) 470 | bchanged = True 471 | if bchanged: 472 | return ViewList(lines) 473 | return None 474 | 475 | env = self.state.document.settings.env 476 | self.arguments = ['console'] 477 | lit_blk_obj = super().run()[0] 478 | 479 | # Only do work when the djangohtml HTML Sphinx builder is being used, 480 | # invoke the default behavior for the rest. 481 | if env.app.builder.name not in ('djangohtml', 'json'): 482 | return [lit_blk_obj] 483 | 484 | lit_blk_obj['uid'] = '%s' % env.new_serialno('console') 485 | # Only add the tabbed UI if there is actually a Windows-specific 486 | # version of the CLI example. 487 | win_content = code_block_to_win(self.content) 488 | if win_content is None: 489 | lit_blk_obj['win_console_text'] = None 490 | else: 491 | self.content = win_content 492 | lit_blk_obj['win_console_text'] = super().run()[0].rawsource 493 | 494 | # Replace the literal_node object returned by Sphinx's CodeBlock with 495 | # the ConsoleNode wrapper. 496 | return [ConsoleNode(lit_blk_obj)] 497 | 498 | 499 | def html_page_context_hook(app, pagename, templatename, context, doctree): 500 | # Put a bool on the context used to render the template. It's used to 501 | # control inclusion of console-tabs.css and activation of the JavaScript. 502 | # This way it's include only from HTML files rendered from reST files where 503 | # the ConsoleDirective is used. 504 | context['include_console_assets'] = getattr(doctree, '_console_directive_used_flag', False) 505 | -------------------------------------------------------------------------------- /docs/source/changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | Version ?.?.? 5 | ------------- 6 | 7 | Bugs Fixed 8 | ~~~~~~~~~~ 9 | 10 | - ``setup.py``: Drop leftover classifiers (`#98 `_) 11 | 12 | 13 | Version 1.5.8 14 | ------------- 15 | 16 | Bugs Fixed 17 | ~~~~~~~~~~ 18 | 19 | - ``setup.py``: Stop installing package ``tests`` (`#85 `_) 20 | - Added Django 4.0 support (`#86 `_, `#87 `_, `#88 `_) 21 | 22 | 23 | Enhancements 24 | ~~~~~~~~~~~~ 25 | 26 | - Update bundled Select2 to 4.0.13 (`#65 `_, `#67 `_) 27 | - Update bundled jQuery to 3.1.5 (`#67 `_) 28 | - Activate support for Python 3.8 (`#69 `_) 29 | - Drop dummy files of little value (`#70 `_) 30 | - Remove unused imports (`#72 `_) 31 | - Improve sample project (`#73 `_) 32 | - Support using Select2 assets of Django Admin (`#74 `_); 33 | this introduces a a new setting ``SELECT2_USE_BUNDLED_SELECT2``. 34 | Default is ``True``, set to ``False`` if you want to use Select2 of Django Admin. 35 | - Demo use outside of Django Admin (`#76 `_) 36 | - Bump Django from 2.2.10 to 2.2.25 in ``/sampleproject`` (`#91 `_) 37 | - Drop end-of-life Django 2.0/2.1/3.0 and Python 3.5/3.6 (`#94 `_, `#95 `_) 38 | 39 | 40 | Infrastructure 41 | ~~~~~~~~~~~~~~ 42 | 43 | - Introduce pre-commit (`#75 `_) 44 | - Actions: Get off deprecated ``::set-env`` (`#78 `_) 45 | - Actions: Make GitHub Dependabot keep our GitHub Actions up to date (`#89 `_) 46 | - Actions: Bump actions/setup-python from 1.1.1 to 2.3.1 (`#90 `_) 47 | - Improve pre-commit GitHub Action + enable cron mode (`#92 `_) 48 | - Execute tox on GitHub Actions rather than Travis CI (`#93 `_) 49 | - Actions: Restore coveralls (`#96 `_) 50 | - coveralls: Stop using discouraged ``--service=github`` (`#97 `_) 51 | 52 | 53 | Version 1.5.7 54 | ------------- 55 | - Merged #64, thanks to *leibowitz*. Fixed situation when widget were not displayed on django 2.2+. 56 | 57 | Version 1.5.6 58 | ------------- 59 | - Fixed #57, thanks to *jaikanthjay46* 60 | 61 | Version 1.5.5 62 | ------------- 63 | - Fixed cascading issue-52 bug 64 | - Introducing django's Jquery to easy-select2 for accessing django's JQuery 65 | 66 | Version 1.5.4 67 | ------------- 68 | - Work with jQuery instead of depending on $, thanks to *leibowitz* 69 | - Fixed a problem with django admin tabularinline (#52), thanks to *leibowitz* 70 | 71 | Version 1.5.3 72 | ------------- 73 | 74 | .. WARNING:: 75 | 76 | Version 1.5.3 changes, read below. 77 | 78 | - Fixed #50 (partly remaining bug in v 1.5.2) - 1st record addition fixed for "Doesn't work for dynamically added forms in inline admins" 79 | - updated easy_select js to fail case when easy-select2.js[line#65]($(e.target).find('div.field-easy-select2:not([id*="__prefix__"])')) is not able to find elements while in DomNodeInserted corresponding to other node insertion than select2 widgets. 80 | 81 | Version 1.5.2 82 | ------------- 83 | 84 | .. WARNING:: 85 | 86 | Version 1.5.2 changes, read below. 87 | 88 | - Fixed #45 (remaining bug in v 1.5.0) - 1st record addition fixed for "Doesn't work for dynamically added forms in inline admins" 89 | - updated easy_select js to handle DomNodeInserted Event for select2() dynamic initialization for all instances 90 | 91 | Version 1.5.1 92 | ------------- 93 | 94 | .. WARNING:: 95 | 96 | Version 1.5.1 changes, read below. 97 | 98 | - Fixed #45 - "Doesn't work for dynamically added forms in inline admins" 99 | - updated easy_select js to handle DomNodeInserted Event for select2() dynamic initialization 100 | 101 | Version 1.5.0 102 | ------------- 103 | 104 | .. WARNING:: 105 | 106 | Version 1.5.0 major changes, read below. 107 | 108 | - Fixed #44 - "mark_safe problem" 109 | - Support for select2 constructor argument injection, within separate initialization block with for select2. 110 | - updated easy-select2 wrapper initialization. Updated to JQuery plugin code design for JS code injection, 111 | allowing direct injection of select2 constructor arguments. 112 | 113 | Version 1.4.0 114 | ------------- 115 | 116 | .. WARNING:: 117 | 118 | Version 1.4.0 introduced backward incompatible changes, read below. 119 | 120 | - Fixed #38 - "Related model combobox doesn't update after add in Django 2" 121 | - Dropping support for Python 2.x 122 | - Django 2.0+ support. Demoapp updated to reflect the needed changes. 123 | - Python 3.x+ support (recommended Python3.4 and above) 124 | 125 | Version 1.3.4 126 | ------------- 127 | 128 | - Django 1.11 support 129 | 130 | 131 | Version 1.3.3 132 | ------------- 133 | 134 | - Fixed #29 — "Application breaks dumpdata command" 135 | 136 | 137 | Version 1.3.2 138 | ------------- 139 | 140 | - Fixed #24, big thanks to *Andrzej Mateja* 141 | 142 | 143 | Version 1.3.1 144 | ------------- 145 | 146 | - support for django staticfiles storage, thanks to *martolini* for idea 147 | 148 | 149 | Version 1.3 150 | ----------- 151 | 152 | .. WARNING:: 153 | 154 | Version 1.3 introduced backward incompatible changes, read below. 155 | 156 | - `Select2` updated to 4.0.0 157 | - updated `jQuery` to 2.1.3 158 | - removed deprecated `select2_meta_factory`, `Select2TextMixin` and 159 | `Select2TextInput`. 160 | 161 | 162 | Version 1.2 163 | ----------- 164 | 1.2.13 165 | ~~~~~~ 166 | - fixed issue #22, thanks to *zeta83* 167 | 168 | 1.2.12 169 | ~~~~~~ 170 | - fixed issue#2 171 | 172 | 1.2.11 173 | ~~~~~~ 174 | - fixed issue#15 - "RemovedInDjango18Warning" 175 | 176 | 1.2.10 177 | ~~~~~~ 178 | - fixed issue#14 - README.rst is not included in MANIFEST.in 179 | 180 | 1.2.9 181 | ~~~~~ 182 | - fixed issue#12 "Inline relations: "Add another " breaks dropdown boxes" 183 | 184 | .. WARNING:: 185 | 186 | Version 1.2.9 introduced backward incompatible change: 187 | `select2attrs` argument of `Select2Mixin.__init__` must be of type dict 188 | 189 | 190 | 1.2.8 191 | ~~~~~ 192 | - fixed incorrect instructions in help_text of ManyToMany fields #2, thanks to *bashu*. 193 | 194 | 1.2.7 195 | ~~~~~ 196 | - setup.py fixes (issue #11), thanks to *JensTimmerman*. 197 | 198 | 1.2.6 199 | ~~~~~ 200 | - Extended select2_modelform function with `form_class` argument to 201 | specify form base class explicitly (issue #10). 202 | 203 | 1.2.5 204 | ~~~~~ 205 | - Fixed issue #9 "apply_select2 not imported in __init__" thanks to *ocZio* for bug report. 206 | 207 | 1.2.4 208 | ~~~~~ 209 | - Fixed issue #6 "Select will not update selection after adding a new option", 210 | thanks to *ismaelbej* for bug report. 211 | 212 | 1.2.3 213 | ~~~~~ 214 | - Python 3.3 support, thanks to *dzerrenner* 215 | 216 | 1.2.2 217 | ~~~~~ 218 | - Rendering select2attrs as unicode or json based on type 219 | 220 | Now, if select2attrs is instance of basestring (str or unicode), 221 | it will be casted to unicode, else it will be turned to json string. 222 | 223 | 1.2.1 224 | ~~~~~ 225 | - Extended package-level imports with Select2TextInput 226 | 227 | 1.2.0 228 | ~~~~~ 229 | - added Select2TextInput, thanks to *mkoistinen* 230 | 231 | Version 1.1 232 | ----------- 233 | 234 | 1.1.1 235 | ~~~~~ 236 | - issue#1 fix (django-admin-sortable compatibility), thanks to @mkoistinen 237 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Easy-select2 documentation build configuration file, created by 4 | # sphinx-quickstart on Thu Apr 3 13:11:53 2014. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import os 15 | import sys 16 | 17 | lib_path = os.path.abspath('../..') 18 | project_path = os.path.abspath('../../sampleproject/') 19 | 20 | sys.path.insert(0, lib_path) 21 | sys.path.insert(0, project_path) 22 | 23 | os.environ['DJANGO_SETTINGS_MODULE'] = 'sampleproject.settings' 24 | 25 | # If extensions (or modules to document with autodoc) are in another directory, 26 | # add these directories to sys.path here. If the directory is relative to the 27 | # documentation root, use os.path.abspath to make it absolute, like shown here. 28 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "_ext"))) 29 | 30 | # -- General configuration ----------------------------------------------------- 31 | 32 | # If your documentation needs a minimal Sphinx version, state it here. 33 | #needs_sphinx = '1.0' 34 | 35 | # Add any Sphinx extension module names here, as strings. They can be extensions 36 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 37 | extensions = [ 38 | 'djangodocs', 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 39 | 'sphinx.ext.viewcode', 40 | ] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix of source filenames. 46 | source_suffix = '.rst' 47 | 48 | # The encoding of source files. 49 | #source_encoding = 'utf-8-sig' 50 | 51 | # The master toctree document. 52 | master_doc = 'index' 53 | 54 | # General information about the project. 55 | project = u'Easy-select2' 56 | copyright = u'2014, Lobanov Stanislav aka asyncee' 57 | 58 | # The version info for the project you're documenting, acts as replacement for 59 | # |version| and |release|, also used in various other places throughout the 60 | # built documents. 61 | # 62 | # The short X.Y version. 63 | version = '1.2.2' 64 | # The full version, including alpha/beta/rc tags. 65 | release = '1.2.2' 66 | 67 | # The language for content autogenerated by Sphinx. Refer to documentation 68 | # for a list of supported languages. 69 | #language = None 70 | 71 | # There are two options for replacing |today|: either, you set today to some 72 | # non-false value, then it is used: 73 | #today = '' 74 | # Else, today_fmt is used as the format for a strftime call. 75 | #today_fmt = '%B %d, %Y' 76 | 77 | # List of patterns, relative to source directory, that match files and 78 | # directories to ignore when looking for source files. 79 | exclude_patterns = [] 80 | 81 | # The reST default role (used for this markup: `text`) to use for all documents. 82 | #default_role = None 83 | 84 | # If true, '()' will be appended to :func: etc. cross-reference text. 85 | #add_function_parentheses = True 86 | 87 | # If true, the current module name will be prepended to all description 88 | # unit titles (such as .. function::). 89 | #add_module_names = True 90 | 91 | # If true, sectionauthor and moduleauthor directives will be shown in the 92 | # output. They are ignored by default. 93 | #show_authors = False 94 | 95 | # The name of the Pygments (syntax highlighting) style to use. 96 | pygments_style = 'sphinx' 97 | 98 | # A list of ignored prefixes for module index sorting. 99 | #modindex_common_prefix = [] 100 | 101 | # If true, keep warnings as "system message" paragraphs in the built documents. 102 | #keep_warnings = False 103 | 104 | 105 | # -- Options for HTML output --------------------------------------------------- 106 | 107 | # The theme to use for HTML and HTML Help pages. See the documentation for 108 | # a list of builtin themes. 109 | html_theme = 'default' 110 | 111 | # Theme options are theme-specific and customize the look and feel of a theme 112 | # further. For a list of options available for each theme, see the 113 | # documentation. 114 | #html_theme_options = {} 115 | 116 | # Add any paths that contain custom themes here, relative to this directory. 117 | #html_theme_path = [] 118 | 119 | # The name for this set of Sphinx documents. If None, it defaults to 120 | # " v documentation". 121 | #html_title = None 122 | 123 | # A shorter title for the navigation bar. Default is the same as html_title. 124 | #html_short_title = None 125 | 126 | # The name of an image file (relative to this directory) to place at the top 127 | # of the sidebar. 128 | #html_logo = None 129 | 130 | # The name of an image file (within the static path) to use as favicon of the 131 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 132 | # pixels large. 133 | #html_favicon = None 134 | 135 | # Add any paths that contain custom static files (such as style sheets) here, 136 | # relative to this directory. They are copied after the builtin static files, 137 | # so a file named "default.css" will overwrite the builtin "default.css". 138 | html_static_path = ['_static'] 139 | 140 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 141 | # using the given strftime format. 142 | #html_last_updated_fmt = '%b %d, %Y' 143 | 144 | # If true, SmartyPants will be used to convert quotes and dashes to 145 | # typographically correct entities. 146 | #html_use_smartypants = True 147 | 148 | # Custom sidebar templates, maps document names to template names. 149 | #html_sidebars = {} 150 | 151 | # Additional templates that should be rendered to pages, maps page names to 152 | # template names. 153 | #html_additional_pages = {} 154 | 155 | # If false, no module index is generated. 156 | #html_domain_indices = True 157 | 158 | # If false, no index is generated. 159 | #html_use_index = True 160 | 161 | # If true, the index is split into individual pages for each letter. 162 | #html_split_index = False 163 | 164 | # If true, links to the reST sources are added to the pages. 165 | #html_show_sourcelink = True 166 | 167 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 168 | #html_show_sphinx = True 169 | 170 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 171 | #html_show_copyright = True 172 | 173 | # If true, an OpenSearch description file will be output, and all pages will 174 | # contain a tag referring to it. The value of this option must be the 175 | # base URL from which the finished HTML is served. 176 | #html_use_opensearch = '' 177 | 178 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 179 | #html_file_suffix = None 180 | 181 | # Output file base name for HTML help builder. 182 | htmlhelp_basename = 'Easy-select2doc' 183 | 184 | 185 | # -- Options for LaTeX output -------------------------------------------------- 186 | 187 | latex_elements = { 188 | # The paper size ('letterpaper' or 'a4paper'). 189 | #'papersize': 'letterpaper', 190 | 191 | # The font size ('10pt', '11pt' or '12pt'). 192 | #'pointsize': '10pt', 193 | 194 | # Additional stuff for the LaTeX preamble. 195 | #'preamble': '', 196 | } 197 | 198 | # Grouping the document tree into LaTeX files. List of tuples 199 | # (source start file, target name, title, author, documentclass [howto/manual]). 200 | latex_documents = [ 201 | ('index', 'Easy-select2.tex', u'Easy-select2 Documentation', 202 | u'Lobanov Stanislav aka asyncee', 'manual'), 203 | ] 204 | 205 | # The name of an image file (relative to this directory) to place at the top of 206 | # the title page. 207 | #latex_logo = None 208 | 209 | # For "manual" documents, if this is true, then toplevel headings are parts, 210 | # not chapters. 211 | #latex_use_parts = False 212 | 213 | # If true, show page references after internal links. 214 | #latex_show_pagerefs = False 215 | 216 | # If true, show URL addresses after external links. 217 | #latex_show_urls = False 218 | 219 | # Documents to append as an appendix to all manuals. 220 | #latex_appendices = [] 221 | 222 | # If false, no module index is generated. 223 | #latex_domain_indices = True 224 | 225 | 226 | # -- Options for manual page output -------------------------------------------- 227 | 228 | # One entry per manual page. List of tuples 229 | # (source start file, name, description, authors, manual section). 230 | man_pages = [ 231 | ('index', 'easy-select2', u'Easy-select2 Documentation', 232 | [u'Lobanov Stanislav aka asyncee'], 1) 233 | ] 234 | 235 | # If true, show URL addresses after external links. 236 | #man_show_urls = False 237 | 238 | 239 | # -- Options for Texinfo output ------------------------------------------------ 240 | 241 | # Grouping the document tree into Texinfo files. List of tuples 242 | # (source start file, target name, title, author, 243 | # dir menu entry, description, category) 244 | texinfo_documents = [ 245 | ('index', 'Easy-select2', u'Easy-select2 Documentation', 246 | u'Lobanov Stanislav aka asyncee', 'Easy-select2', 'One line description of project.', 247 | 'Miscellaneous'), 248 | ] 249 | 250 | # Documents to append as an appendix to all manuals. 251 | #texinfo_appendices = [] 252 | 253 | # If false, no module index is generated. 254 | #texinfo_domain_indices = True 255 | 256 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 257 | #texinfo_show_urls = 'footnote' 258 | 259 | # If true, do not generate a @detailmenu in the "Top" node's menu. 260 | #texinfo_no_detailmenu = False 261 | 262 | 263 | # Example configuration for intersphinx: refer to the Python standard library. 264 | intersphinx_mapping = {'http://docs.python.org/': None} 265 | -------------------------------------------------------------------------------- /docs/source/configuration.rst: -------------------------------------------------------------------------------- 1 | Configuration 2 | ------------- 3 | 4 | ``django-easy-select2`` bundles jQuery and Select2 static files. 5 | You can use them, or specify your own files to include in widget. 6 | 7 | To use bundled static, just install an application. 8 | 9 | To use your custom static files, you can specify next settings in your 10 | settings.py: 11 | 12 | - ``SELECT2_JS`` - path to ``select2.js`` file. Specify path without 13 | static directory, because full URL will be interpolated using 14 | ``static`` function from ``staticfiles`` application. 15 | Default: ``easy_select2/vendor/select2/select2.min.js`` 16 | 17 | - ``SELECT2_CSS`` - path to ``select2.css`` file. 18 | Default: ``easy_select2/vendor/select2/select2.min.css`` 19 | 20 | - ``SELECT2_USE_BUNDLED_JQUERY`` - default is ``True``. Set to 21 | ``False`` if you want to use jQuery of Django Admin, instead. 22 | 23 | - ``SELECT2_USE_BUNDLED_SELECT2`` - default is ``True``. Set to 24 | ``False`` if you want to use Select2 of Django Admin, instead. 25 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Easy-select2 documentation master file, created by 2 | sphinx-quickstart on Thu Apr 3 13:11:53 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Select2 widget for django admin 7 | =============================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :numbered: 14 | 15 | installation 16 | quickstart 17 | configuration 18 | usage 19 | reference 20 | sampleproject 21 | changelog 22 | 23 | 24 | .. include:: intro.rst 25 | 26 | 27 | Continue to :ref:`installation`. 28 | 29 | 30 | Indices and tables 31 | ================== 32 | 33 | * :ref:`genindex` 34 | * :ref:`modindex` 35 | * :ref:`search` 36 | -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation: 2 | 3 | Installation 4 | ============ 5 | 6 | 1. install this package as usual, using ``python setup.py install``, 7 | ``pip install django-easy-select2`` or download sources and install to your 8 | python path. 9 | 2. add ``easy_select2`` to ``INSTALLED_APPS`` in your settings.py 10 | 3. Use ``python manage.py collectstatic`` or manually copy easy_select2's static 11 | directory to your project's static directory (if you serve your static with 12 | nginx, for example). 13 | 4. Modify your admin.py. 14 | 5. Check out admin in browser. 15 | -------------------------------------------------------------------------------- /docs/source/intro.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | This is django application that brings select2 widget to select inputs 4 | in admin. 5 | 6 | 7 | How it looks 8 | ------------ 9 | 10 | Select one of existing values with single-valued choice field 11 | (ForeignKeyField, for example): 12 | 13 | .. image:: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_single.png 14 | :target: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_single.png 15 | 16 | Easily select 1 or more "categories" for your project, you can also 17 | add a new one in the normal, Django-Admin manner by using the green + button 18 | with multiple-valued choice field (ManyToManyField): 19 | 20 | .. image:: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_multiple.png 21 | :target: https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_multiple.png 22 | -------------------------------------------------------------------------------- /docs/source/quickstart.rst: -------------------------------------------------------------------------------- 1 | Quickstart 2 | ---------- 3 | 4 | In your admin.py:: 5 | 6 | from django.contrib import admin 7 | from easy_select2 import select2_modelform 8 | from polls.models import Poll 9 | 10 | PollForm = select2_modelform(Poll, attrs={'width': '250px'}) 11 | 12 | class PollAdmin(admin.ModelAdmin): 13 | form = PollForm 14 | 15 | 16 | Thats all. All your choice widgets are select2 widgets 250px wide. 17 | -------------------------------------------------------------------------------- /docs/source/reference.rst: -------------------------------------------------------------------------------- 1 | Reference 2 | ========= 3 | 4 | Widgets 5 | ------- 6 | .. automodule:: easy_select2.widgets 7 | :members: 8 | 9 | Utils 10 | ----- 11 | .. automodule:: easy_select2.utils 12 | :members: 13 | -------------------------------------------------------------------------------- /docs/source/sampleproject.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../../sampleproject/README.rst 2 | -------------------------------------------------------------------------------- /docs/source/usage.rst: -------------------------------------------------------------------------------- 1 | Usage 2 | ----- 3 | 4 | There are :class:`.Select2` and 5 | :class:`.Select2Multiple` widget classes for choice fields. 6 | 7 | You can use ``Select2`` and ``Select2Multiple`` on any form field, 8 | as usual django widget:: 9 | 10 | class Form(forms.Form): 11 | field = forms.ModelChoiceField(queryset=qs, widget=Select2()) 12 | 13 | or:: 14 | 15 | class Form(forms.Form): 16 | field = forms.ModelMultipleChoiceField(queryset=qs, widget=Select2Multiple( 17 | select2attrs={'width': 'auto'} 18 | )) 19 | 20 | ``Select2`` and ``Select2Multiple`` is simple classes build with 21 | :class:`.Select2Mixin`:: 22 | 23 | class Select2Multiple(Select2Mixin, forms.SelectMultiple): 24 | pass 25 | 26 | class Select2(Select2Mixin, forms.Select): 27 | pass 28 | 29 | ``Select2Mixin`` is a simple widget mixin with predefined ``Media`` 30 | class and custom render method, which applies `$.fn.select2()` 31 | method on html input. 32 | 33 | .. WARNING:: 34 | 35 | Since version 1.2.9 :attr:`select2attrs` should be of type `dict` 36 | or AssertionError will be raised. 37 | 38 | If you want to use it with all form fields automatically, without 39 | specifying each field, you can create your ``ModelForm`` class with 40 | ``Meta`` class constructed by custom ``Meta`` factory:: 41 | 42 | from easy_select2 import select2_modelform_meta 43 | 44 | class SomeModelForm(forms.ModelForm): 45 | Meta = select2_modelform_meta(SomeModel) 46 | 47 | :func:`.select2_modelform_meta` is a simple factory, that produces a 48 | ``Meta`` class with model attribute set to specified model and 49 | :attr:`widgets` attribute set to dictionary, containing all selectable 50 | fields on model. 51 | Every selectable field will be converted from standard widget to 52 | ``Select2`` or ``Select2Multiple`` widget. 53 | 54 | If you are lazy, you can use ``ModelForm`` factory to build ready-to-use 55 | ModelForm for model with :func:`.select2_modelform`:: 56 | 57 | from easy_select2 import select2_modelform 58 | 59 | MyModelForm = select2_modelform(MyModel) 60 | 61 | is the same like:: 62 | 63 | class MyModelForm(forms.ModelForm): 64 | Meta = select2_modelform_meta(models.SomeModelForm) 65 | 66 | You can also specify your base form class instead of default 67 | forms.ModelForm:: 68 | 69 | from easy_select2 import select2_modelform 70 | 71 | MyModelForm = select2_modelform(MyModel, form_class=forms.ModelForm) 72 | 73 | MyModelForm is an instance of ModelForm with ``model`` attribute 74 | set to ``MyModel``, and appropriate ``Meta`` class. 75 | 76 | There is also an :func:`.apply_select2` function that dynamically 77 | creates new widget class mixed with ``Select2Mixin``. 78 | 79 | Usage, for example:: 80 | 81 | class SomeModelForm(admin.ModelForm): 82 | class Meta: 83 | widgets = { 84 | 'field': apply_select2(forms.Select), 85 | } 86 | 87 | So, ``apply_select2(forms.Select)`` will return new class, named 88 | Select2Select, mixed with Select2Mixin. 89 | -------------------------------------------------------------------------------- /easy_select2/__init__.py: -------------------------------------------------------------------------------- 1 | from easy_select2.utils import apply_select2, select2_modelform, select2_modelform_meta 2 | from easy_select2.widgets import Select2, Select2Mixin, Select2Multiple 3 | 4 | __all__ = ['Select2', 'Select2Mixin', 'Select2Multiple', 'apply_select2', 5 | 'select2_modelform', 'select2_modelform_meta'] 6 | -------------------------------------------------------------------------------- /easy_select2/forms.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from django import forms 4 | from django.utils.encoding import force_str 5 | from django.utils.translation import gettext_lazy as _ 6 | 7 | M = _('Hold down "Control", or "Command" on a Mac, to select more than one.') 8 | 9 | 10 | class FixedModelForm(forms.ModelForm): 11 | """ 12 | Simple child of ModelForm that removes the 'Hold down "Control" ...' 13 | message that is enforced in select multiple fields. 14 | 15 | See https://github.com/asyncee/django-easy-select2/issues/2 16 | and https://code.djangoproject.com/ticket/9321 17 | """ 18 | 19 | def __init__(self, *args, **kwargs): 20 | super(FixedModelForm, self).__init__(*args, **kwargs) 21 | 22 | msg = force_str(M) 23 | 24 | for name, field in self.fields.items(): 25 | field.help_text = field.help_text.replace(msg, '') 26 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/css/easy_select2.css: -------------------------------------------------------------------------------- 1 | ul.select2-selection__rendered li { 2 | list-style-type: none; 3 | } 4 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/js/easy_select2.js: -------------------------------------------------------------------------------- 1 | var _jq = (jQuery || django.jQuery) 2 | 3 | // We need this exports because Select2 needs window.jQuery 4 | // to initialize. In fact it removes jQuery.noConflict(true) if 5 | // django.jQuery is used. 6 | if (window.jQuery == undefined) { 7 | window.jQuery = _jq; 8 | } 9 | if (window.$ == undefined) { 10 | window.$ = _jq; 11 | } 12 | 13 | 14 | /** 15 | * $ - external JQuery ref 16 | * _djq - django Jquery ref 17 | */ 18 | (function ($, _djq) { 19 | "use strict"; 20 | // store for keeping all the select2 widget ids for fail-safe parsing later 21 | var _all_easy_select2_ids = []; 22 | /** 23 | * passing the current element to initialize and the options to initialize with 24 | * @param $el - Jquery object to initialize with select2 25 | * @param obj - select2 constructor options 26 | */ 27 | function redisplay_select2($el, obj){ 28 | if(!$.fn.select2){ 29 | if(jQuery.fn.select2){ 30 | $ = jQuery 31 | } else if (_djq.fn.select2) { 32 | $ = _djq; 33 | } 34 | } 35 | var $selectEle = $("#" + $el.attr('id')); 36 | if($selectEle.hasClass("select2-hidden-accessible")){ 37 | $selectEle.select2('destroy').select2(obj); 38 | } else{ 39 | $selectEle.select2(obj); 40 | } 41 | $selectEle.change(function (e) { 42 | var $pencilEle = $('#change_'+$(this).attr('id')); 43 | 44 | if($pencilEle.length < 1 ) return; 45 | 46 | $pencilEle.attr('href', 47 | $pencilEle.attr('data-href-template').replace('__fk__', $(this).val()) 48 | ); 49 | }); 50 | _all_easy_select2_ids.push($el.attr('id')); 51 | } 52 | 53 | /** 54 | * core function call for easy_select2 55 | * @param options - select2 constructor properties 56 | */ 57 | function add_select2_handlers(options){ 58 | 59 | 60 | $('div.field-easy-select2:not([id*="__prefix__"])').each(function(){ 61 | // taking data-* for select2 constructor properties for backward compatibility 62 | var obj = $(this).data(); 63 | 64 | // merging the options and data properties, modifying the first 65 | // NOTE: obj properties will be overwritten by options 66 | // https://api.jquery.com/jquery.extend/ 67 | $.extend(obj, options); 68 | redisplay_select2($(this), obj); 69 | }); 70 | 71 | $(document).bind('DOMNodeInserted', function (e) { 72 | var $changedEle = $(e.target); 73 | if(!$changedEle.parentsUntil('select').length < 1) return; 74 | 75 | updateSelect($changedEle); 76 | }); 77 | 78 | function updateSelect($changedEle) { 79 | var $select2Eles = $changedEle.find('div.field-easy-select2:not([id*="__prefix__"])'); 80 | if($select2Eles.length) { 81 | $changedEle.find('div.field-easy-select2:not([id*="__prefix__"])').each(function () { 82 | // taking data-* for select2 constructor properties for backward compatibility 83 | var obj = $(this).data(); 84 | // merging the options and data properties, modifying the first 85 | // NOTE: obj properties will be overwritten by options 86 | // https://api.jquery.com/jquery.extend/ 87 | 88 | $.extend(obj, options); 89 | redisplay_select2($(this), obj); 90 | }); 91 | } else { 92 | $.each(_all_easy_select2_ids, function(idx, val){ 93 | var obj = $("#" + val).data(); 94 | $.extend(obj, options); 95 | $("#" + val).select2('destroy').select2(); 96 | }); 97 | } 98 | }; 99 | 100 | // using django.jQuery for accessing django specific events 101 | _djq(document).on('formset:added', function (event, $row, formsetName) { 102 | updateSelect($row); 103 | }); 104 | } 105 | 106 | /** 107 | * JQuery plugin for django-easy-select2 108 | * @param options - object containing select2 constructor properties 109 | */ 110 | $.fn.easy_select = function(options){ 111 | add_select2_handlers(options); 112 | }; 113 | 114 | }(jQuery || django.jQuery, django.jQuery)); 115 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/js/init.js: -------------------------------------------------------------------------------- 1 | var _jq = (jQuery || django.jQuery); 2 | 3 | _jq(document).ready(function(){ 4 | // easy_select2() can take select2 constructor arguments object 5 | _jq('body').easy_select(); 6 | }); 7 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/jquery/COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/css/select2.css: -------------------------------------------------------------------------------- 1 | .select2-container { 2 | box-sizing: border-box; 3 | display: inline-block; 4 | margin: 0; 5 | position: relative; 6 | vertical-align: middle; } 7 | .select2-container .select2-selection--single { 8 | box-sizing: border-box; 9 | cursor: pointer; 10 | display: block; 11 | height: 28px; 12 | user-select: none; 13 | -webkit-user-select: none; } 14 | .select2-container .select2-selection--single .select2-selection__rendered { 15 | display: block; 16 | padding-left: 8px; 17 | padding-right: 20px; 18 | overflow: hidden; 19 | text-overflow: ellipsis; 20 | white-space: nowrap; } 21 | .select2-container .select2-selection--single .select2-selection__clear { 22 | position: relative; } 23 | .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { 24 | padding-right: 8px; 25 | padding-left: 20px; } 26 | .select2-container .select2-selection--multiple { 27 | box-sizing: border-box; 28 | cursor: pointer; 29 | display: block; 30 | min-height: 32px; 31 | user-select: none; 32 | -webkit-user-select: none; } 33 | .select2-container .select2-selection--multiple .select2-selection__rendered { 34 | display: inline-block; 35 | overflow: hidden; 36 | padding-left: 8px; 37 | text-overflow: ellipsis; 38 | white-space: nowrap; } 39 | .select2-container .select2-search--inline { 40 | float: left; } 41 | .select2-container .select2-search--inline .select2-search__field { 42 | box-sizing: border-box; 43 | border: none; 44 | font-size: 100%; 45 | margin-top: 5px; 46 | padding: 0; } 47 | .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { 48 | -webkit-appearance: none; } 49 | 50 | .select2-dropdown { 51 | background-color: white; 52 | border: 1px solid #aaa; 53 | border-radius: 4px; 54 | box-sizing: border-box; 55 | display: block; 56 | position: absolute; 57 | left: -100000px; 58 | width: 100%; 59 | z-index: 1051; } 60 | 61 | .select2-results { 62 | display: block; } 63 | 64 | .select2-results__options { 65 | list-style: none; 66 | margin: 0; 67 | padding: 0; } 68 | 69 | .select2-results__option { 70 | padding: 6px; 71 | user-select: none; 72 | -webkit-user-select: none; } 73 | .select2-results__option[aria-selected] { 74 | cursor: pointer; } 75 | 76 | .select2-container--open .select2-dropdown { 77 | left: 0; } 78 | 79 | .select2-container--open .select2-dropdown--above { 80 | border-bottom: none; 81 | border-bottom-left-radius: 0; 82 | border-bottom-right-radius: 0; } 83 | 84 | .select2-container--open .select2-dropdown--below { 85 | border-top: none; 86 | border-top-left-radius: 0; 87 | border-top-right-radius: 0; } 88 | 89 | .select2-search--dropdown { 90 | display: block; 91 | padding: 4px; } 92 | .select2-search--dropdown .select2-search__field { 93 | padding: 4px; 94 | width: 100%; 95 | box-sizing: border-box; } 96 | .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { 97 | -webkit-appearance: none; } 98 | .select2-search--dropdown.select2-search--hide { 99 | display: none; } 100 | 101 | .select2-close-mask { 102 | border: 0; 103 | margin: 0; 104 | padding: 0; 105 | display: block; 106 | position: fixed; 107 | left: 0; 108 | top: 0; 109 | min-height: 100%; 110 | min-width: 100%; 111 | height: auto; 112 | width: auto; 113 | opacity: 0; 114 | z-index: 99; 115 | background-color: #fff; 116 | filter: alpha(opacity=0); } 117 | 118 | .select2-hidden-accessible { 119 | border: 0 !important; 120 | clip: rect(0 0 0 0) !important; 121 | -webkit-clip-path: inset(50%) !important; 122 | clip-path: inset(50%) !important; 123 | height: 1px !important; 124 | overflow: hidden !important; 125 | padding: 0 !important; 126 | position: absolute !important; 127 | width: 1px !important; 128 | white-space: nowrap !important; } 129 | 130 | .select2-container--default .select2-selection--single { 131 | background-color: #fff; 132 | border: 1px solid #aaa; 133 | border-radius: 4px; } 134 | .select2-container--default .select2-selection--single .select2-selection__rendered { 135 | color: #444; 136 | line-height: 28px; } 137 | .select2-container--default .select2-selection--single .select2-selection__clear { 138 | cursor: pointer; 139 | float: right; 140 | font-weight: bold; } 141 | .select2-container--default .select2-selection--single .select2-selection__placeholder { 142 | color: #999; } 143 | .select2-container--default .select2-selection--single .select2-selection__arrow { 144 | height: 26px; 145 | position: absolute; 146 | top: 1px; 147 | right: 1px; 148 | width: 20px; } 149 | .select2-container--default .select2-selection--single .select2-selection__arrow b { 150 | border-color: #888 transparent transparent transparent; 151 | border-style: solid; 152 | border-width: 5px 4px 0 4px; 153 | height: 0; 154 | left: 50%; 155 | margin-left: -4px; 156 | margin-top: -2px; 157 | position: absolute; 158 | top: 50%; 159 | width: 0; } 160 | 161 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { 162 | float: left; } 163 | 164 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { 165 | left: 1px; 166 | right: auto; } 167 | 168 | .select2-container--default.select2-container--disabled .select2-selection--single { 169 | background-color: #eee; 170 | cursor: default; } 171 | .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { 172 | display: none; } 173 | 174 | .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { 175 | border-color: transparent transparent #888 transparent; 176 | border-width: 0 4px 5px 4px; } 177 | 178 | .select2-container--default .select2-selection--multiple { 179 | background-color: white; 180 | border: 1px solid #aaa; 181 | border-radius: 4px; 182 | cursor: text; } 183 | .select2-container--default .select2-selection--multiple .select2-selection__rendered { 184 | box-sizing: border-box; 185 | list-style: none; 186 | margin: 0; 187 | padding: 0 5px; 188 | width: 100%; } 189 | .select2-container--default .select2-selection--multiple .select2-selection__rendered li { 190 | list-style: none; } 191 | .select2-container--default .select2-selection--multiple .select2-selection__clear { 192 | cursor: pointer; 193 | float: right; 194 | font-weight: bold; 195 | margin-top: 5px; 196 | margin-right: 10px; 197 | padding: 1px; } 198 | .select2-container--default .select2-selection--multiple .select2-selection__choice { 199 | background-color: #e4e4e4; 200 | border: 1px solid #aaa; 201 | border-radius: 4px; 202 | cursor: default; 203 | float: left; 204 | margin-right: 5px; 205 | margin-top: 5px; 206 | padding: 0 5px; } 207 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { 208 | color: #999; 209 | cursor: pointer; 210 | display: inline-block; 211 | font-weight: bold; 212 | margin-right: 2px; } 213 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { 214 | color: #333; } 215 | 216 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { 217 | float: right; } 218 | 219 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 220 | margin-left: 5px; 221 | margin-right: auto; } 222 | 223 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 224 | margin-left: 2px; 225 | margin-right: auto; } 226 | 227 | .select2-container--default.select2-container--focus .select2-selection--multiple { 228 | border: solid black 1px; 229 | outline: 0; } 230 | 231 | .select2-container--default.select2-container--disabled .select2-selection--multiple { 232 | background-color: #eee; 233 | cursor: default; } 234 | 235 | .select2-container--default.select2-container--disabled .select2-selection__choice__remove { 236 | display: none; } 237 | 238 | .select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { 239 | border-top-left-radius: 0; 240 | border-top-right-radius: 0; } 241 | 242 | .select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { 243 | border-bottom-left-radius: 0; 244 | border-bottom-right-radius: 0; } 245 | 246 | .select2-container--default .select2-search--dropdown .select2-search__field { 247 | border: 1px solid #aaa; } 248 | 249 | .select2-container--default .select2-search--inline .select2-search__field { 250 | background: transparent; 251 | border: none; 252 | outline: 0; 253 | box-shadow: none; 254 | -webkit-appearance: textfield; } 255 | 256 | .select2-container--default .select2-results > .select2-results__options { 257 | max-height: 200px; 258 | overflow-y: auto; } 259 | 260 | .select2-container--default .select2-results__option[role=group] { 261 | padding: 0; } 262 | 263 | .select2-container--default .select2-results__option[aria-disabled=true] { 264 | color: #999; } 265 | 266 | .select2-container--default .select2-results__option[aria-selected=true] { 267 | background-color: #ddd; } 268 | 269 | .select2-container--default .select2-results__option .select2-results__option { 270 | padding-left: 1em; } 271 | .select2-container--default .select2-results__option .select2-results__option .select2-results__group { 272 | padding-left: 0; } 273 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option { 274 | margin-left: -1em; 275 | padding-left: 2em; } 276 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 277 | margin-left: -2em; 278 | padding-left: 3em; } 279 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 280 | margin-left: -3em; 281 | padding-left: 4em; } 282 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 283 | margin-left: -4em; 284 | padding-left: 5em; } 285 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 286 | margin-left: -5em; 287 | padding-left: 6em; } 288 | 289 | .select2-container--default .select2-results__option--highlighted[aria-selected] { 290 | background-color: #5897fb; 291 | color: white; } 292 | 293 | .select2-container--default .select2-results__group { 294 | cursor: default; 295 | display: block; 296 | padding: 6px; } 297 | 298 | .select2-container--classic .select2-selection--single { 299 | background-color: #f7f7f7; 300 | border: 1px solid #aaa; 301 | border-radius: 4px; 302 | outline: 0; 303 | background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); 304 | background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); 305 | background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); 306 | background-repeat: repeat-x; 307 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 308 | .select2-container--classic .select2-selection--single:focus { 309 | border: 1px solid #5897fb; } 310 | .select2-container--classic .select2-selection--single .select2-selection__rendered { 311 | color: #444; 312 | line-height: 28px; } 313 | .select2-container--classic .select2-selection--single .select2-selection__clear { 314 | cursor: pointer; 315 | float: right; 316 | font-weight: bold; 317 | margin-right: 10px; } 318 | .select2-container--classic .select2-selection--single .select2-selection__placeholder { 319 | color: #999; } 320 | .select2-container--classic .select2-selection--single .select2-selection__arrow { 321 | background-color: #ddd; 322 | border: none; 323 | border-left: 1px solid #aaa; 324 | border-top-right-radius: 4px; 325 | border-bottom-right-radius: 4px; 326 | height: 26px; 327 | position: absolute; 328 | top: 1px; 329 | right: 1px; 330 | width: 20px; 331 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 332 | background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 333 | background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); 334 | background-repeat: repeat-x; 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } 336 | .select2-container--classic .select2-selection--single .select2-selection__arrow b { 337 | border-color: #888 transparent transparent transparent; 338 | border-style: solid; 339 | border-width: 5px 4px 0 4px; 340 | height: 0; 341 | left: 50%; 342 | margin-left: -4px; 343 | margin-top: -2px; 344 | position: absolute; 345 | top: 50%; 346 | width: 0; } 347 | 348 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { 349 | float: left; } 350 | 351 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { 352 | border: none; 353 | border-right: 1px solid #aaa; 354 | border-radius: 0; 355 | border-top-left-radius: 4px; 356 | border-bottom-left-radius: 4px; 357 | left: 1px; 358 | right: auto; } 359 | 360 | .select2-container--classic.select2-container--open .select2-selection--single { 361 | border: 1px solid #5897fb; } 362 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { 363 | background: transparent; 364 | border: none; } 365 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { 366 | border-color: transparent transparent #888 transparent; 367 | border-width: 0 4px 5px 4px; } 368 | 369 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { 370 | border-top: none; 371 | border-top-left-radius: 0; 372 | border-top-right-radius: 0; 373 | background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); 374 | background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); 375 | background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); 376 | background-repeat: repeat-x; 377 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 378 | 379 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { 380 | border-bottom: none; 381 | border-bottom-left-radius: 0; 382 | border-bottom-right-radius: 0; 383 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); 384 | background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); 385 | background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); 386 | background-repeat: repeat-x; 387 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } 388 | 389 | .select2-container--classic .select2-selection--multiple { 390 | background-color: white; 391 | border: 1px solid #aaa; 392 | border-radius: 4px; 393 | cursor: text; 394 | outline: 0; } 395 | .select2-container--classic .select2-selection--multiple:focus { 396 | border: 1px solid #5897fb; } 397 | .select2-container--classic .select2-selection--multiple .select2-selection__rendered { 398 | list-style: none; 399 | margin: 0; 400 | padding: 0 5px; } 401 | .select2-container--classic .select2-selection--multiple .select2-selection__clear { 402 | display: none; } 403 | .select2-container--classic .select2-selection--multiple .select2-selection__choice { 404 | background-color: #e4e4e4; 405 | border: 1px solid #aaa; 406 | border-radius: 4px; 407 | cursor: default; 408 | float: left; 409 | margin-right: 5px; 410 | margin-top: 5px; 411 | padding: 0 5px; } 412 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { 413 | color: #888; 414 | cursor: pointer; 415 | display: inline-block; 416 | font-weight: bold; 417 | margin-right: 2px; } 418 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { 419 | color: #555; } 420 | 421 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 422 | float: right; 423 | margin-left: 5px; 424 | margin-right: auto; } 425 | 426 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 427 | margin-left: 2px; 428 | margin-right: auto; } 429 | 430 | .select2-container--classic.select2-container--open .select2-selection--multiple { 431 | border: 1px solid #5897fb; } 432 | 433 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { 434 | border-top: none; 435 | border-top-left-radius: 0; 436 | border-top-right-radius: 0; } 437 | 438 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { 439 | border-bottom: none; 440 | border-bottom-left-radius: 0; 441 | border-bottom-right-radius: 0; } 442 | 443 | .select2-container--classic .select2-search--dropdown .select2-search__field { 444 | border: 1px solid #aaa; 445 | outline: 0; } 446 | 447 | .select2-container--classic .select2-search--inline .select2-search__field { 448 | outline: 0; 449 | box-shadow: none; } 450 | 451 | .select2-container--classic .select2-dropdown { 452 | background-color: white; 453 | border: 1px solid transparent; } 454 | 455 | .select2-container--classic .select2-dropdown--above { 456 | border-bottom: none; } 457 | 458 | .select2-container--classic .select2-dropdown--below { 459 | border-top: none; } 460 | 461 | .select2-container--classic .select2-results > .select2-results__options { 462 | max-height: 200px; 463 | overflow-y: auto; } 464 | 465 | .select2-container--classic .select2-results__option[role=group] { 466 | padding: 0; } 467 | 468 | .select2-container--classic .select2-results__option[aria-disabled=true] { 469 | color: grey; } 470 | 471 | .select2-container--classic .select2-results__option--highlighted[aria-selected] { 472 | background-color: #3875d7; 473 | color: white; } 474 | 475 | .select2-container--classic .select2-results__group { 476 | cursor: default; 477 | display: block; 478 | padding: 6px; } 479 | 480 | .select2-container--classic.select2-container--open .select2-dropdown { 481 | border-color: #5897fb; } 482 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/css/select2.min.css: -------------------------------------------------------------------------------- 1 | .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} 2 | -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/af.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ar.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/az.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/bg.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/bn.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/bs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ca.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/cs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/da.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/de.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Element";return 1!=e.maximum&&(n+="e"),n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/dsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/el.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/en.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/es.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/et.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/eu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها می‌توانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/fi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/fr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/gl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/he.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/hi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/hr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/hsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/hu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/hy.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/id.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/is.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/it.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ja.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(n){return n.input.length-n.maximum+" 文字を削除してください"},inputTooShort:function(n){return"少なくとも "+(n.minimum-n.input.length)+" 文字を入力してください"},loadingMore:function(){return"読み込み中…"},maximumSelected:function(n){return n.maximum+" 件しか選択できません"},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"},removeAllItems:function(){return"すべてのアイテムを削除"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ka.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/km.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(n){return"សូមលុបចេញ "+(n.input.length-n.maximum)+" អក្សរ"},inputTooShort:function(n){return"សូមបញ្ចូល"+(n.minimum-n.input.length)+" អក្សរ រឺ ច្រើនជាងនេះ"},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(n){return"អ្នកអាចជ្រើសរើសបានតែ "+n.maximum+" ជម្រើសប៉ុណ្ណោះ"},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."},removeAllItems:function(){return"លុបធាតុទាំងអស់"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ko.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/lt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/lt",[],function(){function n(n,e,i,t){return n%10==1&&(n%100<11||n%100>19)?e:n%10>=2&&n%10<=9&&(n%100<11||n%100>19)?i:t}return{inputTooLong:function(e){var i=e.input.length-e.maximum,t="Pašalinkite "+i+" simbol";return t+=n(i,"į","ius","ių")},inputTooShort:function(e){var i=e.minimum-e.input.length,t="Įrašykite dar "+i+" simbol";return t+=n(i,"į","ius","ių")},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(e){var i="Jūs galite pasirinkti tik "+e.maximum+" element";return i+=n(e.maximum,"ą","us","ų")},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"},removeAllItems:function(){return"Pašalinti visus elementus"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/lv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/lv",[],function(){function e(e,n,u,i){return 11===e?n:e%10==1?u:i}return{inputTooLong:function(n){var u=n.input.length-n.maximum,i="Lūdzu ievadiet par "+u;return(i+=" simbol"+e(u,"iem","u","iem"))+" mazāk"},inputTooShort:function(n){var u=n.minimum-n.input.length,i="Lūdzu ievadiet vēl "+u;return i+=" simbol"+e(u,"us","u","us")},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(n){var u="Jūs varat izvēlēties ne vairāk kā "+n.maximum;return u+=" element"+e(n.maximum,"us","u","us")},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"},removeAllItems:function(){return"Noņemt visus vienumus"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/mk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/mk",[],function(){return{inputTooLong:function(n){var e=(n.input.length,n.maximum,"Ве молиме внесете "+n.maximum+" помалку карактер");return 1!==n.maximum&&(e+="и"),e},inputTooShort:function(n){var e=(n.minimum,n.input.length,"Ве молиме внесете уште "+n.maximum+" карактер");return 1!==n.maximum&&(e+="и"),e},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(n){var e="Можете да изберете само "+n.maximum+" ставк";return 1===n.maximum?e+="а":e+="и",e},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"},removeAllItems:function(){return"Отстрани ги сите предмети"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ms.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(n){return"Sila hapuskan "+(n.input.length-n.maximum)+" aksara"},inputTooShort:function(n){return"Sila masukkan "+(n.minimum-n.input.length)+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(n){return"Anda hanya boleh memilih "+n.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Keluarkan semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/nb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ne.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/nl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){return"Gelieve "+(e.input.length-e.maximum)+" karakters te verwijderen"},inputTooShort:function(e){return"Gelieve "+(e.minimum-e.input.length)+" of meer karakters in te voeren"},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var n=1==e.maximum?"kan":"kunnen",r="Er "+n+" maar "+e.maximum+" item";return 1!=e.maximum&&(r+="s"),r+=" worden geselecteerd"},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"},removeAllItems:function(){return"Verwijder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/pl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/pl",[],function(){var n=["znak","znaki","znaków"],e=["element","elementy","elementów"],r=function(n,e){return 1===n?e[0]:n>1&&n<=4?e[1]:n>=5?e[2]:void 0};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Usuń "+t+" "+r(t,n)},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Podaj przynajmniej "+t+" "+r(t,n)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(n){return"Możesz zaznaczyć tylko "+n.maximum+" "+r(n.maximum,e)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"},removeAllItems:function(){return"Usuń wszystkie przedmioty"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ps.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/pt-BR.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Apague "+n+" caracter";return 1!=n&&(r+="es"),r},inputTooShort:function(e){return"Digite "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var n="Você só pode selecionar "+e.maximum+" ite";return 1==e.maximum?n+="m":n+="ns",n},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/pt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var r=e.input.length-e.maximum,n="Por favor apague "+r+" ";return n+=1!=r?"caracteres":"caractere"},inputTooShort:function(e){return"Introduza "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var r="Apenas pode seleccionar "+e.maximum+" ";return r+=1!=e.maximum?"itens":"item"},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ro.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return 1!==t&&(n+="e"),n},inputTooShort:function(e){return"Vă rugăm să introduceți "+(e.minimum-e.input.length)+" sau mai multe caractere"},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",1!==e.maximum&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"},removeAllItems:function(){return"Eliminați toate elementele"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/ru.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ru",[],function(){function n(n,e,r,u){return n%10<5&&n%10>0&&n%100<5||n%100>20?n%10>1?r:e:u}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Пожалуйста, введите на "+r+" символ";return u+=n(r,"","a","ов"),u+=" меньше"},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Пожалуйста, введите ещё хотя бы "+r+" символ";return u+=n(r,"","a","ов")},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(e){var r="Вы можете выбрать не более "+e.maximum+" элемент";return r+=n(e.maximum,"","a","ов")},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"},removeAllItems:function(){return"Удалить все элементы"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadajte o jeden znak menej":t>=2&&t<=4?"Prosím, zadajte o "+e[t](!0)+" znaky menej":"Prosím, zadajte o "+t+" znakov menej"},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadajte ešte jeden znak":t<=4?"Prosím, zadajte ešte ďalšie "+e[t](!0)+" znaky":"Prosím, zadajte ešte ďalších "+t+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(n){return 1==n.maximum?"Môžete zvoliť len jednu položku":n.maximum>=2&&n.maximum<=4?"Môžete zvoliť najviac "+e[n.maximum](!1)+" položky":"Môžete zvoliť najviac "+n.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"},removeAllItems:function(){return"Odstráňte všetky položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sq.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sr-Cyrl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr-Cyrl",[],function(){function n(n,e,r,u){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:u}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Обришите "+r+" симбол";return u+=n(r,"","а","а")},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Укуцајте бар још "+r+" симбол";return u+=n(r,"","а","а")},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(e){var r="Можете изабрати само "+e.maximum+" ставк";return r+=n(e.maximum,"у","е","и")},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr",[],function(){function n(n,e,r,t){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(e){var r=e.input.length-e.maximum,t="Obrišite "+r+" simbol";return t+=n(r,"","a","a")},inputTooShort:function(e){var r=e.minimum-e.input.length,t="Ukucajte bar još "+r+" simbol";return t+=n(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(e){var r="Možete izabrati samo "+e.maximum+" stavk";return r+=n(e.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/sv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(n){return"Vänligen sudda ut "+(n.input.length-n.maximum)+" tecken"},inputTooShort:function(n){return"Vänligen skriv in "+(n.minimum-n.input.length)+" eller fler tecken"},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(n){return"Du kan max välja "+n.maximum+" element"},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"},removeAllItems:function(){return"Ta bort alla objekt"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/th.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(n){return"โปรดลบออก "+(n.input.length-n.maximum)+" ตัวอักษร"},inputTooShort:function(n){return"โปรดพิมพ์เพิ่มอีก "+(n.minimum-n.input.length)+" ตัวอักษร"},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(n){return"คุณสามารถเลือกได้ไม่เกิน "+n.maximum+" รายการ"},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"},removeAllItems:function(){return"ลบรายการทั้งหมด"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/tk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/tr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(n){return n.input.length-n.maximum+" karakter daha girmelisiniz"},inputTooShort:function(n){return"En az "+(n.minimum-n.input.length)+" karakter daha girmelisiniz"},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(n){return"Sadece "+n.maximum+" seçim yapabilirsiniz"},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"},removeAllItems:function(){return"Tüm öğeleri kaldır"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/uk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/uk",[],function(){function n(n,e,u,r){return n%100>10&&n%100<15?r:n%10==1?e:n%10>1&&n%10<5?u:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(e){return"Будь ласка, видаліть "+(e.input.length-e.maximum)+" "+n(e.maximum,"літеру","літери","літер")},inputTooShort:function(n){return"Будь ласка, введіть "+(n.minimum-n.input.length)+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(e){return"Ви можете вибрати лише "+e.maximum+" "+n(e.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"},removeAllItems:function(){return"Видалити всі елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/vi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/vi",[],function(){return{inputTooLong:function(n){return"Vui lòng xóa bớt "+(n.input.length-n.maximum)+" ký tự"},inputTooShort:function(n){return"Vui lòng nhập thêm từ "+(n.minimum-n.input.length)+" ký tự trở lên"},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(n){return"Chỉ có thể chọn được "+n.maximum+" lựa chọn"},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"},removeAllItems:function(){return"Xóa tất cả các mục"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/zh-CN.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/static/easy_select2/vendor/select2-4.0.13/js/i18n/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /easy_select2/utils.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from django.db.models import ForeignKey 4 | 5 | from easy_select2 import forms as es2_forms 6 | from easy_select2.widgets import Select2, Select2Mixin, Select2Multiple 7 | 8 | 9 | # TODO: merge meta_fields and kwargs, which is the same. 10 | def select2_modelform_meta(model, 11 | meta_fields=None, 12 | widgets=None, 13 | attrs=None, 14 | **kwargs): 15 | """ 16 | Return `Meta` class with Select2-enabled widgets for fields 17 | with choices (e.g. ForeignKey, CharField, etc) for use with 18 | ModelForm. 19 | 20 | Arguments: 21 | model - a model class to create `Meta` class for. 22 | meta_fields - dictionary with `Meta` class fields, for 23 | example, {'fields': ['id', 'name']} 24 | attrs - select2 widget attributes (width, for example), 25 | must be of type `dict`. 26 | **kwargs - will be merged with meta_fields. 27 | """ 28 | widgets = widgets or {} 29 | meta_fields = meta_fields or {} 30 | 31 | # TODO: assert attrs is of type `dict` 32 | 33 | for field in model._meta.fields: 34 | if isinstance(field, ForeignKey) or field.choices: 35 | widgets.update({field.name: Select2(select2attrs=attrs)}) 36 | 37 | for field in model._meta.many_to_many: 38 | widgets.update({field.name: Select2Multiple(select2attrs=attrs)}) 39 | 40 | meta_fields.update({ 41 | 'model': model, 42 | 'widgets': widgets, 43 | }) 44 | if 'exclude' not in kwargs and 'fields' not in kwargs: 45 | meta_fields.update({'exclude': []}) 46 | meta_fields.update(**kwargs) 47 | meta = type('Meta', (object,), meta_fields) 48 | 49 | return meta 50 | 51 | 52 | def select2_modelform( 53 | model, attrs=None, form_class=es2_forms.FixedModelForm): 54 | """ 55 | Return ModelForm class for model with select2 widgets. 56 | 57 | Arguments: 58 | attrs: select2 widget attributes (width, for example) of type `dict`. 59 | form_class: modelform base class, `forms.ModelForm` by default. 60 | 61 | :: 62 | 63 | SomeModelForm = select2_modelform(models.SomeModelBanner) 64 | 65 | is the same like:: 66 | 67 | class SomeModelForm(forms.ModelForm): 68 | Meta = select2_modelform_meta(models.SomeModelForm) 69 | """ 70 | classname = '%sForm' % model._meta.object_name 71 | meta = select2_modelform_meta(model, attrs=attrs) 72 | return type(classname, (form_class,), {'Meta': meta}) 73 | 74 | 75 | def apply_select2(widget_cls): 76 | """ 77 | Dynamically create new widget class mixed with Select2Mixin. 78 | 79 | Args: 80 | widget_cls: class of source widget. 81 | 82 | Usage, for example:: 83 | 84 | class SomeModelForm(admin.ModelForm): 85 | class Meta: 86 | widgets = { 87 | 'field': apply_select2(forms.Select), 88 | } 89 | 90 | So, `apply_select2(forms.Select)` will return new class, 91 | named Select2Select. 92 | """ 93 | cname = 'Select2%s' % widget_cls.__name__ 94 | return type(cname, (Select2Mixin, widget_cls), {}) 95 | -------------------------------------------------------------------------------- /easy_select2/widgets.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from django import forms 4 | from django.conf import settings 5 | from django.utils.safestring import mark_safe 6 | 7 | 8 | class Select2Mixin(object): 9 | """ 10 | This mixin provides a mechanism to construct custom widget 11 | class, that will be rendered using Select2 input. 12 | 13 | Generally should be mixed with widgets that render select input. 14 | """ 15 | html = """""" 19 | 20 | def __init__(self, select2attrs=None, *args, **kwargs): 21 | """ 22 | Initialize default select2 attributes. 23 | 24 | If width is not provided, sets Select2 width to 250px. 25 | 26 | Args: 27 | select2attrs: a dictionary, which then passed to 28 | Select2 constructor function as options. 29 | """ 30 | self.select2attrs = select2attrs or {} 31 | assert_msg = "select2attrs attribute must be dict, not {}" 32 | assert isinstance(self.select2attrs, dict), assert_msg.format( 33 | self.select2attrs.__class__.__name__ 34 | ) 35 | if 'width' not in self.select2attrs: 36 | self.select2attrs.update({'width': '250px'}) 37 | self.static_settings() 38 | super(Select2Mixin, self).__init__(*args, **kwargs) 39 | 40 | def static_settings(self): 41 | SELECT2_USE_BUNDLED_SELECT2 = getattr( 42 | settings, 'SELECT2_USE_BUNDLED_SELECT2', True) 43 | if SELECT2_USE_BUNDLED_SELECT2: 44 | SELECT2_VERSION = '4.0.13' 45 | DEFAULT_SELECT2_CSS = 'easy_select2/vendor/select2-{}/css/select2.min.css'.format(SELECT2_VERSION) 46 | DEFAULT_SELECT2_JS = 'easy_select2/vendor/select2-{}/js/select2.min.js'.format(SELECT2_VERSION) 47 | else: # use Django admin's copy 48 | DEFAULT_SELECT2_CSS = 'admin/css/vendor/select2/select2.min.css' 49 | DEFAULT_SELECT2_JS = 'admin/js/vendor/select2/select2.full.min.js' 50 | 51 | SELECT2_JS = getattr( 52 | settings, 53 | 'SELECT2_JS', 54 | DEFAULT_SELECT2_JS, 55 | ) 56 | SELECT2_CSS = getattr( 57 | settings, 58 | 'SELECT2_CSS', 59 | DEFAULT_SELECT2_CSS, 60 | ) 61 | SELECT2_USE_BUNDLED_JQUERY = getattr( 62 | settings, 'SELECT2_USE_BUNDLED_JQUERY', True) 63 | 64 | self.SELECT2_WIDGET_JS = [ 65 | 'easy_select2/js/init.js', 66 | 'easy_select2/js/easy_select2.js', 67 | SELECT2_JS, 68 | ] 69 | 70 | if SELECT2_USE_BUNDLED_JQUERY: 71 | jquery_min_file = 'easy_select2/vendor/jquery/jquery-3.5.1.min.js' 72 | self.SELECT2_WIDGET_JS.insert(0, jquery_min_file) 73 | else: 74 | self.SELECT2_WIDGET_JS.insert(0, 'admin/js/jquery.init.js') 75 | 76 | self.SELECT2_WIDGET_CSS = { 77 | 'screen': [ 78 | SELECT2_CSS, 79 | 'easy_select2/css/easy_select2.css', 80 | ], 81 | } 82 | 83 | # This function is taken from django-select2 84 | def get_options(self): 85 | """Return dictionary of options to be used by Select2.""" 86 | return self.select2attrs 87 | 88 | # This function is taken from django-select2 89 | def render_select2_options_code(self, options, id_): 90 | """Render options for select2.""" 91 | output = [] 92 | for key, value in options.items(): 93 | if isinstance(value, (dict, list)): 94 | value = json.dumps(value) 95 | output.append("data-{name}='{value}'".format( 96 | name=key, 97 | value=mark_safe(value))) 98 | return mark_safe(' '.join(output)) 99 | 100 | def render_js_code(self, id_, *args, **kwargs): 101 | """Render html container for Select2 widget with options.""" 102 | if id_: 103 | options = self.render_select2_options_code( 104 | dict(self.get_options()), id_) 105 | return mark_safe(self.html.format(id=id_, options=options)) 106 | return u'' 107 | 108 | def render(self, name, value, attrs=None, **kwargs): 109 | """ 110 | Extend base class's `render` method by appending 111 | javascript inline text to html output. 112 | """ 113 | output = super(Select2Mixin, self).render( 114 | name, value, attrs=attrs, **kwargs) 115 | id_ = attrs['id'] 116 | output += self.render_js_code( 117 | id_, name, value, attrs=attrs, **kwargs) 118 | return mark_safe(output) 119 | 120 | @property 121 | def media(self): 122 | return forms.Media( 123 | css=self.SELECT2_WIDGET_CSS, 124 | js=self.SELECT2_WIDGET_JS 125 | ) 126 | 127 | 128 | class Select2(Select2Mixin, forms.Select): 129 | """Implement single-valued select widget with Select2.""" 130 | pass 131 | 132 | 133 | class Select2Multiple(Select2Mixin, forms.SelectMultiple): 134 | """Implement multiple select widget with Select2.""" 135 | pass 136 | -------------------------------------------------------------------------------- /sampleproject/README.rst: -------------------------------------------------------------------------------- 1 | Sampleproject 2 | ============= 3 | 4 | Sample project useful for testing django applications and other utility needs. 5 | 6 | 7 | Installation 8 | ------------ 9 | 10 | .. code-block:: bash 11 | 12 | git clone https://github.com/asyncee/django-easy-select2.git 13 | cd django-easy-select2/sampleproject 14 | ./bootstrap.sh # creates virtualenv and installs django (from requirements.txt) 15 | source env/bin/activate 16 | ./manage.py migrate 17 | ./manage.py createsuperuser 18 | ./manage.py runserver 19 | 20 | 21 | Configuration 22 | ------------- 23 | 24 | Project ships with sane defaults (settings are pretty verbose): 25 | 26 | - sqlite3 database 27 | - filebased cache in /tmp 28 | - cached sessions 29 | - console email backend 30 | - non-cached template loaders 31 | - `css/js/img` default static dirs 32 | - default `templates` directory 33 | - nice default loggers 34 | 35 | 36 | Usage 37 | ----- 38 | 39 | After you bootstrapped a project, you can fill it with some data and play with 40 | Note model admin. 41 | -------------------------------------------------------------------------------- /sampleproject/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | on_error_exit() { 5 | echo "ERROR: Command \"${BASH_COMMAND}\" at ${BASH_SOURCE} line ${BASH_LINENO} failed with exit code $?." >&2 6 | } 7 | trap on_error_exit ERR 8 | 9 | cd "$(dirname "$0")" 10 | 11 | echo ">>> Removing old environment" 12 | if [ ! -d env ]; then 13 | rm -rf env 14 | fi 15 | echo ">>> Installing django into new virtualenv" 16 | virtualenv env -p python3 17 | env/bin/pip install --upgrade pip setuptools wheel 18 | env/bin/pip install -r requirements.txt 19 | env/bin/pip install -e ../ 20 | -------------------------------------------------------------------------------- /sampleproject/demoapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/demoapp/__init__.py -------------------------------------------------------------------------------- /sampleproject/demoapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from easy_select2 import select2_modelform 4 | 5 | from .models import Category, Note 6 | 7 | 8 | class NoteAdmin(admin.ModelAdmin): 9 | form = select2_modelform(Note) 10 | 11 | 12 | admin.site.register(Category) 13 | admin.site.register(Note, NoteAdmin) 14 | -------------------------------------------------------------------------------- /sampleproject/demoapp/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-05-20 17:29 2 | 3 | import django.db.models.deletion 4 | from django.conf import settings 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Category', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('name', models.CharField(max_length=50)), 22 | ], 23 | options={ 24 | 'verbose_name_plural': 'categories', 25 | }, 26 | ), 27 | migrations.CreateModel( 28 | name='EmptyModel', 29 | fields=[ 30 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 31 | ], 32 | ), 33 | migrations.CreateModel( 34 | name='Related', 35 | fields=[ 36 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 37 | ('name', models.CharField(max_length=50)), 38 | ], 39 | ), 40 | migrations.CreateModel( 41 | name='TestFieldsModel', 42 | fields=[ 43 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 44 | ('choice_field', models.IntegerField(choices=[(0, 'Zero'), (1, 'One')])), 45 | ('text', models.TextField()), 46 | ('fk_field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='demoapp.Related')), 47 | ('m2m_field', models.ManyToManyField(related_name='_testfieldsmodel_m2m_field_+', to='demoapp.Related')), 48 | ], 49 | ), 50 | migrations.CreateModel( 51 | name='Note', 52 | fields=[ 53 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 54 | ('categories', models.ManyToManyField(to='demoapp.Category')), 55 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 56 | ], 57 | ), 58 | ] 59 | -------------------------------------------------------------------------------- /sampleproject/demoapp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/demoapp/migrations/__init__.py -------------------------------------------------------------------------------- /sampleproject/demoapp/models.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.db import models 3 | 4 | 5 | class Category(models.Model): 6 | name = models.CharField(max_length=50) 7 | 8 | class Meta: 9 | verbose_name_plural = 'categories' 10 | 11 | def __unicode__(self): 12 | return self.name 13 | 14 | def __str__(self): 15 | return self.name 16 | 17 | 18 | class Note(models.Model): 19 | user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) # To demonstrate select2 20 | categories = models.ManyToManyField(Category) # To demonstrate select2 multiple 21 | 22 | def __unicode__(self): 23 | return u'Note %d' % self.id 24 | 25 | def __str__(self): 26 | return 'Note %d' % self.id 27 | 28 | 29 | class Related(models.Model): 30 | name = models.CharField(max_length=50) 31 | 32 | 33 | class TestFieldsModel(models.Model): 34 | CHOICES = ((0, 'Zero'), (1, 'One')) 35 | choice_field = models.IntegerField(choices=CHOICES) 36 | fk_field = models.ForeignKey(Related, related_name='+', on_delete=models.CASCADE) 37 | m2m_field = models.ManyToManyField(Related, related_name='+') 38 | text = models.TextField() 39 | 40 | 41 | class EmptyModel(models.Model): 42 | pass 43 | -------------------------------------------------------------------------------- /sampleproject/demoapp/templates/demoapp/note_form.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | {% if form.instance.pk %}Edit {{ form.instance }}{% else %}Create Note{% endif%} 7 | {{ form.media.css }} 8 | 9 | 10 | {{ form.media.js }} 11 | 12 | 13 |

{% if form.instance.pk %}Edit {{ form.instance }}{% else %}Create Note{% endif%}

14 |
15 | {% csrf_token %} 16 | {{ form.as_p }} 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /sampleproject/demoapp/templates/demoapp/note_list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Notes 6 | 7 | 8 |

Notes

9 |

10 | Welcome to this little demo of django-easy-select2! 11 |

12 | 13 |

Existing Notes

14 | {% if note_list %} 15 |
    16 | {% for note in note_list %} 17 |
  • {{ note }}
  • 18 | {% endfor %} 19 |
20 | {% else %} 21 | none 22 | {% endif %} 23 | 24 |

What do you want to do?

25 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /sampleproject/demoapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .views import NoteCreateView, NoteEditView, NoteListView 4 | 5 | urlpatterns = [ 6 | path('', NoteListView.as_view(), name='note-list'), 7 | path('create', NoteCreateView.as_view(), name='note-create'), 8 | path('/edit', NoteEditView.as_view(), name='note-edit'), 9 | ] 10 | -------------------------------------------------------------------------------- /sampleproject/demoapp/views.py: -------------------------------------------------------------------------------- 1 | from django.urls import reverse_lazy 2 | from django.views.generic import ListView, UpdateView 3 | from django.views.generic.edit import CreateView 4 | 5 | from easy_select2 import select2_modelform 6 | 7 | from .models import Note 8 | 9 | 10 | class NoteCreateView(CreateView): 11 | model = Note 12 | form_class = select2_modelform(Note) 13 | success_url = reverse_lazy('note-list') 14 | 15 | 16 | class NoteEditView(UpdateView): 17 | model = Note 18 | form_class = select2_modelform(Note) 19 | success_url = reverse_lazy('note-list') 20 | 21 | 22 | class NoteListView(ListView): 23 | model = Note 24 | -------------------------------------------------------------------------------- /sampleproject/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sampleproject.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /sampleproject/requirements.txt: -------------------------------------------------------------------------------- 1 | django==4.2.21 2 | 3 | #django-easy-select2 4 | -------------------------------------------------------------------------------- /sampleproject/sampleproject/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/sampleproject/__init__.py -------------------------------------------------------------------------------- /sampleproject/sampleproject/local_settings.py: -------------------------------------------------------------------------------- 1 | DEBUG = True 2 | 3 | TEMPLATE_DEBUG = True 4 | 5 | DATABASES = { 6 | 'default': { 7 | 'ENGINE': 'django.db.backends.sqlite3', 8 | 'NAME': 'db.sqlite3', 9 | 'USER': '', 10 | 'PASSWORD': '', 11 | 'HOST': '', 12 | 'PORT': '', 13 | 'CONN_MAX_AGE': 0, 14 | } 15 | } 16 | 17 | CACHES = { 18 | 'default': { 19 | 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 20 | 'LOCATION': '/tmp/django_sampleproject_cache', 21 | } 22 | } 23 | 24 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 25 | 26 | INTERNAL_IPS = ['127.0.0.1'] 27 | -------------------------------------------------------------------------------- /sampleproject/sampleproject/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Settings for sampleproject project. 3 | """ 4 | 5 | import os 6 | 7 | BASE_DIR = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | SECRET_KEY = 'CHANGE_IT_FOR_MORE_SECURITY' 10 | 11 | INSTALLED_APPS = ( 12 | # django apps 13 | 'django.contrib.admin', 14 | 'django.contrib.auth', 15 | 'django.contrib.contenttypes', 16 | 'django.contrib.sessions', 17 | 'django.contrib.messages', 18 | 'django.contrib.staticfiles', 19 | 20 | # third-party apps 21 | 'easy_select2', 22 | 23 | # project apps 24 | 'demoapp', 25 | ) 26 | 27 | MIDDLEWARE = ( 28 | 'django.middleware.gzip.GZipMiddleware', 29 | 'django.contrib.sessions.middleware.SessionMiddleware', 30 | 'django.middleware.common.CommonMiddleware', 31 | 'django.middleware.common.BrokenLinkEmailsMiddleware', 32 | 'django.middleware.csrf.CsrfViewMiddleware', 33 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 34 | 'django.contrib.messages.middleware.MessageMiddleware', 35 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 36 | ) 37 | 38 | ROOT_URLCONF = 'sampleproject.urls' 39 | 40 | WSGI_APPLICATION = 'sampleproject.wsgi.application' 41 | 42 | # LANGUAGE_CODE = 'ru-RU' 43 | 44 | # TIME_ZONE = 'Europe/Moscow' 45 | 46 | USE_I18N = True 47 | 48 | USE_L10N = True 49 | 50 | # FIRST_DAY_OF_WEEK = 1 51 | 52 | USE_TZ = False 53 | 54 | TEMPLATES = [ 55 | { 56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 57 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 58 | 'OPTIONS': { 59 | 'context_processors': [ 60 | 'django.template.context_processors.debug', 61 | 'django.template.context_processors.request', 62 | 'django.contrib.auth.context_processors.auth', 63 | 'django.contrib.messages.context_processors.messages', 64 | ], 65 | 'loaders': [ 66 | 'django.template.loaders.filesystem.Loader', 67 | 'django.template.loaders.app_directories.Loader', 68 | ] 69 | }, 70 | }, 71 | ] 72 | 73 | STATICFILES_FINDERS = ( 74 | 'django.contrib.staticfiles.finders.FileSystemFinder', 75 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 76 | ) 77 | 78 | STATIC_URL = '/static/' 79 | 80 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') 81 | 82 | STATICFILES_DIRS = ( 83 | ('css', os.path.join(STATIC_ROOT, 'css')), 84 | ('js', os.path.join(STATIC_ROOT, 'js')), 85 | ('img', os.path.join(STATIC_ROOT, 'img')), 86 | ) 87 | 88 | MEDIA_URL = '/media/' 89 | 90 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 91 | 92 | CSRF_COOKIE_NAME = '__csrf' 93 | 94 | LANGUAGE_COOKIE_NAME = '__lang' 95 | 96 | SESSION_COOKIE_NAME = '__sid' 97 | 98 | USE_ETAGS = False 99 | 100 | LOGIN_REDIRECT_URL = '/' 101 | LOGIN_URL = 'auth_login' 102 | LOGOUT_URL = 'auth_logout' 103 | 104 | SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 105 | SESSION_EXPIRE_AT_BROWSER_CLOSE = False 106 | 107 | MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' 108 | 109 | LOGGING = { 110 | 'version': 1, 111 | 'disable_existing_loggers': False, 112 | 'filters': { 113 | 'require_debug_false': { 114 | '()': 'django.utils.log.RequireDebugFalse' 115 | } 116 | }, 117 | 'handlers': { 118 | 'mail_admins': { 119 | 'level': 'ERROR', 120 | 'filters': ['require_debug_false'], 121 | 'class': 'django.utils.log.AdminEmailHandler', 122 | 'include_html': True, 123 | }, 124 | 'file_error_log': { 125 | 'level': 'ERROR', 126 | 'class': 'logging.FileHandler', 127 | 'filename': 'error.log' 128 | }, 129 | }, 130 | 'loggers': { 131 | 'django.request': { 132 | 'handlers': ['mail_admins', 'file_error_log'], 133 | 'level': 'ERROR', 134 | 'propagate': True, 135 | }, 136 | } 137 | } 138 | 139 | SELECT2_USE_BUNDLED_JQUERY = False 140 | 141 | from .local_settings import * # noqa: F401,E402,F403 # isort:skip 142 | -------------------------------------------------------------------------------- /sampleproject/sampleproject/static/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/sampleproject/static/css/.gitkeep -------------------------------------------------------------------------------- /sampleproject/sampleproject/static/img/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/sampleproject/static/img/.gitkeep -------------------------------------------------------------------------------- /sampleproject/sampleproject/static/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/sampleproject/static/js/.gitkeep -------------------------------------------------------------------------------- /sampleproject/sampleproject/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/sampleproject/sampleproject/templates/.gitkeep -------------------------------------------------------------------------------- /sampleproject/sampleproject/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.conf.urls import url 3 | from django.conf.urls.static import static 4 | from django.contrib import admin 5 | from django.urls import include 6 | from django.urls.base import reverse_lazy 7 | from django.views.generic.base import RedirectView 8 | 9 | admin.autodiscover() 10 | 11 | urlpatterns = [ 12 | url(r'^admin/', admin.site.urls), 13 | url(r'^notes/', include('demoapp.urls')), 14 | url(r'', RedirectView.as_view(url=reverse_lazy('note-list')), 15 | name='frontpage'), 16 | ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 17 | -------------------------------------------------------------------------------- /sampleproject/sampleproject/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for sampleproject project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en//howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sampleproject.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /screenshots/select2_multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/screenshots/select2_multiple.png -------------------------------------------------------------------------------- /screenshots/select2_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/screenshots/select2_single.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from setuptools import find_packages, setup 5 | from setuptools.command.test import test as TestCommand 6 | 7 | # Some initialization 8 | here = os.path.abspath(os.path.dirname(__file__)) 9 | long_description = open(os.path.join(here, 'README.rst')).read() 10 | 11 | 12 | data_files = [] 13 | root_dir = os.path.dirname(__file__) 14 | if root_dir: 15 | os.chdir(root_dir) 16 | 17 | 18 | # this code snippet is taken from django-registration setup.py script 19 | for dirpath, dirnames, filenames in os.walk('easy_select2'): 20 | # Ignore dirnames that start with '.' 21 | for i, dirname in enumerate(dirnames): 22 | if dirname.startswith('.'): 23 | del dirnames[i] 24 | if filenames: 25 | prefix = dirpath[13:] # Strip "easy_select2/" or "easy_select2\" 26 | for f in filenames: 27 | data_files.append(os.path.join(prefix, f)) 28 | 29 | 30 | class Tox(TestCommand): 31 | def finalize_options(self): 32 | TestCommand.finalize_options(self) 33 | self.test_args = [] 34 | self.test_suite = True 35 | 36 | def run_tests(self): 37 | # import here, cause outside the eggs aren't loaded 38 | import tox 39 | errcode = tox.cmdline(self.test_args) 40 | sys.exit(errcode) 41 | 42 | 43 | setup( 44 | name="django-easy-select2", 45 | version="1.5.8", 46 | packages=find_packages(exclude=('tests', )), 47 | author="asyncee", 48 | description="Django select2 theme for select input widgets.", 49 | long_description=long_description, 50 | license="MIT", 51 | keywords="django select2", 52 | url='https://github.com/asyncee/django-easy-select2', 53 | download_url='https://pypi.python.org/pypi/django-easy-select2/', 54 | 55 | python_requires='>=3.9', 56 | install_requires=[ 57 | 'Django>=2.2', 58 | ], 59 | 60 | classifiers=[ 61 | 'Development Status :: 5 - Production/Stable', 62 | 'Environment :: Web Environment', 63 | 'Framework :: Django', 64 | 'Intended Audience :: Developers', 65 | 'License :: OSI Approved :: MIT License', 66 | 'Programming Language :: Python', 67 | 'Programming Language :: Python :: 3', 68 | 'Programming Language :: Python :: 3 :: Only', 69 | 'Programming Language :: Python :: 3.9', 70 | 'Programming Language :: Python :: 3.10', 71 | 'Topic :: Software Development :: Widget Sets', 72 | ], 73 | 74 | package_dir={'easy_select2': 'easy_select2'}, 75 | package_data={'easy_select2': data_files}, 76 | zip_safe=False, 77 | 78 | tests_require=['tox'], 79 | cmdclass={'test': Tox}, 80 | ) 81 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncee/django-easy-select2/8a487403f50ab29858ead26b42d79fcde9443919/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_forms.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from demoapp.models import TestFieldsModel 4 | 5 | from easy_select2.forms import FixedModelForm 6 | 7 | 8 | class TestFixedModelForm(FixedModelForm): 9 | class Meta: 10 | model = TestFieldsModel 11 | exclude = [] 12 | 13 | 14 | def test_fixedmodelform(): 15 | form = TestFixedModelForm() 16 | assert form.fields['fk_field'].help_text.strip() == '' 17 | assert form.fields['m2m_field'].help_text.strip() == '' 18 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import mock 4 | import pytest 5 | from demoapp import models as m 6 | from django import forms 7 | 8 | from easy_select2 import forms as es2_forms 9 | from easy_select2 import utils, widgets 10 | 11 | 12 | def test_apply_select2(): 13 | cls = utils.apply_select2(forms.Select) 14 | assert cls.__name__ == 'Select2Select' 15 | assert cls.__bases__ == (widgets.Select2Mixin, forms.Select) 16 | 17 | 18 | def test_select2_modelform_meta_empty_widgets(): 19 | cm = utils.select2_modelform_meta(m.EmptyModel) 20 | assert cm.__name__ == 'Meta' 21 | assert cm.__bases__ == (object,) 22 | assert cm.model == m.EmptyModel 23 | assert cm.widgets == {} 24 | 25 | 26 | def test_select2_modelform_meta_widgets_without_arguments(): 27 | cm = utils.select2_modelform_meta(m.TestFieldsModel) 28 | assert cm.__name__ == 'Meta' 29 | assert cm.__bases__ == (object,) 30 | assert cm.model == m.TestFieldsModel 31 | assert cm.widgets != {} 32 | assert isinstance(cm.widgets['fk_field'], widgets.Select2) 33 | assert isinstance(cm.widgets['choice_field'], widgets.Select2) 34 | assert isinstance(cm.widgets['m2m_field'], widgets.Select2Multiple) 35 | assert 'text' not in cm.widgets 36 | 37 | 38 | def test_select2_modelform_meta_with_arguments(): 39 | cm = utils.select2_modelform_meta( 40 | m.TestFieldsModel, 41 | meta_fields={'extra_field': 1}, 42 | widgets={ 43 | 'text': forms.TextInput, 44 | 'fk_field': forms.TextInput, # must change to Select2 45 | }, 46 | ) 47 | assert cm.extra_field == 1 48 | assert cm.widgets['text'] == forms.TextInput 49 | assert isinstance(cm.widgets['fk_field'], widgets.Select2) 50 | 51 | 52 | def test_select2_modelform_meta_kwargs(): 53 | cm = utils.select2_modelform_meta(m.TestFieldsModel) 54 | assert cm.exclude == [] 55 | cm = utils.select2_modelform_meta( 56 | m.TestFieldsModel, 57 | fields=['text'], 58 | ) 59 | assert cm.fields == ['text'] 60 | cm = utils.select2_modelform_meta( 61 | m.TestFieldsModel, 62 | exclude=['text'], 63 | ) 64 | assert cm.exclude == ['text'] 65 | 66 | 67 | # Select2 has already been imported by easy_select2.utils module 68 | @mock.patch('easy_select2.utils.Select2Multiple') 69 | @mock.patch('easy_select2.utils.Select2') 70 | def test_select2_modelform_meta_with_blank_attrs_argument( 71 | Select2Mock, Select2MultipleMock): 72 | utils.select2_modelform_meta(m.TestFieldsModel) 73 | Select2Mock.assert_called_with(select2attrs=None) 74 | assert Select2Mock.call_count == 2 75 | Select2MultipleMock.assert_called_with(select2attrs=None) 76 | assert Select2MultipleMock.call_count == 1 77 | 78 | 79 | # Select2 has already been imported by easy_select2.utils module 80 | @mock.patch('easy_select2.utils.Select2Multiple') 81 | @mock.patch('easy_select2.utils.Select2') 82 | def test_select2_modelform_meta_with_attrs_argument( 83 | Select2Mock, Select2MultipleMock): 84 | attrs = {'attribute': True} 85 | utils.select2_modelform_meta(m.TestFieldsModel, attrs=attrs) 86 | Select2Mock.assert_called_with(select2attrs=attrs) 87 | assert Select2Mock.call_count == 2 88 | Select2MultipleMock.assert_called_with(select2attrs=attrs) 89 | assert Select2MultipleMock.call_count == 1 90 | 91 | 92 | def test_select2_modelform(): 93 | form_class = utils.select2_modelform(m.TestFieldsModel) 94 | assert form_class.__name__ == 'TestFieldsModelForm' 95 | assert issubclass(form_class, forms.ModelForm) 96 | assert hasattr(form_class, 'Meta') 97 | 98 | 99 | @pytest.mark.django_db 100 | def test_select2_modelform_renders_successfully(): 101 | form_class = utils.select2_modelform(m.TestFieldsModel) 102 | form = form_class() 103 | assert 'select2' in form.as_p() 104 | 105 | 106 | def test_select2_modelform_form_class_argument(): 107 | class TestForm(forms.ModelForm): 108 | pass 109 | 110 | form_class = utils.select2_modelform( 111 | m.TestFieldsModel, 112 | form_class=TestForm, 113 | ) 114 | assert issubclass(form_class, TestForm) 115 | 116 | form_class = utils.select2_modelform(m.TestFieldsModel) 117 | assert issubclass(form_class, es2_forms.FixedModelForm) 118 | 119 | 120 | @mock.patch('easy_select2.utils.select2_modelform_meta') 121 | def test_select2_modelform_attrs_argument(mock): 122 | utils.select2_modelform(m.TestFieldsModel) 123 | mock.assert_called_with(m.TestFieldsModel, attrs=None) 124 | attrs = {'attr': False} 125 | utils.select2_modelform(m.TestFieldsModel, attrs=attrs) 126 | mock.assert_called_with(m.TestFieldsModel, attrs=attrs) 127 | -------------------------------------------------------------------------------- /tests/test_widgets.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import mock 4 | import pytest 5 | from django.contrib.staticfiles.storage import staticfiles_storage 6 | 7 | from easy_select2 import widgets 8 | 9 | 10 | def test_select2mixin_constructor(): 11 | s = widgets.Select2Mixin() 12 | assert isinstance(s.select2attrs, dict) 13 | assert s.select2attrs['width'] == '250px' 14 | 15 | s1 = widgets.Select2Mixin(select2attrs={'auto': True}) 16 | assert s1.select2attrs['auto'] is True 17 | 18 | with pytest.raises(AssertionError): 19 | widgets.Select2Mixin(select2attrs="wrong value") 20 | 21 | 22 | def test_select2mixin_get_options(): 23 | s = widgets.Select2Mixin() 24 | assert isinstance(s.get_options(), dict) 25 | 26 | 27 | def test_select2mixin_render_options_code(): 28 | s = widgets.Select2Mixin() 29 | options = OrderedDict() 30 | options['number'] = 1 31 | options['string'] = u'string' 32 | options['dict'] = {'k': 'v'} 33 | options['list'] = [1, 'two'] 34 | result = s.render_select2_options_code(options, 'some_id') 35 | expected = ( 36 | "data-number='1' " 37 | "data-string='string' " 38 | "data-dict='{\"k\": \"v\"}' " 39 | "data-list='[1, \"two\"]'" 40 | ) 41 | assert result == expected 42 | 43 | 44 | @mock.patch.object(widgets.Select2Mixin, 'render_select2_options_code') 45 | def test_select2mixin_render_js_code(mocked): 46 | mocked.return_value = "some_options" 47 | s = widgets.Select2Mixin() 48 | s.html = "{id}: {options}" 49 | result = s.render_js_code("some_id") 50 | expected = "some_id: some_options" 51 | assert result == expected 52 | 53 | 54 | def test_select2mixin_render_js_code_should_return_empty_string(): 55 | s = widgets.Select2Mixin() 56 | assert s.render_js_code(id_=None) == u'' 57 | 58 | 59 | class SuperWithRender(object): 60 | def render(self, *args, **kwargs): 61 | return "super" 62 | 63 | 64 | class TestRender(widgets.Select2Mixin, SuperWithRender): 65 | pass 66 | 67 | 68 | @mock.patch.object(TestRender, 'render_js_code') 69 | def test_select2mixin_render(mocked): 70 | mocked.return_value = "some_js" 71 | s = TestRender() 72 | result = s.render('name', 'value', attrs={'id': 'some_id'}) 73 | expected = "supersome_js" 74 | assert result == expected 75 | 76 | 77 | def test_staticfiles_url(settings): 78 | s = widgets.Select2Mixin() 79 | js = s.media._js 80 | css = s.media._css 81 | 82 | def all_startswith(string, iterable): 83 | return all([staticfiles_storage.url(x).startswith(string) 84 | for x in iterable]) 85 | 86 | assert all_startswith( 87 | settings.STATIC_URL, 88 | js, 89 | ) 90 | for v in css.values(): 91 | assert all_startswith( 92 | settings.STATIC_URL, 93 | v, 94 | ) 95 | 96 | 97 | def test_django_jquery__bundled(settings): 98 | settings.SELECT2_USE_BUNDLED_JQUERY = True 99 | s = widgets.Select2Mixin() 100 | assert s.media._js[0].startswith('easy_select2/vendor/jquery/jquery-') 101 | assert s.media._js[0].endswith('.min.js') 102 | 103 | 104 | def test_django_jquery__not_bundled(settings): 105 | settings.SELECT2_USE_BUNDLED_JQUERY = False 106 | s = widgets.Select2Mixin() 107 | assert s.media._js[0] == 'admin/js/jquery.init.js' 108 | 109 | 110 | def test_django_select2__bundled(settings): 111 | settings.SELECT2_USE_BUNDLED_SELECT2 = True 112 | s = widgets.Select2Mixin() 113 | assert s.media._css['screen'][0].startswith('easy_select2/vendor/select2-') 114 | assert s.media._css['screen'][0].endswith('/css/select2.min.css') 115 | assert s.media._js[3].startswith('easy_select2/vendor/select2-') 116 | assert s.media._js[3].endswith('/js/select2.min.js') 117 | 118 | 119 | def test_django_select2__not_bundled(settings): 120 | settings.SELECT2_USE_BUNDLED_SELECT2 = False 121 | s = widgets.Select2Mixin() 122 | assert s.media._css['screen'][0] == 'admin/css/vendor/select2/select2.min.css' 123 | assert s.media._js[3] == 'admin/js/vendor/select2/select2.full.min.js' 124 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | # No particular need for Python 3.8 and 3.9 3 | envlist = 4 | py39-django22, 5 | py310-{django32,django40,coverage}, 6 | 7 | [base] 8 | deps = 9 | mock 10 | pytest 11 | pytest-django 12 | setenv = 13 | DJANGO_SETTINGS_MODULE=sampleproject.settings 14 | PYTHONPATH={toxinidir}/sampleproject 15 | 16 | [testenv] 17 | deps = 18 | {[base]deps} 19 | django22: django>=2.2,<2.3 20 | django32: django>=3.2,<3.3 21 | django40: django>=4.0,<4.1 22 | commands = pytest tests 23 | setenv = {[base]setenv} 24 | 25 | [testenv:py310-coverage] 26 | deps = 27 | {[base]deps} 28 | django 29 | coverage 30 | coveralls 31 | commands = 32 | coverage run --source easy_select2 -m pytest tests 33 | coverage report -m 34 | bash -c 'set -x; [[ -z $\{COVERALLS_REPO_TOKEN\} ]] || coveralls' 35 | setenv = {[base]setenv} 36 | # not GITHUB_ACTIONS! 37 | # not GITHUB_TOKEN! 38 | passenv = 39 | COVERALLS_REPO_TOKEN 40 | GITHUB_HEAD_REF 41 | GITHUB_REF 42 | GITHUB_REPOSITORY 43 | GITHUB_RUN_ID 44 | GITHUB_RUN_NUMBER 45 | GITHUB_SHA 46 | allowlist_externals = bash 47 | --------------------------------------------------------------------------------